Firmware
mixer.h
1 /****************************************************************************
2  *
3  * Copyright (C) 2012 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
128 #pragma once
129 
130 #include <stdint.h>
131 
134  float negative_scale;
135  float positive_scale;
136  float offset;
137  float min_output;
138  float max_output;
139 };
140 
143  uint8_t control_group;
144  uint8_t control_index;
145  struct mixer_scaler_s scaler;
146 };
147 
150  uint8_t control_count;
151  struct mixer_scaler_s output_scaler;
152  struct mixer_control_s controls[0];
153 };
154 
155 #define MIXER_SIMPLE_SIZE(_icount) (sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_control_s))
156 
157 
162 class Mixer
163 {
164 public:
165  enum class Airmode : int32_t {
166  disabled = 0,
167  roll_pitch = 1,
168  roll_pitch_yaw = 2
169  };
170 
173 
183  typedef int (* ControlCallback)(uintptr_t handle,
184  uint8_t control_group,
185  uint8_t control_index,
186  float &control);
187 
193  Mixer(ControlCallback control_cb, uintptr_t cb_handle);
194  virtual ~Mixer() {}
195 
203  virtual unsigned mix(float *outputs, unsigned space) = 0;
204 
210  virtual uint16_t get_saturation_status(void) = 0;
211 
218  virtual void groups_required(uint32_t &groups) = 0;
219 
226  virtual void set_max_delta_out_once(float delta_out_max) {}
227 
233  virtual unsigned set_trim(float trim) = 0;
234 
240  virtual unsigned get_trim(float *trim) = 0;
241 
242  /*
243  * @brief Sets the thrust factor used to calculate mapping from desired thrust to pwm.
244  *
245  * @param[in] val The value
246  */
247  virtual void set_thrust_factor(float val) {}
248 
254  virtual void set_airmode(Airmode airmode) {};
255 
256 protected:
258  ControlCallback _control_cb;
259  uintptr_t _cb_handle;
260 
268  float get_control(uint8_t group, uint8_t index);
269 
277  static float scale(const mixer_scaler_s &scaler, float input);
278 
285  static int scale_check(struct mixer_scaler_s &scaler);
286 
294  static const char *findtag(const char *buf, unsigned &buflen, char tag);
295 
302  static char findnexttag(const char *buf, unsigned buflen);
303 
311  static const char *skipline(const char *buf, unsigned &buflen);
312 
316  static bool string_well_formed(const char *buf, unsigned &buflen);
317 
318 private:
319 
320  /* do not allow to copy due to pointer data members */
321  Mixer(const Mixer &);
322  Mixer &operator=(const Mixer &);
323 };
324 
329 class MixerGroup : public Mixer
330 {
331 public:
332  MixerGroup(ControlCallback control_cb, uintptr_t cb_handle);
333  ~MixerGroup();
334 
335  unsigned mix(float *outputs, unsigned space) override;
336  uint16_t get_saturation_status(void) override;
337  void groups_required(uint32_t &groups) override;
338 
344  void add_mixer(Mixer *mixer);
345 
349  void reset();
350 
354  unsigned count();
355 
411  int load_from_buf(const char *buf, unsigned &buflen);
412 
423  void set_max_delta_out_once(float delta_out_max) override;
424 
425  /*
426  * Invoke the set_offset method of each mixer in the group
427  * for each value in page r_page_servo_control_trim
428  */
429  unsigned set_trims(int16_t *v, unsigned n);
430 
431  unsigned set_trim(float trim) override
432  {
433  return 0;
434  }
435 
436  unsigned get_trims(int16_t *values);
437 
438  unsigned get_trim(float *trim) override
439  {
440  return 0;
441  }
442 
448  void set_thrust_factor(float val) override;
449 
450  void set_airmode(Airmode airmode) override;
451 
452 private:
453  Mixer *_first;
455  /* do not allow to copy due to pointer data members */
456  MixerGroup(const MixerGroup &);
457  MixerGroup operator=(const MixerGroup &);
458 };
459 
465 class NullMixer : public Mixer
466 {
467 public:
468  NullMixer();
469  ~NullMixer() {}
470 
484  static NullMixer *from_text(const char *buf, unsigned &buflen);
485 
486  unsigned mix(float *outputs, unsigned space) override;
487  uint16_t get_saturation_status(void) override;
488  void groups_required(uint32_t &groups) override;
489  unsigned set_trim(float trim) override
490  {
491  return 1;
492  }
493 
494  unsigned get_trim(float *trim) override
495  {
496  return 1;
497  }
498 
499 };
500 
506 class SimpleMixer : public Mixer
507 {
508 public:
516  SimpleMixer(ControlCallback control_cb,
517  uintptr_t cb_handle,
518  mixer_simple_s *mixinfo);
519  ~SimpleMixer();
520 
537  static SimpleMixer *from_text(Mixer::ControlCallback control_cb,
538  uintptr_t cb_handle,
539  const char *buf,
540  unsigned &buflen);
541 
555  static SimpleMixer *pwm_input(Mixer::ControlCallback control_cb, uintptr_t cb_handle, unsigned input, uint16_t min,
556  uint16_t mid, uint16_t max);
557 
558  unsigned mix(float *outputs, unsigned space) override;
559  uint16_t get_saturation_status(void) override;
560  void groups_required(uint32_t &groups) override;
561 
570  int check();
571 
572  unsigned set_trim(float trim) override;
573 
574  unsigned get_trim(float *trim) override;
575 
576 protected:
577 
578 private:
579  mixer_simple_s *_pinfo;
580 
581  static int parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler);
582  static int parse_control_scaler(const char *buf,
583  unsigned &buflen,
584  mixer_scaler_s &scaler,
585  uint8_t &control_group,
586  uint8_t &control_index);
587 
588  /* do not allow to copy due to ptr data members */
589  SimpleMixer(const SimpleMixer &);
590  SimpleMixer operator=(const SimpleMixer &);
591 };
592 
598 typedef unsigned int MultirotorGeometryUnderlyingType;
599 enum class MultirotorGeometry : MultirotorGeometryUnderlyingType;
600 
607 class MultirotorMixer : public Mixer
608 {
609 public:
614  struct Rotor {
615  float roll_scale;
616  float pitch_scale;
617  float yaw_scale;
618  float thrust_scale;
619  };
620 
637  MultirotorMixer(ControlCallback control_cb,
638  uintptr_t cb_handle,
639  MultirotorGeometry geometry,
640  float roll_scale,
641  float pitch_scale,
642  float yaw_scale,
643  float idle_speed);
644 
653  MultirotorMixer(ControlCallback control_cb,
654  uintptr_t cb_handle,
655  Rotor *rotors,
656  unsigned rotor_count);
657 
658  ~MultirotorMixer();
659 
676  static MultirotorMixer *from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf,
677  unsigned &buflen);
678 
679  unsigned mix(float *outputs, unsigned space) override;
680  uint16_t get_saturation_status(void) override;
681  void groups_required(uint32_t &groups) override;
682 
693  void set_max_delta_out_once(float delta_out_max) override { _delta_out_max = delta_out_max; }
694 
695  unsigned set_trim(float trim) override
696  {
697  return _rotor_count;
698  }
699 
700  unsigned get_trim(float *trim) override
701  {
702  return _rotor_count;
703  }
704 
710  void set_thrust_factor(float val) override { _thrust_factor = val; }
711 
712  void set_airmode(Airmode airmode) override;
713 
715  struct {
716  uint16_t valid : 1; // 0 - true when the saturation status is used
717  uint16_t motor_pos : 1; // 1 - true when any motor has saturated in the positive direction
718  uint16_t motor_neg : 1; // 2 - true when any motor has saturated in the negative direction
719  uint16_t roll_pos : 1; // 3 - true when a positive roll demand change will increase saturation
720  uint16_t roll_neg : 1; // 4 - true when a negative roll demand change will increase saturation
721  uint16_t pitch_pos : 1; // 5 - true when a positive pitch demand change will increase saturation
722  uint16_t pitch_neg : 1; // 6 - true when a negative pitch demand change will increase saturation
723  uint16_t yaw_pos : 1; // 7 - true when a positive yaw demand change will increase saturation
724  uint16_t yaw_neg : 1; // 8 - true when a negative yaw demand change will increase saturation
725  uint16_t thrust_pos : 1; // 9 - true when a positive thrust demand change will increase saturation
726  uint16_t thrust_neg : 1; //10 - true when a negative thrust demand change will increase saturation
727  } flags;
728  uint16_t value;
729  };
730 
731 private:
739  float compute_desaturation_gain(const float *desaturation_vector, const float *outputs, saturation_status &sat_status,
740  float min_output, float max_output) const;
741 
760  void minimize_saturation(const float *desaturation_vector, float *outputs, saturation_status &sat_status,
761  float min_output = 0.f, float max_output = 1.f, bool reduce_only = false) const;
762 
770  inline void mix_airmode_rp(float roll, float pitch, float yaw, float thrust, float *outputs);
771 
778  inline void mix_airmode_rpy(float roll, float pitch, float yaw, float thrust, float *outputs);
779 
788  inline void mix_airmode_disabled(float roll, float pitch, float yaw, float thrust, float *outputs);
789 
800  inline void mix_yaw(float yaw, float *outputs);
801 
802  void update_saturation_status(unsigned index, bool clipping_high, bool clipping_low_roll_pitch, bool clipping_low_yaw);
803 
804  float _roll_scale;
805  float _pitch_scale;
806  float _yaw_scale;
807  float _idle_speed;
808  float _delta_out_max;
809  float _thrust_factor;
810 
811  Airmode _airmode;
812 
813  saturation_status _saturation_status;
814 
815  unsigned _rotor_count;
816  const Rotor *_rotors;
817 
818  float *_outputs_prev = nullptr;
819  float *_tmp_array = nullptr;
820 
821  /* do not allow to copy due to ptr data members */
823  MultirotorMixer operator=(const MultirotorMixer &);
824 };
825 
828  float angle;
829  float arm_length;
830  float scale;
831  float offset;
832  float min_output;
833  float max_output;
834 };
835 
836 #define HELI_CURVES_NR_POINTS 5
837 
839 struct mixer_heli_s {
840  uint8_t control_count;
841  float throttle_curve[HELI_CURVES_NR_POINTS];
842  float pitch_curve[HELI_CURVES_NR_POINTS];
843  struct mixer_heli_servo_s servos[4];
844 };
845 
852 class HelicopterMixer : public Mixer
853 {
854 public:
862  HelicopterMixer(ControlCallback control_cb,
863  uintptr_t cb_handle,
864  mixer_heli_s *mixer_info);
865 
866  ~HelicopterMixer() = default;
867 
884  static HelicopterMixer *from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf,
885  unsigned &buflen);
886 
887  unsigned mix(float *outputs, unsigned space) override;
888  void groups_required(uint32_t &groups) override;
889 
890  uint16_t get_saturation_status(void) override { return 0; }
891 
892  unsigned set_trim(float trim) override
893  {
894  return 4;
895  }
896 
897  unsigned get_trim(float *trim) override
898  {
899  return 4;
900  }
901 
902 private:
903  mixer_heli_s _mixer_info;
904 
905  /* do not allow to copy */
907  HelicopterMixer operator=(const HelicopterMixer &);
908 };
unsigned get_trim(float *trim) override
Get trim offset for this mixer.
Definition: mixer.h:438
simple mixer
Definition: mixer.h:149
Abstract class defining a mixer mixing zero or more inputs to one or more outputs.
Definition: mixer.h:162
float roll_scale
scales roll for this rotor
Definition: mixer.h:615
void set_thrust_factor(float val) override
Sets the thrust factor used to calculate mapping from desired thrust to pwm.
Definition: mixer.h:710
Definition: mixer.h:714
float yaw_scale
scales yaw for this rotor
Definition: mixer.h:617
void set_max_delta_out_once(float delta_out_max) override
Update slew rate parameter.
Definition: mixer.h:693
Simple summing mixer.
Definition: mixer.h:506
virtual void set_airmode(Airmode airmode)
Set airmode.
Definition: mixer.h:254
unsigned set_trim(float trim) override
Set trim offset for this mixer.
Definition: mixer.h:892
Group of mixers, built up from single mixers and processed in order when mixing.
Definition: mixer.h:329
unsigned get_trim(float *trim) override
Get trim offset for this mixer.
Definition: mixer.h:700
uint16_t get_saturation_status(void) override
Get the saturation status.
Definition: mixer.h:890
Mixer * _next
next mixer in a list
Definition: mixer.h:172
virtual void set_max_delta_out_once(float delta_out_max)
Empty method, only implemented for MultirotorMixer and MixerGroup class.
Definition: mixer.h:226
void reset(enum BMP280_BUS busid)
Reset the driver.
Definition: bmp280.cpp:743
Definition: blocks.cpp:46
uint8_t control_count
number of inputs
Definition: mixer.h:840
Multi-rotor mixer for pre-defined vehicle geometries.
Definition: mixer.h:607
float pitch_scale
scales pitch for this rotor
Definition: mixer.h:616
Generic helicopter mixer for helicopters with swash plate.
Definition: mixer.h:852
simple channel scaler
Definition: mixer.h:133
mixer input
Definition: mixer.h:142
helicopter swash plate mixer
Definition: mixer.h:839
uint8_t control_count
number of inputs
Definition: mixer.h:150
unsigned get_trim(float *trim) override
Get trim offset for this mixer.
Definition: mixer.h:494
unsigned set_trim(float trim) override
Set trim offset for this mixer.
Definition: mixer.h:695
helicopter swash servo mixer
Definition: mixer.h:827
Precalculated rotor mix.
Definition: mixer.h:614
uint8_t control_index
index within the control group
Definition: mixer.h:144
uint8_t control_group
group from which the input reads
Definition: mixer.h:143
int(* ControlCallback)(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control)
Fetch a control value.
Definition: mixer.h:183
float thrust_scale
scales thrust for this rotor
Definition: mixer.h:618
unsigned set_trim(float trim) override
Set trim offset for this mixer.
Definition: mixer.h:489
unsigned set_trim(float trim) override
Set trim offset for this mixer.
Definition: mixer.h:431
Null mixer; returns zero.
Definition: mixer.h:465
unsigned get_trim(float *trim) override
Get trim offset for this mixer.
Definition: mixer.h:897