feat(simulation): add per-IMU fault injection to SIH

Adds two runtime parameters for injecting accelerometer faults on a
specific simulated IMU:

- SIH_FAULT_IMU: selects which IMU (1 or 2) receives faults, 0 = off
- SIH_FAULT_VIBE: amplitude of Z-axis vibration noise in m/s^2

Values above ~155 m/s^2 trigger the PX4Accelerometer clip detection,
which propagates through vehicle_imu -> EKF2 as bad_acc_clipping
filter_fault_flags. This enables SITL reproduction of EKF2 selector
bugs where one IMU's clipping faults cause instance switching against
a diverged estimator (e.g. #27013).

Params can be set via PX4_PARAM_SIH_FAULT_IMU=2
PX4_PARAM_SIH_FAULT_VIBE=200 env vars or changed at runtime.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
This commit is contained in:
Ramon Roche
2026-04-12 16:25:29 -07:00
parent 23abfe3a46
commit 20802d509a
3 changed files with 40 additions and 2 deletions
+11 -1
View File
@@ -639,6 +639,10 @@ void Sih::reconstruct_sensors_signals(const hrt_abstime &time_now_us)
const Vector3f specific_force_B = R_E2B * _specific_force_E;
const Vector3f earth_spin_rate_B = R_E2B * Vector3f(0.f, 0.f, CONSTANTS_EARTH_SPIN_RATE);
// Fault injection: which IMU index (0-based), -1 means none
const int fault_imu = _sih_fault_imu.get() - 1; // param is 1-indexed, -1 means off
const float fault_vibe = _sih_fault_vibe.get();
// Publish to all simulated IMUs with independent noise
for (uint8_t i = 0; i < IMU_COUNT; i++) {
Vector3f accel_noise;
@@ -653,7 +657,13 @@ void Sih::reconstruct_sensors_signals(const hrt_abstime &time_now_us)
gyro_noise = noiseGauss3f(0.01f, 0.01f, 0.01f);
}
const Vector3f accel = specific_force_B + accel_noise;
Vector3f accel = specific_force_B + accel_noise;
// Inject high-amplitude Z-axis vibration on the selected IMU
if ((int)i == fault_imu && fault_vibe > FLT_EPSILON) {
accel(2) += fault_vibe * generate_wgn();
}
const Vector3f gyro = _w_B + earth_spin_rate_B + gyro_noise;
_px4_accel[i].update(time_now_us, accel(0), accel(1), accel(2));
+4 -1
View File
@@ -353,6 +353,9 @@ private:
(ParamInt<px4::params::SIH_VEHICLE_TYPE>) _sih_vtype,
(ParamFloat<px4::params::SIH_WIND_N>) _sih_wind_n,
(ParamFloat<px4::params::SIH_WIND_E>) _sih_wind_e,
(ParamFloat<px4::params::SIH_RNGBC_NOISE>) _sih_ranging_beacon_noise
(ParamFloat<px4::params::SIH_RNGBC_NOISE>) _sih_ranging_beacon_noise,
// fault injection
(ParamInt<px4::params::SIH_FAULT_IMU>) _sih_fault_imu,
(ParamFloat<px4::params::SIH_FAULT_VIBE>) _sih_fault_vibe
)
};
@@ -369,3 +369,28 @@ parameters:
default: 6000.0
min: 0.1
decimal: 1
SIH_FAULT_IMU:
description:
short: IMU index for fault injection
long: |-
Selects which simulated IMU receives injected faults.
0 disables fault injection. 1 selects IMU 0, 2 selects IMU 1.
Can be changed at runtime to start/stop faults mid-flight.
type: int32
default: 0
min: 0
max: 2
SIH_FAULT_VIBE:
description:
short: Accel vibration amplitude for fault injection
long: |-
Adds random high-amplitude noise to the Z-axis of the selected IMU.
Values above ~155 m/s^2 will trigger accelerometer clipping detection,
which in turn triggers the EKF bad_acc_clipping fault flag.
Set to 0 to disable vibration injection even when SIH_FAULT_IMU is set.
type: float
default: 0.0
unit: m/s^2
min: 0.0
max: 500.0
decimal: 1