Manifest Field Reference
Every field of the dataset manifest, generated from its JSON Schema. The prose chapter The Dataset Manifest explains how the pieces fit together; this page is the exhaustive list. The schema itself is app/src/schemas/dataset_spec.json in the repository, and the desktop app builds its manifest form from it.
Paths in a manifest are relative to the directory that holds it unless they are absolute. A field marked required has no default and must be present; an optional field may be omitted.
DatasetSpec
Top-level dataset manifest. Authoritative description of where the user's calibration data lives and how to interpret it.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
cameras | array of CameraSource | yes | Per-camera image sources. Length must match the topology's expected camera count (a single-camera topology requires exactly one entry, a rig topology at least two, rig_handeye_laserline at least one). | |
target | TargetSpec | yes | Calibration-target specification. Tagged enum on kind. | |
topology | Topology | yes | Calibration topology — selects which problem type the runner will dispatch to. | |
_unresolved | array of string | no | Field paths the manifest generator could not determine. Validated to be empty before the runner accepts the manifest. Populated as e.g. ["pose_convention.transform"]. | |
description | string | no | Free-form human-readable description. | |
detector | DetectorSpec | no | Detector-stage overrides shared by target families. Defaults preserve the detector's built-in behavior. | |
laser | LaserExtractionSpec | no | Laser-line extraction parameters for the laser topologies. None means defaults — extraction tuning has safe defaults and is not a fail-fast ambiguity. Rejected on non-laser topologies. | |
pose_convention | PoseConvention | no | Frame conventions for robot poses. No defaults — every component is required when robot_poses is set. | |
pose_pairing | PosePairing | no | How per-camera images are paired across views (and optionally with robot poses). None is permitted only where pairing is irrelevant: a single camera without robot poses. | |
robot_poses | RobotPoseSource | no | Robot-pose source for hand-eye topologies. None for pure-intrinsics calibrations. | |
upstream_calibration | string | no | Path to a frozen upstream RigHandeyeExport JSON, relative to the manifest directory unless absolute. Required for Topology::RigLaserlineDevice, rejected elsewhere. Joint hand-eye laserline calibration computes its own hand-eye warm start and does not use this field. | |
version | integer | no | 1 | Format-version sentinel. Always 1 for now; bumped on breaking schema revisions. |
Unknown fields are rejected.
CameraSource
Per-camera image source.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Stable camera identifier (e.g. "cam0"). Used as a key in pose pairings and downstream exports. |
images | ImagePattern | yes | Glob pattern (e.g. "cam0/*.png") or explicit list of image paths, relative to the manifest's directory unless absolute. |
laser_images | ImagePattern | no | Laser-frame image source for the laser topologies. One laser image per view, captured by the same sensor with the line projector on; roi_xywh applies to laser frames too. Laser images pair with target views through pose_pairing. |
roi_xywh | array of 4 integer | no | Optional rectangular ROI in source-image pixels — [x, y, w, h]. When set, only the cropped region is fed to the detector and stored in the export's image manifest. |
Unknown fields are rejected.
ImagePattern
How image paths for a camera are listed.
Tagged on kind; the fields depend on the variant.
kind = "glob": Single shell-glob pattern, evaluated relative to the manifest directory. Example: "cam0/*.png".
| Field | Type | Required | Description |
|---|---|---|---|
pattern | string | yes | The glob pattern. |
kind = "list": Explicit ordered list of paths.
| Field | Type | Required | Description |
|---|---|---|---|
paths | array of string | yes | Paths relative to the manifest directory unless absolute. |
TargetSpec
Calibration-target metadata. Tagged on kind.
Tagged on kind; the fields depend on the variant.
kind = "chessboard": Standard checkerboard. Counts are interior corners (i.e. 9x6 ⇒ a 10×7 black-and-white square grid).
A plain chessboard has no markers: each view is labelled from the detection's own top-left corner. Where views share one target frame (single-camera hand-eye and every rig topology) the runner therefore keeps a view only when its corners reach every edge of the board. In a rig, each camera's labels are turned to agree with the other cameras of the view, so a board seen turned is kept. Where the target is fixed through the views (hand-eye), the board must appear the same way up in every image of camera 0 (cols across and rows down); a board seen turned by 90° is dropped, and one seen upside down, or a square board seen turned by 90°, cannot be told apart. Use a ChArUco or PuzzleBoard target to calibrate a shared frame from partial views.
| Field | Type | Required | Description |
|---|---|---|---|
cols | integer | yes | Number of interior corners across the board (the image's columns axis when the board is seen as declared). |
rows | integer | yes | Number of interior corners down the board (the image's rows axis when the board is seen as declared). |
square_size_m | number | yes | Edge length of one square in metres. |
kind = "charuco": ChArUco board. Marker IDs and dictionary live here so detection is fully deterministic from the manifest.
| Field | Type | Required | Description |
|---|---|---|---|
cols | integer | yes | Number of squares along the cols axis. |
dictionary | string | yes | ArUco dictionary identifier (e.g. "DICT_4X4_50"). The detector validates this against the supported set. |
marker_size_m | number | yes | Edge length of an embedded marker in metres. |
rows | integer | yes | Number of squares along the rows axis (full grid, not interior corners). |
square_size_m | number | yes | Edge length of one square in metres. |
kind = "puzzleboard": Puzzleboard target: a self-identifying chessboard. The layout name carries the board's dimensions, so the manifest fully determines detection.
| Field | Type | Required | Description |
|---|---|---|---|
cell_size_m | number | yes | Edge length of one cell in metres. |
layout | string | yes | Board dimensions as puzzle_<rows>x<cols> (e.g. "puzzle_12x12"; the puzzle_ prefix is optional). |
kind = "ringgrid": Coded ring-grid target (the ringgrid crate). The board is a hex-lattice of self-identifying ring markers; its geometry mirrors ringgrid::BoardLayout so the manifest fully determines detection.
| Field | Type | Required | Description |
|---|---|---|---|
long_row_cols | integer | yes | Number of columns in the longest (even-indexed) row. Shorter rows are derived by the hex-lattice layout. |
marker_inner_radius_m | number | yes | Inner ring radius in metres. |
marker_outer_radius_m | number | yes | Outer ring radius in metres. |
marker_ring_width_m | number | yes | Width of each ring band in metres. |
pitch_m | number | yes | Center-to-center spacing between adjacent markers in metres. |
rows | integer | yes | Number of marker rows. |
Topology
Calibration topology — selects the problem-type dispatch.
A topology describes the data (how many cameras, robot poses, laser images), not the camera model: a tilted (Scheimpflug) single camera is a planar_intrinsics dataset whose calibration config names the sensor.
| Value | Description |
|---|---|
planar_intrinsics | Single camera, planar target — PlanarIntrinsicsProblem (any camera model, including a tilted sensor). |
single_cam_handeye | Single camera mounted on a robot — SingleCamHandeyeProblem. |
laserline_device | Camera + laser plane — LaserlineDeviceProblem. |
rig_extrinsics | Multi-camera rig, target only — RigExtrinsicsProblem. |
rig_handeye | Multi-camera rig + robot — RigHandeyeProblem. |
rig_handeye_laserline | Multi-camera rig + robot + laser planes — joint hand-eye/laser BA. |
rig_laserline_device | Multi-camera rig + laser planes — RigLaserlineDeviceProblem. |
DetectorSpec
Target-detector overrides. These options affect feature detection only; they are hashed into the detection-cache key by the runner.
| Field | Type | Required | Description |
|---|---|---|---|
chess_corners | ChessCornersDetectorSpec | no | ChESS corner extractor options shared by chessboard-like detectors (plain chessboard and ChArUco). |
min_features_per_view | integer | no | Minimum detected features for a view (or a camera's slot in a rig view) to be kept, in every topology. None keeps the runner default (4, the homography minimum). Raise it for detectors whose sparse detections are unreliable — e.g. ring-grid decodes with < 8 markers are noisy enough to poison a solve. A plain chessboard needs no floor to stay consistent: where views share one target frame the runner already keeps only views that span the whole board. |
Unknown fields are rejected.
ChessCornersDetectorSpec
ChESS corner extractor overrides.
| Field | Type | Required | Description |
|---|---|---|---|
covariance | CornerCovarianceSpec | no | Attach the detector's per-corner position covariance to every observation. Absent (the default) = off. The covariance is the image noise propagated through the corner localizer, plus the localizer's systematic-error model. When present, a calibration weights each corner by it (whitened residuals) and its report gives the unit-weight scale factor σ̂₀ instead of an RMS in pixels. Off by default, and not recommended for calibration. On real chessboard and ChArUco images, weighting by it did not improve the accuracy on held-out views and made it slightly worse on some cameras; its stated uncertainty was no closer to the real scatter. Supported by the chessboard and charuco targets only: the PuzzleBoard detector runs on an upscaled image, for which no covariance is reported, and ring grids have none. A manifest that sets it for another target is an error. |
min_corner_strength | number | no | Minimum corner strength for a detected corner to enter the grid builder. None keeps the detector default (33.0). The floor is on the strategy's response scale; under Radon the default never binds.The default drops weakly-firing corners, which is the right trade whenever corners are plentiful. Set 0.0 to disable it on small or soft image tiles, where the floor can remove a third of the board and the resulting sparse view conditions worse than the weak corners did. |
strategy | CornerStrategySpec | no | Corner detector. None keeps ChESS. |
threshold_value | number | no | Acceptance threshold on the corner response. None keeps the strategy's default.Under ChESS it is an absolute floor on the raw response: a corner is kept when its response exceeds it. Under Radon it is a fraction in (0, 1] of the frame's maximum response.A sibling threshold_mode key is rejected by deny_unknown_fields: the corner detector has no threshold mode. |
Unknown fields are rejected.
CornerCovarianceSpec
Per-corner covariance options; see [ChessCornersDetectorSpec::covariance].
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
image_noise | ImageNoiseSpec | no | "estimate" | The image noise that the propagated covariance is expressed in. Defaults to estimate: the noise is estimated from each image, which is unreliable on JPEG or demosaiced images; give known for those. |
Unknown fields are rejected.
ImageNoiseSpec
The pixel-noise level behind a corner covariance.
In JSON / TOML: "estimate" or { known = 2.0 }.
Tagged on kind; the fields depend on the variant.
kind = "": Estimate the noise from each image. Unreliable on JPEG or demosaiced images, where a corner then reports no covariance and the run fails.
kind = "": The standard deviation of the image's pixel noise, in gray levels of the 8-bit image (finite and >= 0), e.g. the standard deviation of the difference of two frames of a static scene divided by √2.
| Field | Type | Required | Description |
|---|---|---|---|
known | number | yes |
Unknown fields are rejected.
CornerStrategySpec
The corner detector a chessboard-like detector runs.
| Value | Description |
|---|---|
chess | The ChESS response. Fast; the default. |
radon | The whole-image Radon response. Several times slower than ChESS, and less biased at a corner's sub-pixel position on sharp, finely sampled boards (e.g. rendered ones). |
LaserExtractionSpec
Laser-line extraction parameters. Consumed by the runner's injected LaserPixelExtractor; hashed (canonical JSON) into the detection-cache key so edits re-extract.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
min_points | integer | no | 20 | Minimum extracted points for a usable laser view. Views below the bar are dropped (single camera) or become gap slots (rig). Must be at least 2 (a line needs two points); 0/1 would let an empty extraction pass as usable and leave the plane unconstrained. |
neg_thresh | number | no | 4.0 | Negative-edge response threshold. |
pos_thresh | number | no | 4.0 | Positive-edge response threshold. |
scan_axis | LaserScanAxis | no | "cols" | Scan direction. cols walks image columns (one point per column; for laser lines running mostly left-to-right), rows walks image rows. |
sigma | number | no | 1.2 | Gaussian derivative sigma in pixels for the edge detector. |
Unknown fields are rejected.
LaserScanAxis
Laser scan direction.
| Value | Description |
|---|---|
cols | One detection per image column. |
rows | One detection per image row. |
PoseConvention
Frame conventions for the robot pose stream.
All three components are required (no defaults). Each is a closed enum so the runtime supports a finite, validated set of conventions.
| Field | Type | Required | Description |
|---|---|---|---|
rotation_format | RotationFormat | yes | How rotation is parameterised in the file. |
transform | TransformConvention | yes | Which transform the pose row encodes. |
translation_units | TranslationUnits | yes | Translation units in the file. |
Unknown fields are rejected.
RotationFormat
Rotation parameterisation in the file.
| Value | Description |
|---|---|
quat_xyzw | Hamilton quaternion as [qx, qy, qz, qw]. |
quat_wxyz | Hamilton quaternion as [qw, qx, qy, qz]. |
euler_xyz_deg | Intrinsic XYZ Euler angles in degrees. |
euler_xyz_rad | Intrinsic XYZ Euler angles in radians. |
euler_zyx_deg | Intrinsic ZYX Euler angles in degrees. |
euler_zyx_rad | Intrinsic ZYX Euler angles in radians. |
axis_angle_rad | Axis-angle vector (length encodes magnitude, radians). |
matrix4x4_row_major | Row-major 4×4 homogeneous matrix flattened across 16 columns. |
TransformConvention
Which transform a pose row encodes.
| Value | Description |
|---|---|
t_base_tcp | T_base_tcp — gripper pose in the robot base frame (KUKA, UR default). |
t_tcp_base | T_tcp_base — base pose in the gripper frame (some ABB exports). |
t_world_tcp | T_world_tcp — gripper pose in a fixed world frame (less common; some lab-frame setups). |
t_tcp_world | T_tcp_world — world pose in the gripper frame. |
TranslationUnits
Translation units in the file.
| Value | Description |
|---|---|
m | Metres (SI, preferred). |
mm | Millimetres (some ABB / Fanuc exports). |
PosePairing
How per-camera image lists align across views and (optionally) align with robot poses.
Tagged on kind; the fields depend on the variant.
kind = "by_index": All cameras have the same number of images, paired by index (image[i] from cam0 ↔ image[i] from cam1 ↔ pose[i]).
kind = "shared_filename_token": A regex applied to filenames extracts a shared "view token" (e.g. timestamp or pose id). All cameras and the pose file must produce the same set of tokens.
| Field | Type | Required | Description |
|---|---|---|---|
group | string | yes | Name of the capture group whose value identifies the view. |
regex | string | yes | Regex with at least one named capture group. |
RobotPoseSource
Where and how robot poses are stored on disk.
| Field | Type | Required | Description |
|---|---|---|---|
format | RobotPoseFormat | yes | File-format selector. |
path | string | yes | Path to the pose file, relative to the manifest directory unless absolute. |
columns | PoseColumnMap | no | Column / field mapping from the user's file to the canonical fields the converter consumes. Required for the tabular formats (csv / json / jsonl) unless matrix_field is set; must be absent for rowmajor4x4 and counted4x4, whose matrix layout is fixed. |
matrix_field | string | no | For json / jsonl files whose rows store the whole pose as a single nested 4×4 (or flat-16) array field, names that field (e.g. "tcp2base"). Mutually exclusive with columns; requires pose_convention.rotation_format = matrix4x4_row_major. Translation comes from the matrix's fourth column, scaled by translation_units. No pose_id ⇒ by_index pairing only. |
Unknown fields are rejected.
RobotPoseFormat
Robot-pose file format.
| Value | Description |
|---|---|
csv | Comma-separated values with a header row. |
json | JSON array of objects. |
jsonl | JSONL (one JSON object per line). |
rowmajor4x4 | Headerless text: each non-empty line is 16 whitespace-separated floats forming a row-major 4×4 homogeneous transform (KUKA-style exports). Requires pose_convention.rotation_format = "matrix4x4_row_major" and no columns mapping. |
counted4x4 | Headerless text: the matrix count, then that many row-major 4×4 homogeneous transforms as whitespace-separated floats on any number of lines (the layout of the robot-world hand-eye datasets of Tabb and Ahmad Yousef). Same requirements as rowmajor4x4. |
PoseColumnMap
Mapping from user-defined column / field names to the canonical pose fields. All seven of tx, ty, tz, qx, qy, qz, qw are required when rotation_format is a quaternion; the runner rejects partial mappings as a fail-fast event.
| Field | Type | Required | Description |
|---|---|---|---|
rotation | array of string | yes | Rotation columns. Length and meaning depend on the pose_convention.rotation_format. |
tx | string | yes | Translation x column. |
ty | string | yes | Translation y column. |
tz | string | yes | Translation z column. |
pose_id | string | no | Optional view-id column (string or integer). When absent, the pose row index is used as the implicit pose id. |
Unknown fields are rejected.