Skip to content

Calibration の実行

fibril_sim calibrate は recorded episode を同じ外部入力と初期条件で simulation に replay し、観測 residual を小さくする physical parameter を推定します。 candidate parameter ごとに通常の SimulationPlan を再構築するため、calibration 専用の simulation execution path は持ちません。

optimizer へ渡す一次表現は scalar objective ではなく、episode、signal、timestamp、component で識別された residual vector です。 Ceres は bound-constrained solve と covariance を担当します。 residual Jacobian は parameter bounds を越えない central/one-sided finite difference adapter で評価し、Ceres の Problem::Evaluate() から同じ Jacobian contract を取得します。

Calibration request の形式

calibration request schema は 3.1 です。 training と validation は episode の配列で、各 episode は複数の signal を独立した sample rate で持てます。

schema_version:
  major: 3
  minor: 1
manifest: simulation.yaml

parameters:
  - id: wheel_damping
    unit: N_m_s_per_rad
    provenance: bench-test-2026-08
    lower: 0.01
    upper: 4.0
    initial: 0.4
    nominal: 0.5
    parameterization: log_positive
    target:
      type: mujoco
      kind: joint_damping
      object: wheel_joint
      component_index: 0

  - id: encoder_bias
    lower: -0.1
    upper: 0.1
    initial: 0.0
    parameterization: normalized_linear
    target:
      type: component_config
      component: wheel_encoder
      config_path: bias

observations:
  - id: wheel_position
    source: joint_position
    name: wheel_joint
    sample_every_steps: 1
  - id: imu_motion
    source: device_output
    name: chassis_imu
    sample_type: fibril_sim/imu_sample/v1

training:
  - id: run-01
    episode_seed: 9
    weight: 1.0
    initial_state:
      - type: joint
        joint: wheel_joint
        qpos: [0.0]
        qvel: [1.2]
    recorded_inputs:
      - source_id: motor/command
        source_sequence: 1
        payload_type: fibril_sim/motor_command/v1
        payload_json: '{"mode":"duty","value":0.3}'
        commit_tick: 0
        acceptance_sequence: 0
    signals:
      wheel_position:
        alignment: linear
        residual_scale: 0.002
        scale_semantics: measurement_standard_deviation
        samples:
          - time_ns: 10000000
            values: [0.011]
      imu_motion:
        alignment: nearest
        residual_scales: [0.01, 0.01, 0.01, 0.05, 0.05, 0.05]
        scale_semantics: measurement_standard_deviation
        samples:
          - time_ns: 12000000
            values: [0.0, 0.0, 0.2, 0.0, 0.0, 9.81]

validation:
  - id: run-held-out
    signals:
      wheel_position:
        alignment: exact
        residual_scale: 0.002
        scale_semantics: measurement_standard_deviation
        samples:
          - time_ns: 10000000
            values: [0.012]
      imu_motion:
        alignment: nearest
        residual_scales: [0.01, 0.01, 0.01, 0.05, 0.05, 0.05]
        scale_semantics: measurement_standard_deviation
        samples:
          - time_ns: 12000000
            values: [0.0, 0.0, 0.19, 0.0, 0.0, 9.81]

optimizer:
  type: ceres
  max_iterations: 50

objective:
  standardized_gaussian_residuals: true

execution:
  max_parallelism: 4
  cache_entries: 256

analysis:
  profile_likelihood:
    enabled: true
    samples_per_parameter: 21
  information_matrix: true

fit:
  max_training_rms: 3.0
  max_validation_rms: 4.0
  max_local_condition_number: 1000000
  max_episode_rms_ratio: 3.0
  reject_parameter_near_bound: true

context:
  metric_id: standardized_least_squares
  input_provenance: recording-sha256
  parameter_set_id: drivetrain-v3
  seed: 9

Parameter metadata と optimization coordinate

physical parameter は unit、provenance、bounds、initial value、nominal value、parameterization を持ちます。 Ceres が探索する coordinate と simulation に渡す physical value は分離されています。

linear は physical value をそのまま optimizer coordinate にします。 normalized_linear は nominal value または initial value を原点とし、明示した coordinate_scale、nominal value、parameter range の順で scale を決めます。 log_positive は正の physical parameter を対数座標で探索します。

local Jacobian と SVD は optimizer parameterization に依存しない dimensionless coordinate delta_p / physical_scale へ変換して評価されます。 physical_scale は coordinate_scale、nominal value、parameter range の優先順で決まります。 covariance も同じ normalized coordinate へ変換して保持し、結果出力時に physical unit へ写像されます。

Candidate Plan の生成

calibration core の境界は CalibrationParameterValues -> SimulationPlan です。 parameter の適用方法は CandidatePlanBuilder adapter が担当します。

component_config target は Component profile を解決した後の effective config にある numeric scalar へ overlay します。 したがって instance YAML に展開されていない profile 由来の noise、bias、limit も calibration target にできます。 同じ parameter を複数 target へ bind できます。

mujoco target は MJCF の文字列や XML path を編集しません。 calibration adapter は physical parameter を typed MujocoParameterOverlay、virtual-device parameter を ComponentParameterOverlay に解決し、SimulationBuilder の construction input として渡します。 ComponentParameterOverlay は Component profile composition の後、ComponentFactory が effective config を検証する前に適用されます。 MujocoParameterOverlay は MJCF を parse した後、mj_compile より前に適用されます。

現在の typed MuJoCo target は body_mass、body_inertia、joint_damping、joint_frictionloss、joint_armature、geom_friction、geom_solref、geom_solimp に加え、actuator と native DC motor の parameter を扱います。 actuator target は actuator_gear、actuator_forcerange、actuator_position_kp、actuator_position_kv、actuator_adhesion_gain です。 native DC motor target は dcmotor_resistance、dcmotor_effective_motor_constant、dcmotor_inductance、dcmotor_controller_kp、dcmotor_controller_ki、dcmotor_controller_kd、dcmotor_controller_slewmax、dcmotor_controller_integral_limit、dcmotor_voltage_limit です。 dcmotor_effective_motor_constant は compiled MuJoCo model が保持する effective sqrt(Kt * Ke) を target にし、MJCF authoring 時の二要素 motorconst="Kt Ke" を別々に同定する target ではありません。 dcmotor_inductance、dcmotor_controller_ki、dcmotor_controller_slewmax は MuJoCo DC motor の optional activation state 数を変え得るため、Builder は parameter 適用時に actdim も同じ parameter set から再構成します。 body_mass と body_inertia は geom から慣性が推定される body でも有効になるよう、元の compiled inertial properties を explicit inertial へ materialize してから typed assignment を適用します。 SimulationBuilder は同じ MuJoCo field に複数 parameter を bind する overlay と、scalar target に 0 以外の component_index を指定する overlay を拒否します。 overlay は target identity で canonicalize されます。 MuJoCo overlay は parameter ID、target kind、object、component、value、Component overlay は parameter ID、Component ID、config path、value が parameter_set_hash に含まれます。 arbitrary mjSpec callback は Extension API として公開しません。 通常の model composition と nominal parameter authoring は MJCF が所有します。

programmatic API では CandidatePlanBuilder 自体を差し替えられるため、extension config や model variant も calibration core を変更せずに扱えます。

Recorded-input replay と初期条件

各 candidate は fresh SimulationInstance から始まります。 episode の initial_state を SimulationInstance::inject_state() で適用した後、recording の external input を enqueue_recorded_trace_inputs() へ渡します。

この replay は recorded commit_tick と recorded acceptance order を通常の ingress contract に通します。 calibration code が actuator state や controller input を直接書き換えることはありません。

initial_state は joint qpos/qvel、mocap pose、actuator activation を指定できます。 base Manifest が scenario keyframe と scenario initial external input を指定している場合、それらは通常の SimulationPlan::create_instance() lifecycle で先に復元されます。

episode ごとに horizon_steps を指定できます。 省略した場合は、その episode の最終 reference timestamp を含むまで physics timestep から rollout 長を計算します。 snapshot signal の linear alignment では、最終 reference timestamp を挟む次の observation boundary まで自動的に延長します。 event-driven な device_output / actuator_application に linear alignment を使う場合は、次イベントの時刻を一般には推定できないため horizon_steps を明示します。

Observation selector の指定

observation は raw array index だけでなく semantic name で指定できます。 joint_position、joint_velocity、sensor、body_position、body_quaternion は candidate Plan の compiled mjModel に対して名前解決されます。

qpos、qvel、sensordata は indices を指定する low-level selector として残っています。 actuator application は trace の endpoint ID で観測できます。 actuator_application が含まれる CLI request では candidate Plan の trace を自動的に有効化します。

device_output は stable sample_type に対応する typed decoder を通します。 device_output では indices で decoded vector の component を選択できます。 event-driven selector では sample_every_steps は 1 固定で、snapshot selector にだけ physics-step subsampling を指定できます。 selector の無効な name / sample_type / indices 組み合わせは黙って無視せず request error にします。 CLI は standard component の digital input、joint encoder、rangefinder、motor feedback、body kinematics、IMU を登録しています。 custom DeviceOutput は programmatic API の CalibrationDeviceOutputDecoderRegistry に decoder を登録します。

複数 signal の alignment

各 signal は独立した timestamp 列と alignment policy を持ちます。 policy は exact、linear、zero_order_hold、nearest です。

reference episode の sample 列が residual layout を決めます。 exact で candidate sample が欠けた場合は、その点を黙って捨てず evaluation を失敗させます。 この制約により candidate parameter によって residual dimension が変わることを防ぎます。

body_quaternion は MuJoCo の wxyz quaternion として扱います。 time alignment の linear は component-wise linear interpolation ではなく shortest-path SLERP を使い、residual は q と -q を同一姿勢として扱う 3 次元 rotation-vector error です。

Residual scaling と robust loss

一つの scalar residual は概念上、次の形です。

r = sqrt(episode_weight) * (simulated - recorded) / residual_scale

scale_semantics は measurement_standard_deviation、characteristic_scale、user_scale を区別します。 異なる unit の component を一つの vector signal に含める場合は residual_scales で residual component ごとの scale を指定できます。 quaternion signal の residual_scales は quaternion 4 成分ではなく rotation-vector residual 3 成分に対応します。

episode weight は engineering objective weight です。 physical fit の training_summary / validation_summary と episode 間 RMS 比は weight を外した residual で評価します。 standardized_gaussian_residuals: true を指定する場合、training と validation の全 signal が measurement_standard_deviation であり、かつ全 episode の weight が 1.0 でなければ request を拒否します。 これにより任意の engineering weight を Fisher information や likelihood-ratio interval と誤解しません。

Huber、Soft L1、Cauchy、Arctan、Tukey loss は Ceres の LossFunction 実装を利用します。 robustification は scalar measurement ごとに適用され、simulation rollout 自体は一度だけ評価されます。

Gaussian prior は physical parameter coordinate 上の追加 residual として表現されます。 prior residual は __prior__ episode として summary から分離できます。

結果の optimization_summary は robustification と prior を含む optimizer 実際の residual を集計します。 training_summary はそれらを適用する前の recorded-data residual を集計するため、physical fit の判定が prior によって良く見えることはありません。

複数 episode の objective

training episode は一つの global parameter set を共有します。 各 episode の residual vector を宣言順に stack し、Ceres へ一つの固定 residual vector として渡します。 一つの parameter evaluation では candidate SimulationPlan を一度だけ構築し、その immutable Plan から episode ごとに独立した SimulationInstance を作ります。

execution.max_parallelism が 2 以上の場合、独立した episode rollout を並列評価します。 flatten 順序は declaration order に固定されるため、parallelism を変更しても residual order は変わりません。

結果には aggregate、per-episode、per-signal の residual count、SSE、RMS が含まれます。

Local identifiability の評価

Ceres の Problem::Evaluate() から最終 residual Jacobian を取得します。 finite difference は optimizer bound の外側を評価しない共通 adapter に集約され、bound 上では feasible side の one-sided difference を使います。

optimizer objective に prior、robust loss、または engineering episode weight が含まれる場合、同じ bound-aware differentiation contract で unweighted raw training-data residual を fitted point でもう一度 linearize します。 local identifiability と information matrix はこの data-only Jacobian を使うため、prior による拘束をデータ自身の同定性として報告しません。

Eigen の SVD から singular values、numerical rank、condition number、right-singular-vector parameter directions を出力します。 これは fitted point 周辺の local practical identifiability diagnostic であり、structural identifiability の証明ではありません。

Ceres の Covariance は rank-deficient case を含めて local covariance を計算します。 correlation と physical-coordinate covariance も結果に含まれます。

likelihood_interpretation_valid が true の場合だけ、physical parameter standard deviation と local normal approximation による 95% interval を統計区間として出力します。 standardized Gaussian data であっても robust loss または prior を objective に追加した場合、このフラグは false になります。

Profile likelihood の評価

analysis.profile_likelihood を有効にすると、一つの parameter を固定して残りを Ceres で再最適化します。 profile curve は非線形な practical identifiability の確認に使えます。

standardized Gaussian likelihood と解釈できる objective の場合は chi-squared threshold を Boost.Math から取得します。 confidence bound の crossing は coarse grid の bracket から Boost.Math TOMS748 で絞り込み、その評価点ごとに残りの parameter を再最適化します。 profile には fitted optimum 自身も必ず評価点として含めます。 confidence threshold が parameter bound までに交差しない場合は、その bound を返したうえで confidence_*_bound_limited を true にします。

robust loss や prior を含む場合も profile curve 自体は計算できますが、likelihood-ratio confidence interval は出力しません。

Information matrix の評価

analysis.information_matrix: true は最終 Jacobian から J^T J を計算します。 standardized Gaussian likelihood と解釈できる場合だけ fisher_information_approximation と表示します。 それ以外は同じ数値を sensitivity_gram_matrix として出力します。

出力には coordinate_system も含まれます。 eigenvalues、numerical rank、full-rank の場合の log determinant を experiment-design utility から利用できます。 calibration package 自体は excitation trajectory を生成しません。

Fit の評価

optimizer の終了理由と physical fit の採否は別の結果です。 optimization_termination は converged、max_iterations、no_convergence を表します。

fit criteria を指定すると、training RMS、validation RMS、local condition number、episode 間 RMS ratio、bound proximity から plausible_fit または no_plausible_fit を判定します。 episode 間 RMS ratio が閾値を超えた場合は cross_episode_inconsistency を理由コードとして記録します。 criteria を指定しない場合は indeterminate です。

no_plausible_fit は「指定した parameter range とモデルで観測を十分説明できなかった」ことを表します。 contact model が悪い、sensor frame が逆、recorded input が欠けている、といった原因までは calibration result から推定しません。

Cache と provenance

execution.cache_entries は full residual evaluation を parameter set ごとに memoize します。 cache は一つの calibration run の中だけで使われ、training と validation は別 scope です。

result context には training/validation episode content hash、objective version、alignment contract、observation spec hash、optimizer ID、optimizer option hash、seed を保存します。 candidate Plan provenance には Manifest/model/compiled-model/asset/parameter-set hash と MuJoCo/build identity が含まれます。

結果には parameter の bounds、unit、provenance、parameterization を含む parameter_contract と、parameter ID から semantic target への対応およびその hash を保存します。 --json の top level parameter_overlay は fitted physical value と target contract だけを抜き出した portable overlay artifact です。 採用した fit を通常の simulation construction へ持ち込む場合は、この artifact を versioned YAML/JSON resource として保存し、SimulationManifest 3.1 の parameter_overlays から参照します。 この経路では nominal MJCF を fitted value で書き換えず、同じ typed overlay contract を calibration と通常実行で共有します。

Calibration を実行する

fibril_sim calibrate calibration.yaml

automation で結果を処理する場合は --json を使います。

fibril_sim calibrate calibration.yaml --json

full result と fitted parameter overlay を artifact として直接保存する場合は次を使います。

1
2
3
fibril_sim calibrate calibration.yaml \
  --output calibration-result.json \
  --output-overlay drivetrain-fit.json

--output-overlay は --json の top-level parameter_overlay と同じ versioned artifact を保存します。 採用した fit はこの file を SimulationManifest の parameter_overlays から参照して通常実行へ持ち込みます。

少数の仮説値を明示的に比較する場合は Parameter Experiments を使います。 fibril_sim calibrate は実測 episode に対する parameter identification に限定し、generic な Cartesian sweep を public CLI として提供しません。