46 #include <mathlib/mathlib.h> 48 #ifdef MIXER_MULTIROTOR_USE_MOCK_GEOMETRY 56 { -0.707107, 0.707107, 1.000000, 1.000000 },
57 { 0.707107, -0.707107, 1.000000, 1.000000 },
58 { 0.707107, 0.707107, -1.000000, 1.000000 },
59 { -0.707107, -0.707107, -1.000000, 1.000000 },
64 const unsigned _config_rotor_count[] = {4};
65 const char *_config_key[] = {
"4x"};
72 #include "mixer_multirotor_normalized.generated.h" 77 #define debug(fmt, args...) do { } while(0) 83 float roll_scale,
float pitch_scale,
float yaw_scale,
float idle_speed) :
84 MultirotorMixer(control_cb, cb_handle, _config_index[(int)geometry], _config_rotor_count[(int)geometry])
93 unsigned rotor_count) :
94 Mixer(control_cb, cb_handle),
114 MultirotorGeometry geometry = MultirotorGeometry::MAX_GEOMETRY;
124 if (sscanf(buf,
"R: %7s %d %d %d %d%n", geomname, &s[0], &s[1], &s[2], &s[3], &used) != 5) {
125 debug(
"multirotor parse failed on '%s'", buf);
129 if (used > (
int)buflen) {
130 debug(
"OVERFLOW: multirotor spec used %d of %u", used, buflen);
136 if (buf ==
nullptr) {
137 debug(
"no line ending, line is incomplete");
141 debug(
"remaining in buf: %d, first char: %c", buflen, buf[0]);
145 if (!strcmp(geomname, _config_key[i])) {
146 geometry = (MultirotorGeometry)i;
151 if (geometry == MultirotorGeometry::MAX_GEOMETRY) {
152 debug(
"unrecognised geometry '%s'", geomname);
156 debug(
"adding multirotor mixer '%s'", geomname);
181 if (outputs[i] < min_output) {
182 float k = (min_output - outputs[i]) / desaturation_vector[i];
184 if (k < k_min) { k_min = k; }
186 if (k > k_max) { k_max = k; }
191 if (outputs[i] > max_output) {
192 float k = (max_output - outputs[i]) / desaturation_vector[i];
194 if (k < k_min) { k_min = k; }
196 if (k > k_max) { k_max = k; }
203 return k_min + k_max;
208 saturation_status &sat_status,
float min_output,
float max_output,
bool reduce_only)
const 212 if (reduce_only && k1 > 0.
f) {
217 outputs[i] += k1 * desaturation_vector[i];
226 outputs[i] += k2 * desaturation_vector[i];
374 (1.0
f - _thrust_factor) / (4.0
f * _thrust_factor * _thrust_factor) + (outputs[i] < 0.0
f ? 0.0
f : outputs[i] /
383 bool clipping_high =
false;
384 bool clipping_low_roll_pitch =
false;
385 bool clipping_low_yaw =
false;
394 clipping_low_roll_pitch =
true;
395 clipping_low_yaw =
true;
398 clipping_low_yaw =
true;
408 clipping_high =
true;
412 clipping_low_roll_pitch =
true;
413 clipping_low_yaw =
true;
439 bool clipping_low_yaw)
444 if (
_rotors[index].roll_scale > 0.0
f) {
448 }
else if (
_rotors[index].roll_scale < 0.0
f) {
454 if (
_rotors[index].pitch_scale > 0.0
f) {
458 }
else if (
_rotors[index].pitch_scale < 0.0
f) {
464 if (
_rotors[index].yaw_scale > 0.0
f) {
468 }
else if (
_rotors[index].yaw_scale < 0.0
f) {
479 if (clipping_low_roll_pitch) {
481 if (
_rotors[index].roll_scale > 0.0
f) {
485 }
else if (
_rotors[index].roll_scale < 0.0
f) {
491 if (
_rotors[index].pitch_scale > 0.0
f) {
495 }
else if (
_rotors[index].pitch_scale < 0.0
f) {
504 if (clipping_low_yaw) {
506 if (
_rotors[index].yaw_scale > 0.0
f) {
510 }
else if (
_rotors[index].yaw_scale < 0.0
f) {
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
float thrust_scale
scales thrust for this rotor
void update_saturation_status(unsigned index, bool clipping_high, bool clipping_low_roll_pitch, bool clipping_low_yaw)
void minimize_saturation(const float *desaturation_vector, float *outputs, saturation_status &sat_status, float min_output=0.f, float max_output=1.f, bool reduce_only=false) const
Minimize the saturation of the actuators by adding or substracting a fraction of desaturation_vector...
static const char * skipline(const char *buf, unsigned &buflen)
Skip a line.
static MultirotorMixer * from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen)
Factory method.
void mix_yaw(float yaw, float *outputs)
Mix yaw by updating an existing output vector (that already contains roll/pitch/thrust).
uint8_t MultirotorGeometryUnderlyingType
Supported multirotor geometries.
void mix_airmode_rpy(float roll, float pitch, float yaw, float thrust, float *outputs)
Mix roll, pitch, yaw, thrust and set the outputs vector.
int(* ControlCallback)(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control)
Fetch a control value.
float compute_desaturation_gain(const float *desaturation_vector, const float *outputs, saturation_status &sat_status, float min_output, float max_output) const
Computes the gain k by which desaturation_vector has to be multiplied in order to unsaturate the outp...
static bool string_well_formed(const char *buf, unsigned &buflen)
Check wether the string is well formed and suitable for parsing.
saturation_status _saturation_status
void mix_airmode_rp(float roll, float pitch, float yaw, float thrust, float *outputs)
Mix roll, pitch, yaw, thrust and set the outputs vector.
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
#define debug(fmt, args...)
virtual ~MultirotorMixer()
float get_control(uint8_t group, uint8_t index)
Invoke the client callback to fetch a control value.
MultirotorMixer(ControlCallback control_cb, uintptr_t cb_handle, MultirotorGeometry geometry, float roll_scale, float pitch_scale, float yaw_scale, float idle_speed)
Constructor.
float pitch_scale
scales pitch for this rotor
void mix_airmode_disabled(float roll, float pitch, float yaw, float thrust, float *outputs)
Mix roll, pitch, yaw, thrust and set the outputs vector.
unsigned mix(float *outputs, unsigned space) override
Perform the mixing function.
float roll_scale
scales roll for this rotor
Multi-rotor mixer for pre-defined vehicle geometries.
float yaw_scale
scales yaw for this rotor
Abstract class defining a mixer mixing zero or more inputs to one or more outputs.
struct MultirotorMixer::saturation_status::@66 flags