Skip to content

Commit e59afce

Browse files
committed
Enable directly injecting motor failures using e.g. failure motor off -i 1
Only if SYS_FAILURE_EN is enabled and CA_FAILURE_MODE is > 0.
1 parent 786e0a1 commit e59afce

8 files changed

Lines changed: 44 additions & 4 deletions

File tree

msg/ControlAllocatorStatus.msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ int8[16] actuator_saturation # Indicates actuator saturation status.
1919
# Note 2: an actuator with limited dynamics can be indicated as upper-saturated even if it as not reached its maximum value.
2020

2121
uint16 handled_motor_failure_mask # Bitmask of failed motors that were removed from the allocation / effectiveness matrix. Not necessarily identical to the report from FailureDetector
22+
uint16 motor_stop_mask # Bitmaks of motors stopped by failure injection

msg/FailureDetectorStatus.msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ bool fd_motor
1212

1313
float32 imbalanced_prop_metric # Metric of the imbalanced propeller check (low-passed)
1414
uint16 motor_failure_mask # Bit-mask with motor indices, indicating critical motor failures
15+
uint16 motor_stop_mask # Bitmaks of motors stopped by failure injection

src/modules/commander/Commander.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,7 @@ void Commander::run()
19561956
fd_status.fd_motor = _failure_detector.getStatusFlags().motor;
19571957
fd_status.imbalanced_prop_metric = _failure_detector.getImbalancedPropMetric();
19581958
fd_status.motor_failure_mask = _failure_detector.getMotorFailures();
1959+
fd_status.motor_stop_mask = _failure_detector.getMotorStopMask();
19591960
fd_status.timestamp = hrt_absolute_time();
19601961
_failure_detector_status_pub.publish(fd_status);
19611962
}

src/modules/commander/failure_detector/FailureDetector.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class FailureDetector : public ModuleParams
8989
const decltype(failure_detector_status_u::flags) &getStatusFlags() const { return _status.flags; }
9090
float getImbalancedPropMetric() const { return _imbalanced_prop_lpf.getState(); }
9191
uint16_t getMotorFailures() const { return _motor_failure_esc_timed_out_mask | _motor_failure_esc_under_current_mask; }
92+
uint16_t getMotorStopMask() { return _failure_injector.getMotorStopMask(); }
9293

9394
private:
9495
void updateAttitudeStatus(const vehicle_status_s &vehicle_status);

src/modules/commander/failure_detector/FailureInjector.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,23 @@
3333

3434
#include "FailureInjector.hpp"
3535

36+
#include <parameters/param.h>
3637
#include <uORB/topics/actuator_motors.h>
3738

39+
FailureInjector::FailureInjector()
40+
{
41+
int32_t param_sys_failure_en = 0;
42+
43+
if ((param_get(param_find("SYS_FAILURE_EN"), &param_sys_failure_en) == PX4_OK)
44+
&& (param_sys_failure_en == 1)) {
45+
_failure_injection_enabled = true;
46+
}
47+
}
48+
3849
void FailureInjector::update()
3950
{
51+
if (!_failure_injection_enabled) { return; }
52+
4053
vehicle_command_s vehicle_command;
4154

4255
while (_vehicle_command_sub.update(&vehicle_command)) {
@@ -59,14 +72,21 @@ void FailureInjector::update()
5972
switch (failure_type) {
6073
case vehicle_command_s::FAILURE_TYPE_OK:
6174
supported = true;
62-
PX4_INFO("CMD_INJECT_FAILURE, motor %d ok", i);
75+
PX4_INFO("CMD_INJECT_FAILURE, motor %d ok", i + 1);
76+
_motor_stop_mask &= ~(1 << i);
6377
_esc_telemetry_blocked_mask &= ~(1 << i);
6478
_esc_telemetry_wrong_mask &= ~(1 << i);
6579
break;
6680

6781
case vehicle_command_s::FAILURE_TYPE_OFF:
6882
supported = true;
69-
PX4_INFO("CMD_INJECT_FAILURE, motor %d no esc telemetry", i);
83+
PX4_INFO("CMD_INJECT_FAILURE, motor %d off", i + 1);
84+
_motor_stop_mask |= 1 << i;
85+
break;
86+
87+
case vehicle_command_s::FAILURE_TYPE_STUCK:
88+
supported = true;
89+
PX4_INFO("CMD_INJECT_FAILURE, motor %d no esc telemetry", i + 1);
7090
_esc_telemetry_blocked_mask |= 1 << i;
7191
break;
7292

@@ -91,6 +111,8 @@ void FailureInjector::update()
91111

92112
void FailureInjector::manipulateEscStatus(esc_status_s &status)
93113
{
114+
if (!_failure_injection_enabled) { return; }
115+
94116
if (_esc_telemetry_blocked_mask != 0 || _esc_telemetry_wrong_mask != 0) {
95117
for (int i = 0; i < status.esc_count; i++) {
96118
const unsigned i_esc = status.esc[i].actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1;

src/modules/commander/failure_detector/FailureInjector.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,18 @@
4242
class FailureInjector
4343
{
4444
public:
45+
FailureInjector();
46+
4547
void update();
4648

4749
void manipulateEscStatus(esc_status_s &status);
50+
uint32_t getMotorStopMask() { return _motor_stop_mask; }
4851
private:
4952
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
5053
uORB::Publication<vehicle_command_ack_s> _command_ack_pub{ORB_ID(vehicle_command_ack)};
5154

55+
bool _failure_injection_enabled = false;
56+
uint32_t _motor_stop_mask{};
5257
uint32_t _esc_telemetry_blocked_mask{};
5358
uint32_t _esc_telemetry_wrong_mask{};
5459
};

src/modules/control_allocator/ControlAllocator.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ ControlAllocator::publish_control_allocator_status(int matrix_index)
641641

642642
// Handled motor failures
643643
control_allocator_status.handled_motor_failure_mask = _handled_motor_failure_bitmask;
644+
control_allocator_status.motor_stop_mask = _motor_stop_mask;
644645

645646
_control_allocator_status_pub[matrix_index].publish(control_allocator_status);
646647
}
@@ -665,7 +666,9 @@ ControlAllocator::publish_actuator_controls()
665666
int actuator_idx = 0;
666667
int actuator_idx_matrix[ActuatorEffectiveness::MAX_NUM_MATRICES] {};
667668

668-
uint32_t stopped_motors = _actuator_effectiveness->getStoppedMotors() | _handled_motor_failure_bitmask;
669+
uint32_t stopped_motors = _actuator_effectiveness->getStoppedMotors()
670+
| _handled_motor_failure_bitmask
671+
| _motor_stop_mask;
669672

670673
// motors
671674
int motors_idx;
@@ -716,8 +719,13 @@ ControlAllocator::check_for_motor_failures()
716719

717720
if ((FailureMode)_param_ca_failure_mode.get() > FailureMode::IGNORE
718721
&& _failure_detector_status_sub.update(&failure_detector_status)) {
719-
if (failure_detector_status.fd_motor) {
720722

723+
if (_motor_stop_mask != failure_detector_status.motor_stop_mask) {
724+
_motor_stop_mask = failure_detector_status.motor_stop_mask;
725+
PX4_WARN("Stopping motors (%d)", _motor_stop_mask);
726+
}
727+
728+
if (failure_detector_status.fd_motor) {
721729
if (_handled_motor_failure_bitmask != failure_detector_status.motor_failure_mask) {
722730
// motor failure bitmask changed
723731
switch ((FailureMode)_param_ca_failure_mode.get()) {

src/modules/control_allocator/ControlAllocator.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class ControlAllocator : public ModuleBase<ControlAllocator>, public ModuleParam
201201
// Reflects motor failures that are currently handled, not motor failures that are reported.
202202
// For example, the system might report two motor failures, but only the first one is handled by CA
203203
uint16_t _handled_motor_failure_bitmask{0};
204+
uint16_t _motor_stop_mask{0};
204205

205206
perf_counter_t _loop_perf; /**< loop duration performance counter */
206207

0 commit comments

Comments
 (0)