Test any published attitude control law on your bus.¶
Without reimplementing it.
Generalized Attitude Control for Small Spacecraft — SmallSat 2026, poster SSC26-P2-54.
You scanned the poster. Everything below runs against the shipped library.
Install¶
pip install generalized-adcs
Same line as the poster. Python 3.10+.
A published magnetic law gets a wheel¶
The Lovera–Astolfi law is magnetorquer-only: it projects its desired torque onto the plane perpendicular to B and never commands a wheel. Change the allocator, not the law, and the same feedback starts using the wheel:
law = Lovera_Law(J=sat.J_0, kp=2e-5, kd=2e-2) # unmodified
mtq_only = PipelineController(sat, law) # published
with_wheel = PipelineController(sat, law, # + the wheel
alloc_config=AllocationConfig(method='lp'))
mtq_only reproduces the published MTQ_Lovera controller to machine
precision — max \(|\Delta u|\) = 2.2e-16 over 200 random states, 122 of
them bit-identical. with_wheel is the same law on the same bus, now
commanding the wheel, because goal formulation, compensation and allocation
are separate stages around it.
On 3MTQ+1RW over 100 paired trials, that one change takes Lovera from 0% to 29% convergence on full attitude and 41% to 80% on vector pointing; Wisniewski goes from 2% to 39% and 16% to 72% (paper Table 7).
How it works¶
The adapter is a five-stage pipeline. A control law is Stage 2; everything around it adapts the law to the hardware you actually have.
Stage |
Block |
What it does |
|---|---|---|
1 |
Goal formulation |
Converts any goal (full attitude, pointing vector, none) into the error
signals the law declares it wants, plus the rate projector |
2 |
Control law |
Your code. Maps error signals to a desired body torque. |
3 |
Interface |
Adapts laws that emit actuator commands rather than torque. |
4 |
Compensation |
Gyroscopic, frame-rotation, disturbance feedforward, damping injection — each skipped if the law says it does that term itself. |
5 |
Allocation |
LP / QP / weighted-QP / pseudoinverse / cross-product, plus momentum management, onto the actual actuator set. |
Bring your own law¶
Implement one method. Declare what error signals you want, and the rest of the pipeline reconfigures around you:
class MyLaw(ControlLaw):
interface = LawInterface() # full attitude + rate
kp, kd = 2e-5, 2e-2
def compute(self, q_err, w_err=None, **kw):
return -(self.kp * q_err + self.kd * w_err)
ctrl = PipelineController(sat, MyLaw(), # steps 2-3
alloc_config=AllocationConfig(method='lp'))
No double-counting¶
A law that already performs its own gyroscopic term declares it, and Stage 4 skips that term rather than adding it twice:
class Lovera(ControlLaw):
# law does its own w x (Jw + h), so
# Stage 4 must not add it again:
interface = LawInterface(includes_gyroscopic=True)
Hand-forcing gyroscopic compensation around such a law demonstrably changes
the output; the declaration is what prevents it
(testing/test_pipeline/test_lovera_law.py).
Goal type as a design lever¶
Attitude_Goal and Vector_Goal are the abstract interfaces; use a
concrete goal such as Fixed_Attitude_Goal or ECI_Goal:
full = Fixed_Attitude_Goal(q_tgt) # 49% converge
vec = ECI_Goal(u_tgt) # 83% converge
u_full = ctrl.find_u(x, sens, sat, os_now, full)
u_vec = ctrl.find_u(x, sens, sat, os_now, vec)
# same law, same bus - Stage 1 converts each goal
Swap the allocator¶
AllocationConfig(method='lp') # direction kept
AllocationConfig(method='qp') # size kept, tilts
AllocationConfig(method='clipping') # pinv, then clip
AllocationConfig(method='magnetic_cross') # MTQ only
Inside the achievable torque polytope every allocator returns the request, so LP and QP differ only under saturation. There LP holds direction to \(0.00^\circ\) and gives up magnitude; QP recovers roughly 50% more magnitude at up to \(26.9^\circ\) of tilt. On 3MTQ+1RW full attitude the LP wins (42% vs 39%); on a magnetorquer-only bus the QP does (paper Table 6, §IV-F).
Every block on this page is executed verbatim by
papers/SSC26_poster/verify_snippets.py, so what is printed is what runs.
Paper and citation¶
P. McKeen, N. Scheuer and K. Cahoy, Generalized Attitude Control for Small Spacecraft, SSC26-P2-54, 40th Annual Small Satellite Conference, Salt Lake City UT, August 2026.
@inproceedings{mckeen2026generalized,
title = {Generalized Attitude Control for Small Spacecraft},
author = {McKeen, Patrick and Scheuer, Niclas and Cahoy, Kerri},
booktitle = {Proceedings of the 40th Annual Small Satellite Conference},
number = {SSC26-P2-54},
year = {2026},
address = {Salt Lake City, UT},
}
Where to go next¶
SSC26 · Run it in your browser — run it in your browser, no install
SSC26 · The paper — the paper and how to cite it
SSC26 · The code — the repository, and where each stage lives
SSC26 · Contact — questions, collaboration, bug reports
Installation — full installation guide
Tutorials — tutorials