Skip to content

Trace と replay のアーキテクチャ

semantic trace の目的は、run の最終結果を保存することではなく、divergence の最初の causal boundary を残すことです。 そのため ExternalInput、Device、actuator、physics state を一つの数値 vector に潰しません。

永続化形式

trace persistence には MCAP を使います。 frame と metadata は versioned schema を持ち、Plan provenance と Plan inspection document も trace sink に渡せます。

trace は simulation runtime の semantic record であり、ROS message recording の代替ではありません。 ROS message の raw record/replay が必要な場合は fibril_sim_ros の rosbag2 adapter を使います。

Capture policy の選択

trace を有効にしただけでは、毎 physics step の full numerical/contact dump は行いません。 通常実行の既定は causal capture で、ExternalInput、Device delivery envelope、actuator application、domain、semantic event を残し、Device payload、full numerical state、contact wrench は省略します。

詳細観測が必要な場合は用途に応じて capture policy を上げます。

  • causal: 通常の常時 trace。replay と causal divergence の追跡用。
  • numerical: causal + Device payload + post-physics numerical state。numerical state は decimation 可能。
  • contact: causal + contact topology / frame / wrench。
  • full: numerical + contact を毎 step 記録する最大 detail の trace。

CLI の fibril_sim run では --trace-detail causal|numerical|contact|full を使います。 numerical は既定で10 stepごとに numerical state を取り、--trace-state-every N で変更できます。 trace frame 自身が capture policy と、その frame に numerical state が存在するかを保持するため、replay と query は間引きされた trace を区別できます。

Device boundary の記録

Device trace は三つの boundary を区別します。

  1. raw source
  2. Device semantics 適用後の acquired value
  3. runtime 外へ配信可能になった delivered value

Fibril Simulation runtime は stage、Device ID、sequence、nominal time、actual time などの envelope を所有します。 payload schema は Device が versioned namespaced format として所有します。

standard Device は三 boundary の payload trace を提供します。 plugin-defined Device が payload codec を提供しない場合でも timing metadata は残せます。

Controller output の記録

controller は SimulationInstance の外側にあり、その output は ExternalInput として runtime に入ります。 したがって production software output の causal record は、source ID、source sequence、acceptance sequence、commit tick、payload を持つ committed ExternalInput です。 SIL 専用の controller execution record や controller command record は持ちません。

Actuator boundary の記録

command latency、timeout、hardware-specific conversion は component-owned ActuatorDriver の内部状態です。 kernel trace は ActuatorApplication の execution boundary、timeout safe-state selection、MuJoCo に適用した value、resolved MuJoCo actuator identity、completed post-physics boundary の actuator force を記録します。

controller output と downstream virtual hardware の差は、committed ExternalInput と ActuatorApplication を比較して特定します。 applied command と mechanism response の差は actuator force、joint-space qfrc_actuator / qfrc_constraint、qvel を同じ boundary で比較して特定します。

ExternalInput の replay

ingress acceptance には run-unique acceptance_sequence を割り当てます。 commit phase は accepted set を cut し、effective time、source ID、source sequence、acceptance sequence による canonical ordering で処理します。

recorded replay は payload だけでなく acceptance ordering identity と commit tick を復元します。 producer arrival timing を適当に再現する方式では、deferred input と same-time input の visibility が変わるためです。

D1 と D2

diagnostic comparison は D1 semantic/causal comparison と D2 numerical comparison を分けます。

D1 は ID、ordering、payload structure、boolean や enum の semantic value などを比較します。 D2 は numerical leaf を configured tolerance で比較します。

たとえば mode button の false と true は D1 divergence です。 floating-point range の微小差は D2 tolerance で評価します。

Post-physics numerical state の記録

full numerical trace は qpos、qvel、sensordata、body world position / quaternion、qfrc_actuator、qfrc_constraint を completed post-physics boundary で保持します。 contact も geom/flex endpoint identity と element identity、dimension、exclude、efc_address、solver constraint participation を semantic topology として記録し、distance、position、full contact frame、adhesion、contact-frame 6D wrench は numerical evidence として比較します。

contact record の存在と solver-active contact は区別します。 constraint_active は completed boundary で efc_address >= 0 の contact を表し、その contact では mj_contactForce() から得た contact-frame wrench を保持します。 contact wrench は world-frame force ではないため、consumer が world axis へ解釈する場合は同じ record の full contact frame を使います。

永続 trace の query

fibril_sim_trace の source は decoded frame を一件ずつ visit できる streaming API を持ちます。 fibril_sim trace info/query はこの API 上に実装し、long trace を一度すべて std::vector<SimulationTraceFrame> へ展開しなくても時間窓を絞れます。

query の semantic name resolution は query 実行時の SimulationPlan に対して一度行い、recorded qpos / qvel / body arrays の raw index を user-facing contract にしません。

ROS host boundary の扱い

live ROS execution でも mutable SimulationInstance は SimulationHost worker thread が単独所有します。 trace enabled の場合、worker は step 完了後に drain_trace_frames() して immutable SimulationHostFrame へ移し、ROS frontend / node 側が persistent sink へ書きます。 trace persistence を理由に physics owner thread へ MCAP I/O や ROS callback access を持ち込みません。

診断結果

比較 report は equivalent、diverged、insufficient_evidence を区別します。 空 trace や必要 signal の欠落を「差が見つからなかったから equivalent」と扱うと、観測不足と同値性を混同するためです。