Documents

Physics

Attitude, control, magnetics

Rigid-body attitude dynamics with MRPs, PD attitude laws, and magnetic actuation through the local geomagnetic field. The RL policy chooses the attitude target; the controller and magnetorquers track it.

Kinematics and dynamics

\[ \dot{\boldsymbol\sigma}=\tfrac14\bigl[(1-\sigma^2)\mathbf I_3+2[\boldsymbol\sigma\times]+2\boldsymbol\sigma\boldsymbol\sigma^T\bigr]\boldsymbol\omega,\qquad \dot{\boldsymbol\omega}=\mathbf I^{-1}\bigl(\boldsymbol\tau-\boldsymbol\omega\times\mathbf I\boldsymbol\omega\bigr) \]
  • MRP with the shadow-set switch at |σ| > 1 after every RK4 step. DCM: \(C=I+[8S^2-4(1-\sigma^2)S]/(1+\sigma^2)^2\) (Schaub & Junkins).
  • Total torque = aero + SRP + Earth radiation + gravity gradient + control. Torques are held over each 2 s substep.
  • Inertia: default diag(0.0125, 0.0125, 0.025) kg m². set_inertia accepts a full tensor; v10r6 and the SolarCat vehicles compute it from vehicle*.yaml.
  • mode: point (closed loop), detumble (B-dot), prescribed (the attitude is set to the target each substep with ω = 0; used for decay studies).

Command path

  1. The policy outputs a quaternion. The env normalises it (identity if invalid).
  2. slerp_clip limits the change from the held command to max_slew_rad (40–45°) per step.
  3. cmd_frame: inertial holds q_BN. flow, flowB and flowS hold the command in the flow frame and re-evaluate the target every substep with orbit-rate feed-forward ω = C_BN h/r².
  4. Optional set_nav(r, v): flow-frame targets come from an onboard two-body RK4 nav state instead of truth (SC_v3 no-GNSS studies).

Attitude laws

\[ \text{MRP: }\ \boldsymbol\tau=-K_p\,\boldsymbol\sigma_{BR}-K_d(\boldsymbol\omega-\boldsymbol\omega_r)+\boldsymbol\omega\times\mathbf I\boldsymbol\omega,\qquad \text{Quaternion: }\ \boldsymbol\tau=-K_p\,\mathbf q_{e,v}-K_d(\boldsymbol\omega-\boldsymbol\omega_r)+\boldsymbol\omega\times\mathbf I\boldsymbol\omega \]
  • Per-axis torque clip (max_torque). A body-rate limiter rescales the command if the predicted |ω| exceeds max_body_rate (0.125°/s default).
  • Gains: config/plant/gains_mrp.yaml (v8+), otherwise kp = 4e-4 and kd = 8e-3. attitude.law or --controller selects the law.
  • attitude.ideal_torque: true applies the PD torque as a pure body couple. That was the v2.1 plant the v8–v14 campaigns were tuned on (.physics_ideal.yaml). The default false routes it through the magnetorquers.

Magnetic actuation

\[ \boldsymbol\tau=\mathbf m\times\mathbf B,\qquad \text{3 coils: }\ \mathbf m=\mathrm{clip}\Bigl(\frac{\mathbf B\times\boldsymbol\tau_\mathrm{cmd}}{|\mathbf B|^2},\ \mathbf m_\mathrm{max}\Bigr) \]
  • Nothing can be produced along B, so tau_shortfall_frac = 1 − |τ|/|τ_cmd| reports the missing torque.
  • Torque rods (v10r6, SolarCat six-rod): torque-space least squares \(d=A^T(AA^T)^+\tau\) with \(a_k=u_k\times B\), then one uniform scale so that \(|d_k|\le d_{\max,k}\). Rods can be gated on or off by the policy.
  • mtq_duty (0, 1]: the coil on-fraction per substep. The rest is the magnetometer window.
  • B-dot detumble: \(\mathbf m=-k\,\dot{\mathbf B}\) (finite difference), used in brownout recovery.
  • Power (power.py): I²R-quadratic in the applied dipole (v8+), 249 mW peak for the 3-coil card.

Geomagnetic field

  • magnetics.model: wmm: spherical harmonics to degree 12 with secular variation, Schmidt semi-normalised (mag/field.cpp).
  • dipole: tilted dipole from the IGRF-13/WMM2020 g₁⁰, g₁¹, h₁¹ coefficients. The fast preset uses it.
  • The env refuses a silent dipole fallback when a WMM file was requested but failed to load.
WMM epoch The default data/WMM.COF is WMM-2020 (valid 2020–2025), but the simulation epoch is 2026-01-15. The model is being extrapolated past its validity window. data/WMM2025.COF is already in the repo; set ARLAMX_WMM=data/WMM2025.COF to use it.

Onboard pieces (flight-representative side)

  • propagator.py / propagator_f32.cpp: FP32 two-body + J2 + exponential drag + held along-track SRP. Used for the observation forecast blocks and the Duo arbiter.
  • nav.py: no-GNSS navigation (FP32 J2 + drag from the launch state, eclipse-timing fixes from the solar panels).
  • estimators.py: environmental-torque Kalman filter (τ, τ̇ states) from the rigid-body torque measurement.
  • sensors.py: gyro, accelerometer, magnetometer and GNSS noise/bias from datasheet YAMLs (sensors_solarcat.yaml, sensors_gaussian.yaml).
  • int8.py, quantize.py, inference_budget.py: integer-only actor for STM32U575-class hardware.

References

  1. Schaub, H. & Junkins, J. L. (2018). Analytical Mechanics of Space Systems, 4th ed., ch. 3.
  2. Wie, B., Weiss, H. & Arapostathis, A. (1989). Quaternion feedback regulator. JGCD 12(3).
  3. Stickler, A. C. & Alfriend, K. T. (1976). Elementary magnetic attitude control system. J. Spacecraft 13(5).
  4. Chulliat, A. et al. (2020, 2025). The US/UK World Magnetic Model.
  5. Markley, F. L. & Crassidis, J. L. (2014). Fundamentals of Spacecraft Attitude Determination and Control, ch. 3.