Skip to main content
Version: Next

metrical init


  • Create a plex from a dataset.
  • Modify an existing plex based on a dataset.


metrical init [OPTIONS] --topic-to-model <topic_name:model> <INPUT_DATA_PATH> [OUTPUT_JSON]


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 $OUTPUT_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. It outputs a handy table of these components at the very beginning of the Init process, so that you know the data you need is being processed:

    >> Topics with assigned UUIDs + Models <<
| Topic | Assigned UUID (first 8 char) | Assigned Model |
| /lidar/velo1 | 1ad5e919 | no_offset |
| /camera/cam_ir/left | 44c82979 | opencv_radtan |
| /camera/cam_ir/right | 5b74a88c | opencv_radtan |
| /camera/cam_color/wvl | 9e5add28 | eucm |
| All other topics have been ignored | | |

Seed Intrinsics and Extrinsics from another Plex

Sometimes, it's impossible to calibrate every sensor at once. Your rig may be too large, or sensors are hidden out of reach after installation. Don't worry! MetriCal can handle it by seeding future Init commands with an existing plex that only has a few complete components.

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 $INPUT_PLEX $DATA $OUTPUT_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.



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.

The output JSON in which to save the final plex. [default: plex.json]


Init mode supports all global options, as well as the following:

-p, --plex-path <PLEX_PATH>

The plex.json used as a starting point.

-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 mode:

-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

Camera Models:

  • no_distortion
  • pinhole_with_brown_conrady
  • pinhole_with_kannala_brandt
  • opencv_radtan
  • opencv_fisheye
  • opencv_rational
  • eucm
  • double_sphere
  • omni

LiDAR Models:

  • no_offset

IMU Models:

  • no_intrinsics
  • scale
  • scale_shear
  • scale_shear_rotation
  • scale_shear_rotation_g_sensitivity
-s, --preset-device <PRESET_DEVICE>

A list of devices that Tangram has documented as useful calibration presets. Specify a device and follow it with a list of topics or folder names that are part of that device type. This flag may be repeated for multiple devices.

When a preset device is assigned, Init will print out helpful pointers about calibrating that device to the console. It will also issue warnings when streams aren't correctly configured for that device's recommended calibration procedure, a la:

👉 RealSense 435 Calibration Pointers (if flashing to device):
- IR camera settings: Y16 format (16-bit), resolution of 1280x800 @ 15fps
- Color camera settings: YUY2 format, resolution of 1920x1080 @ 15fps
- Pause often during capture. The cameras do not temporally sync when streaming the above settings.
- Capture features in the entire field of view of the image.
For more, visit
RealSense Left IR stream cam_0_ir_1 is not Y16 format! This means that it's already rectified;
make sure to assign this topic the `no_distortion` model.

Sometimes, a different configuration can be desireable; for instance, your RealSense calibration might be fine, and you just want to register it to another sensor. These warnings are just MetriCal's way of making sure you know what you're doing.

Example: There are three streams, ir_left, ir_right, and visible, which all belong to a RealSense 435. Indicate to Plex Smith that this is the case with the following argument:

-s RealSense435:["ir_left", "ir_right", "visible"]

Order matters; reference the available models below for the proper order. If there is no available topic for a stream, indicate this with a _:

-s RealSense435:["ir_left", _, "visible"]

Available devices:

  • RealSense415: [left ir, right ir, color]
  • RealSense435: [left ir, right ir, color]
  • RealSense435Imu: [left ir, right ir, color, imu]
  • RealSense455Imu: [left ir, right ir, color, imu]


1. Create a fresh 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 $OUTPUT_PLEX

2. Use an old plex to seed a new plex

metrical init --plex_path $INPUT_PLEX $DATA $OUTPUT_PLEX

3. Use a preset device to seed a new plex

In this case, we have two RealSense 435 with two ROS streams each: /cam[n]/ir_left and /cam[n]/ir_right. We only have two of its three streams, so we use _ to designate the missing camera streams from the visible (RGB) cameras.

metrical init \
-s RealSense435:["/cam0/ir_left", "/cam0/ir_right", _] \
-s RealSense435:["/cam1/ir_left", "/cam1/ir_right", _] \