Blueprints
Couple navigation to the physics stack
Navigation, chemistry, aero and control are entries in one ordered stage tuple executed after every marcher step. Composition is static, so there is no dyn dispatch and no scheduler.
Coupling::between_steps() builds a cons-tuple of PhysicsStage values that
becomes the loop body after every marcher step. The return type is
impl PhysicsStage<2, FloatType>.
From the corridor’s coupling stack, examples/avionics_examples/src/shared/world.rs:159-210:
Coupling::between_steps()
.then(
VibrationalLagStage::new(
utils::ft(T_VE_INITIAL),
utils::ft(FALLBACK_PRESSURE_ATM),
utils::ft(REDUCED_MASS_AMU),
utils::ft(THETA_VIB),
utils::ft(SHEATH_PEAK_AGE_S),
)
.with_pressure_field("pressure_atm"),
)
.then(
FiniteRateIonizationStage::new(utils::ft(FALLBACK_N_TOT))
.with_density_field("n_tot")
.with_sheath_renewal(utils::ft(SHEATH_PEAK_AGE_S)),
)
.then(FreestreamFeeds)
.then(RegimeClassify::new(utils::ft(L_CHAR), utils::trigger()))
.then(
BankSteeredLift::new(
utils::ft(RHO_REF),
utils::ft(CDA_OVER_M),
utils::ft(L_OVER_D),
)
.with_speed_field("equivalent_airspeed"),
)
.then(SuttonGravesLoads)
.then(TruthGnss { noise_draw })
.then(
TrajectoryNav::new(
core::array::from_fn(|i| utils::ft(Q_DIAG[i])),
utils::ft(GNSS_VAR),
utils::ft(OPTICAL_VAR),
)
.with_imu(imu),
)
.then(CommandedBank)
.then(WeatherTelemetry)
.then(CyberneticCorrect::new(SafetyEnvelope::new(
utils::ft(MAX_HEAT_FLUX),
utils::ft(MAX_G_LOAD),
utils::ft(MAX_BANK_RAD),
)))
.build()
Cadence
TrajectoryNav runs one ReentryNavEngine predict and one ESKF correct per
entry. Because it sits in the same tuple as the fluid and chemistry stages, the
filter advances at the marcher’s step cadence rather than in a separate loop.
Ordering
Stage order is load-bearing in two places.
TruthGnss publishes the fix that TrajectoryNav consumes on the same step.
Reversing the two would fold the previous step’s fix.
CyberneticCorrect runs last, so it clamps what the guidance stage wrote. It
carries the SafetyEnvelope limits on heat flux, g-load and bank angle.
State handoff
Stages communicate through CoupledField. initial_field() seeds the engine
that TrajectoryNav then threads through the march
(world.rs:215-242):
field.set_nav(ReentryNavEngine::new(...))
The ImuModel passed to .with_imu(imu) scales the accelerometer bias away
from the filter’s standard-day priors. The
weather example varies that departure
across six atmospheres and measures the effect on dead-reckoning drift.
Composition cost
PhysicsStage is implemented for () and for the (A, B) cons-tuple
(deep_causality_cfd/src/types/flow/coupling.rs:298-335). The stack is a
compile-time type, so stage dispatch is static and adding a stage costs no
indirection.
powered_descent_coupling (world.rs:271-286) is the same stack extended with
the burn stages.
Worked examples using this