Components::DetumbleManager
The Detumble Manager component implements a B-dot style detumbling controller. It coordinates angular-velocity measurements, dipole moment commands, and magnetorquer actuation to reduce the spacecraft rotation rate. The component operates as a scheduled passive component and drives a set of configured magnetorquer coils.
Usage Examples
The Detumble Manager is designed to be scheduled periodically to drive its internal state machine:
- COOLDOWN – wait for sensors and the magnetic environment to settle after a torque command.
- SENSING_ANGULAR_VELOCITY – read angular velocity magnitude, compare against configurable thresholds, and select a detumble strategy (IDLE, BDOT, or HYSTERESIS).
- SENSING_MAGNETIC_FIELD – collect a fixed window of magnetic field samples for the B-Dot controller.
- ACTUATING_BDOT – command magnetorquers using a dipole moment computed by the internal B-Dot controller.
- ACTUATING_HYSTERESIS – command magnetorquers using a bang‑bang hysteresis strategy along a selected axis.
Typical Usage
- The component is instantiated and initialized during system startup.
- Parameters are loaded (mode, thresholds, timing, coil properties).
- The deployment calls
configure()in the component configuration phase to cache coil parameters and publish related telemetry. - The scheduler periodically calls the
runport. - On each run:
- The component checks the operating mode (DISABLED or AUTO).
- The state machine executes COOLDOWN, SENSING_ANGULAR_VELOCITY, SENSING_MAGNETIC_FIELD, ACTUATING_BDOT, or ACTUATING_HYSTERESIS actions.
- When appropriate, it requests:
- Angular velocity magnitude via
angularVelocityMagnitudeGet. - Magnetic field samples via
magneticFieldGetand sampling period viamagneticFieldSamplingPeriodGet.
- Angular velocity magnitude via
- It computes a dipole moment using the internal
BDothelper (for BDOT strategy) or selects a bang‑bang axis (for HYSTERESIS strategy). - It starts or stops the magnetorquers via the
x*/y*/z*Startandx*/y*/z*Stopports.
Class Diagram
classDiagram
namespace Components {
class DetumbleManagerComponentBase {
<<Auto-generated>>
}
class DetumbleManager {
+ DetumbleManager(const char* compName)
+ ~DetumbleManager()
+ configure(): void
- run_handler(FwIndexType portNum, U32 context): void
- setMode_handler(FwIndexType portNum, const DetumbleMode& mode): void
- systemModeChanged_handler(FwIndexType portNum, const SystemMode& mode): void
- SET_MODE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, DetumbleMode mode): void
- startMagnetorquers(I8 x_plus, I8 x_minus, I8 y_plus, I8 y_minus, I8 z_minus): void
- stopMagnetorquers(): void
- stateCooldownActions(): void
- stateEnterCooldownActions(): void
- stateExitCooldownActions(): void
- stateSensingAngularVelocityActions(): void
- stateEnterSensingAngularVelocityActions(): void
- stateExitSensingAngularVelocityActions(F64 angular_velocity_magnitude_deg_sec): void
- stateSensingMagneticFieldActions(): void
- stateActuatingBDotActions(): void
- stateEnterActuatingBDotActions(): void
- stateExitActuatingBDotActions(): void
- stateActuatingHysteresisActions(): void
- m_bdot: BDot
- m_strategy_selector: StrategySelector
- m_x_plus_magnetorquer: Magnetorquer
- m_x_minus_magnetorquer: Magnetorquer
- m_y_plus_magnetorquer: Magnetorquer
- m_y_minus_magnetorquer: Magnetorquer
- m_z_minus_magnetorquer: Magnetorquer
- m_mode: DetumbleMode
- m_state: DetumbleState
- m_strategy: DetumbleStrategy
- m_cooldown_start_time: Fw::Time
- m_torque_start_time: Fw::Time
- last_cycle_time: Fw::Time
}
}
DetumbleManagerComponentBase <|-- DetumbleManager : inherits
DetumbleManager "1" *-- "1" BDot
DetumbleManager "1" *-- "1" StrategySelector
DetumbleManager "1" *-- "5" Magnetorquer
Helper Classes
BDot
classDiagram
class BDot {
+ BDot()
+ ~BDot()
+ getMagneticMoment() double[3]
+ configure(gain: double, magnetometer_sampling_period: microseconds, rate_group_max_period: microseconds) void
+ addSample(magnetic_field: double[3], timestamp: microseconds) void
+ samplingComplete() bool
+ getTimeBetweenSamples() microseconds
+ emptySampleSet() void
- computeBDot() double[3]
- getMagnitude() double
- m_gain: double
- m_magnetometer_sampling_period: microseconds
- m_rate_group_max_period: microseconds
- m_sampling_set: Sample[5]
- m_sample_count: size_t
}
Magnetorquer
classDiagram
class Magnetorquer {
+ Magnetorquer()
+ ~Magnetorquer()
+ dipoleMomentToCurrent(dipole_moment_component: double) int8
- getCoilArea() double
- getMaxCoilCurrent() double
- computeTargetCurrent(dipole_moment_component: double) double
- computeClampedCurrent(target_current: double) int8
+ m_turns: double
+ m_voltage: double
+ m_resistance: double
+ m_direction_sign: DirectionSign
+ m_shape: CoilShape
+ m_width: double
+ m_length: double
+ m_diameter: double
}
class CoilShape {
<<enumeration>>
RECTANGULAR
CIRCULAR
}
class DirectionSign {
<<enumeration>>
POSITIVE
NEGATIVE
}
Magnetorquer -- CoilShape
Magnetorquer -- DirectionSign
StrategySelector
classDiagram
class StrategySelector {
+ StrategySelector()
+ ~StrategySelector()
+ fromAngularVelocityMagnitude(angular_velocity_magnitude_deg_sec: double) Strategy
+ configure(bdot_max_threshold: double, deadband_upper_threshold: double, deadband_lower_threshold: double)
- m_bdot_max_threshold: double
- m_deadband_lower_threshold: double
- m_deadband_upper_threshold: double
- m_rotation_target: double
}
class Strategy {
<<enumeration>>
IDLE
BDOT
HYSTERESIS
}
StrategySelector -- Strategy
Default Parameters and Mathematical Constants
BDot Maximum Threshold
The B-Dot maximum threshold parameter defines the upper rotational rate (deg/s) above which the hysteresis strategy is used instead of B-Dot. This threshold is computed as:
where:
- \(\omega_{\max}\) is the maximum angular velocity (deg/s),
- \(\Delta t\) is the duration of the actuation,
- \(\delta T\) is the time elapsed between the measurement of \(\dot{B}\).
For the PROVES CubeSat mission, we have:
Given:
- Actuation duration, \(\Delta t = 0.32\ \text{s}\) (configured via TORQUE_DURATION parameter)
- Time between \(\dot{B}\) measurements, \(\delta T = 0.08\ \text{s}\) (based on DetumbleManager rate group \(20Hz\) and B-Dot sample window of \(5\) samples)
In this reference deployment the BDOT_MAX_THRESHOLD parameter defaults to \(720\,\text{deg/s}\) (see the FPP definition), well under the computed maximum of \(1125\ \text{deg/s}\) to provide a buffer for margin of error. Above the configured threshold, the hysteresis strategy is used, which is less sensitive to timing issues.
TORQUE_DURATION Decision
The TORQUE_DURATION parameter defines the duration of a single torque actuation. We can choose this duration based on the maximum angular velocity we wish to control via the B-Dot controller. Given the maximum angular velocity of \(1125\ \text{deg/s}\), bound by the magnetic field sampling duration, we can select a torque duration that allows us to control up to this rate.
We set the TORQUE_DURATION parameter to \(320ms\) in this reference deployment, which allows us to control angular velocities up to \(1125\ \text{deg/s}\) as computed above.
COOLDOWN_DURATION Decision
The COOLDOWN_DURATION parameter defines the time spent waiting after a torque command before sensing angular velocity again. This cooldown period allows the magnetic environment and sensors to settle after actuation so that measurements are not contaminated by residual fields. The LIS2MDL magnetometer takes new measurements every \(10ms\) (\(100Hz\)). To ensure at least one new measurement is available after actuation, we set the COOLDOWN_DURATION parameter to \(20ms\) in this reference deployment.
DEADBAND_LOWER_THRESHOLD Decision
The DEADBAND_LOWER_THRESHOLD parameter defines the rotational rate (deg/s) below which detumbling is considered complete and the IDLE strategy is selected. This threshold should be set low enough to ensure that the spacecraft is sufficiently detumbled for mission operations, but high enough to prevent the satellite from settling into a poor orientation (like antenna board directly pointed at the sun) or suffer thermal issues due to heat taken on from the sun.
BDot Implementation Options
The B-Dot algorithm estimates the time derivative of the magnetic field vector \(\dot{B}\) to compute the required dipole moment for detumbling. Several methods exist for estimating \(\dot{B}\) from various sensor inputs:
1. Cross Product Method
The cross product method estimates \(\dot{B}\) using the cross product of an angular velocity vector \(\omega\) and the magnetic field vector \(B\):
Both the angular velocity and magnetic field vectors are available to the DetumbleManager component via ports in the ImuManager component. This method requires accurate angular velocity measurements and is sensitive to noise in both measurements.
References: - Discrete Control with First Order Bdot Controller - Dr. Carlos Montalvo - University of South Alabama .
2. Derivative Method
The derivative method estimates \(\dot{B}\) using finite differences between consecutive magnetic field readings:
This method is straightforward to implement and requires only magnetic field measurements. However, like the cross product method it is sensitive to noise. Also, in Discrete Control with First Order Bdot Controller, Dr. Montalvo notes that this method did not perform as well as the cross product method in simulations.
References: - Lecture slides on Control Systems - Dr. Jan Bekkeng - University of Oslo - Discrete Control with First Order Bdot Controller - Dr. Carlos Montalvo - University of South Alabama.
3. Least Squares Method
The least squares method fits a line to a series of magnetic field readings over time and computes the slope of that line as an estimate of \(\dot{B}\).
This method can be more robust to noise, especially when multiple readings are available.
References: - Hardware-In-The-Loop and Software-In-The-Loop Testing of the MOVE-II CubeSat - Jonis Kiesbye et al. - 2019
4. 5-Point Central Difference Method
The central difference method uses a five-point stencil to estimate \(\dot{B}\), providing a higher-order approximation:
Where \(B_i\) are magnetic field readings at different time points and \(\Delta t\) is the time interval between readings. The DetumbleManager is on a \(50Hz\) rate group so the time between readings is \(0.02 s\).
The 5‑point central finite‑difference formula is obtained by combining Taylor expansions at five equally spaced points so that the combination reproduces the first derivative and cancels as many low‑order error terms as possible. The derivation of the 5‑point central finite‑difference formula is as follows:
Let \(f(t)\) be smooth and suppose values are known at five equally spaced points
with corresponding values
Expand \(f\) at points \(t_0\pm\Delta t\) and \(t_0\pm 2\Delta t\) using Taylor series about \(t_0\).
Write derivatives at \(t_0\) as
Then
These expansions are the raw material for building a linear combination that isolates \(f_0'\).
Consider a general linear combination of the five samples:
The goal is to choose \(a,b,c,d,e\) so that
so that after division by \(\Delta t\) the result approximates \(f'(t_0)\).
Because a central first‑derivative operator should be antisymmetric about the center, impose
This automatically makes the approximation odd in \(\Delta t\), which matches the behavior of a first derivative.
With this symmetry,
Substitute the expansions and collect terms by derivative order. Using the series above, the contributions to \(L\) are:
- Constant term (involving \(f_0\)):
so the constant always cancels; that is consistent with \(f'(t)\) being zero for constant functions. - First‑derivative term (involving \(f_0'\)):
$$ a\bigl(-2f_0'\Delta t - 2f_0'\Delta t\bigr) + b\bigl(-f_0'\Delta t - f_0'\Delta t\bigr) = (-4a - 2b) f_0' \Delta t. $$ - Third‑derivative term (involving \(f_0^{(3)}\)), from the \(\Delta t^3\) terms:
Terms in \(f_0''\) already cancel because of the symmetry \(a=-e,b=-d\), and higher derivatives are left as truncation error.
To make \(L\) approximate \(f_0'\Delta t\) with high accuracy, require
- The coefficient of \(f_0'\Delta t\) is \(1\):
- The coefficient of \(f_0^{(3)}\Delta t^3\) vanishes (cancel cubic error):
So the coefficients must satisfy the system
Solving:
Thus
Factor a common denominator \(12\):
From the construction,
so dividing by \(\Delta t\) gives the final 5‑point central derivative formula:
BDot Implementation Decision
After evaluating the options, we selected the 5-Point Central Difference Method for the following reasons: - Noise Robustness: The central difference method can better handle noisy measurements by averaging over multiple readings. - Simplicity: It requires only magnetic field measurements, addition and division, simplifying the system architecture. - Performance: While the cross product and least squared methods may offer better performance in some scenarios, the central difference method provides a good balance between performance and robustness for our application.
k Gain Constant Default Value
The gain constant k in the B-Dot algorithm determines the strength of the magnetic moment command in response to the estimated \(\dot{B}\). A higher k value results in stronger torques, while a lower k value results in gentler torques.
We can determine the k constant based on the following formula:
where: - \(m_{max}\) is the maximum magnetic moment achievable by the magnetorquers (A⋅m²), - \(||\dot{B}_{max}||\) is the maximum expected rate of change of the magnetic field (G/s).
For the PROVES CubeSat mission, we estimated using the lowest performing magnetorquer (Z- coil) and an altitude of 420 km:
Given: - Maximum coil current, \(I_{\max} = 3.3\ \text{V} / 150.7\ \text{m}\Omega\) - Number of turns, \(n = 153\) - Coil diameter, \(d = 0.05755\ \text{m}\) - Coil area, \(A = \frac{1}{2}\pi \cdot (\frac{1}{2}\ 0.05755\ \text{m})^2\)
And
Given: - Maximum angular velocity controllable by the B-Dot controller, \(\omega_{\max} \approx 19.635\ \text{rad/s}\) (computed below) - Maximum magnetic field at 420 km altitude, \(B_{\max} \approx 0.4\ G\)
Therefore:
We set the default k gain constant to \(3.0 \ s\) in this reference deployment, providing a small margin below the computed maximum to account for uncertainties.
Port Descriptions
| Name | Type | Description |
|---|---|---|
| run | sync input | Scheduler port that advances the detumble state machine |
| setMode | sync input | Port for setting the detumble mode (DISABLED or AUTO) |
| systemModeChanged | sync input | Port for receiving system mode change notifications (SAFE disables detumble) |
| angularVelocityMagnitudeGet | output | Requests current angular velocity magnitude |
| magneticFieldGet | output | Requests current magnetic field vector (gauss) |
| magneticFieldSamplingPeriodGet | output | Requests magnetometer sampling period |
| xPlusStart | output | Command to start the X+ magnetorquer with a signed current value |
| xPlusStop | output | Command to stop the X+ magnetorquer |
| xMinusStart | output | Command to start the X− magnetorquer with a signed current value |
| xMinusStop | output | Command to stop the X− magnetorquer |
| yPlusStart | output | Command to start the Y+ magnetorquer with a signed current value |
| yPlusStop | output | Command to stop the Y+ magnetorquer |
| yMinusStart | output | Command to start the Y− magnetorquer with a signed current value |
| yMinusStop | output | Command to stop the Y− magnetorquer |
| zMinusStart | output | Command to start the Z− magnetorquer with a signed current value |
| zMinusStop | output | Command to stop the Z− magnetorquer |
| timeCaller | time get | Requests current system time for timing COOLDOWN and TORQUING |
| logTextOut | text event | Sends textual events |
| logOut | event | Sends binary events |
| tlmOut | telemetry | Sends telemetry channels |
| prmGetOut | param get | Retrieves parameter values |
| prmSetOut | param set | Updates parameter values |
| cmdRegOut | command reg | Registers commands |
| cmdIn | command recv | Receives commands |
| cmdResponseOut | command resp | Sends command responses |
Parameters and Telemetry (Summary)
- Mode and thresholds
BDOT_MAX_THRESHOLD(F64): Upper rotational threshold (deg/s) above which hysteresis is used.DEADBAND_UPPER_THRESHOLD(F64): Upper deadband rotational threshold (deg/s).DEADBAND_LOWER_THRESHOLD(F64): Lower deadband rotational threshold (deg/s).GAIN(F64): Gain used for B-Dot algorithm.HYSTERESIS_AXIS(HysteresisAxis): Axis used for hysteresis detumbling.
COOLDOWN_DURATION(Fw.TimeIntervalValue): Time spent waiting after a torque command.-
TORQUE_DURATION(Fw.TimeIntervalValue): Duration of a single torque actuation. -
Coil configuration (per axis/coil)
- Voltage, resistance, number of turns, dimensions, and shape.
-
A full set exists for X+, X−, Y+, Y−, and Z− coils.
-
Key telemetry
Mode(DetumbleMode): Current operating mode.State(DetumbleState): COOLDOWN, SENSING_ANGULAR_VELOCITY, SENSING_MAGNETIC_FIELD, ACTUATING_BDOT, or ACTUATING_HYSTERESIS.
DetumbleStrategy(DetumbleStrategy): IDLE, BDOT, or HYSTERESIS.BdotMaxThresholdParam,DeadbandUpperThresholdParam,DeadbandLowerThresholdParam,GainParam.HysteresisAxisParam.CooldownDurationParam,TorqueDurationParam, and measuredTorqueDuration.TimeBetweenMagneticFieldReadings.
-
Per-coil configuration telemetry for all coils (voltage, resistance, turns, geometry, shape).
-
Events
DetumbleStarted: Logged when a detumble cycle starts, with the current angular velocity magnitude.DetumbleCompleted: Logged when detumbling is considered complete (IDLE strategy selected).MagneticFieldRetrievalFailed: Logged ifmagneticFieldGetdoes not succeed.MagneticFieldSamplingPeriodRetrievalFailed: Logged ifmagneticFieldSamplingPeriodGetdoes not succeed.AngularVelocityRetrievalFailed: Logged ifangularVelocityMagnitudeGetdoes not succeed.
Sequence Diagrams
State Machine Overview (AUTO mode)
sequenceDiagram
participant Scheduler
participant DetumbleManager
participant AngularSource as Angular Velocity Source
participant MagSource as Magnetic Field Source
participant MTQ as Magnetorquer Drivers
Scheduler->>DetumbleManager: run()
alt OPERATING_MODE == DISABLED
DetumbleManager->>MTQ: x*/y*/z*Stop
note right of DetumbleManager: State reset to COOLDOWN
else AUTO
opt COOLDOWN
DetumbleManager->>DetumbleManager: stateCooldownActions()
DetumbleManager->>timeCaller: getTime()
timeCaller-->>DetumbleManager: current time
note right of DetumbleManager: After COOLDOWN_DURATION, transition to SENSING_ANGULAR_VELOCITY
end
opt SENSING_ANGULAR_VELOCITY
DetumbleManager->>DetumbleManager: stateEnterSensingAngularVelocityActions()
DetumbleManager->>AngularSource: angularVelocityMagnitudeGet(DEG_PER_SEC)
AngularSource-->>DetumbleManager: angular velocity magnitude, status
alt retrieval failed
DetumbleManager->>DetumbleManager: log AngularVelocityRetrievalFailed
else
DetumbleManager->>DetumbleManager: Select Strategy (IDLE, BDOT, HYSTERESIS)
alt Strategy == IDLE
DetumbleManager->>DetumbleManager: log DetumbleCompleted
note right of DetumbleManager: Stay in SENSING_ANGULAR_VELOCITY, no torquing
else Strategy == BDOT
DetumbleManager->>DetumbleManager: log DetumbleStarted
note right of DetumbleManager: Transition to SENSING_MAGNETIC_FIELD
else Strategy == HYSTERESIS
DetumbleManager->>DetumbleManager: log DetumbleStarted
note right of DetumbleManager: Transition to ACTUATING_HYSTERESIS
end
end
end
opt SENSING_MAGNETIC_FIELD (BDOT)
loop until samplingComplete()
DetumbleManager->>MagSource: magneticFieldGet()
MagSource-->>DetumbleManager: magnetic field, status
alt retrieval failed
DetumbleManager->>DetumbleManager: log MagneticFieldRetrievalFailed
else
DetumbleManager->>DetumbleManager: BDot.addSample(B, timestamp)
end
end
note right of DetumbleManager: When sample window full, transition to ACTUATING_BDOT
end
opt ACTUATING_BDOT
DetumbleManager->>DetumbleManager: stateEnterActuatingBDotActions()
DetumbleManager->>MagSource: magneticFieldSamplingPeriodGet()
MagSource-->>DetumbleManager: sampling period, status
alt retrieval failed
DetumbleManager->>DetumbleManager: log MagneticFieldSamplingPeriodRetrievalFailed
else
DetumbleManager->>DetumbleManager: BDot.configure(gain, sampling_period)
DetumbleManager->>DetumbleManager: dipole = BDot.getMagneticMoment()
DetumbleManager->>MTQ: x*/y*/z*Start(currents from dipole)
DetumbleManager->>timeCaller: getTime()
timeCaller-->>DetumbleManager: current time
alt torque interval elapsed (TORQUE_DURATION)
DetumbleManager->>MTQ: x*/y*/z*Stop
DetumbleManager->>DetumbleManager: BDot.emptySampleSet()
note right of DetumbleManager: Transition to COOLDOWN
end
end
end
opt ACTUATING_HYSTERESIS
DetumbleManager->>DetumbleManager: read HYSTERESIS_AXIS param
DetumbleManager->>MTQ: x*/y*/z*Start(saturated currents along axis)
note right of DetumbleManager: Immediately transition to COOLDOWN
end
end
Requirements
| Name | Description | Validation |
|---|---|---|
| Mode Control | The component shall support DISABLED and AUTO modes via OPERATING_MODE. |
Parameter set and telemetry Mode observed over GDS. |
| External Control | The component shall provide an input port to allow other components to set the detumble mode. | Verify that calling the setMode port updates the component mode. |
| System Safe Mode | The component shall disable detumbling when the system enters SAFE mode. | Simulate a system mode change to SAFE and verify detumbling is disabled. |
| Safe Disable | When in DISABLED mode, all magnetorquer outputs shall be turned off and the internal state reset. | Force DISABLED, verify all *Stop ports are called. |
| Deadband Activation | The component shall implement a deadband using upper and lower thresholds to prevent rapid switching between IDLE and active detumbling. | Verify that detumbling starts only above the upper threshold and stops only below the lower threshold. |
| Hysteresis Strategy | The component shall employ a hysteresis (bang-bang) strategy when the angular velocity exceeds the BDOT_MAX_THRESHOLD. |
Verify that the Hysteresis strategy is selected when angular velocity is high. |
| B-Dot Strategy | The component shall employ a B-Dot strategy when the angular velocity is within the active range (above deadband, below BDOT_MAX_THRESHOLD). |
Verify that the B-Dot strategy is selected when angular velocity is in the intermediate range. |
| Cooldown Timing | After TORQUING, the component shall remain in COOLDOWN for at least COOLDOWN_DURATION before SENSING. |
Instrument time via timeCaller and observe state changes. |
| Parameter Telemetry | Coil configuration parameters shall be telemetered for all coils after configuration. | Call configure() and verify coil telemetry channels. |
| Error Reporting | The component shall emit warning events when angular velocity or magnetic field retrieval fails. | Force non-success return codes and observe events. |
Change Log
| Date | Description |
|---|---|
| 2025-12-20 | Initial design document drafted for Detumble Manager component |