Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
motor_mixing.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2012 The Paparazzi Team
3  *
4  * This file is part of Paparazzi.
5  *
6  * Paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
29 #include "paparazzi.h"
30 
31 //#include <stdint.h>
32 #ifndef INT32_MIN
33 #define INT32_MIN (-2147483647-1)
34 #endif
35 
36 #ifndef INT32_MAX
37 #define INT32_MAX (2147483647)
38 #endif
39 
40 #if defined MOTOR_MIXING_MIN_MOTOR || defined MOTOR_MIXING_MAX_MOTOR
41 #error MIN_MOTOR and MAX_MOTOR have to be set via neutral/max of the respective servo
42 #endif
43 #define MOTOR_MIXING_MIN_MOTOR 0
44 #define MOTOR_MIXING_MAX_MOTOR MAX_PPRZ
45 
46 #ifndef MOTOR_MIXING_STOP_MOTOR
47 #define MOTOR_MIXING_STOP_MOTOR -MAX_PPRZ
48 #endif
49 
50 #ifndef MOTOR_MIXING_TRIM_ROLL
51 #define MOTOR_MIXING_TRIM_ROLL 0
52 #endif
53 
54 #ifndef MOTOR_MIXING_TRIM_PITCH
55 #define MOTOR_MIXING_TRIM_PITCH 0
56 #endif
57 
58 #ifndef MOTOR_MIXING_TRIM_YAW
59 #define MOTOR_MIXING_TRIM_YAW 0
60 #endif
61 
68 #ifndef MOTOR_MIXING_MAX_SATURATION_OFFSET
69 #define MOTOR_MIXING_MAX_SATURATION_OFFSET MAX_PPRZ/10
70 #endif
71 
72 #ifndef MOTOR_MIXING_MIN_MOTOR_STARTUP
73 #define MOTOR_MIXING_MIN_MOTOR_STARTUP MOTOR_MIXING_MIN_MOTOR
74 #endif
75 
76 #if defined (MOTOR_MIXING_MAX_NEGATIVE_MOTOR_STEP) || defined (MOTOR_MIXING_MAX_POSITIVE_MOTOR_STEP)
77 #define MOTOR_MIXING_USE_MAX_MOTOR_STEP_BINDING
78 
79 #ifndef MOTOR_MIXING_MAX_NEGATIVE_MOTOR_STEP
80 #define MOTOR_MIXING_MAX_NEGATIVE_MOTOR_STEP INT32_MIN
81 #endif
82 /*
83 #ifndef MOTOR_MIXING_MAX_POSITIVE_MOTOR_STEP
84 #define MOTOR_MIXING_MAX_POSITIVE_MOTOR_STEP INT32_MAX
85 #endif
86 */
87 #endif
88 
89 static const int32_t roll_coef[MOTOR_MIXING_NB_MOTOR] = MOTOR_MIXING_ROLL_COEF;
90 static const int32_t pitch_coef[MOTOR_MIXING_NB_MOTOR] = MOTOR_MIXING_PITCH_COEF;
91 static const int32_t yaw_coef[MOTOR_MIXING_NB_MOTOR] = MOTOR_MIXING_YAW_COEF;
92 static const int32_t thrust_coef[MOTOR_MIXING_NB_MOTOR] = MOTOR_MIXING_THRUST_COEF;
93 
95 
97 {
98  uint8_t i;
99  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
100  motor_mixing.commands[i] = 0;
101  motor_mixing.trim[i] =
107  }
110 }
111 
112 static void offset_commands(int32_t offset)
113 {
114  uint8_t j;
115  for (j = 0; j < MOTOR_MIXING_NB_MOTOR; j++) {
116  motor_mixing.commands[j] += (offset);
117  }
118 }
119 
120 static void bound_commands(void)
121 {
122  uint8_t j;
123  for (j = 0; j < MOTOR_MIXING_NB_MOTOR; j++) {
125  }
126 }
127 
128 static void bound_commands_step(void)
129 {
130 #ifdef MOTOR_MIXING_USE_MAX_MOTOR_STEP_BINDING
131  uint8_t j;
132  static int32_t prev_commands[MOTOR_MIXING_NB_MOTOR];
133  static uint8_t initialized = 0;
134 
135  if (initialized == 1) {
136  for (j = 0; j < MOTOR_MIXING_NB_MOTOR; j++) {
137  int32_t new_command_diff = motor_mixing.commands[j] - prev_commands[j];
138  Bound(new_command_diff,
139  MOTOR_MIXING_MAX_NEGATIVE_MOTOR_STEP, MOTOR_MIXING_MAX_POSITIVE_MOTOR_STEP);
140  motor_mixing.commands[j] = prev_commands[j] + new_command_diff;
141  }
142  } else {
143  initialized = 1;
144  }
145 
146  for (j = 0; j < MOTOR_MIXING_NB_MOTOR; j++) {
147  prev_commands[j] = motor_mixing.commands[j];
148  }
149 #endif
150 }
151 
153 {
154  int i;
155  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
156 #ifdef MOTOR_MIXING_STARTUP_DELAY
157  if (counter > i * max_counter / (MOTOR_MIXING_NB_MOTOR + MOTOR_MIXING_STARTUP_DELAY)) {
158  if (counter > MOTOR_MIXING_NB_MOTOR * max_counter /
159  (MOTOR_MIXING_NB_MOTOR + MOTOR_MIXING_STARTUP_DELAY))
160  {
162  (MOTOR_MIXING_MIN_MOTOR - MOTOR_MIXING_MIN_MOTOR_STARTUP) * counter / max_counter;
163  } else {
165  }
166  } else {
167  motor_mixing.commands[i] = 0;
168  }
169 #else
170  if (counter < i * max_counter / MOTOR_MIXING_NB_MOTOR) {
172  }
173 #endif
174  }
175 }
176 
177 void motor_mixing_run(bool_t motors_on, bool_t override_on, pprz_t in_cmd[])
178 {
179  uint8_t i;
180 #if !HITL
181  if (motors_on) {
182 #else
183  if (FALSE) {
184 #endif
185 
186  int32_t tmp_cmd;
187  int32_t max_overflow = 0;
188 
189  /* first calculate the highest priority part of the command:
190  * - add trim + roll + pitch + thrust for each motor
191  * - calc max saturation/overflow when yaw command is also added
192  */
193  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
195  roll_coef[i] * in_cmd[COMMAND_ROLL] +
196  pitch_coef[i] * in_cmd[COMMAND_PITCH] +
197  thrust_coef[i] * in_cmd[COMMAND_THRUST];
198 
199  /* compute the command with yaw for each motor to check how much it would saturate */
200  tmp_cmd = motor_mixing.commands[i] + yaw_coef[i] * in_cmd[COMMAND_YAW];
201  tmp_cmd /= MOTOR_MIXING_SCALE;
202 
203  /* remember max overflow (how much in saturation) */
204  if (-tmp_cmd > max_overflow) {
205  max_overflow = -tmp_cmd;
206  }
207  else if (tmp_cmd - MAX_PPRZ > max_overflow) {
208  max_overflow = tmp_cmd - MAX_PPRZ;
209  }
210  }
211 
212  /* calculate how much authority is left for yaw command */
213  int32_t yaw_authority = ABS(in_cmd[COMMAND_YAW]) - max_overflow;
214  Bound(yaw_authority, 0, MAX_PPRZ);
215  int32_t bounded_yaw_cmd = in_cmd[COMMAND_YAW];
216  BoundAbs(bounded_yaw_cmd, yaw_authority);
217 
218  /* min/max of commands */
219  int32_t min_cmd = INT32_MAX;
220  int32_t max_cmd = INT32_MIN;
221 
222  /* add the bounded yaw command and scale */
223  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
224  motor_mixing.commands[i] += yaw_coef[i] * bounded_yaw_cmd;
225  motor_mixing.commands[i] /= MOTOR_MIXING_SCALE;
226 
227  /* remember min/max */
228  if (motor_mixing.commands[i] < min_cmd) {
229  min_cmd = motor_mixing.commands[i];
230  }
231  if (motor_mixing.commands[i] > max_cmd) {
232  max_cmd = motor_mixing.commands[i];
233  }
234  }
235 
236  if (min_cmd < MOTOR_MIXING_MIN_MOTOR && max_cmd > MOTOR_MIXING_MAX_MOTOR) {
238  }
239 
240  /* In case of both min and max saturation, only lower the throttle
241  * instead of applying both. This should prevent your quad shooting up,
242  * but it might loose altitude in case of such a saturation failure.
243  */
244  if (max_cmd > MOTOR_MIXING_MAX_MOTOR) {
245  int32_t saturation_offset = MOTOR_MIXING_MAX_MOTOR - max_cmd;
246  BoundAbs(saturation_offset, MOTOR_MIXING_MAX_SATURATION_OFFSET);
247  offset_commands(saturation_offset);
249  } else if (min_cmd < MOTOR_MIXING_MIN_MOTOR) {
250  int32_t saturation_offset = MOTOR_MIXING_MIN_MOTOR - min_cmd;
251  BoundAbs(saturation_offset, MOTOR_MIXING_MAX_SATURATION_OFFSET);
252  offset_commands(saturation_offset);
254  }
255 
256  /* For testing motor failure */
257  if (motors_on && override_on) {
258  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
261  }
262  }
263  }
264  bound_commands();
266  } else {
267  for (i = 0; i < MOTOR_MIXING_NB_MOTOR; i++) {
269  }
270  }
271 }
#define MOTOR_MIXING_MAX_MOTOR
Definition: motor_mixing.c:44
static const int32_t roll_coef[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.c:89
#define MOTOR_MIXING_MAX_SATURATION_OFFSET
Maximum offset in case of saturation.
Definition: motor_mixing.c:69
int32_t trim[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.h:38
uint32_t nb_failure
Definition: motor_mixing.h:42
static const int32_t thrust_coef[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.c:92
static void bound_commands_step(void)
Definition: motor_mixing.c:128
void motor_mixing_run(bool_t motors_on, bool_t override_on, pprz_t in_cmd[])
Definition: motor_mixing.c:177
int16_t pprz_t
Definition: paparazzi.h:6
static const int32_t pitch_coef[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.c:90
static void bound_commands(void)
Definition: motor_mixing.c:120
static void offset_commands(int32_t offset)
Definition: motor_mixing.c:112
int32_t override_value[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.h:40
uint32_t nb_saturation
Definition: motor_mixing.h:41
#define INT32_MAX
Definition: motor_mixing.c:37
#define FALSE
Definition: std.h:5
#define MOTOR_MIXING_STOP_MOTOR
Definition: motor_mixing.c:47
void motor_mixing_init(void)
Definition: motor_mixing.c:96
unsigned long uint32_t
Definition: types.h:18
int32_t counter
signed long int32_t
Definition: types.h:19
static const int32_t yaw_coef[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.c:91
#define MOTOR_MIXING_TRIM_YAW
Definition: motor_mixing.c:59
unsigned char uint8_t
Definition: types.h:14
void motor_mixing_run_spinup(uint32_t counter, uint32_t max_counter)
Definition: motor_mixing.c:152
#define MOTOR_MIXING_MIN_MOTOR_STARTUP
Definition: motor_mixing.c:73
#define INT32_MIN
Definition: motor_mixing.c:33
struct MotorMixing motor_mixing
Definition: motor_mixing.c:94
#define MOTOR_MIXING_MIN_MOTOR
Definition: motor_mixing.c:43
#define MOTOR_MIXING_TRIM_ROLL
Definition: motor_mixing.c:51
#define MAX_PPRZ
Definition: paparazzi.h:8
int32_t commands[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.h:37
#define MOTOR_MIXING_TRIM_PITCH
Definition: motor_mixing.c:55
Motor Mixing.
bool_t override_enabled[MOTOR_MIXING_NB_MOTOR]
Definition: motor_mixing.h:39