ADCS Deep Dive — Laser-Comm Pointing Case Study
An end-to-end Attitude Determination & Control System design study for a large laser-comm platform that must hold a beam to ±0.01° with ≤5 arcsec jitter while slewing 30° in 30 s, from LEO to MEO. This walks the whole chain — requirements → disturbances → actuator sizing → sensors → estimator → control laws → allocation → budgets → FDIR — and then red-teams it.
Symbols used on this page are defined in the Nomenclature → attitude & rotations.
Design-study values (representative engineering assumptions), from
ADCS/ADCS_Laser_Pointing.md and its critique companion.
1 · Baseline & requirements
A 3000 kg (wet) / 1500 kg (dry) box bus with 12 m solar arrays; worst-case sizing inertia $I_{max}\approx5500$ kg·m². The requirements drive everything downstream:
| # | Requirement | Value |
|---|---|---|
| R1 | Pointing accuracy (laser) | ±0.01° (36 arcsec), 3σ |
| R2 | Jitter (stability) | ≤ 5 arcsec / 1 s |
| R3 | Pointing knowledge | ±0.005° (18 arcsec) |
| R4/R5 | Slew rate / agility | ≥ 2°/s; 30° + settle in ≤ 30 s |
| R6 | Settling time | ≤ 10 s |
| R7 | Orbit | LEO (400 km) → MEO (10,000 km) |
2 · Disturbance-torque budget
Worst case is LEO; each environmental torque is worked from first principles:
- Gravity gradient: $T_{gg}=\tfrac{3\mu}{2R^3}\lvert I_{zz}-I_{xx}\rvert\sin2\theta \approx 3.8\times10^{-3}$ N·m
- Aerodynamic drag: $T_{aero}=\tfrac12\rho V^2 C_d A(c_{pa}-c_g)\approx 1.9\times10^{-3}$ N·m
- Solar radiation pressure: $T_{srp}=\tfrac{\Phi}{c}A_s(1+q)(c_{ps}-c_g)\approx 5.8\times10^{-5}$ N·m
- Magnetic: $T_{mag}=D\times B\approx 3\times10^{-5}$ N·m
| Regime | RSS disturbance | Dominant term | Momentum per orbit |
|---|---|---|---|
| LEO (400 km) | ≈4.3×10⁻³ N·m | gravity gradient, then drag | ≈3–4 N·m·s |
| MEO (10,000 km) | ≈6×10⁻⁵ N·m | SRP (secular, sun-fixed) | ≈0.3 N·m·s |
The regime problem: drag and gravity gradient fall away with altitude while SRP does not. In LEO the magnetic field is strong enough to dump momentum for free; in MEO it is not, so desaturation must switch to thrusters — which is why the design carries both and arbitrates between them (§9).
3 · Actuator sizing — why CMGs
A bang-bang (accelerate-then-decelerate) 30° slew in 30 s sets the torque and momentum:
$$ \alpha=\frac{4\theta}{t^2}=2.3\times10^{-3}\ \text{rad/s}^2,\qquad T_{slew}=I_{max}\,\alpha\approx 12.8\ \text{N·m},\qquad H=I_{max}\,\omega\approx 190\ \text{N·m·s}. $$Reaction wheels cannot produce 12.8 N·m at sane mass/power, so the primary actuator is a 4-SGCMG pyramid (skew $\beta=54.7°$, rotor momentum $h=75$ N·m·s each, $\dot\delta_{max}=1$ rad/s). A single-gimbal CMG delivers $\mathbf T=\mathbf h\times\dot{\boldsymbol\delta}$ — torque amplification: a small gimbal rate on a large stored momentum yields large torque. Peak per CMG is $h\dot\delta=75$ N·m (≈6× margin), and cluster momentum $\approx4h\approx300$ N·m·s covers the 190 needed.
| Actuator | Qty | Sizing | Role |
|---|---|---|---|
| SGCMG | 4 (pyramid, β=54.7°) | h=75 N·m·s, δ̇=1 rad/s | primary: slew + fine point |
| Reaction wheel | 4 | ~0.2 N·m, 50 N·m·s | fine / backup / quiet hold |
| Magnetorquer | 3 (orthogonal triad) | ~500 A·m² | LEO dumping, detumble |
| Thruster | 12 (couples) | ~1 N, moment arm ~1.5 m | MEO dumping, Δv, safe mode |
3.1 Placement & minimum counts
- General rule: three axes need ≥3 independent actuators; one-fault tolerance needs ≥4. Hence 4 CMGs, 4 wheels, and thrusters in opposing pairs so each pair is a pure couple (no Δv coupling).
- CMG quad pyramid: four gimbal axes on a pyramid at skew 54.7° — chosen because it makes the momentum envelope nearly spherical (equal authority in all directions) and leaves a 1-D null space for singularity avoidance.
- Wheels — three common configurations:
- 3 orthogonal + 1 skew spare — simplest bookkeeping; the spare is only partially effective until you re-map, and its axis must not be coplanar with any two others.
- 4 in a pyramid (all tilted from one axis) — graceful degradation, biased toward one axis.
- 4 in a tetrahedron — maximally isotropic: any three still span 3-space, so a single failure costs momentum envelope but never controllability. Chosen here.
- Magnetorquers: orthogonal triad on the bus, mounted away from the magnetometer, and duty-cycled: torquers off → sample the field → then actuate (measure-then-actuate), or the torquer corrupts its own sensor.
4 · CMG singularities & steering laws
Stack the four per-CMG torque directions into the Jacobian $A(\boldsymbol\delta)\in\mathbb R^{3\times4}$, so cluster torque is $\mathbf T = A\,\dot{\boldsymbol\delta}$ and total momentum is $\mathbf h(\boldsymbol\delta)=\sum_i h\,\hat{\mathbf h}_i(\delta_i)$ with $A=\partial\mathbf h/\partial\boldsymbol\delta$. A singularity is any gimbal set where the four torque axes become coplanar,
$$ \operatorname{rank}A<3,\qquad m=\sqrt{\det\!\big(AA^\top\big)}\to 0 $$and the cluster loses torque authority along the direction normal to that plane. The dangerous ones are internal (elliptic) singularities, which null motion alone cannot always escape. Four steering laws:
| Law | Formula | Behaviour |
|---|---|---|
| (a) Pseudo-inverse | $\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}=A^\top(AA^\top)^{-1}\mathbf T_{cmd}$ | exact torque, but blows up as $m\to0$ |
| (b) Singularity-robust | $\dot{\boldsymbol\delta}=A^\top(AA^\top+\lambda I)^{-1}\mathbf T_{cmd}$ | bounded rates; injects torque error exactly when slewing hard |
| (c) Generalized SR | $(AA^\top+\lambda E)^{-1}$, $E$ with dithered off-diagonals | deterministic perturbation escapes internal singularities |
| (d) Null-motion (baseline) | $\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}+(I_4-A^{+}A)\mathbf d$ | reconfigures gimbals at zero torque — no pointing error |
The SR damping is scheduled on the singularity measure, and the null motion climbs its gradient:
$$ \lambda=\lambda_0\,e^{-\mu m^2}\ (\lambda_0=0.01,\ \mu=10),\qquad \mathbf d = k_n\,\nabla_{\boldsymbol\delta}\,m $$Because $A$ is $3\times4$, the null space is 1-D: there is always a gimbal motion that changes configuration without producing torque. the reference design therefore uses null-motion as the primary (it is free — no torque error, so pointing is untouched), GSR dithering only as a brief escape if trapped internally, and parks the gimbals near the isotropic (high-$m$) point during idle/comm periods so a slew never starts near a singularity.
The singularity story is much clearer interactively. Below are four gimbals on the 54.7° pyramid: each blue vector is one rotor's momentum, the white vector is the cluster total, and the bar is $m=\sqrt{\det(AA^\top)}$. Drive the gimbals until the torque axes go coplanar and watch the measure — and the cluster's authority on one axis — collapse. Then switch on the null-motion sweep: the gimbals move but the torque does not, which is how you escape a singularity for free:
5 · Attitude determination
| Sensor | Qty | Accuracy (1σ) | Role |
|---|---|---|---|
| Star tracker | 2 (cross-boresight) | 1–3″ cross, ~10″ roll | primary fine attitude |
| FOG IMU | 1 (3-axis) | bias 0.01°/hr, ARW 0.002°/√hr | rate + propagation |
| Sun sensors | 6 (4π) | ±1° | safe mode / acquisition |
| Magnetometer | 2 | ±0.5° (LEO) | magnetorquer control |
| GPS | 2 | ~10 m | orbit / time knowledge |
A single star tracker is excellent about its two cross-boresight axes and poor about roll (its own boresight) — roughly 5× worse. Two trackers at ~90° fix that: each one's good axes cover the other's weak axis, giving few-arcsecond 3-axis knowledge, and the pair keeps lock through Sun/Earth exclusion cones.
Sensor σ → knowledge: the useful conversion is that a vector sensor of accuracy $\sigma_v$ constrains the two axes perpendicular to the measured vector and says nothing about rotation about it. Averaging $N$ independent frames helps as $\sigma/\sqrt N$ only for the white (NEA) part — the low-frequency thermo-elastic bias does not average down, which is why alignment ends up dominating the budget (§7).
6 · Estimator — the MEKF
Attitude lives on a manifold, so the filter is multiplicative: it estimates a small attitude error and the gyro bias, then folds the correction back into the quaternion (full theory on the Attitude page).
$$ \hat{\mathbf x}=\begin{bmatrix}\delta\boldsymbol\theta\\ \Delta\mathbf b\end{bmatrix}\in\mathbb R^{6},\qquad \mathbf q = \delta\mathbf q(\delta\boldsymbol\theta)\otimes\hat{\mathbf q} $$The gyro model carries bias, ARW and rate noise; the trackers bound the drift:
$$ \tilde{\boldsymbol\omega}=\boldsymbol\omega+\mathbf b+\boldsymbol\eta_v,\qquad \dot{\mathbf b}=\boldsymbol\eta_u $$Each vector measurement (star direction, Sun vector, magnetic field) has the same sensitivity structure — a measured unit vector is only sensitive to rotations perpendicular to itself:
$$ \mathbf z = \hat{\mathbf b}_{meas}-\hat{\mathbf b}_{pred},\qquad H=\big[\;[\hat{\mathbf b}_{pred}\times]\quad \mathbf 0_{3\times3}\;\big] $$so multiple sensors stack into one taller update, and the reset step applies $\delta\boldsymbol\theta$ to the reference quaternion and zeroes it — keeping the linearization valid and the $3\times3$ attitude covariance meaningful.
Multi-sensor fusion (stacked update). Concatenating the available vector measurements gives one update whose weighting falls out of the noise covariance automatically:
$$ \mathbf z=\begin{bmatrix}\mathbf z_{st}\\ \mathbf z_{sun}\\ \mathbf z_{mag}\end{bmatrix},\quad H=\begin{bmatrix}H_{st}\\ H_{sun}\\ H_{mag}\end{bmatrix},\quad R=\operatorname{diag}\big(R_{st},R_{sun},R_{mag}\big) $$Because $R_{st}\!\sim\!(2^{\prime\prime})^2$ while $R_{sun}\!\sim\!(1°)^2$, the star trackers dominate the gain by ~6 orders of magnitude — the Sun sensor and magnetometer contribute essentially nothing while the trackers are healthy, and take over gracefully when they are not. Since $R$ is block-diagonal the update can be processed one scalar at a time in any order (§3 of the NASA practices), avoiding a matrix inverse.
Converged performance: ~3–6″ attitude knowledge, bias observable to ~0.001°/hr — meeting R3 with margin.
7 · Control laws — Lyapunov, PID and LQR
Everything here is built on the attitude-error kinematics and Euler's rigid-body dynamics. With $\mathbf q_e=\mathbf q_{cmd}^{-1}\otimes\mathbf q$ (error quaternion, vector part $\mathbf q_{ev}$, scalar $q_{e0}$) and $\boldsymbol\omega_e=\boldsymbol\omega-\boldsymbol\omega_{cmd}$:
$$ \dot{\mathbf q}_{ev}=\tfrac12\big(q_{e0}\boldsymbol\omega_e+\mathbf q_{ev}\times\boldsymbol\omega_e\big), \qquad \dot q_{e0}=-\tfrac12\mathbf q_{ev}^\top\boldsymbol\omega_e $$ $$ J\dot{\boldsymbol\omega}=-\,\boldsymbol\omega\times J\boldsymbol\omega+\mathbf T_{ctrl}+\mathbf T_{dist} $$7.1 Quaternion Lyapunov controller (nonlinear, globally stabilizing)
The nonlinearity that breaks naive linear tuning is the gyroscopic term $\boldsymbol\omega\times J\boldsymbol\omega$, which grows with the square of rate — exactly when you slew fast. The Lyapunov design handles it by construction. Take the candidate function (kinetic energy + an attitude "spring" potential):
$$ V=\underbrace{\tfrac12\boldsymbol\omega_e^\top J\boldsymbol\omega_e}_{\text{rotational KE}\;\ge0} +\underbrace{k_p\big[\mathbf q_{ev}^\top\mathbf q_{ev}+(1-q_{e0})^2\big]}_{\text{attitude potential}\;\ge0}, \qquad k_p>0 $$$V$ is positive-definite and vanishes only at $\boldsymbol\omega_e=0$, $\mathbf q_e=[\mathbf 0,1]$ — the target. Differentiating along the dynamics, using the identity $\tfrac{d}{dt}\!\left[\mathbf q_{ev}^\top\mathbf q_{ev}+(1-q_{e0})^2\right]=\mathbf q_{ev}^\top\boldsymbol\omega_e$, the cross terms cancel if we choose
$$ \boxed{\;\mathbf T_{ctrl}= \underbrace{\boldsymbol\omega\times J\boldsymbol\omega}_{\text{gyroscopic feed-forward}} \;-\;\underbrace{k_p\,\operatorname{sgn}(q_{e0})\,\mathbf q_{ev}}_{\text{attitude spring}} \;-\;\underbrace{k_d\,\boldsymbol\omega_e}_{\text{rate damping}}\;} $$which leaves a manifestly non-positive derivative:
$$ \dot V=-k_d\,\boldsymbol\omega_e^\top\boldsymbol\omega_e\;\le\;0 $$$\dot V=0$ only on the set $\boldsymbol\omega_e=0$; on that set the dynamics force $\mathbf q_{ev}\to0$, so by Barbashin–Krasovskii/LaSalle the equilibrium is asymptotically stable for arbitrarily large initial errors — a genuinely global result, unlike a gain-margin argument from a linearization.
Why each term earns its place:
- $\boldsymbol\omega\times J\boldsymbol\omega$ feed-forward — cancels the nonlinear coupling exactly, so the closed loop behaves linearly even during a 2°/s slew. Without it, cross-axis coupling appears as a disturbance that a fixed PD gain must absorb with margin (i.e. slower loops).
- $\operatorname{sgn}(q_{e0})$ — the crucial detail. $\mathbf q$ and $-\mathbf q$ are the same attitude (double cover of $SO(3)$), so a controller that ignores the sign can rotate the long way around: the unwinding phenomenon. The sign flip picks whichever representative has $q_{e0}\ge0$, guaranteeing the shortest-path eigenaxis rotation (≤180°). Cost: a discontinuity at $q_{e0}=0$, so flight code adds hysteresis there.
- $k_d\boldsymbol\omega_e$ — the only dissipation in the system; it is what makes $\dot V<0$.
Gain selection maps directly onto a second-order response per axis:
$$ k_p=2J\omega_n^2,\qquad k_d=2\zeta J\omega_n $$For $J=5500$ kg·m², $\omega_n=2\pi(1\,\text{Hz})\!\approx\!6.3$ rad/s is far too stiff for a flexible bus — the practical choice is $\omega_n\!\sim\!0.1$–$0.3$ rad/s with $\zeta\approx0.7$, keeping the loop below the 0.5–1 Hz array modes (§8). Drive the slew below the CMG torque limit and $k_p$ is capped by $T_{max}$, not by stability.
7.2 PID for the fine-pointing hold
Inside the linear region ($\lvert\boldsymbol\theta_e\rvert<1°$), $\mathbf q_{ev}\approx\tfrac12\boldsymbol\theta_e$ and a PID law is simpler and — critically — can carry an integrator:
$$ \mathbf T_{ctrl}=-K_p\boldsymbol\theta_e-K_d\boldsymbol\omega_e-K_i\!\int\!\boldsymbol\theta_e\,dt+\mathbf T_{ff} $$The integral term is what drives steady-state error to zero against the secular SRP / CG-offset torque — a pure Lyapunov or LQR law leaves a bias offset proportional to disturbance/gain. Requirements: anti-windup whenever the CMGs saturate, and the eigenaxis slew profile fed forward in $\mathbf T_{ff}$.
the reference design therefore gain-schedules: Lyapunov (with gyroscopic feed-forward) for the retarget slew, blending smoothly into PID for the comm hold once inside 1°.
7.3 LQR — optimal gains instead of tuned gains
Lyapunov gives stability but not optimality: any $k_p,k_d>0$ is stable, so how do you pick among them? LQR answers that by minimising a cost. Linearize about the hold ($\boldsymbol\omega$ small, so $\boldsymbol\omega\times J\boldsymbol\omega$ is second-order and drops out) and use $\mathbf x=[\boldsymbol\theta_e^\top,\ \boldsymbol\omega_e^\top]^\top$:
$$ \dot{\mathbf x}=A\mathbf x+B\mathbf u,\qquad A=\begin{bmatrix}\mathbf 0&I_3\\ \mathbf 0&\mathbf 0\end{bmatrix},\qquad B=\begin{bmatrix}\mathbf 0\\ J^{-1}\end{bmatrix},\qquad \mathbf u=\mathbf T_{ctrl} $$which is just three decoupled double integrators. Minimise the quadratic cost
$$ \mathcal J=\int_0^\infty\!\big(\mathbf x^\top Q\,\mathbf x+\mathbf u^\top R\,\mathbf u\big)\,dt, \qquad Q=Q^\top\succeq0,\ R=R^\top\succ0 $$The optimal control is linear feedback whose gain comes from the algebraic Riccati equation:
$$ A^\top P+PA-PBR^{-1}B^\top P+Q=0,\qquad \boxed{\;\mathbf u=-K\mathbf x,\quad K=R^{-1}B^\top P\;} $$For one axis with $J=1$, $Q=\operatorname{diag}(q,0)$, $R=r$, the Riccati solution is closed-form and shows exactly how the weights become a bandwidth and a damping ratio:
$$ K=\Big[\sqrt{q/r}\;,\;\sqrt{2\sqrt{q/r}}\Big] \;\Rightarrow\; \omega_n=(q/r)^{1/4},\qquad \zeta=\tfrac{1}{\sqrt2}\approx0.707 $$That $\zeta=0.707$ falling out for free is the classic LQR result — the optimal double-integrator regulator is exactly critically-damped-ish, which is why hand-tuned PD designs converge on the same answer. Design intent enters through the weights: $Q$ buys pointing accuracy, $R$ buys actuator economy. Weight $\boldsymbol\theta$ heavily for tight pointing, weight $\boldsymbol\omega$ to suppress overshoot, and weight $\mathbf u$ to respect the CMG torque/rate envelope and to avoid exciting flexible modes.
| Law | Guarantee | Handles big angles? | Zero steady-state? | Where used |
|---|---|---|---|---|
| Lyapunov | global asymptotic stability | yes (+ shortest path) | no (unless augmented) | retarget slew |
| PID | local, margin-based | no | yes (integrator) | comm hold |
| LQR | optimal for the cost; guaranteed margins | no (linearized) | no (add LQI/integral) | gain selection, MIMO coupling |
| B-dot | energy dissipation | n/a | n/a | detumble (no attitude needed) |
8 · Two-level control: torque command → actuator allocation
With CMGs, magnetorquers and thrusters all present, writing one monolithic controller per actuator is a combinatorial mess and couples the pointing design to the hardware manifest. The standard answer is a two-level (cascaded) architecture — and it is exactly the structure you proposed:
LQR / Lyapunov
attitude law
virtual torque
control allocation
$B\mathbf u=\mathbf T_{cmd}$
on-times
Level 1 is a 3-DOF problem in physics units: it produces the torque the body needs and knows nothing about hardware. Level 2 is a constrained algebra problem: find actuator commands that produce that torque while respecting limits and preferences. The interface is a plain 3-vector, so you can change the actuator suite without retuning the pointing loop — and you can prove stability of Level 1 assuming only that Level 2 achieves $B\mathbf u\approx\mathbf T_{cmd}$.
8.1 The allocation problem
Let $\mathbf u$ collect every actuator's command and $B$ (the effectiveness matrix) map commands to body torque. With $n$ actuators and 3 axes, $n>3$ makes the system over-actuated — infinitely many solutions, so we pick the best one:
$$ \min_{\mathbf u}\ \tfrac12\lVert W_u\mathbf u\rVert_2^2 \quad\text{s.t.}\quad B\mathbf u=\mathbf T_{cmd},\quad \mathbf u_{min}\le\mathbf u\le\mathbf u_{max} $$Ignoring the inequality, the weighted least-norm solution is the classic weighted pseudo-inverse:
$$ \mathbf u^\star = W^{-1}B^\top\big(BW^{-1}B^\top\big)^{-1}\mathbf T_{cmd}, \qquad W=W_u^\top W_u $$and the general solution adds any null-space term, which is free torque-wise:
$$ \mathbf u=\underbrace{B^{+}\mathbf T_{cmd}}_{\text{achieves the torque}} +\underbrace{(I-B^{+}B)\,\mathbf z}_{\text{null motion: zero torque}} $$That null term is the whole game in over-actuated systems: it is how you de-saturate a CMG, keep gimbals away from singularities, equalize wheel speeds, or shift effort off a failed unit without disturbing the attitude — the same $(I-A^{+}A)\mathbf d$ trick from §4, generalized to the full actuator set.
When saturation matters, the equality-constrained pseudo-inverse is wrong (it can command impossible values). Real options, in increasing fidelity:
| Method | Solves | Notes |
|---|---|---|
| Pseudo-inverse + clip | — | cheapest; clipping changes direction of the delivered torque |
| Redistributed pseudo-inverse | iterate: saturate, freeze, re-solve on the rest | a few passes, deterministic, flight-friendly |
| Weighted QP / active-set | $\min\lVert W_u\mathbf u\rVert^2$ s.t. box + equality | the "right" answer; needs a bounded-time QP solver |
| Linear program (l₁) | max attainable torque / min fuel | natural when the objective is propellant, gives vertex (on/off) solutions |
| Cascaded / prioritized | fill from cheapest actuator, spill to next | matches the physical hierarchy; what the reference platform actually does |
If the demand simply cannot be met, the QP is relaxed to trade direction fidelity against magnitude:
$$ \min_{\mathbf u}\ \lVert B\mathbf u-\mathbf T_{cmd}\rVert_2^2+\gamma\lVert W_u\mathbf u\rVert_2^2 $$Pointing cares far more about torque direction than magnitude — a scaled-down but correctly-aimed torque just slews slower, whereas a mis-aimed one excites the wrong axis.
8.2 What makes each actuator's row of $B$ special
The three actuator families are not interchangeable columns — each has its own structure:
- CMGs — nonlinear, state-dependent, rate-limited. The map is $\mathbf T=A(\boldsymbol\delta)\dot{\boldsymbol\delta}$, so "$B$" changes with gimbal angle and can lose rank (§4). Allocation here is the steering law: $\dot{\boldsymbol\delta}=A^{+}\mathbf T_{cmd}+(I-A^{+}A)\mathbf d$, subject to $\lvert\dot\delta_i\rvert\le\dot\delta_{max}$ and the momentum envelope $\lVert\mathbf h\rVert\le 4h$. CMGs get the lowest cost in $W_u$: they are fast, precise and free.
- Magnetorquers — fundamentally underactuated. Torque is $\mathbf T=\mathbf m\times\mathbf B$, so $B_{mtq}=-[\mathbf B\times]$, a matrix of rank 2: the component along $\mathbf B$ is unreachable at that instant, no matter the dipole. The achievable set is the plane $\perp\mathbf B$, so allocation must project: $$ \mathbf m_{cmd}=\frac{\mathbf B\times\mathbf T_{cmd}}{\lVert\mathbf B\rVert^2} \;\Rightarrow\; \mathbf T_{mtq}=-\frac{[\mathbf B\times]^2}{\lVert\mathbf B\rVert^2}\mathbf T_{cmd} = \mathbf T_{cmd,\perp\mathbf B} $$ Over an orbit $\mathbf B$ sweeps a large solid angle, so all three axes eventually get authority — the averaged system is controllable even though the instantaneous one is not. Also $\lVert\mathbf m\rVert\le m_{max}$ and torque $\propto\lVert\mathbf B\rVert$, hence useless in MEO.
- Thrusters — on/off, non-negative, quantized in time. Each thruster gives a fixed force along a fixed line: $\mathbf T=\sum_i F_i(\mathbf r_i\times\hat{\mathbf f}_i)u_i$ with $u_i\in\{0,1\}$ (or a duty cycle in $[0,1]$). The constraint $u_i\ge0$ is what makes thruster allocation genuinely different — you need opposing pairs to make a pure couple, and the natural solver is an LP minimising total impulse (fuel) rather than a 2-norm. Continuous demand is realized by PWM/PWPF modulation, whose minimum impulse bit sets a torque quantization — and whose pulsing is a jitter source, so thrusters are forbidden during comm windows.
8.3 Arbitration — who is allowed to act, and when
Weights alone are not enough: a supervisor decides which actuators are even eligible, based on task, device state and orbit regime. Two distinct switches exist, and conflating them is a classic design error:
| Switch | Between | Decided by |
|---|---|---|
| Attitude-control actuator | CMG ↔ reaction wheel | task (agility/pointing vs. quiet hold or backup) — not by $\boldsymbol\omega$ |
| Desaturation actuator | magnetorquer ↔ thruster | stored momentum threshold + regime + health + comm window |
Momentum dumping triggers on stored momentum, never on spacecraft angular velocity:
DESAT ARBITRATION (mode manager, low rate)
─────────────────────────────────────────────────────────
IF |h_store| < H_low : IDLE (CMG null-motion only)
ELIF in_comm_window AND |h_store| < H_hard : DEFER (protect jitter)
ELIF |h_store| ≥ H_dump_threshold:
IF regime=LEO AND |B|>B_min AND mag_ok AND ≥2 MTQ axes
: MAGNETORQUER dump (free)
ELIF thrusters_ok : THRUSTER couple dump
ELSE : SAFE (flag: cannot dump)
| Threshold | Meaning | Representative value (300 N·m·s envelope) |
|---|---|---|
| $H_{low}$ | clean target after a dump | ~5% (~15 N·m·s) |
| $H_{dump}$ | start a dump | ~40–50% (~120–150 N·m·s) |
| $H_{hard}$ | dump even during comm | ~80% (~240 N·m·s) |
| $\omega_{acq}$ | detumble → pointing handover | ~0.5 °/s |
The one place rate rules is detumble: B-dot ($\mathbf m=-k\dot{\mathbf B}$) runs while $\lVert\boldsymbol\omega\rVert>\omega_{acq}$ and needs no attitude knowledge at all. Every switch is bumpless: ramp the incoming actuator over a few seconds, feed the predicted reaction forward into the active attitude loop, and put hysteresis on the triggering variable ($\lVert\mathbf B\rVert$, $\lvert h\rvert$, $\lVert\boldsymbol\omega\rVert$) so it cannot chatter.
8.4 Momentum dumping in detail
The bookkeeping that makes dumping make sense: total system momentum is $\mathbf h_{sys}=J\boldsymbol\omega+\mathbf h_w$. Internal actuators can only trade momentum between body and wheels — to actually remove it you need an external torque (magnetic or thruster). During a dump the attitude loop holds the body still while the wheels are deliberately spun down (slowed, not powered off — a powered-off wheel keeps its momentum), and the external torque absorbs the reaction.
The magnetorquer B-cross dump law drives the wheel-momentum error $\Delta\mathbf h_w$ to zero:
$$ \mathbf m_{cmd}=\frac{k}{\lVert\mathbf B\rVert^2}\big(\mathbf B\times\Delta\mathbf h_w\big) \;\Longrightarrow\; \mathbf T_{mtq}=-k\Big(\Delta\mathbf h_w-(\Delta\mathbf h_w\!\cdot\hat{\mathbf B})\hat{\mathbf B}\Big) =-k\,\Delta\mathbf h_{w,\perp} $$i.e. gradient descent on $\lVert\Delta\mathbf h_w\rVert$ restricted to the plane $\perp\mathbf B$. The along-field component waits for the field to rotate — which motivates align-and-dump: rather than dumping continuously and inefficiently, briefly orient (or simply wait for) a favourable field geometry so the momentum to be removed lies perpendicular to $\mathbf B$, then dump hard. For thrusters there are two options: fire body-fixed opposing pairs per axis (simple, no reorientation, some cosine loss), or slew so the stored momentum aligns with the most efficient thruster couple (fuel-optimal, costs a maneuver). the reference platform uses a hybrid, always scheduled outside comm windows. Life-cycle desat propellant works out to a few kg — small, but it is the reason MEO operations are propellant-limited rather than power-limited.
9 · Loop shaping, flexible modes & notch filters
Single-axis rigid plant at worst inertia is a double integrator — 180° of phase lag, so rate feedback is mandatory:
$$ G_{rb}(s)=\frac{1}{Is^2},\qquad I=5500\ \text{kg·m}^2 $$The real spacecraft is not rigid: the 12 m arrays add lightly-damped modes at 0.5–1 Hz with damping $\zeta\sim0.002$–$0.01$, appearing as resonant pole/zero pairs inside or near the intended crossover:
$$ G(s)=\frac{1}{Is^2}+\sum_{k}\frac{\phi_k^2}{s^2+2\zeta_k\omega_k s+\omega_k^2} $$Two mitigation strategies, and they trade against each other:
| Strategy | How | Cost |
|---|---|---|
| Gain stabilization (notch) | put a notch at $\omega_k$ so the mode is below 0 dB | phase lag near crossover; fails if $\omega_k$ shifts (fuel burn, thermal, deployment) |
| Phase stabilization (roll-off) | set crossover well below $\omega_1$ (~1/5–1/10) | slow loop: worse disturbance rejection and settling |
the reference design does both: crossover ~0.1–0.2 Hz (comfortably under the first array mode) plus notches with deliberately wide skirts to tolerate ±20% frequency uncertainty, since a notch tuned to a mode that has moved is worse than no notch. Targets: gain margin ≥ 6 dB, phase margin ≥ 30–40°, and every flexible mode ≥ 8–10 dB attenuated. Digital effects eat margin too — sampling at $f_s$ plus computation delay adds $\angle=-\omega(T_d+T_s/2)$, so the 10 Hz estimator/50 Hz control rates are part of the stability argument, not an implementation detail.
Here is that trade as a loop-gain plot. The lightly-damped array mode appears as a resonant peak; if it crosses 0 dB you get a limit cycle. Either lower the crossover until the mode is buried (phase stabilization, slow) or notch it (gain stabilization, fast) — then mistune the notch and watch the margin evaporate, which is why real notches are built with wide skirts:
10 · Pointing & jitter budget
Definitions matter here — the three requirements measure different things:
- Pointing error — actual vs. desired boresight. What the link actually cares about (R1, 36″).
- Knowledge error — estimated vs. actual attitude. What the estimator delivers (R3, 18″); it bounds how well you can ever point.
- Stability / jitter — motion during the optical integration time, i.e. high-frequency content only (R2, 5″ over 1 s). A slow thermal bias is not jitter; a 10 Hz wobble is.
Errors are separated by kind, RSS'd within a kind, then RSS'd across kinds:
$$ \text{Total}=\sqrt{\text{knowledge}^2+\text{control}^2+\text{alignment}^2+\text{jitter}^2} $$| Budget (3σ) | Terms | RSS | vs. requirement |
|---|---|---|---|
| Knowledge | tracker NEA 3.0″, tracker bias 2.0″, gyro prop 1.5″, MEKF residual 1.0″, time-tag 1.5″, tracker→body align 4.0″ | ≈5.9″ | R3 = 18″ ✓ |
| Control | loop steady-state 5.0″, CMG quantization/steering 5.0″, gimbal ripple 3.0″, residual disturbance 4.0″ | ≈8.7″ | — |
| Alignment | bus→payload 10.0″, thermal distortion 12.0″, launch shift/creep 5.0″ | ≈16.4″ | largest contributor |
| Jitter (1 s) | rotor imbalance 4.0″, array modes 5.0″, thruster pulsing 2.0″, microvibration 2.0″ | ≈7.0″ | R2 = 5″ ✗ |
Mitigations, in order of leverage: (1) a fine-steering mirror inner loop — the real fix; (2) tuned-mass dampers + notches on the array modes; (3) hexapod isolation of the CMG/RW cluster; (4) on-orbit thermal-alignment calibration feed-forward vs. orbit phase; (5) no thruster firing in comm.
11 · The FSM / beacon fine-tracking loop
This is the same two-stage idea as §8, applied optically: a slow, strong, large-range stage (the bus) nested with a fast, weak, small-range stage (the mirror). The bus holds ~20″ — enough to keep the beacon inside the FSM's capture range — and the FSM removes the residual at 100–500 Hz, far above anything a 5500 kg body can do.
| Element | Property |
|---|---|
| FSM actuator | piezo/voice-coil tip-tilt, ±1–2 mrad range, kHz-class bandwidth, ~µrad resolution |
| Sensor | quad-cell / focal-plane beacon tracker, ~1″ NEA, kHz frame rate |
| Loop | high-gain PI + lead, crossover ~100 Hz, integrator kills bus drift |
| Handover | bus keeps the beacon in capture; FSM offloads its DC tilt back to the bus as a slow bias |
Point-ahead angle: because light takes finite time and both terminals move, you must transmit toward where the far terminal will be, not where you see it — an offset of order $\theta_{PAA}\approx 2v_\perp/c$ (tens of µrad), computed from ephemeris and applied as a commanded FSM bias. Its residual knowledge error (~0.5″) is a line item in the final budget. Acquisition sequence: coarse ephemeris point → spiral/raster scan → beacon detect → FSM closed-loop track → data.
| Layer | Line-of-sight contribution |
|---|---|
| Bus residual entering the FSM | ~20″ (kept in capture range) |
| FSM tracking residual | ~1.5″ |
| Beacon NEA | ~1.0″ |
| Point-ahead knowledge | ~0.5″ |
| Net LOS (RSS) | ≈2″ (0.0006°), jitter ≈1.5″/s ✓✓ |
12 · Mode sequence
(B-dot, MTQ)
safe
(Lyapunov + CMG)
(PID + FSM)
management
Transitions are on angular-velocity thresholds (detumble→acquire→fine); desaturation is on stored-momentum thresholds; actuator choice is by task and regime (§8.3).
13 · Fault detection, isolation & recovery
Redundancy: 2 star trackers, 2 magnetometers, 2 GPS, 4 CMGs (one-fault tolerant), 4 wheels, 3 MTQ axes, 12 thrusters in couples. What matters is the detection logic and the graceful-degradation ladder.
| Unit | Failure mode | Detection signature | Response |
|---|---|---|---|
| Star tracker | Sun/Earth blinding, false star ID, freeze | innovation $\chi^2$ spike; stale time-tag; disagreement between heads | reject frames, lean on gyro + 2nd head; bias → consider state |
| Gyro | bias jump, scale-factor drift, axis dropout | persistent innovation bias; tracker-vs-gyro rate mismatch | re-estimate bias, reduce propagation interval, tracker-only attitude |
| CMG | gimbal stall, rotor loss, approaching singularity | $m\to0$; commanded-vs-actual $\dot\delta$ mismatch | 3-CMG reconfiguration (reduced envelope), null-motion escape, RW backup |
| Wheel | saturation, bearing drag, zero-crossing stiction | speed at limit; torque deficit | redistribute via null space, desaturate, drop to 3-wheel |
| MTQ / thruster | coil open, valve stuck open/closed | no torque response; unexpected Δv or attitude drift | switch dump path (MTQ↔thruster); isolate stuck valve, use remaining couples |
Actuator-loss hierarchy: 4 CMGs → 3 CMGs (smaller envelope, more singularities) → reaction wheels (slower slews, relaxed agility) → thrusters (coarse, fuel-consuming, jitter) → magnetic-only safe mode (attitude survival, no comm). Each rung is a declared degraded mode with its own achievable requirements — not an improvisation.
14 · Flexible-mode excitation & damping
The coupled rigid–flexible model, with modal coordinates $\boldsymbol\eta$ and participation matrix $\Phi$:
$$ J\dot{\boldsymbol\omega}+\Phi^\top\ddot{\boldsymbol\eta}=\mathbf T,\qquad \ddot{\boldsymbol\eta}+2Z\Omega\dot{\boldsymbol\eta}+\Omega^2\boldsymbol\eta=-\Phi\dot{\boldsymbol\omega} $$Any torque with energy near $\omega_k$ pumps the modes — so the control signal itself is a disturbance source. Layered strategy:
- Don't excite: input shaping / smooth (jerk-limited, $\sin^2$) slew profiles whose spectra have nulls at the array frequencies; notches on the command path.
- Actively damp (low frequency): positive-position feedback or strain/rate feedback from accelerometers on the arrays, adding damping to 0.5–1 Hz modes without destabilizing the rigid loop.
- Passively damp: tuned-mass and viscoelastic dampers on the array structure — no stability risk, no software.
- High-frequency microvibration (rotor imbalance, cryocoolers, steppers, >10 Hz) is not controllable by the bus at all: it must be isolated (hexapod/passive mounts) and then rejected optically by the FSM.
15 · Red-team "what-if" analysis
| What-if | Effect | Verdict |
|---|---|---|
| Mass +30% | slew torque 12.8→16.6 N·m; slew momentum →250 N·m·s | torque fine (4.5× margin); momentum envelope (300) becomes binding |
| Lost solar wing | destroys inertia symmetry, shifts CG → large SRP/GG torque + cross-coupling | most severe structural case; may exceed authority → reconfigure & relax pointing |
| Propellant slosh / depletion | time-varying inertia and CG | gain-schedule on mass state or design for robustness (H∞/µ margin) |
| Star tracker blinded | lose fine attitude | dual boresight + gyro propagation bridges; redundancy is real only if geometry is right |
| CMG saturates mid-pass | loss of torque authority | pre-pass desaturation + RW backup; the 1.6× momentum margin is the buffer |
| FSM / optical terminal fails | jitter requirement unreachable | no bus-only recovery — R2 is simply not met; mission degrades to lower data rate |
| Array modes shift 20% | notch mistuned → margin loss | wide-skirt notches + low crossover; on-orbit modal ID to retune |
| MEO transfer | magnetic dumping stops working | thruster dumping + propellant budget becomes a lifetime driver |
16 · Why these choices?
- Why an MEKF (not additive EKF, not a quaternion in the state)? Keeps the quaternion unit-norm and the covariance non-singular in the 3-D tangent plane — see Attitude.
- Why quaternions (not Euler)? No gimbal lock, cheap composition, and the natural error algebra for the filter and the Lyapunov proof.
- Why Lyapunov + PID + LQR together? Global validity at large angles, zero steady-state error against secular torque, and a principled way to pick MIMO gains — each covers the others' gap (§7).
- Why a 4-SGCMG pyramid? Torque amplification for agility, one-fault tolerance, a near-spherical momentum envelope at 54.7° skew, and a null space to steer around singularities.
- Why two-level allocation? It decouples the 3-DOF physics problem from the hardware manifest, lets the null space absorb saturation/failures invisibly, and makes actuator changes a Level-2 edit.
- Why two-stage pointing (bus + FSM)? The bus cannot reach 5″ against flexible modes at any gain; the FSM closes the fast residual on a beacon.
Related: Attitude & the MEKF ·
Filtering · NASA nav best practices ·
Star Tracker · IMU.
Source: ADCS/ADCS_Laser_Pointing.md (+ critique companion).