Compare commits

...

6 Commits

Author SHA1 Message Date
Junwoo Hwang d486143eba Move param handles in rc_update into unified struct
- To follow structure & matthias recommendation
2022-05-27 14:55:44 +02:00
Junwoo Hwang 18e664d416 Additional updates 2022-05-24 22:25:08 +02:00
Junwoo Hwang 474540937c Create Trigger Action Enums and start taking trigger action params into account 2022-05-24 21:32:55 +02:00
Junwoo Hwang 432e2439a2 WIP: Continue adding support for Trigger slots 2022-05-24 17:20:06 +02:00
Junwoo Hwang f5f8881daf Continue removing the Button based Flight mode selection code 2022-05-12 18:03:33 +02:00
Junwoo Hwang 51749d646d Initial cut on supporting generic button/switch triggers 2022-05-11 12:15:20 +02:00
4 changed files with 210 additions and 96 deletions
-8
View File
@@ -21,14 +21,6 @@ uint8 FUNCTION_KILLSWITCH = 17
uint8 FUNCTION_TRANSITION = 18
uint8 FUNCTION_GEAR = 19
uint8 FUNCTION_ARMSWITCH = 20
uint8 FUNCTION_FLTBTN_SLOT_1 = 21
uint8 FUNCTION_FLTBTN_SLOT_2 = 22
uint8 FUNCTION_FLTBTN_SLOT_3 = 23
uint8 FUNCTION_FLTBTN_SLOT_4 = 24
uint8 FUNCTION_FLTBTN_SLOT_5 = 25
uint8 FUNCTION_FLTBTN_SLOT_6 = 26
uint8 FUNCTION_FLTBTN_SLOT_COUNT = 6
uint64 timestamp_last_valid # Timestamp of last valid RC signal
float32[18] channels # Scaled to -1..1 (throttle: 0..1)
+87 -26
View File
@@ -1557,37 +1557,98 @@ PARAM_DEFINE_INT32(RC_MAP_TRANS_SW, 0);
PARAM_DEFINE_INT32(RC_MAP_GEAR_SW, 0);
/**
* Button flight mode selection
* Mask to indicate if the channel is a button for the trigger action
*
* This bitmask allows to specify multiple channels for changing flight modes using
* momentary buttons. Each channel is assigned to a mode slot ((lowest channel = slot 1).
* The resulting modes for each slot X is defined by the COM_FLTMODEX parameters.
* The functionality can be used only if RC_MAP_FLTMODE is disabled.
* This bitmask allows to specify multiple channels to indicate whether it's a button.
* If not marked, the channel is assumed to be a switch. This configuration allows the
* rc_update to correctly decode the input signals to trigger appropriate actions.
*
* The maximum number of available slots and hence bits set in the mask is 6.
* @min 0
* @max 258048
* @group Radio Switches
* @bit 0 Mask Channel 1 as a mode button
* @bit 1 Mask Channel 2 as a mode button
* @bit 2 Mask Channel 3 as a mode button
* @bit 3 Mask Channel 4 as a mode button
* @bit 4 Mask Channel 5 as a mode button
* @bit 5 Mask Channel 6 as a mode button
* @bit 6 Mask Channel 7 as a mode button
* @bit 7 Mask Channel 8 as a mode button
* @bit 8 Mask Channel 9 as a mode button
* @bit 9 Mask Channel 10 as a mode button
* @bit 10 Mask Channel 11 as a mode button
* @bit 11 Mask Channel 12 as a mode button
* @bit 12 Mask Channel 13 as a mode button
* @bit 13 Mask Channel 14 as a mode button
* @bit 14 Mask Channel 15 as a mode button
* @bit 15 Mask Channel 16 as a mode button
* @bit 16 Mask Channel 17 as a mode button
* @bit 17 Mask Channel 18 as a mode button
* @group Radio Trigger
* @bit 0 Mask Channel 1 as a button
* @bit 1 Mask Channel 2 as a button
* @bit 2 Mask Channel 3 as a button
* @bit 3 Mask Channel 4 as a button
* @bit 4 Mask Channel 5 as a button
* @bit 5 Mask Channel 6 as a button
* @bit 6 Mask Channel 7 as a button
* @bit 7 Mask Channel 8 as a button
* @bit 8 Mask Channel 9 as a button
* @bit 9 Mask Channel 10 as a button
* @bit 10 Mask Channel 11 as a button
* @bit 11 Mask Channel 12 as a button
* @bit 12 Mask Channel 13 as a button
* @bit 13 Mask Channel 14 as a button
* @bit 14 Mask Channel 15 as a button
* @bit 15 Mask Channel 16 as a button
* @bit 16 Mask Channel 17 as a button
* @bit 17 Mask Channel 18 as a button
*/
PARAM_DEFINE_INT32(RC_MAP_FLTM_BTN, 0);
PARAM_DEFINE_INT32(RC_TRIG_BTN_MASK, 0);
/**
* RC Channel for trigger slot 1
*
* @min 0
* @max 18
* @group Radio Trigger
* @value 0 Unassigned
* @value 1 Channel 1
* @value 2 Channel 2
* @value 3 Channel 3
* @value 4 Channel 4
* @value 5 Channel 5
* @value 6 Channel 6
* @value 7 Channel 7
* @value 8 Channel 8
* @value 9 Channel 9
* @value 10 Channel 10
* @value 11 Channel 11
* @value 12 Channel 12
* @value 13 Channel 13
* @value 14 Channel 14
* @value 15 Channel 15
* @value 16 Channel 16
* @value 17 Channel 17
* @value 18 Channel 18
*/
PARAM_DEFINE_INT32(RC_TRIG1_CHAN, 0);
/**
* Which action the Trigger slot 1 triggers
*
* The flight mode enums follow the convention defined in the commander_state.msg uORB message.
* Everything else (16 ~ ) is a non-flight-mode actions
*
* @min -1
* @max 20
* @group Radio Trigger
* @value -1 Unassigned
* @value 0 Manual
* @value 1 Altitude
* @value 2 Position
* @value 3 Mission
* @value 4 Loiter
* @value 5 Return
* @value 6 Acro
* @value 7 Offboard
* @value 8 Stabilized
* @value 10 Takeoff
* @value 11 Land
* @value 12 Follow Me
* @value 13 Precision Land
* @value 14 Orbit
* @value 15 Auto VTOL Takeoff
* @value 16 Killswitch
* @value 17 Arm
* @value 18 VTOL Transition
* @value 19 Gear
* @value 20 Photo
* @value 21 Video
*/
PARAM_DEFINE_INT32(RC_TRIG1_ACTION, 0);
/**
* AUX1 Passthrough RC channel
+68 -47
View File
@@ -64,7 +64,15 @@ static bool operator !=(const manual_control_switches_s &a, const manual_control
RCUpdate::RCUpdate() :
ModuleParams(nullptr),
WorkItem(MODULE_NAME, px4::wq_configurations::hp_default)
WorkItem(MODULE_NAME, px4::wq_configurations::hp_default),
_trigger_slots_hysteresis{
systemlib::Hysteresis{false},
systemlib::Hysteresis{false},
systemlib::Hysteresis{false},
systemlib::Hysteresis{false},
systemlib::Hysteresis{false},
systemlib::Hysteresis{false}
}
{
// initialize parameter handles
for (unsigned i = 0; i < RC_MAX_CHAN_COUNT; i++) {
@@ -99,10 +107,19 @@ RCUpdate::RCUpdate() :
_parameter_handles.rc_map_param[i] = param_find(name);
}
// Find param handles for Generic Trigger Channel & Actions for slot 1 ~ 6
for (uint8_t trig_slot = 1; trig_slot <= RC_TRIG_SLOT_COUNT; trig_slot++) {
char param_name_buf[17] = {};
snprintf(param_name_buf, sizeof(param_name_buf), "RC_TRIG_%d_CHAN", trig_slot);
_parameter_handles.generic_trigger_chan[trig_slot - 1] = param_find(param_name_buf);
snprintf(param_name_buf, sizeof(param_name_buf), "RC_TRIG_%d_ACTION", trig_slot);
_parameter_handles.generic_trigger_action[trig_slot - 1] = param_find(param_name_buf);
}
rc_parameter_map_poll(true /* forced */);
parameters_updated();
_button_pressed_hysteresis.set_hysteresis_time_from(false, 50_ms);
//_button_pressed_hysteresis.set_hysteresis_time_from(false, 50_ms);
}
RCUpdate::~RCUpdate()
@@ -154,6 +171,16 @@ void RCUpdate::parameters_updated()
update_rc_functions();
// Update and check values of the generic action parameters
for (uint8_t trig_slot = 1; trig_slot <= RC_TRIG_SLOT_COUNT; trig_slot++) {
int32_t new_channel{RC_TRIG_CHAN_UNASSIGNED};
int32_t new_action{RC_TRIG_ACTION_UNASSIGNED};
param_get(_parameter_handles.generic_trigger_chan[trig_slot - 1], &new_channel);
param_get(_parameter_handles.generic_trigger_action[trig_slot - 1], &new_action);
}
// deprecated parameters, will be removed post v1.12 once QGC is updated
{
int32_t rc_map_value = 0;
@@ -230,8 +257,6 @@ void RCUpdate::update_rc_functions()
for (int i = 0; i < rc_parameter_map_s::RC_PARAM_MAP_NCHAN; i++) {
_rc.function[rc_channels_s::FUNCTION_PARAM_1 + i] = _parameters.rc_map_param[i] - 1;
}
map_flight_modes_buttons();
}
void RCUpdate::rc_parameter_map_poll(bool forced)
@@ -306,42 +331,6 @@ void RCUpdate::set_params_from_rc()
}
}
void
RCUpdate::map_flight_modes_buttons()
{
static_assert(rc_channels_s::FUNCTION_FLTBTN_SLOT_1 + manual_control_switches_s::MODE_SLOT_NUM <= sizeof(
_rc.function) / sizeof(_rc.function[0]), "Unexpected number of RC functions");
static_assert(rc_channels_s::FUNCTION_FLTBTN_SLOT_COUNT == manual_control_switches_s::MODE_SLOT_NUM,
"Unexpected number of Flight Modes slots");
// Reset all the slots to -1
for (uint8_t slot = 0; slot < manual_control_switches_s::MODE_SLOT_NUM; slot++) {
_rc.function[rc_channels_s::FUNCTION_FLTBTN_SLOT_1 + slot] = -1;
}
// If the functionality is disabled we don't need to map channels
const int flightmode_buttons = _param_rc_map_flightmode_buttons.get();
if (flightmode_buttons == 0) {
return;
}
uint8_t slot = 0;
for (uint8_t channel = 0; channel < RC_MAX_CHAN_COUNT; channel++) {
if (flightmode_buttons & (1 << channel)) {
PX4_DEBUG("Slot %d assigned to channel %d", slot + 1, channel);
_rc.function[rc_channels_s::FUNCTION_FLTBTN_SLOT_1 + slot] = channel;
slot++;
}
if (slot >= manual_control_switches_s::MODE_SLOT_NUM) {
// we have filled all the available slots
break;
}
}
}
void RCUpdate::Run()
{
if (should_exit()) {
@@ -605,7 +594,45 @@ void RCUpdate::UpdateManualSwitches(const hrt_abstime &timestamp_sample)
switches.mode_slot = num_slots;
}
} else if (_param_rc_map_flightmode_buttons.get() > 0) {
}
// Use the Generic RC Switch / Button only when the RC is in use
if (_manual_control_setpoint_sub.update() &&
_manual_control_setpoint_sub.get().data_source == manual_control_setpoint_s::SOURCE_RC) {
_manual_control_setpoint_source_is_rc = true;
}
// Go through the trigger slots and update the states
const uint32_t rc_trigger_is_button_mask = _param_rc_trig_btn_mask.get();
for (uint8_t trig_slot = 1; trig_slot <= RC_TRIG_SLOT_COUNT; trig_slot++) {
int channel{RC_TRIG_CHAN_UNASSIGNED};
param_get(_trigger_channel_param_handles[trig_slot - 1], &channel);
int action{RC_TRIGGER_ACTION_UNASSIGNED};
param_get(_trigger_action_param_handles[trig_slot - 1], &action);
if (channel > RC_TRIG_CHAN_UNASSIGNED) {
}
}
// Update the Generic Action states
const uint8_t trig1_chan = _param_rc_trig1_chan.get();
const uint8_t trig1_action = _param_rc_trig1_action.get();
// Trigger Channel is configured
if (trig1_chan > 0) {
const bool is_btn = _param_rc_trig_btn_mask.get() & (1 << 0);
if (is_btn) {
} else {
// Is Switch
}
}
else if (_param_rc_map_flightmode_buttons.get() > 0) {
switches.mode_slot = manual_control_switches_s::MODE_SLOT_NONE;
bool is_consistent_button_press = false;
@@ -628,12 +655,6 @@ void RCUpdate::UpdateManualSwitches(const hrt_abstime &timestamp_sample)
break;
}
}
_button_pressed_hysteresis.set_state_and_update(is_consistent_button_press, hrt_absolute_time());
if (_button_pressed_hysteresis.get_state()) {
switches.mode_slot = _potential_button_press_slot;
}
}
switches.return_switch = get_rc_sw2pos_position(rc_channels_s::FUNCTION_RETURN, _param_rc_return_th.get());
+55 -15
View File
@@ -48,6 +48,7 @@
#include <drivers/drv_hrt.h>
#include <lib/mathlib/mathlib.h>
#include <lib/perf/perf_counter.h>
#include <uORB/Publication.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/Subscription.hpp>
@@ -66,6 +67,43 @@ using namespace time_literals;
namespace rc_update
{
// Number of Generic Trigger slots that can be configured
static constexpr uint8_t RC_TRIG_SLOT_COUNT = 6;
// Value of the RC_TRIG#_CHAN when the channel is unassigned
static constexpr uint8_t RC_TRIG_CHAN_UNASSIGNED = 0;
// Value of the RC_TRIG#_ACTION when the action is unassigned
static constexpr uint8_t RC_TRIG_ACTION_UNASSIGNED = -1;
// Enum class translation of the RC_TRIG#_ACTION values
enum RC_TRIGGER_ACTIONS {
RC_TRIGGER_ACTION_UNASSIGNED = -1,
// Commander States (defined in commander_state.msg)
RC_TRIGGER_ACTION_MANUAL_FLIGHTMODE = 0,
RC_TRIGGER_ACTION_ALTITUDE_FLIGHTMODE = 1,
RC_TRIGGER_ACTION_POSITION_FLIGHTMODE = 2,
RC_TRIGGER_ACTION_MISSION_FLIHGTMODE = 3,
RC_TRIGGER_ACTION_HOLD_FLIGHTMODE = 4,
RC_TRIGGER_ACTION_RETURN_FLIGHTMODE = 5,
RC_TRIGGER_ACTION_ACRO_FLIGHTMODE = 6,
RC_TRIGGER_ACTION_OFFBOARD_FLIGHTMODE = 7,
RC_TRIGGER_ACTION_STABILIZED_FLIGHTMODE = 8,
RC_TRIGGER_ACTION_TAKEOFF = 10,
RC_TRIGGER_ACTION_LAND = 11,
RC_TRIGGER_ACTION_FOLLOW_ME_FLIGHTMODE = 12,
RC_TRIGGER_ACTION_PRECISION_LAND_FLIGHTMODE = 13,
RC_TRIGGER_ACTION_ORBIT_FLIGHTMODE = 14,
RC_TRIGGER_ACTION_AUTO_VTOL_TAKEOFF = 15,
// Non- Commander State Actions
RC_TRIGGER_ACTION_KILLSWITCH = 16,
RC_TRIGGER_ACTION_ARM = 17,
RC_TRIGGER_ACTION_VTOL_TRANSITION = 18,
RC_TRIGGER_ACTION_GEAR = 19,
RC_TRIGGER_ACTION_PHOTO = 20,
RC_TRIGGER_ACTION_VIDEO = 21
};
/**
** class RCUpdate
*
@@ -132,8 +170,6 @@ private:
*/
void set_params_from_rc();
void map_flight_modes_buttons();
static constexpr uint8_t RC_MAX_CHAN_COUNT{input_rc_s::RC_INPUT_MAX_CHANNELS}; /**< maximum number of r/c channels we handle */
struct Parameters {
@@ -144,6 +180,9 @@ private:
bool rev[RC_MAX_CHAN_COUNT];
int32_t rc_map_param[rc_parameter_map_s::RC_PARAM_MAP_NCHAN];
uint8_t generic_trigger_chan[RC_TRIG_SLOT_COUNT];
uint8_t generic_trigger_action[RC_TRIG_SLOT_COUNT];
} _parameters{};
struct ParameterHandles {
@@ -154,16 +193,17 @@ private:
param_t dz[RC_MAX_CHAN_COUNT];
param_t rc_map_param[rc_parameter_map_s::RC_PARAM_MAP_NCHAN];
param_t rc_param[rc_parameter_map_s::RC_PARAM_MAP_NCHAN]; /**< param handles for the parameters which are bound
to a RC channel, equivalent float values in the
_parameters struct are not existing
because these parameters are never read. */
param_t rc_param[rc_parameter_map_s::RC_PARAM_MAP_NCHAN];
/**< param handles for the parameters which are bound to a RC channel, equivalent float values
* in the_parameters struct are not existing because these parameters are never read. */
param_t generic_trigger_chan[RC_TRIG_SLOT_COUNT];
param_t generic_trigger_action[RC_TRIG_SLOT_COUNT];
} _parameter_handles{};
uORB::SubscriptionCallbackWorkItem _input_rc_sub{this, ORB_ID(input_rc)};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::SubscriptionData<manual_control_setpoint_s> _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)};
uORB::Subscription _rc_parameter_map_sub{ORB_ID(rc_parameter_map)};
uORB::Subscription _actuator_controls_3_sub{ORB_ID(actuator_controls_3)};
@@ -190,8 +230,12 @@ private:
uint8_t _channel_count_previous{0};
uint8_t _input_source_previous{input_rc_s::RC_INPUT_SOURCE_UNKNOWN};
uint8_t _potential_button_press_slot{0};
systemlib::Hysteresis _button_pressed_hysteresis{false};
// Flag to indicate that RC input is being used for manual control (whether we can use generic action)
bool _manual_control_setpoint_source_is_rc{false};
systemlib::Hysteresis _trigger_slots_hysteresis[RC_TRIG_SLOT_COUNT];
param_t _trigger_channel_param_handles[RC_TRIG_SLOT_COUNT] {};
param_t _trigger_action_param_handles[RC_TRIG_SLOT_COUNT] {};
systemlib::Hysteresis _rc_signal_lost_hysteresis{true};
uint8_t _channel_count_max{0};
@@ -201,17 +245,14 @@ private:
perf_counter_t _valid_data_interval_perf{perf_alloc(PC_INTERVAL, MODULE_NAME": valid data interval")};
DEFINE_PARAMETERS(
(ParamInt<px4::params::RC_MAP_ROLL>) _param_rc_map_roll,
(ParamInt<px4::params::RC_MAP_PITCH>) _param_rc_map_pitch,
(ParamInt<px4::params::RC_MAP_YAW>) _param_rc_map_yaw,
(ParamInt<px4::params::RC_MAP_THROTTLE>) _param_rc_map_throttle,
(ParamInt<px4::params::RC_MAP_FAILSAFE>) _param_rc_map_failsafe,
(ParamInt<px4::params::RC_MAP_FLTMODE>) _param_rc_map_fltmode,
(ParamInt<px4::params::RC_TRIG_BTN_MASK>) _param_rc_trig_btn_mask,
(ParamInt<px4::params::RC_MAP_FLAPS>) _param_rc_map_flaps,
(ParamInt<px4::params::RC_MAP_RETURN_SW>) _param_rc_map_return_sw,
(ParamInt<px4::params::RC_MAP_LOITER_SW>) _param_rc_map_loiter_sw,
(ParamInt<px4::params::RC_MAP_OFFB_SW>) _param_rc_map_offb_sw,
@@ -219,7 +260,6 @@ private:
(ParamInt<px4::params::RC_MAP_ARM_SW>) _param_rc_map_arm_sw,
(ParamInt<px4::params::RC_MAP_TRANS_SW>) _param_rc_map_trans_sw,
(ParamInt<px4::params::RC_MAP_GEAR_SW>) _param_rc_map_gear_sw,
(ParamInt<px4::params::RC_MAP_FLTM_BTN>) _param_rc_map_flightmode_buttons,
(ParamInt<px4::params::RC_MAP_AUX1>) _param_rc_map_aux1,
(ParamInt<px4::params::RC_MAP_AUX2>) _param_rc_map_aux2,