Skip to content
Copy as Markdown

Configuration Parameter Reference

Configuration System explains the two config formats (unified vs. legacy) and how they're parsed. This page is the field-by-field glossary for what each parameter in the calibration: and identification: sections actually means — units, which pipeline step consumes it, and its unified-format equivalent where one exists.

Field names below match the legacy flat format, since that's what you see verbatim in an existing config file (the legacy format was removed in 1.0; these are the keys config_migration reads). The Unified path column gives the equivalent key under tasks.calibration.* / tasks.identification.* in the unified format — unified_to_legacy_config and unified_to_legacy_identif_config (both in figaroh/src/figaroh/*/config.py) convert one to the other, so the two formats agree on meaning even though the layout differs.

calibration: section

Field Meaning Unified path
calib_level Kinematic-error model: joint_offset (one offset per joint, about or along its own axis) or full_params (six placement errors per joint, translation and rotation vector in the joint frame) parameters.calibration_level
estimation Which parameters to estimate and how: method (structural default, excitation, map, map_cv, cv_subset), priors, noise_std, cross-validation settings. See Calibration estimation methods parameters.estimation
non_geom Also identify joint elasticity (gravity-torque-driven compliance, one term per active joint) on top of the geometric model parameters.include_non_geometric
base_frame URDF frame name at the start of the kinematic chain kinematics.base_frame
tool_frame URDF frame name at the end of the chain (usually the gripper/tool mount) kinematics.tool_frame
base_to_ref_frame (optional, eye-hand/camera mode only) A frame reachable from base_frame via a known transform (e.g. a camera housing anchor) eye_hand.camera_frame (requires eye_hand.enabled: true)
ref_frame (optional, eye-hand/camera mode only) The frame the chain restarts from after the known base_to_ref_frame segment; the unknown camera/anchor pose being estimated sits between ref_frame and the true world frame eye_hand.reference_frame (requires eye_hand.enabled: true)
markers[].ref_joint Joint the external marker is rigidly mounted near; its offset from tool_frame is what gets estimated (pEEx/y/z, phiEEx/y/z; pEEx_k ... for marker k). Several markers are points on the same tool_frame, see Several points on the tool measurements.markers[].reference_joint — written by convention, but not currently read back by _extract_marker_info (only measurable_dof, from the first marker, is consumed)
markers[].measure 6-DOF boolean mask [x, y, z, roll, pitch, yaw] — which axes the external sensor (mocap/vision/contact) actually reports for that marker. Every marker uses the first marker's mask measurements.markers[].measurable_dof
free_flyer True if the robot's base itself is unconstrained/floating in the model (mobile-base robots with an unknown per-sample base pose) kinematics.free_flying_base
base_pose Initial guess [x, y, z, roll, pitch, yaw] (m, rad) for the base_frame → world (or anchor → camera, in eye-hand mode) transform being estimated measurements.poses.base_pose
tip_pose Initial guess [x, y, z, roll, pitch, yaw] (m, rad) for the tool_frame → marker transform being estimated measurements.poses.tool_pose
coeff_regularize Removed in 1.0 (#120, #185), default 0. One L2 weight that robot cost functions applied to every joint parameter, penalising metres and radians alike. Core never applied it; a non-zero value is now a ConfigurationError (the migration tool writes 0 and warns). Use estimation.method: map instead (priors of physical size per parameter group, estimation methods) parameters.regularization_coefficient
outlier_eps Position error (meters, norm of the measured x/y/z residuals of a sample, worst marker) above which a sample is excluded and the rest refitted, for up to max_iterations fits. Rotational components do not take part; with no measured position component nothing is excluded. Excluded samples and their errors are in the evaluation (excluded_samples, excluded_sample_errors) and the report parameters.outlier_threshold
random_seed Seed for the random configurations that select the identifiable parameter set (default 0). The selection, hence the result, does not depend on any global random state; the seed is recorded in the run provenance parameters.random_seed
data_file Path to the CSV of recorded (joint configuration, measured marker pose) samples data.source_file
sample_configs_file Optional: path cross-referencing which planned/optimal configuration each data_file row corresponds to. Traceability only — not required for the fit itself data.sample_configurations_file
nb_sample Number of samples expected from data_file data.number_of_samples

Why the camera pose is a free parameter, not a small offset

Everything else in full_params/joint_offset calibration treats the URDF as approximately right — each joint gets a small correction around its known nominal placement. An add-on eye-in-hand/eye-to-hand camera is different: its housing-to-robot mounting pose usually isn't known precisely from CAD/assembly at all, so it can't be treated as a small perturbation. base_to_ref_frame/ref_frame handle this by inserting the camera as a genuine 6-DOF unknown in the middle of the chain (base_pose is a real initial guess, not a near-zero one) rather than folding it into the same small-offset parameters as every other joint.

That's also what makes eye-hand calibration a specialized, harder case: this unknown camera-pose block is estimated simultaneously, from the same measurements, as the per-joint offsets of every joint the camera observes through — "camera is off by X" and "joint N is off by Y" can produce very similar marker-pose residuals, which can leave the problem under-determined or poorly conditioned. Priors (estimation.method: map) and deliberately exciting poses that vary joint loading/configuration widely (sample_configs_file, D-optimal design a la tiago_pro/generate_optimal_configs.py) are the two practical levers against this. A plain single-anchor unknown base frame — base_frame set to universe/base_footprint with no base_to_ref_frame, as in TiagoPro's tiago_pro_calibration_config.yaml (known_baseframe=False in run_calibration.py) — doesn't have this coupling, because nothing downstream of that single anchor is itself another unknown sensor mount; it's one 6-DOF unknown at the root, not one inserted mid-chain and re-estimated jointly with everything past it.

Several points on the tool

Each entry of measurements.markers is one measured point (or pose) on the same tool_frame, for example the points of one mocap rigid body. The CSV has columns x1, y1, z1, x2, ... per marker, and each marker k gets its own offset pEEx_k, pEEy_k, pEEz_k (and phiEE*_k when orientation is measured); the base frame and the joint parameters are shared. Residual rows are ordered marker, then component, then sample.

What several points do and do not give (figaroh-plus#119):

  • The same identifiable joint parameters as one point. Free point offsets absorb any rotation of the tool frame itself, so a joint offset about the tool axis stays unidentifiable. On a TIAGo arm, four points keep exactly the joint parameters one point keeps.
  • Smaller standard errors, about 1/sqrt(n_points) when the points' noise is independent. Points of one rigid body are not fully independent, so expect less.
  • Not necessarily better prediction. On the TIAGo mocap reference, a four-point fit did not predict held-out postures better than marker 1 alone (full_params: 3.39 against 2.80 mm on marker 1); the extra points' rows bring their own errors (reflections, rigid-body tracking, unmodelled wrist effects) into every parameter.
  • One bad point affects the whole sample. Outlier exclusion (outlier_eps) uses each sample's worst point, so a misreflected point removes that sample. A missing (occluded) point, i.e. an empty cell, is refused by the loader with its CSV rows; exclude them with del_list.

Decide per robot and dataset: compare held-out errors per point (the validation report lists them) with a one-point fit before adopting more points.

Eye-hand / camera calibration now has a unified-format equivalent

base_to_ref_frame/ref_frame map to tasks.calibration.eye_hand.{camera_frame,reference_frame} (with eye_hand.enabled: true) — the unified schema template (templates/base_robot_config.yaml) already reserved this section; unified_to_legacy_config just didn't read it. Fixed, so eye-hand configs like examples/tiago/config/tiago_config_hey5.yaml are no longer stuck in the legacy format — see Migrating from legacy to unified format below. (free_flyer/kinematics.free_flying_base had a similar wrong-key bug — the converter read parameters.free_flyer, a key the template never defines — fixed the same way.)

identification: section

robot_params

Field Meaning Unified path
q_lim_def, dq_lim_def, ddq_lim_def, tau_lim_def Joint position/velocity/acceleration/torque limit margins joints.joint_limits.{position,velocity,acceleration,torque} — parsed but not currently consumed anywhere in the identification pipeline (kept for schema/future use)
fv Viscous friction coefficient per joint (N·m·s/rad) mechanics.friction_coefficients.viscous — used only if has_friction
fs Coulomb/static friction coefficient per joint (N·m) mechanics.friction_coefficients.static — used only if has_friction
Ia Reflected actuator (motor + gearbox) inertia per joint (kg·m²) mechanics.actuator_inertias — used only if has_actuator_inertia
offset Constant joint torque offset per joint (N·m) — electrical/sensor bias term mechanics.joint_offsets — used only if has_joint_offset
Iam6, fvm6, fsm6 Same three quantities as Ia/fv/fs, but for the shared "6th motor" of a differential-coupled wrist (two motors jointly drive the last two wrist axes, e.g. Staubli TX40) coupling.{Iam6,fvm6,fsm6} — used only if has_coupled_wrist
reduction_ratio Per-joint gear reduction ratio (motor turns per joint turn); sign encodes actuation direction mechanics.reduction_ratios
ratio_essential Threshold (%) for the "essential parameters" selection technique (Pham et al., 1995) mechanics.ratio_essential — documented intent only; not currently wired into any solver in this codebase

problem_params

Field Meaning Unified path
is_external_wrench Include a measured force/torque sensor wrench as a regressor input problem.include_external_forces
is_joint_torques Regress against joint torque signals (standard inverse-dynamics identification; almost always True) problem.use_joint_torques
force_torque Which F/T channels to use (e.g. ['Fx','Fy','Fz'] or ['All']) — only applied if is_external_wrench is True problem.force_torque_sensors
external_wrench_offsets Also identify a constant bias offset on the F/T sensor reading problem.external_wrench_offsets
has_friction Include the fv/fs columns in the regressor problem.model_components.friction
has_actuator_inertia Include the Ia column in the regressor problem.model_components.actuator_inertia
has_joint_offset Include the offset column in the regressor problem.model_components.joint_offset
is_static_regressor Include the friction + offset ("static") regressor block (no unified equivalent found — always derived)
is_inertia_regressor Include the rigid-body inertial-parameter regressor block (no unified equivalent found — always derived)
has_coupled_wrist Last two wrist joints share differential actuation → adds the Iam6/fvm6/fsm6 terms and a coupling transform to the regressor coupling.has_coupled_wrist
embedded_forces Express the external wrench in a body-embedded (tool) frame rather than a fixed/world frame (no unified equivalent found)
qr_relative_tolerance (optional) QR rank threshold as a fraction of the largest pivot. Columns whose pivot falls below it are treated as unidentifiable instead of fitting noise. Unset: only the absolute 1e-6 threshold applies. 1e-4 is a reasonable start when the log warns about an ill-conditioned base regressor problem.qr_relative_tolerance
active_joints (optional) Restrict identification to this explicit subset of joint names, instead of every active joint in the chain joints.active_joints
torque_fit_joints (optional) Active joints whose measured effort enters the fit and the fit/validation statistics. The other active joints keep their kinematics in the regressor (their motion still loads the fitted joints), but their effort is neither fitted nor scored; validation lists them under not_fitted_joints. Use it for joints whose effort signal is not trusted (unknown force constant, heavy quantisation). Unset: every active joint problem.torque_fit_joints

processing_params

Field Meaning Unified path
cut_off_frequency_butterworth Low-pass Butterworth filter cutoff frequency (Hz) applied to position/velocity/acceleration/torque signals before regression signal_processing.cutoff_frequency
ts Sample period (seconds) of the recorded data signal_processing.sampling_frequency (unified format specifies the rate directly, in Hz, rather than the period)
filter_config.filter_params Arguments of the median + Butterworth filter (f_sample, f_butter, nbutter, med_fil). In the unified format, f_sample, f_butter and nbutter default to sampling_frequency, cutoff_frequency and filter_order (4); an explicit signal_processing.filter_params entry overrides them signal_processing.filter_params

ts → nb_samples is a rate, not a count

Despite the name, the legacy parser computes identif_config["nb_samples"] = int(1 / ts) — i.e. an implied samples-per-second rate, not the number of rows in your data file. Don't be misled by the field name; it isn't used as a row count anywhere downstream.

tls_params (optional — known-payload identification)

Field Meaning
mass_load Known mass (kg) of a test payload attached during a supplementary run, used to refine the identified inertial parameters via total-least-squares
which_body_loaded Index of the link/body in the regressor that carries that payload
sync_joint_motion Parsed by nothing — not even read into identif_config by the legacy parser. Effectively decorative today.

trajectory_params (optional — used by optimal_trajectory.py, not identification.py)

Field Meaning
n_wps Number of waypoints in the generated exciting trajectory
freq Trajectory sample frequency (Hz)
t_s Time window between waypoints (s)
soft_lim Joint-limit safety margin/discount applied during trajectory search
max_attempts Maximum attempts to find a feasible trajectory before giving up
max_iterations IPOPT iteration cap per trajectory segment (default 200; unified config: problem.max_iterations)
segment_attempts Solves per trajectory segment: a failed segment is retried from a new random initial guess (default 1 = no retry; unified config: problem.segment_attempts)
collision_margin Minimum clearance (m) between collision pairs (default 0.01). Pairs: the geometry model's, or, when it has none, every two geometries on non-adjacent bodies (the world and the first moving body count as adjacent); srdf removes pairs (#143). Initial guesses and every solved segment must keep this clearance along the whole spline, checked at collision_check_frequency (default 200 Hz)
collision_checks_per_interval Check points per waypoint interval in the collision constraint, ending at the waypoint (default 1 = waypoints only)
collision_screen Optional (m): exact distances only for pairs within it, the others count as the screen; faster with many mesh pairs (UR10 example: 0.02). Default none = all distances exact

Migrating from legacy to unified format

The legacy flat format was removed in 1.0 (it warned since 0.4.6). Loading a legacy config, whether via BaseCalibration/BaseIdentification.load_param or figaroh.utils.config_parser.get_param_from_yaml, raises a ConfigurationError that names the command below. The migration tool itself still reads legacy files.

figaroh.utils.config_migration converts a legacy config to unified format automatically, using the exact field mapping in the tables above:

python -m figaroh.utils.config_migration \
    --input examples/tiago/config/tiago_config_hey5.yaml \
    --output examples/tiago/config/tiago_config_hey5_unified.yaml \
    --urdf urdf/tiago_48_hey5.urdf   # optional: runs a round-trip self-check
  • --template {base,manipulator,humanoid} (default base) picks which template the output extends: — base (extending base_robot_config.yaml directly) is the safest default since it doesn't risk silently inheriting a specialized template's default the legacy file didn't actually have.
  • Passing --urdf runs the output back through the real unified_to_legacy_config/unified_to_legacy_identif_config and diffs it against the original legacy values — the same self-check mechanism that caught the free_flyer/eye_hand bugs above. A migration that reports MISMATCHES should not be trusted without investigating why.
  • Fields with no unified-format consumer today (is_static_regressor, is_inertia_regressor, sync_joint_motion, the unused joint-limit fields — see the tables above) are preserved under the output's custom: section rather than silently dropped, even though nothing reads them back yet.
  • The tool only converts the file; it doesn't rewrite the example script that loads it, or verify the migrated config still produces the same calibration/identification results on real data — treat that as a required follow-up before switching an example over, the same way the calc_updated_fkm merge was validated against real TIAGo/TIAGo Pro/TALOS/UR10 data before landing.

Next steps