Init Mode
Purpose
- Create an uncalibrated plex from a dataset and other seed plex.
Usage
metrical init [OPTIONS] --topic-to-model <topic_name:model> \
<INPUT_DATA_PATH> <INIT_JSON>
Concepts
Init will infer all components, spatial constraints, and temporal constraints based on the
observations and interactions in the dataset. It will then write this information out in plex form
to a JSON file (listed as $INIT_PLEX
in code samples below). This is our Initial Plex! MetriCal
will use this plex as the initialization to the Calibrate mode.
Let's break down this example Init command:
metrical init -m *cam_ir*:opencv_radtan -m *cam_color*:eucm -m *lidar*:no_offset $DATA $INIT_PLEX
- Assign all topics/folders that match the
*cam_ir*
pattern to the OpenCV Radtan model. - Assign all topics/folders that match the
*cam_color*
pattern to the EUCM model. - Assign all topics/folders that match the
*lidar*
pattern to the No Offset model (just extrinsics) - Use the data in
$DATA
to seed the plex.
MetriCal will discard information from any topics that aren't assigned a model using the command
line. See all of the models available to MetriCal in the
--topic-to-model
/-m
documentation.
Seed an Init Plex
Say you've already calibrated all of your cameras individually, and have great intrinsics results in another plex. You can use those as a starting point for another plex using Init:
metrical init --plex-path $SEED_PLEX $DATA $INIT_PLEX
All components, spatial constraints, and temporal constraints that are in the initial plex will be preserved in the output plex, regardless of whether they are in the dataset. If there is a conflict, the output will be modified to a "best guess" value by MetriCal based on the input plex. An example of this would be changing the image size of a camera based on the observations in the dataset, but keeping any existing spatial constraints intact.
Overwriting Init Plex
By default, MetriCal will prevent you from overwriting a plex if one exits at the $INIT_PLEX
path.
You can tell MetriCal to overwrite this plex by passing the --overwrite
/-y
flag. When this
happens, MetriCal will use the plex currently located at $INIT_PLEX
as a seed itself (along with
any other seeded plex you have passed in). This preserves UUIDs between runs, information upon which
much of MetriCal's caching depends.
If you want to overwrite the Init plex without using the original as a seed, you must manually delete the original plex file.
Init Order of Operations
...with no Seeded Plex
- The Init mode should create a new plex with the given data, only using the named devices.
- All components should have dummy spatial constraints between them.
- All components should have populated temporal constraints between them.
...with Seeded Plex
For all components passed in via -m
, if the topic is...
- IN the dataset + IN the seeded plex:
- The plex component intrinsics are updated. UUIDs are preserved.
- If the intrinsics model asked for in the CLI is different from that of the seeded plex, it should update the model. UUIDs are preserved.
- If a camera model is the same, but the image size is different, it should update the intrinsics to scale to the new image size (if possible). UUIDs are preserved. If not possible, it should throw an error.
- If the camera model is the same, and the image size is the same, we should preserve the component as-is from the seeded plex.
- IN the dataset + NOT IN the seeded plex:
- A new component is created with guessed intrinsics and the right model.
- NOT IN the dataset + IN the seeded plex:
- All information on that component is copied over as-is.
- NOT IN the dataset + NOT IN the seeded plex: - The component and all of its information is
disregarded. Any components not passed in with
-m
, but present in the seeded plex, are dropped from the initialized plex. All constraints that connect two preserved components should themselves be preserved. - If a component is dropped, all constraints that involve it are dropped.
- Synchronization in temporal constraints is preserved. Resolution is modified based on the input data.
...with Multiple Seeded Plex
- Seed plex are ordered by creation timestamp, from newest to oldest
- Plex repair data is created according to the "With Seeded Plex" criteria, going from newest seed
plex to oldest. The newer the plex, the higher its priority; the newest plex's components and
constraints will be used before all others.
- If an older plex contains components or constraints that use a totally different UUID and topic, those components or constraints are carried over in their entirety in the init plex.
- If an older plex contains components or constraints that use the same topic, but a different UUID, that information is considered the same as what was read in the same topic from a newer plex. In this case, any constraints that include the "old" topic+UUID pair are incorporated into the init plex, but the "old" UUID is converted to match that of the component in the newest plex in which it appeared.
Applying the Order of Operations
Item | Seed Plex One | Seed Plex Two | Init Plex |
---|---|---|---|
Timestamp | 100 | 200 (newer) | Matches time of writing |
Components with | , , and | , , and | , , and |
Spatial Constraint | <--> | <--> | <--> |
Temporal Constraint | <--> | <--> | <--> , <--> |
All information in the init plex came directly from Seed Plex Two, since it was newer. However, the temporal constraint between B and C only existed in Seed Plex One. Since we match topics as well as UUIDs, we took this to mean that Seed Plex Two was missing a temporal constraint; we can go ahead and move that to the new init plex.
Examples
Create a plex from input data
Use OpenCV's brown-conrady model for all topics whose name starts with the substring /camera/
.
metrical init --topic-to-model /camera/*:opencv_radtan $DATA $INIT_PLEX
Seed a new plex with previous calibrations
metrical init --seed-cal-path $SEED_PLEX_ONE \
--seed-cal-path $SEED_PLEX_TWO \
--seed-cal-path ... \
$DATA $INIT_PLEX
Arguments
[INPUT_DATA_PATH]
Input data path for this initialization. MetriCal accepts a few data formats:
- Ros1 bags, in the form of a
.bag
file. - Ros2 bags, in the form of a
.mcap
file. - Folders of observations.
[OUTPUT_JSON]
The JSON in which to save the final plex. [default: plex.json]
Options
Universal Options
As with every mode, all universal options are supported (though not all may be used).
-p, --seed-cal-path [SEED_CAL_PATH]
The path to the input plex. This can be a MetriCal results JSON, a plex JSON, or a URDF XML.
-m, --topic-to-model [topic_name:model]
A mapping of topic/folder names to models in the input plex. NOTE: All topics intended for calibration must be enumerated by this argument. If an initial plex is provided, any matching topic models in the plex will be overwritten.
Example: We would like the topic "camera_1" to be modeled using OpenCV's regular distortion model (aka Brown Conrady), and "camera_2" to be modeled using its fisheye model:
-m camera_1:opencv_radtan -m camera_2:opencv_fisheye
One may also use wildcards to designate many topics at a time:
-m /camera/\*:opencv_radtan
Available models
Cameras
- no_distortion
- pinhole_with_brown_conrady
- pinhole_with_kannala_brandt
- opencv_radtan
- opencv_fisheye
- opencv_rational
- eucm
- double_sphere
- omni
Lidar
Imu
-c, --topic-to-component [TOPIC_TO_COMPONENT]
A mapping of ROS topic/folder names to component names/UUIDs in the input plex.
MetriCal only parses data that has a topic-component mapping. Ideally, topics and components share the same name. However, if this is not the case, use this flag to map topic names from the dataset to component names in the plex.
-y, --overwrite-plex
Overwrite the init plex file at this location, if it exists.
Deprecated Options
-s, --preset-device [PRESET_DEVICE]
--preset-device is deprecated, scheduled removal: v13.0. Replacement: N/A, no longer a feature.