NODEDC_MISSION_CORE/docs/adr/0015-simulation-polygon-qua...

6.5 KiB
Raw Blame History

ADR 0015: Simulation Polygon as a qualification boundary

Status

Accepted for architecture; SIM S0 qualification returned GO on 2026-07-24. Navigation behavior, safety behavior and real actuator authority are not accepted.

Context

Mission Core has proven a K1 observation/archive/perception vertical, but the perception outputs do not yet have a closed-loop consumer. Adding Gazebo, PX4, ROS 2 and Nav2 directly to the web process or modeling every experiment as an observation session would blur product ownership, lifecycle, evidence and authority.

Replay, physics simulation, a digital twin, HIL and real shadow also have different causal meaning. A recorded stream cannot react to a hypothetical command, while a closed-loop world can. Calling both SimulationRun would make reports easy to misuse.

Decision

  1. Polygon is a first-class Mission Core bounded context for autonomy qualification and assurance.
  2. Mission Core owns scenarios, qualification-run lifecycle, authority policy, canonical contracts, provenance, evidence admission, evaluation and reports.
  3. Gazebo, PX4 SITL, ROS 2, Nav2, Rerun and datasets are replaceable providers.
  4. QualificationRun is the umbrella aggregate. Its kinds explicitly separate simulation_closed_loop, replay_shadow, digital_twin_closed_loop, controller_in_loop, hil and physical_shadow.
  5. Simulation Orchestrator is the sole process-lifecycle owner. Gazebo and PX4 do not run inside the Mission Core web process, and the browser has no direct PX4 channel.
  6. Gazebo /clock is authoritative in closed-loop simulation. ROS 2 uses simulated time and PX4 uXRCE-DDS time synchronization is disabled for this profile.
  7. Mission Core uses ENU/FLU. PX4 uses NED/FRD. Exactly one adapter boundary converts frames and requires golden tests.
  8. The first command boundary permits only rover speed+steering and speed+yaw-rate profiles with sequence, TTL, heartbeat, watchdog and stop-on-loss behavior. Direct actuator setpoints are rejected.
  9. Source-of-record, derived artifacts and presentation state remain separate. Reset creates a new immutable run/episode.
  10. Ground truth is evaluator-only and is not visible to perception or planning.
  11. SIM S0 targets the reviewed Windows 11 worker through a dedicated MissionCore-Sim WSL2 Ubuntu 24.04 distribution physically under D:\NDC_MISSIONCORE.
  12. SIM S0 does not depend on the existing Docker Desktop runtime. Its WSL backend is C-backed and currently serves unrelated co-tenants.
  13. S1 uses exact px4_msgs directly. The experimental px4-ros2-interface-lib is not a mandatory S1 dependency.
  14. A top-level Polygon UI is gated on accepted contracts and a proven S1 backend lifecycle with persisted run history.
  15. Real actuator authority requires a new decision and physical safety gate.
  16. S0 processes run inside an ephemeral loopback-only Linux network namespace. Micro XRCE-DDS Agent's UDP wildcard bind is acceptable only inside that boundary; no S0 listener may be reachable from the worker LAN or Windows host network.

Consequences

  • Perception can be measured by downstream decisions without granting it hidden behavior authority.
  • Standard planners and future Mission Core planners can be compared on the same scenario and metric profiles.
  • Replay cannot be presented as closed-loop safety evidence.
  • Provider upgrades require explicit compatibility and evidence refresh.
  • More up-front domain and artifact work is required before a visual demo.
  • The AI worker must satisfy D-only, resource and coexistence constraints before installation is accepted.
  • Simulation and HIL reduce risk but do not certify the real trike.

First implementation

The qualification doctor is deliberately read-only:

  • simulation/s0/qualification-profile.yaml is the accepted S0 stack, storage, clock, authority, port and process contract.
  • k1link.simulation.s0 strictly validates that contract and optional digest-bound worker evidence.
  • missioncore-sim s0 doctor inspects the current host without installing, starting or modifying anything.
  • MISSIONCOR-40 tracks factual worker qualification.

The first target bootstrap also includes simulation/s0/worker-smoke.sh. It creates the reviewed loopback-only namespace, starts only the pinned stock-rover providers, observes ROS 2 vehicle status and Gazebo clock, requests PX4 shutdown, checks for owned-process residue and writes D-only factual artifacts. It never arms the vehicle or sends an actuator command.

simulation/s0/gazebo_time_control.py owns the S0 pause/single-step/1×/2× RTF and resource acceptance probe. simulation/s0/build_evidence_manifest.py admits only exact-profile, D-confined, passing 1×/2× runs into the digest-bound evidence generation. These scripts are qualification tooling; the S1 Simulation Orchestrator remains the future product lifecycle owner.

The doctor reports INCOMPLETE until it is running on the reviewed target with resolved/accepted pins and all required evidence. On the accepted profile generation and nine-claim confined evidence set it returned GO; it cannot infer that result from repository state alone.

S1A implementation

k1link.simulation.contracts now defines the first product-owned QualificationRun, provider/authority/artifact provenance, canonical Ackermann and Differential rover setpoints, and qualification events. k1link.simulation.run_store persists them as an immutable manifest plus one-file-per-sequence append-only journals. Exclusive creation and file/directory fsync prevent partially acknowledged records; loading rejects gaps, identity drift, non-regular records and illegal lifecycle history.

The aggregate derives its current state by replay. Terminal runs cannot accept new events, commands or artifacts. A restart never silently resumes an active run: reconciliation terminates it as failed with orchestrator-recovery-interrupted. Reset requires a terminal parent and creates a new linked run/episode. Commands are admitted only for a running closed-loop virtual run with the current authority generation and bounded simulation-time TTL. Replay/shadow commands, direct actuator authority and ungated HIL/controller-in-loop admission fail closed.

This increment proves the local lifecycle/repository contract. It does not yet own provider processes, transmit a PX4 setpoint, execute heartbeat/watchdog failsafe behavior, or qualify navigation/safety behavior. The target orchestrator must place the caller-supplied repository root under the accepted D-only worker boundary.