Skip to main content

SDF Runtime Data Flow

This page complements the system architecture overview. The architecture page explains which subsystems exist and how responsibilities are separated; this page focuses on how configuration, commands, forces, state, reference frames, telemetry, and recorded simulation data move through the running application.

Core rule: the configured initial state may be expressed in ENU or MCI, but after one-time initialization the authoritative translational runtime state is propagated in MCI. MCMF, MSC, ENU, LVLH, and SBF representations are derived from that runtime state.

1. Configuration to Authoritative Runtime State

Spacecraft configuration describes how the initial position and velocity are expressed. It does not define the runtime propagation frame. Current SDF supports two consistent initialization modes: ENU/ENU and MCI/MCI. Mixed position and velocity frame combinations are rejected by the configuration reader.

JSON spacecraft configuration
        ↓
jsonConfigReader
        ↓
customSpacecraft + MissionContext
        ↓
Mission-frame initialization
        ↓
Configured initial-state resolution
        ↓
Authoritative StateVector
(MCI position + MCI velocity)

Landing-site-relative ENU

Landing Site (MSC)
        ↓
MCMF landing-site state
        ↓
Landing-site ENU frame
        ↓
Configured ENU state
        ↓
ENU → MCMF → MCI
        ↓
StateVector

ENU is an input and mission/navigation representation. It is resolved once during initialization.

Direct MCI

Configured MCI state
        ↓
Direct assignment
        ↓
StateVector

Direct MCI initialization remains available for orbital, low-level, analytical, and verification scenarios.

2. Control Input to Actuation

Frontend input and automated control produce commands, not forces. The propulsion subsystem owns conversion from those commands into main-engine and RCS actuator states. Main-engine automation, translational RCS control, and rotational RCS control are resolved as separate command channels.

FrontendInterface LayerBackend
Frontend
Manual RCS axes ─→ inputmapper ─────┐
                                      │
Kill Rotation / Stabilize buttons ────┤
Main-engine / autopilot controls ─────┘
                                      ↓
                               FlightCommandDTO
                                      ↓
                                 cockpitPage
                                      ↓
                              SimulationWorker
Interface Layer
TelemetryMapper
      ↓
ControlCommand
  ├─ mainEngine
  ├─ translation
  ├─ rotation
  ├─ autopilotActive
  ├─ killRotation
  └─ stabilize
Backend
User ControlCommand
        ↓
InputArbiter
  ├─ main-engine authority
  ├─ translation remains manual
  └─ rotation authority
        ↑
        │
simcontrol::runAutopilot(dt)
  ├─ AdaptiveDescentController
  │      ↓
  │   auto main-engine command
  │
  └─ AttitudeController
         ├─ Kill Rotation
         └─ Stabilize
              ↓
        auto rotation command
              ↓
InputArbiter::chooseCommand()
        ↓
simcontrol::processCommands()
        ↓
Main engine + RCS target commands
        ↓
Thrust / RCSControlAllocator

The visual grouping marks the application boundaries explicitly: UI input and worker scheduling remain in the frontend/application layer, TelemetryMapper and the DTO/domain-command translation form the interface boundary, and arbitration, automatic control, simulation orchestration, and propulsion are backend responsibilities.

Rotational-control authority

Manual rotational input is used while neither automatic attitude mode is active. WhenkillRotation or stabilize is active, InputArbiter replaces only the rotational channel with the command generated by AttitudeController. Translational RCS input remains manual, and main-engine automation remains independently controlled by the autopilot flag.

Neither attitude mode active:
user rotation ─────────────────────────────→ active rotation

Kill Rotation active:
SBF angular velocity
        ↓
AttitudeController::killRotation()
        ↓
autoCmd.rotation ──────────────────────────→ active rotation

Stabilize active:
IB attitude + SBF angular velocity
        ↓
AttitudeController::stabilize()
  ├─ capture target attitude on activation
  ├─ quaternion attitude-error feedback
  ├─ angular-rate damping
  └─ hysteresis state
        ↓
autoCmd.rotation ──────────────────────────→ active rotation

Backend step order

The automatic-control command is evaluated from the current spacecraft state before actuation targets are applied and before the physical state advances. The resulting telemetry snapshot is generated only after the completed spacecraft update.

Frontend command transfer
        ↓
simcontrol::runSimulation(dt)
        ↓
runAutopilot(currentState, dt)
  ├─ descent-control calculation
  └─ attitude-control calculation
        ↓
processCommands()
  └─ InputArbiter::chooseCommand()
        ↓
set target main-engine / RCS commands
        ↓
spacecraft::updateStep(dt)
        ↓
getFullSimulationData()
        ↓
append active attitude-mode flags
        ↓
TelemetryMapper → TelemetryDTO
        ↓
append telemetry history
        ↓
emit stateUpdated(...)

3. Propulsion Force Generation to Physics

Main-engine and RCS models generate forces and torques in the spacecraft body frame. The Thrust orchestrator aggregates those outputs before the translational force vector is transformed into MCI.

Main Engine + RCS
        ↓
Thrust Orchestrator
(SBF forces + torques)
        ↓
Current spacecraft attitude
        ↓
SBF → MCI force transform
        ↓
physics::computeAcc()
        ↓
BasicMoonGravityModel
        ↓
Gravity + thrust / mass
        ↓
Total MCI acceleration
The SBF thrust vector is transformed using the current spacecraft attitude, not a static initialization orientation. Controller output remains an actuation request; propulsion owns command-to-force conversion and physics owns state-derivative evaluation.

4. Physics Calculation to State Propagation

spacecraft::updateMovementData() coordinates dynamics and integration. The physics and integrator layers compute updated quantities, while spacecraft commits them to the authoritative state.

Authoritative StateVector
        ↓
spacecraft::updateMovementData()
        ↓
Current-attitude SBF thrust → MCI
        ↓
Translational acceleration
        ↓
EulerIntegrator
        ↓
MCI velocity + position

SBF torque
        ↓
Rotational physics
        ↓
Angular acceleration
        ↓
EulerIntegrator
        ↓
SBF angular velocity + IB attitude
        ↓
StateVector commit
        ↓
spacecraft::updateFrames(time)

Derived frame representations are reconstructed only after the current step has been committed.SimulationFrameContext therefore represents one coherent snapshot of the authoritative state.

5. Mission Context and Derived Runtime Frames

SDF separates stable mission references from state-dependent frame representations.MissionContext contains mission-level references; SimulationFrameContextcontains frame representations derived from the current spacecraft state.

MissionContext

  • Canonical landing site in MSC
  • Derived landing-site state in MCMF
  • Derived landing-site state in MCI
  • Landing-site ENU frame

These are persistent mission references, not propagated spacecraft state.

SimulationFrameContext

  • MCI spacecraft state
  • MCMF spacecraft state
  • MSC latitude / longitude / altitude
  • ENU spacecraft state and ENU frame
  • LVLH spacecraft state and LVLH frame
  • SBF frame derived from current attitude and origin
Authoritative StateVector
        ↓
spacecraft::updateFrames(time)
        ↓
MCI_State
        ↓
MCMF_State
   ├──→ MSC_State
   └──→ ENU_State

MCI_State
   └──→ LVLH_State

StateVector attitude + origin
   └──→ SBF_Frame

6. Backend State to Frontend Telemetry

Backend domain state remains inside the simulation engine. After each completed step, one coherent backend snapshot is mapped into a frontend-facing TelemetryDTO.

FrontendInterface LayerBackend
Backend
spacecraft::time ───────────┐
StateVector ─────────────────┤
SimulationFrameContext ──────┼──→ simData
MissionContext ──────────────┤
propulsion / tanks / sensors ┤
InputArbiter mode flags ─────┘
Interface Layer
TelemetryMapper
      ↓
TelemetryDTO
Frontend / Application
SimulationWorker
   ├──→ telemetry history
   └──→ stateUpdated(...)
             ↓
       Qt thread boundary
             ↓
       cockpit / visualization

The same layer colors are intentionally reused in the reverse direction. Backend state is aggregated intosimData, translated at the interface boundary into TelemetryDTO, and then consumed by the worker/application layer for history recording and UI delivery.

Attitude-control mode telemetry

The active rotational automation mode is read from InputArbiter after the spacecraft step and added to the same simData snapshot. The interface layer maps these values into the dedicatedTelemetryDTO::Automation group.

InputArbiter
  ├─ isKillRotationActive()
  └─ isStabilizeActive()
        ↓
simData
  ├─ killRotationActive
  └─ stabilizeActive
        ↓
TelemetryMapper
        ↓
TelemetryDTO::Automation
  ├─ killRotationActive
  └─ stabilizeActive
        ↓
Cockpit history / XML export

Authoritative simulation time

spacecraft::time
        ↓
simData::time
        ↓
TelemetryMapper
        ↓
TelemetryDTO::time
        ↓
Cockpit / Export

The worker does not maintain a second simulation clock. The backend time used for time-dependent frame derivation is the same time exposed to telemetry consumers and scientific export.

7. Telemetry Recording and XML Export

Scientific export reuses the same TelemetryDTO snapshots consumed by the frontend. Recording is owned by SimulationWorker; XML serialization is delegated toTelemetryXmlExporter.

simData
   ↓
TelemetryMapper
   ↓
TelemetryDTO
   ↓
SimulationWorker
   ├──→ stateUpdated → Cockpit / Visualization
   └──→ telemetryHistory_
                  ↓ export request
          TelemetryXmlExporter
                  ↓
            XML telemetry file

The XML snapshot preserves the automatic attitude-control state explicitly:

<automation>
  <killRotationActive>true|false</killRotationActive>
  <stabilizeActive>true|false</stabilizeActive>
</automation>

This allows controller activation, settling behavior, and RCS response to be correlated precisely during telemetry-based verification without inferring the control mode indirectly from thruster activity.

  • One snapshot is recorded after each completed backend simulation step.
  • Pause adds no snapshots because no backend steps are executed.
  • Stop terminates the active session but does not silently overwrite recorded history.
  • Starting a new run with existing history requires explicit overwrite confirmation before clearing it.
  • TelemetryXmlExporter serializes existing history; it does not generate simulation state.
Cockpit visualization and XML export therefore share one telemetry contract and one coherent per-step snapshot.

8. Simulation Lifecycle

The runtime lifecycle distinguishes initial start, pause/resume, and stop/reset. Resume continues the existing backend state; it must not reinitialize the spacecraft.

Configuration available
        ↓
Start requested
        ↓
initialized?
   ├── no ─→ existing history?
   │             ├── yes → overwrite confirmation → clear history
   │             └── no
   │                    ↓
   │              backend initialize
   │                    ↓
   └── yes ─────────→ start QTimer
                         ↓
                   simulation steps

Pause → stop QTimer only
        ↓
 preserve backend state + time + fuel + attitude
 + active controller state
        ↓
Resume → start QTimer, no reinitialization

Stop → stop QTimer
       → reset UI telemetry
       → backend reset
       → initialized = false
  • Initial start: creates and initializes the backend simulation session.
  • Pause: freezes the step timer while preserving the complete backend state.
  • Resume: continues the existing initialized session.
  • Stop: terminates/resets the active simulation session.
  • Restart after stop: creates a new session from configuration after any required history confirmation.

9. State Ownership Summary

Authoritative runtime state

StateVector is owned by spacecraft and is the source of truth for propagated position, velocity, attitude, and angular velocity.

Simulation time

spacecraft::time is the authoritative backend simulation clock and is propagated through simData into TelemetryDTO.

Mission references

MissionContext holds stable mission-specific navigation references such as the landing site and its derived reference frames.

Derived frame state

SimulationFrameContext is reconstructed from the authoritative state after each commit and is not independently integrated.

Control authority

InputArbiter owns the current manual/automatic authority flags for main-engine, Kill Rotation, and Stabilize command selection.

Attitude-control state

AttitudeController owns the captured Stabilize target quaternion and its internal hysteresis/correction state. It does not own or directly modify spacecraft physical state.

Telemetry snapshot

simData aggregates one backend step into the frontend/export-facing TelemetryDTO contract.

Recorded telemetry

SimulationWorker owns the telemetry history. TelemetryXmlExporterserializes that history without owning simulation state.