Skip to main content
Version: dev-latest

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

ItemSeed Plex OneSeed Plex TwoInit Plex
Timestamp100200 (newer)Matches time of writing
Components with topicuuidtopic_{uuid}A1A_{1}, B2B_{2}, and C3C_{3}A4A_{4}, B5B_{5}, and C6C_{6}A4A_{4}, B5B_{5}, and C6C_{6}
Spatial ConstraintA1A_{1} <--> B2B_{2}A4A_{4} <--> B5B_{5}A4A_{4} <--> B5B_{5}
Temporal ConstraintB2B_{2} <--> C3C_{3}A4A_{4} <--> B5B_{5}A4A_{4} <--> B5B_{5}, B5B_{5} <--> C6C_{6}

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
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.