opengnc.fdir package

Submodules

opengnc.fdir.actuator_fdir module

Actuator Fault Detection, Isolation, and Reconfiguration (FTC).

Provides health monitoring for reaction wheels and thrusters, dynamic weighted pseudo-inverse control allocation with health masking, and underactuated attitude control for 2-wheel degraded recovery.

class opengnc.fdir.actuator_fdir.ActuatorFaultDetector(max_wheel_speed: float = 600.0, torque_tolerance: float = 0.02, persistence_steps: int = 5)[source]

Bases: object

Monitors reaction wheel and thruster health states.

Detects motor lockup, friction torque spikes, tachometer runaway, and command-to-telemetry tracking error.

Parameters:
  • max_wheel_speed (float, optional) – Maximum allowable reaction wheel speed (rad/s). Default is 600.0 (~5700 RPM).

  • torque_tolerance (float, optional) – Allowable torque discrepancy between command and telemetry (N*m). Default is 0.02.

  • persistence_steps (int, optional) – Number of consecutive timesteps with violation before marking FAILED. Default is 5.

check_wheel(name: str, cmd_torque: float, actual_torque: float, current_speed: float) → ActuatorHealth[source]

Evaluate wheel telemetry against health thresholds.

Parameters:
  • name (str) – Actuator identifier.

  • cmd_torque (float) – Commanded torque (N*m).

  • actual_torque (float) – Measured/estimated torque output (N*m).

  • current_speed (float) – Current wheel spin rate (rad/s).

Returns:

Updated health status.

Return type:

ActuatorHealth

register_actuator(name: str) → None[source]

Register a new actuator to monitor.

set_failed(name: str) → None[source]

Manually mark an actuator as FAILED.

class opengnc.fdir.actuator_fdir.ActuatorHealth(value)[source]

Bases: Enum

Health classification for spacecraft actuators.

DEGRADED = 'DEGRADED'
FAILED = 'FAILED'
HEALTHY = 'HEALTHY'
class opengnc.fdir.actuator_fdir.UnderactuatedAttitudeController(actuated_axes: tuple[int, int] = (0, 1), kp: float = 0.5, kd: float = 2.0, km: float = 1000.0)[source]

Bases: object

Underactuated Spacecraft Attitude Controller (2-Reaction-Wheel Recovery).

When one or two reaction wheels fail, leaving only 2 functional reaction wheels, full 3-axis instantaneous controllability via wheels alone is lost. This controller stabilizes the two actuated body axes using high-gain PD control and uses auxiliary magnetic torquers (or cross-coupling precession) to asymptotically damp momentum along the unactuated body axis.

Parameters:
  • actuated_axes (tuple[int, int]) – Indices of the two functional body axes (e.g. (0, 1) for X and Y).

  • kp (float, optional) – Proportional attitude error gain. Default is 0.5.

  • kd (float, optional) – Derivative angular rate damping gain. Default is 2.0.

  • km (float, optional) – Magnetic dipole cross-product gain for unactuated axis. Default is 1000.0.

compute_control(q_err: ndarray, w_err: ndarray, b_field_body: ndarray | None = None) → tuple[ndarray, ndarray][source]

Compute control torques for the 2 functional wheels and auxiliary magnetic dipole.

Parameters:
  • q_err (np.ndarray) – Attitude quaternion error vector $[q_1, q_2, q_3, q_4]^T$ (vector part first 3).

  • w_err (np.ndarray) – Body angular velocity error $[w_x, w_y, w_z]^T$ (rad/s).

  • b_field_body (np.ndarray, optional) – Local geomagnetic field vector in body frame (Tesla).

Returns:

(tau_wheels, magnetic_dipole) - tau_wheels: 3-element torque vector with zero along the unactuated axis. - magnetic_dipole: 3-element commanded magnetic dipole moment $mathbf{m}$ ($A cdot m^2$).

Return type:

tuple[np.ndarray, np.ndarray]

class opengnc.fdir.actuator_fdir.WeightedControlAllocator(b_matrix: ndarray, u_min: ndarray | float = -0.1, u_max: ndarray | float = 0.1)[source]

Bases: object

Dynamic Weighted Control Allocator (WQP / Weighted Pseudo-Inverse).

Maps commanded 3-axis control torque $boldsymbol{tau}_c in mathbb{R}^3$ to actuator commands $mathbf{u} in mathbb{R}^n$ via: $$min_{mathbf{u}} frac{1}{2} mathbf{u}^T mathbf{W}_u mathbf{u} quad text{s.t.} quad mathbf{B} mathbf{u} = boldsymbol{tau}_c$$ subject to $mathbf{u}_{min} le mathbf{u} le mathbf{u}_{max}$.

When an actuator fails, its weight $W_{u, ii}$ is scaled to $infty$ (or its column in $mathbf{B}$ is masked to zero), redistributing torque instantly to remaining functional actuators without perturbing the attitude loop.

Parameters:
  • b_matrix (np.ndarray) – Actuator geometry/effectiveness matrix $mathbf{B} in mathbb{R}^{3 times n}$.

  • u_min (np.ndarray | float, optional) – Minimum torque limit per actuator (N*m). Default is -0.1 N*m.

  • u_max (np.ndarray | float, optional) – Maximum torque limit per actuator (N*m). Default is +0.1 N*m.

allocate(tau_cmd: ndarray) → ndarray[source]

Allocate commanded 3-axis torque to individual actuators.

Parameters:

tau_cmd (np.ndarray) – Commanded torque vector $boldsymbol{tau}_c in mathbb{R}^3$ (N*m).

Returns:

Actuator torque vector $mathbf{u} in mathbb{R}^n$ (N*m).

Return type:

np.ndarray

set_actuator_health(index: int, health: ActuatorHealth) → None[source]

Update weighting and active masking based on actuator health.

Parameters:
  • index (int) – Actuator channel index ($0 le i < n$).

  • health (ActuatorHealth) – Health state from FDI monitor.

u_max: ndarray
u_min: ndarray

opengnc.fdir.executive module

Autonomous FDIR Executive and GNC Mission Health State Machine.

Coordinates sensor fault isolation, actuator control reconfiguration, and autonomous transitions between Nominal, Degraded, Underactuated, and Safe Modes.

class opengnc.fdir.executive.FDIRExecutive(initial_mode: FDIRMode = FDIRMode.NOMINAL, max_rate_runaway: float = 0.1, max_pointing_error_deg: float = 45.0)[source]

Bases: object

Finite State Machine governing autonomous Spacecraft FDIR transitions.

Evaluates collective sensor health, actuator integrity, and dynamic pointing metrics to deterministically transition between operational modes: - NOMINAL: Full sensor fusion and nominal 3-axis control. - DEGRADED_POINTING: Maintained 3-axis pointing with isolated sensor/actuator. - UNDERACTUATED_CONTROL: 2-RW stabilization with auxiliary magnetic damping. - SAFE_MODE_SUN_POINTING: Power preservation & tumbling damping fallback.

Parameters:
  • initial_mode (FDIRMode, optional) – Starting mode for the executive. Default is FDIRMode.NOMINAL.

  • max_rate_runaway (float, optional) – Maximum allowable angular velocity (rad/s) before forcing Safe Mode. Default is 0.1 rad/s (~5.7 deg/s).

  • max_pointing_error_deg (float, optional) – Maximum allowable pointing error (deg) before flagging attitude loss. Default is 45.0 degrees.

evaluate_state(time_s: float, sensor_health: dict[str, SensorHealth], actuator_health: dict[str, ActuatorHealth], pointing_error_deg: float = 0.0, rate_norm: float = 0.0) → FDIRMode[source]

Evaluate system health telemetry and perform mode transitions.

Parameters:
  • time_s (float) – Simulation/mission elapsed time (s).

  • sensor_health (dict[str, SensorHealth]) – Dictionary of sensor states {sensor_name: SensorHealth}.

  • actuator_health (dict[str, ActuatorHealth]) – Dictionary of actuator states {actuator_name: ActuatorHealth}.

  • pointing_error_deg (float, optional) – Current pointing error in degrees. Default is 0.0.

  • rate_norm (float, optional) – Current angular rate magnitude ||omega|| in rad/s. Default is 0.0.

Returns:

Current active FDIR operational mode.

Return type:

FDIRMode

force_safe_mode(time_s: float, reason: str = 'Manual override') → None[source]

Manually force executive into Safe Mode.

get_telemetry() → dict[str, Any][source]

Generate diagnostic telemetry summary of FDIR status.

Returns:

Dictionary containing current mode, transition history, and log.

Return type:

dict[str, Any]

reset_to_nominal(time_s: float) → None[source]

Reset executive back to Nominal Mode after recovery.

class opengnc.fdir.executive.FDIRMode(value)[source]

Bases: Enum

Spacecraft GNC operational modes governed by FDIR.

DEGRADED_POINTING = 'DEGRADED_POINTING'
NOMINAL = 'NOMINAL'
SAFE_MODE_SUN_POINTING = 'SAFE_MODE_SUN_POINTING'
UNDERACTUATED_CONTROL = 'UNDERACTUATED_CONTROL'

opengnc.fdir.sensor_fdir module

Sensor Fault Detection, Isolation, and Characterization (FDIC) for spacecraft GNC.

Implements innovation-based Chi-Square statistical monitors, Generalized Likelihood Ratio Test (GLRT) / CUSUM drift detectors, and analytical redundancy cross-sensor isolation managers.

class opengnc.fdir.sensor_fdir.ChiSquareMonitor(dim: int, confidence: float = 0.99, window_size: int = 5, persistence_threshold: int = 3)[source]

Bases: object

Statistical Innovation Chi-Square ($chi^2$) Fault Monitor.

Evaluates the Normalized Innovation Squared (NIS): $$gamma_k = mathbf{r}_k^T mathbf{S}_k^{-1} mathbf{r}_k$$ Under the null hypothesis $H_0$ (nominal sensor operation), $gamma_k$ follows a central chi-square distribution with $m$ degrees of freedom, where $m = dim(mathbf{r}_k)$.

Parameters:
  • dim (int) – Dimension of the measurement residual vector ($m$).

  • confidence (float, optional) – Confidence level for the statistical hypothesis test (e.g., 0.99 for 1% $P_{FA}$). Default is 0.99.

  • window_size (int, optional) – Sliding window size for cumulative hypothesis testing. Default is 5.

  • persistence_threshold (int, optional) – Consecutive violations required before triggering a persistent alarm. Default is 3.

reset() → None[source]

Reset internal history and violation counters.

update(residual: ndarray, innovation_cov: ndarray) → tuple[bool, float, float][source]

Update monitor with new innovation residual and covariance.

Parameters:
  • residual (np.ndarray) – Measurement innovation residual $mathbf{r}_k = mathbf{z}_k - hat{mathbf{z}}_k$.

  • innovation_cov (np.ndarray) – Innovation covariance matrix $mathbf{S}_k = mathbf{H}_k mathbf{P}_k^- mathbf{H}_k^T + mathbf{R}_k$.

Returns:

(is_fault, current_stat, threshold_used) - is_fault: True if fault condition detected. - current_stat: Computed statistical test metric ($gamma_k$ or window sum). - threshold_used: Threshold corresponding to the test.

Return type:

tuple[bool, float, float]

class opengnc.fdir.sensor_fdir.GLRTMonitor(dim: int, drift_allowance: float = 0.5, alarm_threshold: float = 5.0, nominal_mean: float = 0.0)[source]

Bases: object

Generalized Likelihood Ratio Test (GLRT) / Page’s CUSUM Drift Monitor.

Detects insidious, low-amplitude sensor drift, temperature ramps, or slow random walks that stay below instantaneous $chi^2$ single-step thresholds.

Evaluates two-sided Cumulative Sum (CUSUM) statistics per channel: $$S_k^+ = max(0, S_{k-1}^+ + r_k - mu_0 - K)$$ $$S_k^- = max(0, S_{k-1}^- - r_k + mu_0 - K)$$

Parameters:
  • dim (int) – Dimension of the monitored signal.

  • drift_allowance (float, optional) – Allowance constant $K$ (slack parameter). Default is 0.5.

  • alarm_threshold (float, optional) – Decision threshold $H$. Default is 5.0.

  • nominal_mean (float, optional) – Expected nominal mean $mu_0$ under $H_0$. Default is 0.0.

reset() → None[source]

Reset cumulative sum registers.

update(residual: ndarray | float) → tuple[bool, ndarray][source]

Update CUSUM statistics with a new measurement residual.

Parameters:

residual (np.ndarray | float) – Measurement residual or scalar.

Returns:

(is_fault, max_cusum_stat) - is_fault: True if any channel exceeds the decision threshold $H$. - max_cusum_stat: Maximum cumulative statistic across positive/negative detectors.

Return type:

tuple[bool, np.ndarray]

class opengnc.fdir.sensor_fdir.SensorHealth(value)[source]

Bases: Enum

Health classification for spacecraft sensors.

DEGRADED = 'DEGRADED'
HEALTHY = 'HEALTHY'
ISOLATED = 'ISOLATED'
class opengnc.fdir.sensor_fdir.SensorIsolationManager(sensor_names: list[str], max_consecutive_faults: int = 5, covariance_inflation_factor: float = 10.0)[source]

Bases: object

Analytical Redundancy and Cross-Sensor Isolation Manager.

Coordinates health tracking across redundant sensors, performs pairwise consistency voting to identify out-of-family sensors, and provides dynamic measurement covariance inflation ($R_{eff} = s cdot R$) to prevent filter divergence before hard isolation.

Parameters:
  • sensor_names (list[str]) – List of unique sensor identifiers.

  • max_consecutive_faults (int, optional) – Consecutive faults before a sensor is isolated. Default is 5.

  • covariance_inflation_factor (float, optional) – Scaling factor $s$ applied to degraded sensor covariance. Default is 10.0.

cross_consistency_vote(measurements: dict[str, ndarray], angular_tol_deg: float = 2.0) → list[str][source]

Perform 2-out-of-N cross-consistency voting among vector sensors.

Identifies sensors whose output diverges significantly from the consensus.

Parameters:
  • measurements (dict[str, np.ndarray]) – Dictionary of unit vector measurements {sensor_name: unit_vector}.

  • angular_tol_deg (float, optional) – Maximum allowable angular divergence in degrees. Default is 2.0.

Returns:

List of suspect sensor names that failed consensus voting.

Return type:

list[str]

fault_counters: dict[str, int]
get_effective_covariance(sensor_name: str, base_cov: ndarray) → ndarray[source]

Calculate effective covariance matrix $R_{eff}$ for the sensor.

For healthy sensors, returns $R$. For degraded sensors, returns $s cdot R$. For isolated sensors, returns $infty cdot I$.

Parameters:
  • sensor_name (str) – Identifier of the sensor.

  • base_cov (np.ndarray) – Nominal measurement covariance matrix $R$.

Returns:

Adjusted effective covariance matrix.

Return type:

np.ndarray

isolate_sensor(sensor_name: str) → None[source]

Manually force a sensor into the ISOLATED state.

report_status(sensor_name: str, has_fault: bool) → SensorHealth[source]

Report detection result for a given sensor and update health state.

Parameters:
  • sensor_name (str) – Identifier of the reporting sensor.

  • has_fault (bool) – True if FDI monitor detected an anomaly on this sensor.

Returns:

Updated health status of the sensor.

Return type:

SensorHealth

reset_sensor(sensor_name: str) → None[source]

Manually restore a sensor to HEALTHY state.

sensors: dict[str, SensorHealth]

Module contents

OpenGNC Fault Detection, Isolation, and Recovery (FDIR) Subsystem.

Provides autonomous sensor fault detection, statistical innovation testing, actuator fault-tolerant control reallocation, underactuated attitude stabilization, and mission-level operational health management.

class opengnc.fdir.ActuatorFaultDetector(max_wheel_speed: float = 600.0, torque_tolerance: float = 0.02, persistence_steps: int = 5)[source]

Bases: object

Monitors reaction wheel and thruster health states.

Detects motor lockup, friction torque spikes, tachometer runaway, and command-to-telemetry tracking error.

Parameters:
  • max_wheel_speed (float, optional) – Maximum allowable reaction wheel speed (rad/s). Default is 600.0 (~5700 RPM).

  • torque_tolerance (float, optional) – Allowable torque discrepancy between command and telemetry (N*m). Default is 0.02.

  • persistence_steps (int, optional) – Number of consecutive timesteps with violation before marking FAILED. Default is 5.

actuator_status: dict[str, ActuatorHealth]
check_wheel(name: str, cmd_torque: float, actual_torque: float, current_speed: float) → ActuatorHealth[source]

Evaluate wheel telemetry against health thresholds.

Parameters:
  • name (str) – Actuator identifier.

  • cmd_torque (float) – Commanded torque (N*m).

  • actual_torque (float) – Measured/estimated torque output (N*m).

  • current_speed (float) – Current wheel spin rate (rad/s).

Returns:

Updated health status.

Return type:

ActuatorHealth

register_actuator(name: str) → None[source]

Register a new actuator to monitor.

set_failed(name: str) → None[source]

Manually mark an actuator as FAILED.

violation_counts: dict[str, int]
class opengnc.fdir.ActuatorHealth(value)[source]

Bases: Enum

Health classification for spacecraft actuators.

DEGRADED = 'DEGRADED'
FAILED = 'FAILED'
HEALTHY = 'HEALTHY'
class opengnc.fdir.ChiSquareMonitor(dim: int, confidence: float = 0.99, window_size: int = 5, persistence_threshold: int = 3)[source]

Bases: object

Statistical Innovation Chi-Square ($chi^2$) Fault Monitor.

Evaluates the Normalized Innovation Squared (NIS): $$gamma_k = mathbf{r}_k^T mathbf{S}_k^{-1} mathbf{r}_k$$ Under the null hypothesis $H_0$ (nominal sensor operation), $gamma_k$ follows a central chi-square distribution with $m$ degrees of freedom, where $m = dim(mathbf{r}_k)$.

Parameters:
  • dim (int) – Dimension of the measurement residual vector ($m$).

  • confidence (float, optional) – Confidence level for the statistical hypothesis test (e.g., 0.99 for 1% $P_{FA}$). Default is 0.99.

  • window_size (int, optional) – Sliding window size for cumulative hypothesis testing. Default is 5.

  • persistence_threshold (int, optional) – Consecutive violations required before triggering a persistent alarm. Default is 3.

consecutive_violations: int
history: deque[float]
reset() → None[source]

Reset internal history and violation counters.

update(residual: ndarray, innovation_cov: ndarray) → tuple[bool, float, float][source]

Update monitor with new innovation residual and covariance.

Parameters:
  • residual (np.ndarray) – Measurement innovation residual $mathbf{r}_k = mathbf{z}_k - hat{mathbf{z}}_k$.

  • innovation_cov (np.ndarray) – Innovation covariance matrix $mathbf{S}_k = mathbf{H}_k mathbf{P}_k^- mathbf{H}_k^T + mathbf{R}_k$.

Returns:

(is_fault, current_stat, threshold_used) - is_fault: True if fault condition detected. - current_stat: Computed statistical test metric ($gamma_k$ or window sum). - threshold_used: Threshold corresponding to the test.

Return type:

tuple[bool, float, float]

class opengnc.fdir.FDIRExecutive(initial_mode: FDIRMode = FDIRMode.NOMINAL, max_rate_runaway: float = 0.1, max_pointing_error_deg: float = 45.0)[source]

Bases: object

Finite State Machine governing autonomous Spacecraft FDIR transitions.

Evaluates collective sensor health, actuator integrity, and dynamic pointing metrics to deterministically transition between operational modes: - NOMINAL: Full sensor fusion and nominal 3-axis control. - DEGRADED_POINTING: Maintained 3-axis pointing with isolated sensor/actuator. - UNDERACTUATED_CONTROL: 2-RW stabilization with auxiliary magnetic damping. - SAFE_MODE_SUN_POINTING: Power preservation & tumbling damping fallback.

Parameters:
  • initial_mode (FDIRMode, optional) – Starting mode for the executive. Default is FDIRMode.NOMINAL.

  • max_rate_runaway (float, optional) – Maximum allowable angular velocity (rad/s) before forcing Safe Mode. Default is 0.1 rad/s (~5.7 deg/s).

  • max_pointing_error_deg (float, optional) – Maximum allowable pointing error (deg) before flagging attitude loss. Default is 45.0 degrees.

current_mode: FDIRMode
evaluate_state(time_s: float, sensor_health: dict[str, SensorHealth], actuator_health: dict[str, ActuatorHealth], pointing_error_deg: float = 0.0, rate_norm: float = 0.0) → FDIRMode[source]

Evaluate system health telemetry and perform mode transitions.

Parameters:
  • time_s (float) – Simulation/mission elapsed time (s).

  • sensor_health (dict[str, SensorHealth]) – Dictionary of sensor states {sensor_name: SensorHealth}.

  • actuator_health (dict[str, ActuatorHealth]) – Dictionary of actuator states {actuator_name: ActuatorHealth}.

  • pointing_error_deg (float, optional) – Current pointing error in degrees. Default is 0.0.

  • rate_norm (float, optional) – Current angular rate magnitude ||omega|| in rad/s. Default is 0.0.

Returns:

Current active FDIR operational mode.

Return type:

FDIRMode

force_safe_mode(time_s: float, reason: str = 'Manual override') → None[source]

Manually force executive into Safe Mode.

get_telemetry() → dict[str, Any][source]

Generate diagnostic telemetry summary of FDIR status.

Returns:

Dictionary containing current mode, transition history, and log.

Return type:

dict[str, Any]

mode_history: list[tuple[float, FDIRMode, str]]
reset_to_nominal(time_s: float) → None[source]

Reset executive back to Nominal Mode after recovery.

transition_log: list[str]
class opengnc.fdir.FDIRMode(value)[source]

Bases: Enum

Spacecraft GNC operational modes governed by FDIR.

DEGRADED_POINTING = 'DEGRADED_POINTING'
NOMINAL = 'NOMINAL'
SAFE_MODE_SUN_POINTING = 'SAFE_MODE_SUN_POINTING'
UNDERACTUATED_CONTROL = 'UNDERACTUATED_CONTROL'
class opengnc.fdir.GLRTMonitor(dim: int, drift_allowance: float = 0.5, alarm_threshold: float = 5.0, nominal_mean: float = 0.0)[source]

Bases: object

Generalized Likelihood Ratio Test (GLRT) / Page’s CUSUM Drift Monitor.

Detects insidious, low-amplitude sensor drift, temperature ramps, or slow random walks that stay below instantaneous $chi^2$ single-step thresholds.

Evaluates two-sided Cumulative Sum (CUSUM) statistics per channel: $$S_k^+ = max(0, S_{k-1}^+ + r_k - mu_0 - K)$$ $$S_k^- = max(0, S_{k-1}^- - r_k + mu_0 - K)$$

Parameters:
  • dim (int) – Dimension of the monitored signal.

  • drift_allowance (float, optional) – Allowance constant $K$ (slack parameter). Default is 0.5.

  • alarm_threshold (float, optional) – Decision threshold $H$. Default is 5.0.

  • nominal_mean (float, optional) – Expected nominal mean $mu_0$ under $H_0$. Default is 0.0.

reset() → None[source]

Reset cumulative sum registers.

s_neg: ndarray
s_pos: ndarray
update(residual: ndarray | float) → tuple[bool, ndarray][source]

Update CUSUM statistics with a new measurement residual.

Parameters:

residual (np.ndarray | float) – Measurement residual or scalar.

Returns:

(is_fault, max_cusum_stat) - is_fault: True if any channel exceeds the decision threshold $H$. - max_cusum_stat: Maximum cumulative statistic across positive/negative detectors.

Return type:

tuple[bool, np.ndarray]

class opengnc.fdir.SensorHealth(value)[source]

Bases: Enum

Health classification for spacecraft sensors.

DEGRADED = 'DEGRADED'
HEALTHY = 'HEALTHY'
ISOLATED = 'ISOLATED'
class opengnc.fdir.SensorIsolationManager(sensor_names: list[str], max_consecutive_faults: int = 5, covariance_inflation_factor: float = 10.0)[source]

Bases: object

Analytical Redundancy and Cross-Sensor Isolation Manager.

Coordinates health tracking across redundant sensors, performs pairwise consistency voting to identify out-of-family sensors, and provides dynamic measurement covariance inflation ($R_{eff} = s cdot R$) to prevent filter divergence before hard isolation.

Parameters:
  • sensor_names (list[str]) – List of unique sensor identifiers.

  • max_consecutive_faults (int, optional) – Consecutive faults before a sensor is isolated. Default is 5.

  • covariance_inflation_factor (float, optional) – Scaling factor $s$ applied to degraded sensor covariance. Default is 10.0.

cross_consistency_vote(measurements: dict[str, ndarray], angular_tol_deg: float = 2.0) → list[str][source]

Perform 2-out-of-N cross-consistency voting among vector sensors.

Identifies sensors whose output diverges significantly from the consensus.

Parameters:
  • measurements (dict[str, np.ndarray]) – Dictionary of unit vector measurements {sensor_name: unit_vector}.

  • angular_tol_deg (float, optional) – Maximum allowable angular divergence in degrees. Default is 2.0.

Returns:

List of suspect sensor names that failed consensus voting.

Return type:

list[str]

fault_counters: dict[str, int]
get_effective_covariance(sensor_name: str, base_cov: ndarray) → ndarray[source]

Calculate effective covariance matrix $R_{eff}$ for the sensor.

For healthy sensors, returns $R$. For degraded sensors, returns $s cdot R$. For isolated sensors, returns $infty cdot I$.

Parameters:
  • sensor_name (str) – Identifier of the sensor.

  • base_cov (np.ndarray) – Nominal measurement covariance matrix $R$.

Returns:

Adjusted effective covariance matrix.

Return type:

np.ndarray

isolate_sensor(sensor_name: str) → None[source]

Manually force a sensor into the ISOLATED state.

report_status(sensor_name: str, has_fault: bool) → SensorHealth[source]

Report detection result for a given sensor and update health state.

Parameters:
  • sensor_name (str) – Identifier of the reporting sensor.

  • has_fault (bool) – True if FDI monitor detected an anomaly on this sensor.

Returns:

Updated health status of the sensor.

Return type:

SensorHealth

reset_sensor(sensor_name: str) → None[source]

Manually restore a sensor to HEALTHY state.

sensors: dict[str, SensorHealth]
class opengnc.fdir.UnderactuatedAttitudeController(actuated_axes: tuple[int, int] = (0, 1), kp: float = 0.5, kd: float = 2.0, km: float = 1000.0)[source]

Bases: object

Underactuated Spacecraft Attitude Controller (2-Reaction-Wheel Recovery).

When one or two reaction wheels fail, leaving only 2 functional reaction wheels, full 3-axis instantaneous controllability via wheels alone is lost. This controller stabilizes the two actuated body axes using high-gain PD control and uses auxiliary magnetic torquers (or cross-coupling precession) to asymptotically damp momentum along the unactuated body axis.

Parameters:
  • actuated_axes (tuple[int, int]) – Indices of the two functional body axes (e.g. (0, 1) for X and Y).

  • kp (float, optional) – Proportional attitude error gain. Default is 0.5.

  • kd (float, optional) – Derivative angular rate damping gain. Default is 2.0.

  • km (float, optional) – Magnetic dipole cross-product gain for unactuated axis. Default is 1000.0.

compute_control(q_err: ndarray, w_err: ndarray, b_field_body: ndarray | None = None) → tuple[ndarray, ndarray][source]

Compute control torques for the 2 functional wheels and auxiliary magnetic dipole.

Parameters:
  • q_err (np.ndarray) – Attitude quaternion error vector $[q_1, q_2, q_3, q_4]^T$ (vector part first 3).

  • w_err (np.ndarray) – Body angular velocity error $[w_x, w_y, w_z]^T$ (rad/s).

  • b_field_body (np.ndarray, optional) – Local geomagnetic field vector in body frame (Tesla).

Returns:

(tau_wheels, magnetic_dipole) - tau_wheels: 3-element torque vector with zero along the unactuated axis. - magnetic_dipole: 3-element commanded magnetic dipole moment $mathbf{m}$ ($A cdot m^2$).

Return type:

tuple[np.ndarray, np.ndarray]

class opengnc.fdir.WeightedControlAllocator(b_matrix: ndarray, u_min: ndarray | float = -0.1, u_max: ndarray | float = 0.1)[source]

Bases: object

Dynamic Weighted Control Allocator (WQP / Weighted Pseudo-Inverse).

Maps commanded 3-axis control torque $boldsymbol{tau}_c in mathbb{R}^3$ to actuator commands $mathbf{u} in mathbb{R}^n$ via: $$min_{mathbf{u}} frac{1}{2} mathbf{u}^T mathbf{W}_u mathbf{u} quad text{s.t.} quad mathbf{B} mathbf{u} = boldsymbol{tau}_c$$ subject to $mathbf{u}_{min} le mathbf{u} le mathbf{u}_{max}$.

When an actuator fails, its weight $W_{u, ii}$ is scaled to $infty$ (or its column in $mathbf{B}$ is masked to zero), redistributing torque instantly to remaining functional actuators without perturbing the attitude loop.

Parameters:
  • b_matrix (np.ndarray) – Actuator geometry/effectiveness matrix $mathbf{B} in mathbb{R}^{3 times n}$.

  • u_min (np.ndarray | float, optional) – Minimum torque limit per actuator (N*m). Default is -0.1 N*m.

  • u_max (np.ndarray | float, optional) – Maximum torque limit per actuator (N*m). Default is +0.1 N*m.

allocate(tau_cmd: ndarray) → ndarray[source]

Allocate commanded 3-axis torque to individual actuators.

Parameters:

tau_cmd (np.ndarray) – Commanded torque vector $boldsymbol{tau}_c in mathbb{R}^3$ (N*m).

Returns:

Actuator torque vector $mathbf{u} in mathbb{R}^n$ (N*m).

Return type:

np.ndarray

set_actuator_health(index: int, health: ActuatorHealth) → None[source]

Update weighting and active masking based on actuator health.

Parameters:
  • index (int) – Actuator channel index ($0 le i < n$).

  • health (ActuatorHealth) – Health state from FDI monitor.

u_max: ndarray
u_min: ndarray