Line data Source code
1 : /// @file RC_Channel.h
2 : /// @brief RC_Channel manager, with EEPROM-backed storage of constants.
3 : #pragma once
4 :
5 : #include "RC_Channel_config.h"
6 :
7 : #if AP_RC_CHANNEL_ENABLED
8 :
9 : #include <AP_Common/AP_Common.h>
10 : #include <AP_Param/AP_Param.h>
11 : #include <AP_Math/AP_Math.h>
12 : #include <AP_Common/Bitmask.h>
13 :
14 : #include <AC_Sprayer/AC_Sprayer_config.h>
15 : #include <AP_Airspeed/AP_Airspeed_config.h>
16 : #include <AP_Camera/AP_Camera_config.h>
17 : #include <AP_Compass/AP_Compass_config.h>
18 : #include <AP_Gripper/AP_Gripper_config.h>
19 : #include <AP_OpticalFlow/AP_OpticalFlow_config.h>
20 : #include <AP_Parachute/AP_Parachute_config.h>
21 : #include <AP_RangeFinder/AP_RangeFinder_config.h>
22 : #include <AP_ServoRelayEvents/AP_ServoRelayEvents_config.h>
23 : #include <AP_Torqeedo/AP_Torqeedo_config.h>
24 : #include <AP_VisualOdom/AP_VisualOdom_config.h>
25 : #include <AP_Winch/AP_Winch_config.h>
26 : #include <AP_VideoTX/AP_VideoTX_config.h>
27 : #include <AP_Arming/AP_Arming_config.h>
28 : #include <AP_BattMonitor/AP_BattMonitor_config.h>
29 :
30 : #define NUM_RC_CHANNELS 16
31 :
32 : /// @class RC_Channel
33 : /// @brief Object managing one RC channel
34 : class RC_Channel {
35 : public:
36 : friend class RC_Channels;
37 : // Constructor
38 : RC_Channel(void);
39 :
40 : enum class ControlType {
41 : ANGLE = 0,
42 : RANGE = 1,
43 : };
44 :
45 : // ch returns the radio channel be read, starting at 1. so
46 : // typically Roll=1, Pitch=2, throttle=3, yaw=4. If this returns
47 : // 0 then this is the dummy object which means that one of roll,
48 : // pitch, yaw or throttle has not been configured correctly.
49 0 : uint8_t ch() const { return ch_in + 1; }
50 :
51 : // setup the control preferences
52 : void set_range(uint16_t high);
53 3261753 : uint16_t get_range() const { return high_in; }
54 : void set_angle(uint16_t angle);
55 : bool get_reverse(void) const;
56 : void set_default_dead_zone(int16_t dzone);
57 996110 : uint16_t get_dead_zone(void) const { return dead_zone; }
58 :
59 : // get the center stick position expressed as a control_in value
60 : int16_t get_control_mid() const;
61 :
62 : // read input from hal.rcin - create a control_in value
63 : bool update(void);
64 :
65 : // calculate an angle given dead_zone and trim. This is used by the quadplane code
66 : // for hover throttle
67 : float pwm_to_angle_dz_trim(uint16_t dead_zone, uint16_t trim) const;
68 :
69 : // return a normalised input for a channel, in range -1 to 1,
70 : // centered around the channel trim. Ignore deadzone.
71 : float norm_input() const;
72 :
73 : // return a normalised input for a channel, in range -1 to 1,
74 : // centered around the channel trim. Take into account the deadzone
75 : float norm_input_dz() const;
76 :
77 : // return a normalised input for a channel, in range -1 to 1,
78 : // ignores trim and deadzone
79 : float norm_input_ignore_trim() const;
80 :
81 : // return a normalised input for a channel, in range -1 to 1 (in
82 : // return parameter). Ignores trim and deadzone. Returns false
83 : // if a current value is not available (eg. in RC failsafe)
84 : bool norm_input_ignore_trim(float &norm_in) const;
85 :
86 : // returns true if input is within deadzone of min
87 : bool in_min_dz() const;
88 :
89 : uint8_t percent_input() const;
90 :
91 : static const struct AP_Param::GroupInfo var_info[];
92 :
93 : // return true if input is within deadzone of trim
94 : bool in_trim_dz() const;
95 :
96 130940430 : int16_t get_radio_in() const { return radio_in;}
97 9345 : void set_radio_in(int16_t val) {radio_in = val;}
98 :
99 74996109 : int16_t get_control_in() const { return control_in;}
100 11588 : void set_control_in(int16_t val) { control_in = val;}
101 :
102 : void clear_override();
103 : void set_override(const uint16_t v, const uint32_t timestamp_ms);
104 : bool has_override() const;
105 :
106 : float stick_mixing(const float servo_in);
107 :
108 : // get control input with zero deadzone
109 : float get_control_in_zero_dz(void) const;
110 :
111 3451050 : int16_t get_radio_min() const {return radio_min.get();}
112 :
113 3361172 : int16_t get_radio_max() const {return radio_max.get();}
114 :
115 2450820 : int16_t get_radio_trim() const { return radio_trim.get();}
116 :
117 0 : void set_and_save_trim() { radio_trim.set_and_save_ifchanged(radio_in);}
118 :
119 : // set and save trim if changed
120 : void set_and_save_radio_trim(int16_t val) { radio_trim.set_and_save_ifchanged(val);}
121 :
122 : // check if any of the trim/min/max param are configured, this would indicate that the user has done a calibration at somepoint
123 918 : bool configured() { return radio_min.configured() || radio_max.configured() || radio_trim.configured(); }
124 :
125 1138943 : ControlType get_type(void) const { return type_in; }
126 :
127 : AP_Int16 option; // e.g. activate EPM gripper / enable fence
128 :
129 : // auxiliary switch support
130 : void init_aux();
131 : bool read_aux();
132 :
133 : // Aux Switch enumeration
134 : enum class AUX_FUNC {
135 : DO_NOTHING = 0, // aux switch disabled
136 : FLIP = 2, // flip
137 : SIMPLE_MODE = 3, // change to simple mode
138 : RTL = 4, // change to RTL flight mode
139 : SAVE_TRIM = 5, // save current position as level
140 : #if AP_MISSION_ENABLED
141 : SAVE_WP = 7, // save mission waypoint or RTL if in auto mode
142 : #endif // AP_MISSION_ENABLED
143 : #if AP_CAMERA_ENABLED
144 : CAMERA_TRIGGER = 9, // trigger camera servo or relay
145 : #endif // AP_CAMERA_ENABLED
146 : #if AP_RANGEFINDER_ENABLED
147 : RANGEFINDER = 10, // allow enabling or disabling rangefinder in flight which helps avoid surface tracking when you are far above the ground
148 : #endif // AP_RANGEFINDER_ENABLED
149 : #if AP_FENCE_ENABLED
150 : FENCE = 11, // allow enabling or disabling fence in flight
151 : #endif // AP_FENCE_ENABLED
152 : RESETTOARMEDYAW = 12, // UNUSED
153 : SUPERSIMPLE_MODE = 13, // change to simple mode in middle, super simple at top
154 : ACRO_TRAINER = 14, // low = disabled, middle = leveled, high = leveled and limited
155 : #if HAL_SPRAYER_ENABLED
156 : SPRAYER = 15, // enable/disable the crop sprayer
157 : #endif // HAL_SPRAYER_ENABLED
158 : AUTO = 16, // change to auto flight mode
159 : AUTOTUNE_MODE = 17, // auto tune
160 : LAND = 18, // change to LAND flight mode
161 : #if AP_GRIPPER_ENABLED
162 : GRIPPER = 19, // Operate cargo grippers low=off, middle=neutral, high=on
163 : #endif // AP_GRIPPER_ENABLED
164 : #if HAL_PARACHUTE_ENABLED
165 : PARACHUTE_ENABLE = 21, // Parachute enable/disable
166 : PARACHUTE_RELEASE = 22, // Parachute release
167 : PARACHUTE_3POS = 23, // Parachute disable, enable, release with 3 position switch
168 : #endif // HAL_PARACHUTE_ENABLED
169 : #if AP_MISSION_ENABLED
170 : MISSION_RESET = 24, // Reset auto mission to start from first command
171 : #endif // AP_MISSION_ENABLED
172 : ATTCON_FEEDFWD = 25, // enable/disable the roll and pitch rate feed forward
173 : ATTCON_ACCEL_LIM = 26, // enable/disable the roll, pitch and yaw accel limiting
174 : #if HAL_MOUNT_ENABLED
175 : RETRACT_MOUNT1 = 27, // Retract Mount1
176 : #endif // HAL_MOUNT_ENABLED
177 : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
178 :
179 : RELAY = 28, // Relay pin on/off (only supports first relay)
180 : #endif // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
181 : LANDING_GEAR = 29, // Landing gear controller
182 : LOST_VEHICLE_SOUND = 30, // Play lost vehicle sound
183 : MOTOR_ESTOP = 31, // Emergency Stop Switch
184 : MOTOR_INTERLOCK = 32, // Motor On/Off switch
185 : BRAKE = 33, // Brake flight mode
186 : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
187 : RELAY2 = 34, // Relay2 pin on/off
188 : RELAY3 = 35, // Relay3 pin on/off
189 : RELAY4 = 36, // Relay4 pin on/off
190 : #endif // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
191 : THROW = 37, // change to THROW flight mode
192 : AVOID_ADSB = 38, // enable AP_Avoidance library
193 : PRECISION_LOITER = 39, // enable precision loiter
194 : AVOID_PROXIMITY = 40, // enable object avoidance using proximity sensors (ie. horizontal lidar)
195 : ARMDISARM_UNUSED = 41, // UNUSED
196 : SMART_RTL = 42, // change to SmartRTL flight mode
197 : INVERTED = 43, // enable inverted flight
198 : #if AP_WINCH_ENABLED
199 : WINCH_ENABLE = 44, // winch enable/disable
200 : WINCH_CONTROL = 45, // winch control
201 : #endif // AP_WINCH_ENABLED
202 : RC_OVERRIDE_ENABLE = 46, // enable RC Override
203 : USER_FUNC1 = 47, // user function #1
204 : USER_FUNC2 = 48, // user function #2
205 : USER_FUNC3 = 49, // user function #3
206 : LEARN_CRUISE = 50, // learn cruise throttle (Rover)
207 : MANUAL = 51, // manual mode
208 : ACRO = 52, // acro mode
209 : STEERING = 53, // steering mode
210 : HOLD = 54, // hold mode
211 : GUIDED = 55, // guided mode
212 : LOITER = 56, // loiter mode
213 : FOLLOW = 57, // follow mode
214 : #if AP_MISSION_ENABLED
215 : CLEAR_WP = 58, // clear waypoints
216 : #endif // AP_MISSION_ENABLED
217 : SIMPLE = 59, // simple mode
218 : ZIGZAG = 60, // zigzag mode
219 : ZIGZAG_SaveWP = 61, // zigzag save waypoint
220 : COMPASS_LEARN = 62, // learn compass offsets
221 : SAILBOAT_TACK = 63, // rover sailboat tack
222 : REVERSE_THROTTLE = 64, // reverse throttle input
223 : #if AP_GPS_ENABLED
224 : GPS_DISABLE = 65, // disable GPS for testing
225 : #endif // AP_GPS_ENABLED
226 : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
227 : RELAY5 = 66, // Relay5 pin on/off
228 : RELAY6 = 67, // Relay6 pin on/off
229 : #endif // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
230 : STABILIZE = 68, // stabilize mode
231 : POSHOLD = 69, // poshold mode
232 : ALTHOLD = 70, // althold mode
233 : FLOWHOLD = 71, // flowhold mode
234 : CIRCLE = 72, // circle mode
235 : DRIFT = 73, // drift mode
236 : SAILBOAT_MOTOR_3POS = 74, // Sailboat motoring 3pos
237 : SURFACE_TRACKING = 75, // Surface tracking upwards or downwards
238 : STANDBY = 76, // Standby mode
239 : TAKEOFF = 77, // takeoff
240 : #if AP_CAMERA_RUNCAM_ENABLED
241 : RUNCAM_CONTROL = 78, // control RunCam device
242 : RUNCAM_OSD_CONTROL = 79, // control RunCam OSD
243 : #endif // AP_CAMERA_RUNCAM_ENABLED
244 : #if HAL_VISUALODOM_ENABLED
245 : VISODOM_ALIGN = 80, // align visual odometry camera's attitude to AHRS
246 : #endif // HAL_VISUALODOM_ENABLED
247 : DISARM = 81, // disarm vehicle
248 : Q_ASSIST = 82, // disable, enable and force Q assist
249 : ZIGZAG_Auto = 83, // zigzag auto switch
250 : AIRMODE = 84, // enable / disable airmode for copter
251 : #if HAL_GENERATOR_ENABLED
252 : GENERATOR = 85, // generator control
253 : #endif // HAL_GENERATOR_ENABLED
254 : TER_DISABLE = 86, // disable terrain following in CRUISE/FBWB modes
255 : CROW_SELECT = 87, // select CROW mode for diff spoilers;high disables,mid forces progressive
256 : SOARING = 88, // three-position switch to set soaring mode
257 : LANDING_FLARE = 89, // force flare, throttle forced idle, pitch to LAND_PITCH_DEG, tilts up
258 : EKF_SOURCE_SET = 90, // change EKF data source set between primary, secondary and tertiary
259 : #if AP_AIRSPEED_AUTOCAL_ENABLE
260 : ARSPD_CALIBRATE= 91, // calibrate airspeed ratio
261 : #endif // AP_AIRSPEED_AUTOCAL_ENABLE
262 : FBWA = 92, // Fly-By-Wire-A
263 : #if AP_MISSION_ENABLED
264 : RELOCATE_MISSION = 93, // used in separate branch MISSION_RELATIVE
265 : #endif // AP_MISSION_ENABLED
266 : #if AP_VIDEOTX_ENABLED
267 : VTX_POWER = 94, // VTX power level
268 : #endif // AP_VIDEOTX_ENABLED
269 : FBWA_TAILDRAGGER = 95, // enables FBWA taildragger takeoff mode. Once this feature is enabled it will stay enabled until the aircraft goes above TKOFF_TDRAG_SPD1 airspeed, changes mode, or the pitch goes above the initial pitch when this is engaged or goes below 0 pitch. When enabled the elevator will be forced to TKOFF_TDRAG_ELEV. This option allows for easier takeoffs on taildraggers in FBWA mode, and also makes it easier to test auto-takeoff steering handling in FBWA.
270 : MODE_SWITCH_RESET = 96, // trigger re-reading of mode switch
271 : WIND_VANE_DIR_OFSSET= 97, // flag for windvane direction offset input, used with windvane type 2
272 : TRAINING = 98, // mode training
273 : #if AP_MISSION_ENABLED
274 : AUTO_RTL = 99, // AUTO RTL via DO_LAND_START
275 : #endif // AP_MISSION_ENABLED
276 :
277 : #if AP_INERTIALSENSOR_KILL_IMU_ENABLED
278 : // entries from 100-150 are expected to be developer
279 : // options used for testing
280 : KILL_IMU1 = 100, // disable first IMU (for IMU failure testing)
281 : KILL_IMU2 = 101, // disable second IMU (for IMU failure testing)
282 : #endif // AP_INERTIALSENSOR_KILL_IMU_ENABLED
283 : #if AP_CAMERA_ENABLED
284 : CAM_MODE_TOGGLE = 102, // Momentary switch to cycle camera modes
285 : #endif // AP_CAMERA_ENABLED
286 : #if AP_AHRS_ENABLED
287 : EKF_LANE_SWITCH = 103, // trigger lane switch attempt
288 : EKF_YAW_RESET = 104, // trigger yaw reset attempt
289 : #endif // AP_AHRS_ENABLED
290 : #if AP_GPS_ENABLED
291 : GPS_DISABLE_YAW = 105, // disable GPS yaw for testing
292 : #endif // AP_GPS_ENABLED
293 : #if AP_AIRSPEED_ENABLED
294 : DISABLE_AIRSPEED_USE = 106, // equivalent to AIRSPEED_USE 0
295 : #endif // AP_AIRSPEED_ENABLED
296 : FW_AUTOTUNE = 107, // fixed wing auto tune
297 : QRTL = 108, // QRTL mode
298 : CUSTOM_CONTROLLER = 109, // use Custom Controller
299 : #if AP_INERTIALSENSOR_KILL_IMU_ENABLED
300 : KILL_IMU3 = 110, // disable third IMU (for IMU failure testing)
301 : #endif // AP_INERTIALSENSOR_KILL_IMU_ENABLED
302 : #if HAL_GENERATOR_ENABLED
303 : LOWEHEISER_STARTER = 111, // allows for manually running starter
304 : #endif // HAL_GENERATOR_ENABLED
305 : #if AP_AHRS_ENABLED
306 : AHRS_TYPE = 112, // change AHRS_EKF_TYPE
307 : #endif // AP_AHRS_ENABLED
308 : #if HAL_MOUNT_ENABLED
309 : RETRACT_MOUNT2 = 113, // Retract Mount2
310 : #endif // HAL_MOUNT_ENABLED
311 :
312 : // if you add something here, make sure to update the documentation of the parameter in RC_Channel.cpp!
313 : // also, if you add an option >255, you will need to fix duplicate_options_exist
314 :
315 : // options 150-199 continue user rc switch options
316 : CRUISE = 150, // CRUISE mode
317 : TURTLE = 151, // Turtle mode - flip over after crash
318 : SIMPLE_HEADING_RESET = 152, // reset simple mode reference heading to current
319 : #if AP_ARMING_ENABLED
320 : ARMDISARM = 153, // arm or disarm vehicle
321 : ARMDISARM_AIRMODE = 154, // arm or disarm vehicle enabling airmode
322 : #endif // AP_ARMING_ENABLED
323 : TRIM_TO_CURRENT_SERVO_RC = 155, // trim to current servo and RC
324 : #if HAL_TORQEEDO_ENABLED
325 : TORQEEDO_CLEAR_ERR = 156, // clear torqeedo error
326 : #endif // HAL_TORQEEDO_ENABLED
327 : EMERGENCY_LANDING_EN = 157, //Force long FS action to FBWA for landing out of range
328 : #if AP_OPTICALFLOW_ENABLED
329 : OPTFLOW_CAL = 158, // optical flow calibration
330 : #endif // AP_OPTICALFLOW_ENABLED
331 : FORCEFLYING = 159, // enable or disable land detection for GPS based manual modes preventing land detection and maintainting set_throttle_mix_max
332 : WEATHER_VANE_ENABLE = 160, // enable/disable weathervaning
333 : TURBINE_START = 161, // initialize turbine start sequence
334 : FFT_NOTCH_TUNE = 162, // FFT notch tuning function
335 : #if HAL_MOUNT_ENABLED
336 : MOUNT_YAW_LOCK = 163, // Mount earth frame yaw lock forced on all axes, for all mounts
337 : #endif // HAL_MOUNT_ENABLED
338 : #if HAL_LOGGING_ENABLED
339 : LOG_PAUSE = 164, // Pauses logging if under logging rate control
340 : #endif // HAL_LOGGING_ENABLED
341 : ARM_EMERGENCY_STOP = 165, // ARM on high, MOTOR_ESTOP on low
342 : #if AP_CAMERA_ENABLED
343 : CAMERA_REC_VIDEO = 166, // start recording on high, stop recording on low
344 : CAMERA_ZOOM = 167, // camera zoom high = zoom in, middle = hold, low = zoom out
345 : CAMERA_MANUAL_FOCUS = 168,// camera manual focus. high = long shot, middle = stop focus, low = close shot
346 : CAMERA_AUTO_FOCUS = 169, // camera auto focus
347 : #endif // AP_CAMERA_ENABLED
348 : QSTABILIZE = 170, // QuadPlane QStabilize mode
349 : #if COMPASS_CAL_ENABLED
350 : MAG_CAL = 171, // Calibrate compasses (disarmed only)
351 : #endif // COMPASS_CAL_ENABLED
352 : #if AP_BATTERY_ENABLED
353 : BATTERY_MPPT_ENABLE = 172,// Battery MPPT Power enable. high = ON, mid = auto (controlled by mppt/batt driver), low = OFF. This effects all MPPTs.
354 : #endif // AP_BATTERY_ENABLED
355 : PLANE_AUTO_LANDING_ABORT = 173, // Abort Glide-slope or VTOL landing during payload place or do_land type mission items
356 : #if AP_CAMERA_ENABLED
357 : CAMERA_IMAGE_TRACKING = 174, // camera image tracking
358 : CAMERA_LENS = 175, // camera lens selection
359 : #endif // AP_CAMERA_ENABLED
360 : VFWD_THR_OVERRIDE = 176, // force enabled VTOL forward throttle method
361 : #if HAL_MOUNT_ENABLED
362 : MOUNT_LRF_ENABLE = 177, // mount LRF enable/disable
363 : #endif // HAL_MOUNT_ENABLED
364 : FLIGHTMODE_PAUSE = 178, // e.g. pause movement towards waypoint
365 : ICE_START_STOP = 179, // AP_ICEngine start stop
366 : AUTOTUNE_TEST_GAINS = 180, // auto tune tuning switch to test or revert gains
367 : QUICKTUNE = 181, //quicktune 3 position switch
368 : AHRS_AUTO_TRIM = 182, // in-flight AHRS autotrim
369 : AUTOLAND = 183, //Fixed Wing AUTOLAND Mode
370 : SYSTEMID = 184, // system ID as an aux switch
371 : MOUNT_RP_LOCK = 185, // mount lock modes for roll and pitch axes, for all mounts that support it
372 : #if AP_MOUNT_POI_LOCK_ENABLED
373 : MOUNT_POI_LOCK = 186, // Lock mount target to current ROI seen and switch mount to GPS Targeting mode
374 : #endif // AP_MOUNT_POI_LOCK_ENABLED
375 : #if AP_AHRS_EKF_RESET_ENABLED
376 : EKF_RESET = 187, // trigger full EKF bootstrap reset
377 : #endif // AP_AHRS_EKF_RESET_ENABLED
378 : // inputs from 200 will eventually used to replace RCMAP
379 : ROLL = 201, // roll input
380 : PITCH = 202, // pitch input
381 : THROTTLE = 203, // throttle pilot input
382 : YAW = 204, // yaw pilot input
383 : MAINSAIL = 207, // mainsail input
384 : FLAP = 208, // flap input
385 : FWD_THR = 209, // VTOL manual forward throttle
386 : AIRBRAKE = 210, // manual airbrake control
387 : WALKING_HEIGHT = 211, // walking robot height input
388 : #if HAL_MOUNT_ENABLED
389 : MOUNT1_ROLL = 212, // mount1 roll input
390 : MOUNT1_PITCH = 213, // mount1 pitch input
391 : MOUNT1_YAW = 214, // mount1 yaw input
392 : MOUNT2_ROLL = 215, // mount2 roll input
393 : MOUNT2_PITCH = 216, // mount3 pitch input
394 : MOUNT2_YAW = 217, // mount4 yaw input
395 : #endif // HAL_MOUNT_ENABLED
396 : #if HAL_GENERATOR_ENABLED
397 : LOWEHEISER_THROTTLE= 218, // allows for throttle on slider
398 : #endif // HAL_GENERATOR_ENABLED
399 : #if AP_RC_TRANSMITTER_TUNING_ENABLED
400 : TRANSMITTER_TUNING = 219, // use a transmitter knob or slider for in-flight tuning
401 : TRANSMITTER_TUNING2 = 220, // use another transmitter knob or slider for in-flight tuning
402 : #endif // AP_RC_TRANSMITTER_TUNING_ENABLED
403 :
404 : // inputs 248-249 are reserved for the Skybrush fork at
405 : // https://github.com/skybrush-io/ardupilot
406 :
407 : // inputs 250-254 are reserved for the custom integrations.
408 : // No code which uses these auxiliary channel options will be
409 : // merged into ArduPilot master, so external code can use this
410 : // an not conflict when rebased on newer ArduPilot codebases.
411 : // No guarantees are made in terms of conflicting with other
412 : // external projects. See the SCRIPTING_1 range instead if
413 : // you are writing a Lua script.
414 :
415 : #if AP_SCRIPTING_ENABLED
416 : // inputs for the use of onboard lua scripting
417 : SCRIPTING_1 = 300,
418 : SCRIPTING_2 = 301,
419 : SCRIPTING_3 = 302,
420 : SCRIPTING_4 = 303,
421 : SCRIPTING_5 = 304,
422 : SCRIPTING_6 = 305,
423 : SCRIPTING_7 = 306,
424 : SCRIPTING_8 = 307,
425 : SCRIPTING_9 = 308,
426 : SCRIPTING_10 = 309,
427 : SCRIPTING_11 = 310,
428 : SCRIPTING_12 = 311,
429 : SCRIPTING_13 = 312,
430 : SCRIPTING_14 = 313,
431 : SCRIPTING_15 = 314,
432 : SCRIPTING_16 = 315,
433 : STOP_RESTART_SCRIPTING = 316, // emergency scripting disablement
434 : #endif // AP_SCRIPTING_ENABLED
435 :
436 : // this must be higher than any aux function above
437 : AUX_FUNCTION_MAX = 317,
438 : };
439 :
440 : // auxiliary switch handling (n.b.: we store this as 2-bits!):
441 : enum class AuxSwitchPos : uint8_t {
442 : LOW, // indicates auxiliary switch is in the low position (pwm <1200)
443 : MIDDLE, // indicates auxiliary switch is in the middle position (pwm >1200, <1800)
444 : HIGH // indicates auxiliary switch is in the high position (pwm >1800)
445 : };
446 :
447 : // Trigger structure containing the function, position, source and source index
448 : struct AuxFuncTrigger {
449 : AUX_FUNC func;
450 : AuxSwitchPos pos;
451 : // @LoggerEnum: AuxFuncTrigger::Source
452 : enum class Source : uint8_t {
453 : INIT, // Source index is RC channel index
454 : RC, // Source index is RC channel index
455 : BUTTON, // Source index is button index
456 : MAVLINK, // Source index is MAVLink channel number
457 : MISSION, // Source index is mission item index
458 : SCRIPTING, // Source index is not used (always 0)
459 : } source;
460 : uint16_t source_index;
461 : };
462 :
463 : AuxSwitchPos get_aux_switch_pos() const;
464 :
465 : // aux position for stick gestures used by RunCam menus etc
466 : AuxSwitchPos get_stick_gesture_pos() const;
467 :
468 : // wrapper function around do_aux_function which allows us to log
469 : bool run_aux_function(AUX_FUNC ch_option, AuxSwitchPos pos, AuxFuncTrigger::Source source, uint16_t source_index);
470 :
471 : #if AP_RC_CHANNEL_AUX_FUNCTION_STRINGS_ENABLED
472 : const char *string_for_aux_function(AUX_FUNC function) const;
473 : const char *string_for_aux_pos(AuxSwitchPos pos) const;
474 : #endif
475 : // pwm value under which we consider that Radio value is invalid
476 : static const uint16_t RC_MIN_LIMIT_PWM = 800;
477 : // pwm value above which we consider that Radio value is invalid
478 : static const uint16_t RC_MAX_LIMIT_PWM = 2200;
479 :
480 : // pwm value above which we condider that Radio min value is invalid
481 : static const uint16_t RC_CALIB_MIN_LIMIT_PWM = 1300;
482 : // pwm value under which we condider that Radio max value is invalid
483 : static const uint16_t RC_CALIB_MAX_LIMIT_PWM = 1700;
484 :
485 : // pwm value above which the switch/button will be invoked:
486 : static const uint16_t AUX_SWITCH_PWM_TRIGGER_HIGH = 1800;
487 : // pwm value below which the switch/button will be disabled:
488 : static const uint16_t AUX_SWITCH_PWM_TRIGGER_LOW = 1200;
489 :
490 : // pwm value above which the option will be invoked:
491 : static const uint16_t AUX_PWM_TRIGGER_HIGH = 1700;
492 : // pwm value below which the option will be disabled:
493 : static const uint16_t AUX_PWM_TRIGGER_LOW = 1300;
494 :
495 : protected:
496 :
497 : __INITFUNC__ virtual void init_aux_function(AUX_FUNC ch_option, AuxSwitchPos);
498 :
499 : // virtual function to be overridden my subclasses
500 : virtual bool do_aux_function(const AuxFuncTrigger &trigger);
501 :
502 : void do_aux_function_armdisarm(const AuxSwitchPos ch_flag);
503 : void do_aux_function_avoid_adsb(const AuxSwitchPos ch_flag);
504 : void do_aux_function_avoid_proximity(const AuxSwitchPos ch_flag);
505 : void do_aux_function_camera_trigger(const AuxSwitchPos ch_flag);
506 : bool do_aux_function_record_video(const AuxSwitchPos ch_flag);
507 : bool do_aux_function_camera_zoom(const AuxSwitchPos ch_flag);
508 : bool do_aux_function_camera_manual_focus(const AuxSwitchPos ch_flag);
509 : bool do_aux_function_camera_auto_focus(const AuxSwitchPos ch_flag);
510 : bool do_aux_function_camera_image_tracking(const AuxSwitchPos ch_flag);
511 : bool do_aux_function_camera_lens(const AuxSwitchPos ch_flag);
512 : void do_aux_function_runcam_control(const AuxSwitchPos ch_flag);
513 : void do_aux_function_runcam_osd_control(const AuxSwitchPos ch_flag);
514 : void do_aux_function_fence(const AuxSwitchPos ch_flag);
515 : void do_aux_function_clear_wp(const AuxSwitchPos ch_flag);
516 : void do_aux_function_gripper(const AuxSwitchPos ch_flag);
517 : void do_aux_function_lost_vehicle_sound(const AuxSwitchPos ch_flag);
518 : void do_aux_function_mission_reset(const AuxSwitchPos ch_flag);
519 : void do_aux_function_rc_override_enable(const AuxSwitchPos ch_flag);
520 : void do_aux_function_relay(uint8_t relay, bool val);
521 : void do_aux_function_sprayer(const AuxSwitchPos ch_flag);
522 : void do_aux_function_generator(const AuxSwitchPos ch_flag);
523 : void do_aux_function_fft_notch_tune(const AuxSwitchPos ch_flag);
524 : void do_aux_function_retract_mount(const AuxSwitchPos ch_flag, const uint8_t instance);
525 :
526 : typedef int8_t modeswitch_pos_t;
527 0 : virtual void mode_switch_changed(modeswitch_pos_t new_pos) {
528 : // no action by default (e.g. Tracker, Sub, who do their own thing)
529 0 : };
530 :
531 : // the input channel this corresponds to
532 : uint8_t ch_in;
533 :
534 : private:
535 :
536 : // pwm is stored here; if an override is active, override_value is stored instead
537 : int16_t radio_in;
538 : // stores the raw pwm value read from hal.rcin
539 : int16_t raw_radio_in;
540 :
541 : // value generated from PWM normalised to configured scale
542 : int16_t control_in;
543 :
544 : AP_Int16 radio_min;
545 : AP_Int16 radio_trim;
546 : AP_Int16 radio_max;
547 :
548 : AP_Int8 reversed;
549 : AP_Int16 dead_zone;
550 :
551 : ControlType type_in;
552 : int16_t high_in;
553 :
554 : // overrides
555 : uint16_t override_value;
556 : uint32_t last_override_time;
557 :
558 : // return true if raw input is within deadzone of trim
559 : bool in_raw_trim_dz() const;
560 664 : int16_t get_raw_radio_in() const { return raw_radio_in; }
561 :
562 : float pwm_to_angle() const;
563 : float pwm_to_angle_dz(uint16_t dead_zone) const;
564 :
565 : float pwm_to_range() const;
566 : float pwm_to_range_dz(uint16_t dead_zone) const;
567 :
568 : bool read_3pos_switch(AuxSwitchPos &ret) const WARN_IF_UNUSED;
569 : bool read_6pos_switch(int8_t& position) WARN_IF_UNUSED;
570 :
571 : // Structure used to detect and debounce switch changes
572 : struct {
573 : int8_t debounce_position = -1;
574 : int8_t current_position = -1;
575 : uint32_t last_edge_time_ms;
576 : bool initialised;
577 : } switch_state;
578 :
579 : void reset_mode_switch();
580 : void read_mode_switch();
581 : bool debounce_completed(int8_t position);
582 : // returns true if the first time we successfully read the
583 : // channel's three-position-switch position we should record that
584 : // position as the current position *without* executing the
585 : // associated auxiliary function. e.g. do not attempt to arm a
586 : // vehicle when the user turns on their transmitter with the arm
587 : // switch high!
588 : bool init_position_on_first_radio_read(AUX_FUNC func) const;
589 :
590 : #if AP_RC_CHANNEL_AUX_FUNCTION_STRINGS_ENABLED
591 : // Structure to lookup switch change announcements
592 : struct LookupTable{
593 : AUX_FUNC option;
594 : const char *announcement;
595 : };
596 :
597 : static const LookupTable lookuptable[];
598 : #endif
599 : };
600 :
601 :
602 : /*
603 : class RC_Channels. Hold the full set of RC_Channel objects
604 : */
605 : class RC_Channels {
606 : public:
607 : friend class SRV_Channels;
608 : friend class RC_Channel;
609 : // constructor
610 : RC_Channels(void);
611 :
612 : __INITFUNC__ void init(void);
613 :
614 : // get singleton instance
615 665596969 : static RC_Channels *get_singleton() {
616 665596969 : return _singleton;
617 : }
618 :
619 : static const struct AP_Param::GroupInfo var_info[];
620 :
621 : // this function is implemented in the child class in the vehicle
622 : // code
623 : virtual RC_Channel *channel(uint8_t chan) = 0;
624 : virtual const RC_Channel *channel(uint8_t chan) const = 0;
625 : // helper used by scripting to convert the above function from 0 to 1 indexeing
626 : // range is checked correctly by the underlying channel function
627 3851 : RC_Channel *lua_rc_channel(const uint8_t chan) {
628 3851 : return channel(chan -1);
629 : }
630 :
631 : uint8_t get_radio_in(uint16_t *chans, const uint8_t num_channels); // reads a block of chanel radio_in values starting from channel 0
632 : // returns the number of valid channels
633 :
634 : static uint8_t get_valid_channel_count(void); // returns the number of valid channels in the last read
635 : static int16_t get_receiver_rssi(void); // returns [0, 255] for receiver RSSI (0 is no link) if present, otherwise -1
636 : static int16_t get_receiver_link_quality(void); // returns 0-100 % of last 100 packets received at receiver are valid
637 : bool read_input(void); // returns true if new input has been read in
638 : static void clear_overrides(void); // clears any active overrides
639 : static void set_override(const uint8_t chan, const int16_t value, const uint32_t timestamp_ms = 0); // set a channels override value
640 : static bool has_active_overrides(void); // returns true if there are overrides applied that are valid
641 :
642 : // returns a mask indicating which channels have overrides. Bit 0
643 : // is RC channel 1. Beware this is not a cheap call.
644 : uint16_t get_override_mask() const;
645 :
646 : class RC_Channel *find_channel_for_option(const RC_Channel::AUX_FUNC option);
647 : bool duplicate_options_exist();
648 :
649 : void init_aux_all();
650 : void read_aux_all();
651 :
652 : // mode switch handling
653 : void reset_mode_switch();
654 : virtual void read_mode_switch();
655 :
656 0 : virtual bool in_rc_failsafe() const { return true; };
657 : virtual bool has_valid_input() const;
658 356241 : virtual RC_Channel *get_arming_channel(void) const { return nullptr; };
659 :
660 4110 : bool gcs_overrides_enabled() const { return _gcs_overrides_enabled; }
661 44 : void set_gcs_overrides_enabled(bool enable) {
662 44 : _gcs_overrides_enabled = enable;
663 44 : if (!_gcs_overrides_enabled) {
664 25 : clear_overrides();
665 : }
666 44 : }
667 :
668 : enum class Option {
669 : IGNORE_RECEIVER = (1U << 0), // RC receiver modules
670 : IGNORE_OVERRIDES = (1U << 1), // MAVLink overrides
671 : IGNORE_FAILSAFE = (1U << 2), // ignore RC failsafe bits
672 : FPORT_PAD = (1U << 3), // pad fport telem output
673 : LOG_RAW_DATA = (1U << 4), // log rc input bytes
674 : ARMING_CHECK_THROTTLE = (1U << 5), // run an arming check for neutral throttle
675 : ARMING_SKIP_CHECK_RPY = (1U << 6), // skip the an arming checks for the roll/pitch/yaw channels
676 : ALLOW_SWITCH_REV = (1U << 7), // honor the reversed flag on switches
677 : CRSF_CUSTOM_TELEMETRY = (1U << 8), // use passthrough data for crsf telemetry
678 : SUPPRESS_CRSF_MESSAGE = (1U << 9), // suppress CRSF mode/rate message for ELRS systems
679 : MULTI_RECEIVER_SUPPORT = (1U << 10), // allow multiple receivers
680 : USE_CRSF_LQ_AS_RSSI = (1U << 11), // returns CRSF link quality as RSSI value, instead of RSSI
681 : CRSF_FM_DISARM_STAR = (1U << 12), // when disarmed, add a star at the end of the flight mode in CRSF telemetry
682 : ELRS_420KBAUD = (1U << 13), // use 420kbaud for ELRS protocol
683 : CLEAR_OVERRIDES_BY_RC = (1U << 14), // clear MAVLink overrides when the pilot moves the RC sticks (per-vehicle definition)
684 : };
685 :
686 279869948 : bool option_is_enabled(Option option) const {
687 279869948 : return _options & uint32_t(option);
688 : }
689 :
690 182985 : virtual bool arming_check_throttle() const {
691 182985 : return option_is_enabled(Option::ARMING_CHECK_THROTTLE);
692 : }
693 :
694 : // returns true if overrides should time out. If true is returned
695 : // then returned_timeout_ms will contain the timeout in
696 : // milliseconds, with 0 meaning overrides are disabled.
697 2691019 : bool get_override_timeout_ms(uint32_t &returned_timeout_ms) const {
698 2691019 : const float value = _override_timeout.get();
699 2691019 : if (is_positive(value)) {
700 2686926 : returned_timeout_ms = uint32_t(value * 1e3f);
701 2686926 : return true;
702 : }
703 4093 : if (is_zero(value)) {
704 112 : returned_timeout_ms = 0;
705 112 : return true;
706 : }
707 : // overrides will not time out
708 3981 : return false;
709 : }
710 :
711 : // get mask of enabled protocols
712 : uint32_t enabled_protocols() const;
713 :
714 : // returns true if we have had a direct detach RC receiver, does not include overrides
715 122758294 : bool has_had_rc_receiver() const { return _has_had_rc_receiver; }
716 :
717 : // returns true if we have had an override on any channel
718 316 : bool has_had_rc_override() const { return _has_had_override; }
719 :
720 : /*
721 : get the RC input PWM value given a channel number. Note that
722 : channel numbers start at 1, as this API is designed for use in
723 : LUA
724 : */
725 : bool get_pwm(uint8_t channel, uint16_t &pwm) const;
726 :
727 1028 : uint32_t last_input_ms() const { return last_update_ms; };
728 :
729 : // method for other parts of the system (e.g. Button and mavlink)
730 : // to trigger auxiliary functions
731 29 : bool run_aux_function(RC_Channel::AUX_FUNC ch_option, RC_Channel::AuxSwitchPos pos, RC_Channel::AuxFuncTrigger::Source source, uint16_t source_index) {
732 29 : return channel(0)->run_aux_function(ch_option, pos, source, source_index);
733 : }
734 :
735 : // check if flight mode channel is assigned RC option
736 : // return true if assigned
737 : bool flight_mode_channel_conflicts_with_rc_option() const;
738 :
739 : // flight_mode_channel_number must be overridden in vehicle specific code
740 : virtual int8_t flight_mode_channel_number() const = 0;
741 :
742 : // set and get calibrating flag, stops arming if true
743 43 : void calibrating(bool b) { gcs_is_calibrating = b; }
744 140537 : bool calibrating() { return gcs_is_calibrating; }
745 :
746 : #if AP_SCRIPTING_ENABLED
747 : // get last aux cached value for scripting. Returns false if never set, otherwise 0,1,2
748 : bool get_aux_cached(RC_Channel::AUX_FUNC aux_fn, uint8_t &pos);
749 : #endif
750 :
751 : // returns true if we've ever seen RC input, via overrides or via
752 : // AP_RCProtocol
753 137199395 : bool has_ever_seen_rc_input() const {
754 137199395 : return _has_ever_seen_rc_input;
755 : }
756 :
757 : // get failsafe timeout in milliseconds
758 66524604 : uint32_t get_fs_timeout_ms() const { return MAX(_fs_timeout * 1000, 100); }
759 :
760 : // methods which return RC input channels used for various axes.
761 : const RC_Channel &get_roll_channel() const;
762 : const RC_Channel &get_pitch_channel() const;
763 : const RC_Channel &get_yaw_channel() const;
764 : const RC_Channel &get_throttle_channel() const;
765 : const RC_Channel &get_forward_channel() const;
766 : const RC_Channel &get_lateral_channel() const;
767 :
768 : RC_Channel &get_roll_channel();
769 : RC_Channel &get_pitch_channel();
770 : RC_Channel &get_yaw_channel();
771 : RC_Channel &get_throttle_channel();
772 : RC_Channel &get_forward_channel();
773 : RC_Channel &get_lateral_channel();
774 :
775 3731 : bool seen_neutral_rudder() const { return have_seen_neutral_rudder; }
776 :
777 : // returns true when pilot input should clear an active MAVLink override; vehicles override to define which axes count
778 : virtual bool has_pilot_input_for_override_clear();
779 :
780 : protected:
781 :
782 3585 : void new_override_received() {
783 3585 : has_new_overrides = true;
784 3585 : _has_had_override = true;
785 3585 : }
786 :
787 : // returns true if the channel's raw pwm is outside its trim deadzone
788 : static bool channel_outside_trim_dz(const RC_Channel &ch);
789 :
790 : // returns true if throttle moved beyond deadzone since override start
791 : bool throttle_moved_since_override_start() const;
792 :
793 : private:
794 : static RC_Channels *_singleton;
795 : // this static arrangement is to avoid static pointers in AP_Param tables
796 : static RC_Channel *channels;
797 :
798 : uint32_t last_update_ms;
799 : bool has_new_overrides;
800 : bool _has_had_rc_receiver; // true if we have had a direct detach RC receiver, does not include overrides
801 : bool _has_had_override; // true if we have had an override on any channel
802 : int16_t override_start_throttle; // throttle value at the moment an override was activated
803 :
804 : AP_Float _override_timeout;
805 : AP_Int32 _options;
806 : AP_Int32 _protocols;
807 : AP_Float _fs_timeout;
808 :
809 : // set to true if we see overrides or other RC input
810 : bool _has_ever_seen_rc_input;
811 :
812 : RC_Channel *flight_mode_channel();
813 : const RC_Channel *flight_mode_channel() const;
814 :
815 : // Allow override by default at start
816 : bool _gcs_overrides_enabled = true;
817 :
818 : // true if GCS is performing a RC calibration
819 : bool gcs_is_calibrating;
820 :
821 : #if AP_SCRIPTING_ENABLED
822 : // bitmask of last aux function value, 2 bits per function
823 : // value 0 means never set, otherwise level+1
824 : HAL_Semaphore aux_cache_sem;
825 : Bitmask<unsigned(RC_Channel::AUX_FUNC::AUX_FUNCTION_MAX)*2> aux_cached;
826 :
827 : void set_aux_cached(RC_Channel::AUX_FUNC aux_fn, RC_Channel::AuxSwitchPos pos);
828 : #endif
829 :
830 : const RC_Channel &get_rcmap_channel_nonnull(uint8_t rcmap_number) const;
831 : RC_Channel &get_rcmap_channel_nonnull(uint8_t rcmap_number);
832 :
833 : // time that rudder arming has been running
834 : uint32_t rudder_arm_timer;
835 : // true if we have seen a neutral rudder control input after
836 : // arming via rudder-input:
837 : bool have_seen_neutral_rudder;
838 : // check for arm/disarm command based on rudder stick position:
839 : void rudder_arm_disarm_check();
840 :
841 : // returns true if pilot stick input has exited any deadzone (or throttle moved)
842 : bool should_ignore_overrides(void);
843 967932 : void set_override_start_throttle(int16_t pwm) { override_start_throttle = pwm; }
844 : };
845 :
846 : RC_Channels &rc();
847 :
848 : #endif // AP_RC_CHANNEL_ENABLED
|