RC_Channel.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /// @file RC_Channel.h
  2. /// @brief RC_Channel manager, with EEPROM-backed storage of constants.
  3. #pragma once
  4. #include <AP_Common/AP_Common.h>
  5. #include <AP_Param/AP_Param.h>
  6. #define NUM_RC_CHANNELS 16
  7. /// @class RC_Channel
  8. /// @brief Object managing one RC channel
  9. class RC_Channel {
  10. public:
  11. friend class SRV_Channels;
  12. friend class RC_Channels;
  13. // Constructor
  14. RC_Channel(void);
  15. int16_t radio_in;
  16. AP_Int16 radio_min;
  17. AP_Int16 radio_trim;
  18. AP_Int16 radio_max;
  19. enum ChannelType {
  20. RC_CHANNEL_TYPE_ANGLE = 0,
  21. RC_CHANNEL_TYPE_RANGE = 1,
  22. };
  23. // setup the control preferences
  24. void set_range(uint16_t high);
  25. uint16_t get_range() const { return high_in; }
  26. void set_angle(uint16_t angle);
  27. bool get_reverse(void) const;
  28. void set_default_dead_zone(int16_t dzone);
  29. uint16_t get_dead_zone(void) const { return dead_zone; }
  30. // get the center stick position expressed as a control_in value
  31. int16_t get_control_mid() const;
  32. // read input from hal.rcin - create a control_in value
  33. bool update(void);
  34. void recompute_pwm_no_deadzone();
  35. // calculate an angle given dead_zone and trim. This is used by the quadplane code
  36. // for hover throttle
  37. int16_t pwm_to_angle_dz_trim(uint16_t dead_zone, uint16_t trim) const;
  38. /*
  39. return a normalised input for a channel, in range -1 to 1,
  40. centered around the channel trim. Ignore deadzone.
  41. */
  42. float norm_input() const;
  43. /*
  44. return a normalised input for a channel, in range -1 to 1,
  45. centered around the channel trim. Take into account the deadzone
  46. */
  47. float norm_input_dz() const;
  48. uint8_t percent_input() const;
  49. int16_t pwm_to_range() const;
  50. int16_t pwm_to_range_dz(uint16_t dead_zone) const;
  51. static const struct AP_Param::GroupInfo var_info[];
  52. // return true if input is within deadzone of trim
  53. bool in_trim_dz() const;
  54. int16_t get_radio_in() const { return radio_in;}
  55. void set_radio_in(int16_t val) {radio_in = val;}
  56. int16_t get_control_in() const { return control_in;}
  57. void set_control_in(int16_t val) { control_in = val;}
  58. void clear_override();
  59. void set_override(const uint16_t v, const uint32_t timestamp_us);
  60. bool has_override() const;
  61. int16_t stick_mixing(const int16_t servo_in);
  62. // get control input with zero deadzone
  63. int16_t get_control_in_zero_dz(void) const;
  64. int16_t get_radio_min() const {return radio_min.get();}
  65. void set_radio_min(int16_t val) { radio_min = val;}
  66. int16_t get_radio_max() const {return radio_max.get();}
  67. void set_radio_max(int16_t val) {radio_max = val;}
  68. int16_t get_radio_trim() const { return radio_trim.get();}
  69. void set_radio_trim(int16_t val) { radio_trim.set(val);}
  70. void save_radio_trim() { radio_trim.save();}
  71. void set_and_save_trim() { radio_trim.set_and_save_ifchanged(radio_in);}
  72. // set and save trim if changed
  73. void set_and_save_radio_trim(int16_t val) { radio_trim.set_and_save_ifchanged(val);}
  74. ChannelType get_type(void) const { return type_in; }
  75. AP_Int16 option; // e.g. activate EPM gripper / enable fence
  76. // auxillary switch support:
  77. void init_aux();
  78. bool read_aux();
  79. // Aux Switch enumeration
  80. enum class AUX_FUNC {
  81. DO_NOTHING = 0, // aux switch disabled
  82. FLIP = 2, // flip
  83. SIMPLE_MODE = 3, // change to simple mode
  84. RTL = 4, // change to RTL flight mode
  85. SAVE_TRIM = 5, // save current position as level
  86. SAVE_WP = 7, // save mission waypoint or RTL if in auto mode
  87. CAMERA_TRIGGER = 9, // trigger camera servo or relay
  88. RANGEFINDER = 10, // allow enabling or disabling rangefinder in flight which helps avoid surface tracking when you are far above the ground
  89. FENCE = 11, // allow enabling or disabling fence in flight
  90. RESETTOARMEDYAW = 12, // UNUSED
  91. SUPERSIMPLE_MODE = 13, // change to simple mode in middle, super simple at top
  92. ACRO_TRAINER = 14, // low = disabled, middle = leveled, high = leveled and limited
  93. SPRAYER = 15, // enable/disable the crop sprayer
  94. AUTO = 16, // change to auto flight mode
  95. AUTOTUNE = 17, // auto tune
  96. LAND = 18, // change to LAND flight mode
  97. GRIPPER = 19, // Operate cargo grippers low=off, middle=neutral, high=on
  98. PARACHUTE_ENABLE = 21, // Parachute enable/disable
  99. PARACHUTE_RELEASE = 22, // Parachute release
  100. PARACHUTE_3POS = 23, // Parachute disable, enable, release with 3 position switch
  101. MISSION_RESET = 24, // Reset auto mission to start from first command
  102. ATTCON_FEEDFWD = 25, // enable/disable the roll and pitch rate feed forward
  103. ATTCON_ACCEL_LIM = 26, // enable/disable the roll, pitch and yaw accel limiting
  104. RETRACT_MOUNT = 27, // Retract Mount
  105. RELAY = 28, // Relay pin on/off (only supports first relay)
  106. LANDING_GEAR = 29, // Landing gear controller
  107. LOST_VEHICLE_SOUND = 30, // Play lost vehicle sound
  108. MOTOR_ESTOP = 31, // Emergency Stop Switch
  109. MOTOR_INTERLOCK = 32, // Motor On/Off switch
  110. BRAKE = 33, // Brake flight mode
  111. RELAY2 = 34, // Relay2 pin on/off
  112. RELAY3 = 35, // Relay3 pin on/off
  113. RELAY4 = 36, // Relay4 pin on/off
  114. THROW = 37, // change to THROW flight mode
  115. AVOID_ADSB = 38, // enable AP_Avoidance library
  116. PRECISION_LOITER = 39, // enable precision loiter
  117. AVOID_PROXIMITY = 40, // enable object avoidance using proximity sensors (ie. horizontal lidar)
  118. ARMDISARM = 41, // arm or disarm vehicle
  119. SMART_RTL = 42, // change to SmartRTL flight mode
  120. INVERTED = 43, // enable inverted flight
  121. WINCH_ENABLE = 44, // winch enable/disable
  122. WINCH_CONTROL = 45, // winch control
  123. RC_OVERRIDE_ENABLE = 46, // enable RC Override
  124. USER_FUNC1 = 47, // user function #1
  125. USER_FUNC2 = 48, // user function #2
  126. USER_FUNC3 = 49, // user function #3
  127. LEARN_CRUISE = 50, // learn cruise throttle (Rover)
  128. MANUAL = 51, // manual mode
  129. ACRO = 52, // acro mode
  130. STEERING = 53, // steering mode
  131. HOLD = 54, // hold mode
  132. GUIDED = 55, // guided mode
  133. LOITER = 56, // loiter mode
  134. FOLLOW = 57, // follow mode
  135. CLEAR_WP = 58, // clear waypoints
  136. SIMPLE = 59, // simple mode
  137. ZIGZAG = 60, // zigzag mode
  138. ZIGZAG_SaveWP = 61, // zigzag save waypoint
  139. COMPASS_LEARN = 62, // learn compass offsets
  140. SAILBOAT_TACK = 63, // rover sailboat tack
  141. REVERSE_THROTTLE = 64, // reverse throttle input
  142. GPS_DISABLE = 65, // disable GPS for testing
  143. RELAY5 = 66, // Relay5 pin on/off
  144. RELAY6 = 67, // Relay6 pin on/off
  145. STABILIZE = 68, // stabilize mode
  146. POSHOLD = 69, // poshold mode
  147. ALTHOLD = 70, // althold mode
  148. FLOWHOLD = 71, // flowhold mode
  149. CIRCLE = 72, // circle mode
  150. DRIFT = 73, // drift mode
  151. SAILBOAT_MOTOR_3POS = 74, // Sailboat motoring 3pos
  152. KILL_IMU1 = 100, // disable first IMU (for IMU failure testing)
  153. KILL_IMU2 = 101, // disable second IMU (for IMU failure testing)
  154. // if you add something here, make sure to update the documentation of the parameter in RC_Channel.cpp!
  155. // also, if you add an option >255, you will need to fix duplicate_options_exist
  156. // inputs eventually used to replace RCMAP
  157. MAINSAIL = 207, // mainsail input
  158. };
  159. typedef enum AUX_FUNC aux_func_t;
  160. protected:
  161. // auxillary switch handling (n.b.: we store this as 2-bits!):
  162. enum aux_switch_pos_t : uint8_t {
  163. LOW, // indicates auxiliary switch is in the low position (pwm <1200)
  164. MIDDLE, // indicates auxiliary switch is in the middle position (pwm >1200, <1800)
  165. HIGH // indicates auxiliary switch is in the high position (pwm >1800)
  166. };
  167. virtual void init_aux_function(aux_func_t ch_option, aux_switch_pos_t);
  168. virtual void do_aux_function(aux_func_t ch_option, aux_switch_pos_t);
  169. void do_aux_function_avoid_proximity(const aux_switch_pos_t ch_flag);
  170. void do_aux_function_camera_trigger(const aux_switch_pos_t ch_flag);
  171. void do_aux_function_fence(const aux_switch_pos_t ch_flag);
  172. void do_aux_function_clear_wp(const aux_switch_pos_t ch_flag);
  173. void do_aux_function_gripper(const aux_switch_pos_t ch_flag);
  174. void do_aux_function_lost_vehicle_sound(const aux_switch_pos_t ch_flag);
  175. void do_aux_function_mission_reset(const aux_switch_pos_t ch_flag);
  176. void do_aux_function_rc_override_enable(const aux_switch_pos_t ch_flag);
  177. void do_aux_function_relay(uint8_t relay, bool val);
  178. void do_aux_function_sprayer(const aux_switch_pos_t ch_flag);
  179. typedef int8_t modeswitch_pos_t;
  180. virtual void mode_switch_changed(modeswitch_pos_t new_pos) {
  181. // no action by default (e.g. Tracker, Sub, who do their own thing)
  182. };
  183. private:
  184. // pwm is stored here
  185. // value generated from PWM normalised to configured scale
  186. int16_t control_in;
  187. AP_Int8 reversed;
  188. AP_Int16 dead_zone;
  189. ChannelType type_in;
  190. int16_t high_in;
  191. // the input channel this corresponds to
  192. uint8_t ch_in;
  193. // overrides
  194. uint16_t override_value;
  195. uint32_t last_override_time;
  196. int16_t pwm_to_angle() const;
  197. int16_t pwm_to_angle_dz(uint16_t dead_zone) const;
  198. // pwm value above which the option will be invoked:
  199. static const uint16_t AUX_PWM_TRIGGER_HIGH = 1800;
  200. // pwm value below which the option will be disabled:
  201. static const uint16_t AUX_PWM_TRIGGER_LOW = 1200;
  202. bool read_3pos_switch(aux_switch_pos_t &ret) const WARN_IF_UNUSED;
  203. // Structure used to detect and debounce switch changes
  204. struct {
  205. int8_t debounce_position = -1;
  206. int8_t current_position = -1;
  207. uint32_t last_edge_time_ms;
  208. } switch_state;
  209. void reset_mode_switch();
  210. void read_mode_switch();
  211. bool debounce_completed(int8_t position);
  212. };
  213. /*
  214. class RC_Channels. Hold the full set of RC_Channel objects
  215. */
  216. class RC_Channels {
  217. public:
  218. friend class SRV_Channels;
  219. friend class RC_Channel;
  220. // constructor
  221. RC_Channels(void);
  222. void init(void);
  223. // get singleton instance
  224. static RC_Channels *get_singleton() {
  225. return _singleton;
  226. }
  227. static const struct AP_Param::GroupInfo var_info[];
  228. // compatability functions for Plane:
  229. static uint16_t get_radio_in(const uint8_t chan) {
  230. RC_Channel *c = _singleton->channel(chan);
  231. if (c == nullptr) {
  232. return 0;
  233. }
  234. return c->get_radio_in();
  235. }
  236. static RC_Channel *rc_channel(const uint8_t chan) {
  237. return _singleton->channel(chan);
  238. }
  239. //end compatability functions for Plane
  240. virtual RC_Channel *channel(uint8_t chan) = 0;
  241. 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
  242. // returns the number of valid channels
  243. static uint8_t get_valid_channel_count(void); // returns the number of valid channels in the last read
  244. static int16_t get_receiver_rssi(void); // returns [0, 255] for receiver RSSI (0 is no link) if present, otherwise -1
  245. bool read_input(void); // returns true if new input has been read in
  246. static void clear_overrides(void); // clears any active overrides
  247. static bool receiver_bind(const int dsmMode); // puts the receiver in bind mode if present, returns true if success
  248. static void set_override(const uint8_t chan, const int16_t value, const uint32_t timestamp_ms = 0); // set a channels override value
  249. static bool has_active_overrides(void); // returns true if there are overrides applied that are valid
  250. class RC_Channel *find_channel_for_option(const RC_Channel::aux_func_t option);
  251. bool duplicate_options_exist();
  252. void init_aux_all();
  253. void read_aux_all();
  254. // mode switch handling
  255. void reset_mode_switch();
  256. virtual void read_mode_switch();
  257. // has_valid_input should be pure-virtual when Plane is converted
  258. virtual bool has_valid_input() const { return false; };
  259. bool gcs_overrides_enabled() const { return _gcs_overrides_enabled; }
  260. void set_gcs_overrides_enabled(bool enable) {
  261. _gcs_overrides_enabled = enable;
  262. if (!_gcs_overrides_enabled) {
  263. clear_overrides();
  264. }
  265. }
  266. // should we ignore RC failsafe bits from receivers?
  267. bool ignore_rc_failsafe(void) const {
  268. return get_singleton() != nullptr && (_options & uint32_t(Option::IGNORE_FAILSAFE));
  269. }
  270. bool ignore_overrides() const {
  271. return _options & uint32_t(Option::IGNORE_OVERRIDES);
  272. }
  273. bool ignore_receiver() const {
  274. return _options & uint32_t(Option::IGNORE_RECEIVER);
  275. }
  276. float override_timeout_ms() const {
  277. return _override_timeout.get() * 1e3f;
  278. }
  279. protected:
  280. enum class Option {
  281. IGNORE_RECEIVER = (1 << 0), // RC receiver modules
  282. IGNORE_OVERRIDES = (1 << 1), // MAVLink overrides
  283. IGNORE_FAILSAFE = (1 << 2), // ignore RC failsafe bits
  284. };
  285. void new_override_received() {
  286. has_new_overrides = true;
  287. }
  288. private:
  289. static RC_Channels *_singleton;
  290. // this static arrangement is to avoid static pointers in AP_Param tables
  291. static RC_Channel *channels;
  292. bool has_new_overrides;
  293. AP_Float _override_timeout;
  294. AP_Int32 _options;
  295. // flight_mode_channel_number must be overridden:
  296. virtual int8_t flight_mode_channel_number() const = 0;
  297. RC_Channel *flight_mode_channel();
  298. // Allow override by default at start
  299. bool _gcs_overrides_enabled = true;
  300. };
  301. RC_Channels &rc();