Skip to content

Commit 5ebf1b9

Browse files
committed
add rc_override reason struct to command manager (from issue #371)
1 parent cafe458 commit 5ebf1b9

File tree

5 files changed

+146
-103
lines changed

5 files changed

+146
-103
lines changed

include/command_manager.h

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class CommandManager : public ParamListenerInterface
8686
control_channel_t * combined;
8787
} mux_t;
8888

89-
mux_t muxes[6] = {{&rc_command_.Qx, &offboard_command_.Qx, &combined_command_.Qx},
89+
mux_t muxes_[6] = {{&rc_command_.Qx, &offboard_command_.Qx, &combined_command_.Qx},
9090
{&rc_command_.Qy, &offboard_command_.Qy, &combined_command_.Qy},
9191
{&rc_command_.Qz, &offboard_command_.Qz, &combined_command_.Qz},
9292
{&rc_command_.Fx, &offboard_command_.Fx, &combined_command_.Fx},
@@ -146,40 +146,96 @@ class CommandManager : public ParamListenerInterface
146146
MUX_FX,
147147
MUX_FY,
148148
MUX_FZ,
149+
NUM_MUX_CHANNELS
150+
};
151+
152+
enum RCOverrideReason : uint16_t
153+
{
154+
OVERRIDE_NO_OVERRIDE = 0x0,
155+
OVERRIDE_ATT_SWITCH = 0x1,
156+
OVERRIDE_THR_SWITCH = 0x2,
157+
OVERRIDE_X = 0x4,
158+
OVERRIDE_Y = 0x8,
159+
OVERRIDE_Z = 0x10,
160+
OVERRIDE_T = 0x20,
161+
OVERRIDE_OFFBOARD_X_INACTIVE = 0x40,
162+
OVERRIDE_OFFBOARD_Y_INACTIVE = 0x80,
163+
OVERRIDE_OFFBOARD_Z_INACTIVE = 0x100,
164+
OVERRIDE_OFFBOARD_T_INACTIVE = 0x200,
149165
};
150166

151167
typedef struct
152168
{
153169
RC::Stick rc_channel;
154170
uint32_t last_override_time;
155-
} rc_stick_override_t;
156-
157-
rc_stick_override_t rc_stick_override_[3] = {{RC::STICK_X, 0},
158-
{RC::STICK_Y, 0},
159-
{RC::STICK_Z, 0}};
171+
RCOverrideReason stick_override_reason;
172+
RCOverrideReason offboard_inactive_override_reason;
173+
uint16_t override_mask;
174+
} channel_override_t;
175+
176+
channel_override_t channel_override_[6] = {
177+
{RC::STICK_X, 0, OVERRIDE_X, OVERRIDE_OFFBOARD_X_INACTIVE, X_OVERRIDDEN},
178+
{RC::STICK_Y, 0, OVERRIDE_Y, OVERRIDE_OFFBOARD_Y_INACTIVE, Y_OVERRIDDEN},
179+
{RC::STICK_Z, 0, OVERRIDE_Z, OVERRIDE_OFFBOARD_Z_INACTIVE, Z_OVERRIDDEN},
180+
{RC::STICK_F, 0, OVERRIDE_T, OVERRIDE_OFFBOARD_T_INACTIVE, T_OVERRIDDEN},
181+
{RC::STICK_F, 0, OVERRIDE_T, OVERRIDE_OFFBOARD_T_INACTIVE, T_OVERRIDDEN},
182+
{RC::STICK_F, 0, OVERRIDE_T, OVERRIDE_OFFBOARD_T_INACTIVE,
183+
T_OVERRIDDEN} // Note that throttle overriding works a bit differently
184+
};
160185

161186
ROSflight & RF_;
162187

163188
bool new_command_;
164-
uint8_t rc_override_;
189+
uint16_t rc_override_;
165190

166191
control_t & failsafe_command_;
167192

168193
void param_change_callback(uint16_t param_id) override;
169194
void init_failsafe();
170195

171-
uint8_t do_roll_pitch_yaw_muxing(MuxChannel channel);
172-
uint8_t do_throttle_muxing(void);
173-
void do_min_throttle_muxing();
196+
/**
197+
* @brief Checks which channels are overridden
198+
* @details There are many reasons that a channel could be overriden. These reasons include:
199+
* - A stick is deflected
200+
* - The commanded throttle is less than the RC throttle, and the MIN_THROTTLE parameter is set
201+
* - The attitude or throttle override switch is flipped
202+
* - The onboard computer has not sent any commands recently
203+
* The returned bitfield indicates which reasons have caused an override.
204+
* By anding with a constant such as X_OVERRIDDEN, you can check if a specific channel is overridden.
205+
* @return A bitfield, with overriden reasons indicated
206+
*/
207+
uint16_t determine_override_status();
208+
uint16_t check_if_attitude_channel_is_overriden_by_rc(MuxChannel channel);
209+
uint16_t check_if_throttle_channel_is_overriden_by_rc();
210+
void do_muxing(uint16_t rc_override);
211+
void do_channel_muxing(MuxChannel channel, uint16_t rc_override);
174212

175213
void interpret_rc(void);
176214
bool stick_deviated(MuxChannel channel);
177215

178216
public:
217+
static constexpr uint16_t X_OVERRIDDEN{OVERRIDE_ATT_SWITCH | OVERRIDE_X | OVERRIDE_OFFBOARD_X_INACTIVE};
218+
static constexpr uint16_t Y_OVERRIDDEN{OVERRIDE_ATT_SWITCH | OVERRIDE_Y | OVERRIDE_OFFBOARD_Y_INACTIVE};
219+
static constexpr uint16_t Z_OVERRIDDEN{OVERRIDE_ATT_SWITCH | OVERRIDE_Z | OVERRIDE_OFFBOARD_Z_INACTIVE};
220+
static constexpr uint16_t T_OVERRIDDEN{OVERRIDE_THR_SWITCH | OVERRIDE_T | OVERRIDE_OFFBOARD_T_INACTIVE};
221+
static constexpr uint16_t ATTITUDE_OVERRIDDEN{X_OVERRIDDEN | Y_OVERRIDDEN | Z_OVERRIDDEN};
222+
179223
CommandManager(ROSflight & _rf);
180224
void init();
181225
bool run();
182-
uint8_t rc_override_active();
226+
/**
227+
* @brief Checks which channels are overridden, and why
228+
* @details There are many reasons that a channel could be overriden. These reasons include:
229+
* - A stick is deflected
230+
* - The commanded throttle is less than the RC throttle, and the MIN_THROTTLE parameter is set
231+
* - The attitude or throttle override switch is flipped
232+
* - The onboard computer has not sent any commands recently
233+
* The returned bitfield indicates which reasons have caused an override.
234+
* Because c++ can use integers as booleans, this function can be treated as providing a boolean
235+
* This value is updated if a new RC command is available
236+
* @return A bitfield, with overriden reasons indicated
237+
*/
238+
uint16_t get_rc_override();
183239
bool offboard_control_active();
184240
void set_new_offboard_command(control_t new_offboard_command);
185241
void set_new_rc_command(control_t new_rc_command);

include/mixer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include "param_listener.h"
3636
#include "controller.h"
37+
#include "command_manager.h"
3738

3839
#include <eigen/Eigen/Dense>
3940
#include <eigen/Eigen/SVD>

src/comm_manager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ void CommManager::send_status(void)
373373

374374
comm_link_.send_status(
375375
sysid_, RF_.state_manager_.state().armed, RF_.state_manager_.state().failsafe,
376-
RF_.command_manager_.rc_override_active(), RF_.command_manager_.offboard_control_active(),
376+
RF_.command_manager_.get_rc_override(), RF_.command_manager_.offboard_control_active(),
377377
RF_.state_manager_.state().error_codes, control_mode, RF_.board_.sensors_errors_count(),
378378
RF_.get_loop_time_us());
379379
}

src/command_manager.cpp

Lines changed: 71 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,17 @@
3838

3939
namespace rosflight_firmware
4040
{
41-
typedef enum
42-
{
43-
ATT_MODE_RATE,
44-
ATT_MODE_ANGLE
45-
} att_mode_t;
46-
47-
typedef struct
48-
{
49-
RC::Stick rc_channel;
50-
uint32_t last_override_time;
51-
} rc_stick_override_t;
52-
53-
rc_stick_override_t rc_stick_override[] = {{RC::STICK_X, 0}, {RC::STICK_Y, 0}, {RC::STICK_Z, 0}};
54-
55-
typedef struct
56-
{
57-
control_channel_t * rc;
58-
control_channel_t * onboard;
59-
control_channel_t * combined;
60-
} mux_t;
6141

6242
CommandManager::CommandManager(ROSflight & _rf)
6343
: RF_(_rf)
6444
, failsafe_command_(multirotor_failsafe_command_)
6545
{}
6646

67-
void CommandManager::init() { init_failsafe(); }
47+
void CommandManager::init()
48+
{
49+
init_failsafe();
50+
rc_override_ = determine_override_status();
51+
}
6852

6953
void CommandManager::param_change_callback(uint16_t param_id)
7054
{
@@ -124,27 +108,22 @@ void CommandManager::interpret_rc(void)
124108
rc_command_.Qz.value = RF_.rc_.stick(RC::STICK_Z);
125109

126110
// Load the RC command based on the axis associated with the RC F command
111+
rc_command_.Fx.value = 0.0;
112+
rc_command_.Fy.value = 0.0;
113+
rc_command_.Fz.value = 0.0;
127114
switch (static_cast<rc_f_axis_t>(RF_.params_.get_param_int(PARAM_RC_F_AXIS))) {
128-
case X_AXIS: // RC F = X axis
115+
case X_AXIS:
129116
rc_command_.Fx.value = RF_.rc_.stick(RC::STICK_F);
130-
rc_command_.Fy.value = 0.0;
131-
rc_command_.Fz.value = 0.0;
132117
break;
133-
case Y_AXIS: // RC F = Y axis
134-
rc_command_.Fx.value = 0.0;
118+
case Y_AXIS:
135119
rc_command_.Fy.value = RF_.rc_.stick(RC::STICK_F);
136-
rc_command_.Fz.value = 0.0;
137120
break;
138121
case Z_AXIS:
139-
rc_command_.Fx.value = 0.0;
140-
rc_command_.Fy.value = 0.0;
141122
rc_command_.Fz.value = RF_.rc_.stick(RC::STICK_F);
142123
break;
143124
default:
144125
RF_.comm_manager_.log(CommLinkInterface::LogSeverity::LOG_WARNING,
145126
"Invalid RC F axis. Defaulting to z-axis.");
146-
rc_command_.Fx.value = 0.0;
147-
rc_command_.Fy.value = 0.0;
148127
rc_command_.Fz.value = RF_.rc_.stick(RC::STICK_F);
149128
break;
150129
}
@@ -199,50 +178,60 @@ bool CommandManager::stick_deviated(MuxChannel channel)
199178
uint32_t now = RF_.board_.clock_millis();
200179

201180
// if we are still in the lag time, return true
202-
if (now < rc_stick_override_[channel].last_override_time
181+
if (now < channel_override_[channel].last_override_time
203182
+ RF_.params_.get_param_int(PARAM_OVERRIDE_LAG_TIME)) {
204183
return true;
205184
} else {
206-
if (fabsf(RF_.rc_.stick(rc_stick_override_[channel].rc_channel))
185+
if (fabsf(RF_.rc_.stick(channel_override_[channel].rc_channel))
207186
> RF_.params_.get_param_float(PARAM_RC_OVERRIDE_DEVIATION)) {
208-
rc_stick_override_[channel].last_override_time = now;
187+
channel_override_[channel].last_override_time = now;
209188
return true;
210189
}
211190
return false;
212191
}
213192
}
214193

215-
uint8_t CommandManager::do_roll_pitch_yaw_muxing(MuxChannel channel)
194+
uint16_t CommandManager::determine_override_status()
216195
{
217-
bool override_this_channel = false;
218196
// Check if the override switch exists and is triggered, or if the sticks have deviated enough to
219197
// trigger an override
220-
if ((RF_.rc_.switch_mapped(RC::SWITCH_ATT_OVERRIDE) && RF_.rc_.switch_on(RC::SWITCH_ATT_OVERRIDE))
221-
|| stick_deviated(channel)) {
222-
override_this_channel = true;
223-
} else { // Otherwise only have RC override if the offboard channel is inactive
224-
if (muxes[channel].onboard->active) {
225-
override_this_channel = false;
226-
} else {
227-
override_this_channel = true;
228-
}
198+
uint16_t rc_override{0};
199+
if (RF_.rc_.switch_mapped(RC::SWITCH_ATT_OVERRIDE) && RF_.rc_.switch_on(RC::SWITCH_ATT_OVERRIDE)) {
200+
rc_override |= OVERRIDE_ATT_SWITCH;
229201
}
230-
// set the combined channel output depending on whether RC is overriding for this channel or not
231-
*muxes[channel].combined = override_this_channel ? *muxes[channel].rc : *muxes[channel].onboard;
232-
if (override_this_channel) return 1U;
233-
else return 0;
202+
if (RF_.rc_.switch_mapped(RC::SWITCH_THROTTLE_OVERRIDE) && RF_.rc_.switch_on(RC::SWITCH_THROTTLE_OVERRIDE)) {
203+
rc_override |= OVERRIDE_THR_SWITCH;
204+
}
205+
206+
rc_override |= check_if_attitude_channel_is_overriden_by_rc(MUX_QX);
207+
rc_override |= check_if_attitude_channel_is_overriden_by_rc(MUX_QY);
208+
rc_override |= check_if_attitude_channel_is_overriden_by_rc(MUX_QZ);
209+
rc_override |= check_if_throttle_channel_is_overriden_by_rc();
210+
211+
return rc_override;
234212
}
235213

236-
uint8_t CommandManager::do_throttle_muxing(void)
214+
uint16_t CommandManager::check_if_attitude_channel_is_overriden_by_rc(MuxChannel channel)
215+
{
216+
uint16_t rc_overrides{0};
217+
if (stick_deviated(channel)) {
218+
rc_overrides |= channel_override_[channel].stick_override_reason;
219+
}
220+
if (!(muxes_[channel].onboard->active)) {
221+
rc_overrides |= channel_override_[channel].offboard_inactive_override_reason;
222+
}
223+
return rc_overrides;
224+
}
225+
226+
uint16_t CommandManager::check_if_throttle_channel_is_overriden_by_rc()
237227
{
238-
bool override_this_channel = false;
239228
MuxChannel selected_channel;
240-
// Determine which channel to check based on which axis the RC channel corresponds to
229+
// Determine which channel to check based on which axis the RC F channel corresponds to
241230
switch (static_cast<rc_f_axis_t>(RF_.params_.get_param_int(PARAM_RC_F_AXIS))) {
242-
case X_AXIS:
231+
case X_AXIS:
243232
selected_channel = MUX_FX;
244233
break;
245-
case Y_AXIS:
234+
case Y_AXIS:
246235
selected_channel = MUX_FY;
247236
break;
248237
case Z_AXIS:
@@ -255,43 +244,38 @@ uint8_t CommandManager::do_throttle_muxing(void)
255244
break;
256245
}
257246

258-
// Check if the override switch exists and is triggered
259-
if (RF_.rc_.switch_mapped(RC::SWITCH_THROTTLE_OVERRIDE)
260-
&& RF_.rc_.switch_on(RC::SWITCH_THROTTLE_OVERRIDE)) {
261-
override_this_channel = true;
262-
} else { // Otherwise check if the offboard throttle channel is active, if it isn't, have RC override
263-
if (muxes[selected_channel].onboard->active) {
264-
// Check if the parameter flag is set to have us always take the smaller throttle
265-
if (RF_.params_.get_param_int(PARAM_RC_OVERRIDE_TAKE_MIN_THROTTLE)) {
266-
override_this_channel = (muxes[selected_channel].rc->value < muxes[selected_channel].onboard->value);
267-
} else {
268-
override_this_channel = false;
269-
}
270-
} else {
271-
override_this_channel = true;
247+
uint16_t rc_overrides{0};
248+
if (!(muxes_[selected_channel].onboard->active)) {
249+
rc_overrides |= OVERRIDE_OFFBOARD_T_INACTIVE;
250+
}
251+
if (RF_.params_.get_param_int(PARAM_RC_OVERRIDE_TAKE_MIN_THROTTLE)) {
252+
if (muxes_[selected_channel].rc->value < muxes_[selected_channel].onboard->value) {
253+
rc_overrides |= OVERRIDE_T;
272254
}
273255
}
256+
return rc_overrides;
257+
}
274258

275-
// Set the combined channel output depending on whether RC is overriding for this channel or not
276-
// Either RC overrides all force inputs, or none
277-
if (override_this_channel) {
278-
*muxes[MUX_FX].combined = *muxes[MUX_FX].rc;
279-
*muxes[MUX_FY].combined = *muxes[MUX_FY].rc;
280-
*muxes[MUX_FZ].combined = *muxes[MUX_FZ].rc;
281-
} else {
282-
*muxes[MUX_FX].combined = *muxes[MUX_FX].onboard;
283-
*muxes[MUX_FY].combined = *muxes[MUX_FY].onboard;
284-
*muxes[MUX_FZ].combined = *muxes[MUX_FZ].onboard;
259+
void CommandManager::do_muxing(uint16_t rc_override)
260+
{
261+
for (uint8_t channel{0}; channel < NUM_MUX_CHANNELS; ++channel) {
262+
do_channel_muxing(static_cast<MuxChannel>(channel), rc_override);
285263
}
286-
return override_this_channel;
287264
}
288265

289-
uint8_t CommandManager::rc_override_active() { return rc_override_; }
266+
void CommandManager::do_channel_muxing(MuxChannel channel, uint16_t rc_override )
267+
{
268+
bool override_this_channel = (rc_override & channel_override_[channel].override_mask);
269+
// set the combined channel output depending on whether RC is overriding for this channel or not
270+
*muxes_[channel].combined = override_this_channel ? *muxes_[channel].rc : *muxes_[channel].onboard;
271+
}
272+
273+
uint16_t CommandManager::get_rc_override() { return rc_override_; }
290274

291275
bool CommandManager::offboard_control_active()
292276
{
293-
for (int i = 0; i < 4; i++) {
294-
if (muxes[i].onboard->active) { return true; }
277+
for (uint8_t channel{0}; channel < NUM_MUX_CHANNELS; ++channel) {
278+
if (muxes_[channel].onboard->active) { return true; }
295279
}
296280
return false;
297281
}
@@ -316,7 +300,7 @@ void CommandManager::override_combined_command_with_rc()
316300

317301
bool CommandManager::run()
318302
{
319-
bool last_rc_override = rc_override_active();
303+
uint16_t last_rc_override = get_rc_override();
320304

321305
// Check for and apply failsafe command
322306
if (RF_.state_manager_.state().failsafe) {
@@ -338,21 +322,19 @@ bool CommandManager::run()
338322
}
339323

340324
// Perform muxing
341-
rc_override_ = do_roll_pitch_yaw_muxing(MUX_QX);
342-
rc_override_ |= do_roll_pitch_yaw_muxing(MUX_QY);
343-
rc_override_ |= do_roll_pitch_yaw_muxing(MUX_QZ);
344-
rc_override_ += 2U*do_throttle_muxing();
325+
rc_override_ = determine_override_status();
326+
do_muxing(rc_override_);
345327

346328
// Light to indicate override
347-
if (rc_override_active()) {
329+
if (rc_override_) {
348330
RF_.board_.led0_on();
349331
} else {
350332
RF_.board_.led0_off();
351333
}
352334
}
353335

354336
// There was a change in rc_override state
355-
if (last_rc_override != rc_override_active()) { RF_.comm_manager_.update_status(); }
337+
if (last_rc_override != get_rc_override()) { RF_.comm_manager_.update_status(); }
356338
return true;
357339
}
358340

0 commit comments

Comments
 (0)