Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
stabilization.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2009 Antoine Drouin <poinix@gmail.com>
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 
28 #include "state.h"
29 
30 #if (STABILIZATION_FILTER_COMMANDS_ROLL_PITCH || STABILIZATION_FILTER_COMMANDS_YAW)
32 #endif
33 
35 
36 #if STABILIZATION_FILTER_CMD_ROLL_PITCH
37 #ifndef STABILIZATION_FILTER_CMD_ROLL_CUTOFF
38 #define STABILIZATION_FILTER_CMD_ROLL_CUTOFF 20.0
39 #endif
40 
41 #ifndef STABILIZATION_FILTER_CMD_PITCH_CUTOFF
42 #define STABILIZATION_FILTER_CMD_PITCH_CUTOFF 20.0
43 #endif
44 
45 struct SecondOrderLowPass_int filter_roll;
46 struct SecondOrderLowPass_int filter_pitch;
47 #endif
48 
49 #if STABILIZATION_FILTER_CMD_YAW
50 #ifndef STABILIZATION_FILTER_CMD_YAW_CUTOFF
51 #define STABILIZATION_FILTER_CMD_YAW_CUTOFF 20.0
52 #endif
53 
54 struct SecondOrderLowPass_int filter_yaw;
55 #endif
56 
58 {
59  for (uint8_t i = 0; i < COMMANDS_NB; i++) {
60  stabilization_cmd[i] = 0;
61  }
62 
63  // Initialize low pass filters
64 #if STABILIZATION_FILTER_CMD_ROLL_PITCH
65  init_second_order_low_pass_int(&filter_roll, STABILIZATION_FILTER_CMD_ROLL_CUTOFF, 0.7071, 1.0 / PERIODIC_FREQUENCY,
66  0.0);
67  init_second_order_low_pass_int(&filter_pitch, STABILIZATION_FILTER_CMD_PITCH_CUTOFF, 0.7071, 1.0 / PERIODIC_FREQUENCY,
68  0.0);
69 #endif
70 
71 #if STABILIZATION_FILTER_CMD_YAW
72  init_second_order_low_pass_int(&filter_yaw, STABILIZATION_FILTER_CMD_YAW_CUTOFF, 0.7071, 1.0 / PERIODIC_FREQUENCY, 0.0);
73 #endif
74 
75 }
76 
77 // compute sp_euler phi/theta for debugging/telemetry FIXME really needed ?
78 /* Rotate horizontal commands to body frame by psi */
79 static struct Int32Eulers stab_sp_rotate_i(struct Int32Vect2 *vect, int32_t heading)
80 {
81  struct Int32Eulers sp;
83  int32_t s_psi, c_psi;
84  PPRZ_ITRIG_SIN(s_psi, psi);
85  PPRZ_ITRIG_COS(c_psi, psi);
86  sp.phi = (-s_psi * vect->x + c_psi * vect->y) >> INT32_TRIG_FRAC;
87  sp.theta = -(c_psi * vect->x + s_psi * vect->y) >> INT32_TRIG_FRAC;
88  sp.psi = heading;
89  return sp;
90 }
91 
92 /* Rotate horizontal commands to body frame by psi */
93 static struct FloatEulers stab_sp_rotate_f(struct FloatVect2 *vect, float heading)
94 {
95  struct FloatEulers sp;
97  float s_psi = sinf(psi);
98  float c_psi = cosf(psi);
99  sp.phi = -s_psi * vect->x + c_psi * vect->y;
100  sp.theta = -c_psi * vect->x + s_psi * vect->y;
101  sp.psi = heading;
102  return sp;
103 }
104 
105 
107 {
108  /* Filter the commands & bound the result */
109 #if STABILIZATION_FILTER_CMD_ROLL_PITCH
110  stabilization_cmd[COMMAND_ROLL] = update_second_order_low_pass_int(&filter_roll, stabilization_cmd[COMMAND_ROLL]);
111  stabilization_cmd[COMMAND_PITCH] = update_second_order_low_pass_int(&filter_pitch, stabilization_cmd[COMMAND_PITCH]);
112 
113  BoundAbs(stabilization_cmd[COMMAND_ROLL], MAX_PPRZ);
114  BoundAbs(stabilization_cmd[COMMAND_PITCH], MAX_PPRZ);
115 #endif
116 #if STABILIZATION_FILTER_CMD_YAW
117  stabilization_cmd[COMMAND_YAW] = update_second_order_low_pass_int(&filter_yaw, stabilization_cmd[COMMAND_YAW]);
118 
119  BoundAbs(stabilization_cmd[COMMAND_YAW], MAX_PPRZ);
120 #endif
121 }
122 
124 {
125  if ((sp->type == STAB_SP_QUAT) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
126  if (sp->format == STAB_SP_INT) {
127  return sp->sp.quat_i;
128  } else {
129  struct Int32Quat quat;
130  QUAT_BFP_OF_REAL(quat, sp->sp.quat_f);
131  return quat;
132  }
133  } else if (sp->type == STAB_SP_EULERS) {
134  if (sp->format == STAB_SP_INT) {
135  struct Int32Quat quat;
136  int32_quat_of_eulers(&quat, &sp->sp.eulers_i);
137  return quat;
138  } else {
139  struct Int32Quat quat;
140  struct Int32Eulers eulers;
141  EULERS_BFP_OF_REAL(eulers, sp->sp.eulers_f);
142  int32_quat_of_eulers(&quat, &eulers);
143  return quat;
144  }
145  } else if (sp->type == STAB_SP_LTP) {
146  if (sp->format == STAB_SP_INT) {
147  struct Int32Quat quat;
148  quat_from_earth_cmd_i(&quat, &sp->sp.ltp_i.vect, sp->sp.ltp_i.heading);
149  return quat;
150  } else {
151  struct FloatQuat quat_f;
152  struct Int32Quat quat_i;
153  quat_from_earth_cmd_f(&quat_f, &sp->sp.ltp_f.vect, sp->sp.ltp_f.heading);
154  QUAT_BFP_OF_REAL(quat_i, quat_f);
155  return quat_i;
156  }
157  } else {
158  // error, rates setpoint
159  struct Int32Quat quat;
160  int32_quat_identity(&quat);
161  return quat;
162  }
163 }
164 
166 {
167  if ((sp->type == STAB_SP_QUAT) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
168  if (sp->format == STAB_SP_FLOAT) {
169  return sp->sp.quat_f;
170  } else {
171  struct FloatQuat quat;
172  QUAT_FLOAT_OF_BFP(quat, sp->sp.quat_i);
173  return quat;
174  }
175  } else if (sp->type == STAB_SP_EULERS) {
176  if (sp->format == STAB_SP_FLOAT) {
177  struct FloatQuat quat;
178  float_quat_of_eulers(&quat, &sp->sp.eulers_f);
179  return quat;
180  } else {
181  struct FloatQuat quat;
182  struct FloatEulers eulers;
183  EULERS_FLOAT_OF_BFP(eulers, sp->sp.eulers_i);
184  float_quat_of_eulers(&quat, &eulers);
185  return quat;
186  }
187  } else if (sp->type == STAB_SP_LTP) {
188  if (sp->format == STAB_SP_FLOAT) {
189  struct FloatQuat quat;
190  quat_from_earth_cmd_f(&quat, &sp->sp.ltp_f.vect, sp->sp.ltp_f.heading);
191  return quat;
192  } else {
193  struct FloatQuat quat_f;
194  struct Int32Quat quat_i;
195  quat_from_earth_cmd_i(&quat_i, &sp->sp.ltp_i.vect, sp->sp.ltp_i.heading);
196  QUAT_FLOAT_OF_BFP(quat_f, quat_i);
197  return quat_f;
198  }
199  } else {
200  // error, rates setpoint
201  struct FloatQuat quat;
202  float_quat_identity(&quat);
203  return quat;
204  }
205 }
206 
208 {
209  if (sp->type == STAB_SP_EULERS) {
210  if (sp->format == STAB_SP_INT) {
211  return sp->sp.eulers_i;
212  } else {
213  struct Int32Eulers eulers;
214  EULERS_BFP_OF_REAL(eulers, sp->sp.eulers_f);
215  return eulers;
216  }
217  } else if ((sp->type == STAB_SP_QUAT) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
218  if (sp->format == STAB_SP_INT) {
219  struct Int32Eulers eulers;
220  int32_eulers_of_quat(&eulers, &sp->sp.quat_i);
221  return eulers;
222  } else {
223  struct Int32Eulers eulers;
224  struct Int32Quat quat;
225  QUAT_BFP_OF_REAL(quat, sp->sp.quat_f);
226  int32_eulers_of_quat(&eulers, &quat);
227  return eulers;
228  }
229  } else if (sp->type == STAB_SP_LTP) {
230  if (sp->format == STAB_SP_INT) {
231  struct Int32Eulers eulers = stab_sp_rotate_i(&sp->sp.ltp_i.vect, sp->sp.ltp_i.heading);
232  return eulers;
233  } else {
234  struct FloatEulers eulers_f = stab_sp_rotate_f(&sp->sp.ltp_f.vect, sp->sp.ltp_f.heading);
235  struct Int32Eulers eulers_i;
236  EULERS_BFP_OF_REAL(eulers_i, eulers_f);
237  return eulers_i;
238  }
239  } else {
240  // error, rates setpoint
241  struct Int32Eulers eulers = {0};
242  return eulers;
243  }
244 }
245 
247 {
248  if (sp->type == STAB_SP_EULERS) {
249  if (sp->format == STAB_SP_FLOAT) {
250  return sp->sp.eulers_f;
251  } else {
252  struct FloatEulers eulers;
253  EULERS_FLOAT_OF_BFP(eulers, sp->sp.eulers_i);
254  return eulers;
255  }
256  } else if ((sp->type == STAB_SP_QUAT) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
257  if (sp->format == STAB_SP_FLOAT) {
258  struct FloatEulers eulers;
259  float_eulers_of_quat(&eulers, &sp->sp.quat_f);
260  return eulers;
261  } else {
262  struct FloatEulers eulers;
263  struct FloatQuat quat;
264  QUAT_FLOAT_OF_BFP(quat, sp->sp.quat_i);
265  float_eulers_of_quat(&eulers, &quat);
266  return eulers;
267  }
268  } else if (sp->type == STAB_SP_LTP) {
269  if (sp->format == STAB_SP_FLOAT) {
270  struct FloatEulers eulers = stab_sp_rotate_f(&sp->sp.ltp_f.vect, sp->sp.ltp_f.heading);
271  return eulers;
272  } else {
273  struct Int32Eulers eulers_i = stab_sp_rotate_i(&sp->sp.ltp_i.vect, sp->sp.ltp_i.heading);
274  struct FloatEulers eulers_f;
275  EULERS_FLOAT_OF_BFP(eulers_f, eulers_i);
276  return eulers_f;
277  }
278  } else {
279  // error, rates setpoint
280  struct FloatEulers eulers = {0, 0, 0};
281  return eulers;
282  }
283 }
284 
286 {
287  if ((sp->type == STAB_SP_RATES) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
288  if (sp->format == STAB_SP_INT) {
289  return sp->r_sp.rates_i;
290  } else {
291  struct Int32Rates rates;
292  RATES_BFP_OF_REAL(rates, sp->r_sp.rates_f);
293  return rates;
294  }
295  } else {
296  // error, attitude setpoint
297  struct Int32Rates rates = {0, 0, 0};
298  return rates;
299  }
300 }
301 
303 {
304  if ((sp->type == STAB_SP_RATES) || (sp->type == STAB_SP_QUAT_FF_RATE)) {
305  if (sp->format == STAB_SP_FLOAT) {
306  return sp->r_sp.rates_f;
307  } else {
308  struct FloatRates rates;
309  RATES_FLOAT_OF_BFP(rates, sp->r_sp.rates_i);
310  return rates;
311  }
312  } else {
313  // error, attitude setpoint
314  struct FloatRates rates = {0, 0, 0};
315  return rates;
316  }
317 }
318 
320 {
321  struct StabilizationSetpoint sp = {
322  .type = STAB_SP_QUAT,
323  .format = STAB_SP_INT,
324  .sp.quat_i = *quat
325  };
326  return sp;
327 }
328 
330 {
331  struct StabilizationSetpoint sp = {
332  .type = STAB_SP_QUAT,
333  .format = STAB_SP_FLOAT,
334  .sp.quat_f = *quat
335  };
336  return sp;
337 }
338 
340 {
341  struct StabilizationSetpoint sp = {
342  .type = STAB_SP_QUAT_FF_RATE,
343  .format = STAB_SP_FLOAT,
344  .sp.quat_f = *quat,
345  .r_sp.rates_f = *rates
346  };
347  return sp;
348 }
349 
351 {
352  struct StabilizationSetpoint sp = {
353  .type = STAB_SP_EULERS,
354  .format = STAB_SP_INT,
355  .sp.eulers_i = *eulers
356  };
357  return sp;
358 }
359 
361 {
362  struct StabilizationSetpoint sp = {
363  .type = STAB_SP_EULERS,
364  .format = STAB_SP_FLOAT,
365  .sp.eulers_f = *eulers
366  };
367  return sp;
368 }
369 
371 {
372  struct StabilizationSetpoint sp = {
373  .type = STAB_SP_LTP,
374  .format = STAB_SP_INT,
375  .sp.ltp_i.vect = *vect,
376  .sp.ltp_i.heading = heading
377  };
378  return sp;
379 }
380 
382 {
383  struct StabilizationSetpoint sp = {
384  .type = STAB_SP_LTP,
385  .format = STAB_SP_FLOAT,
386  .sp.ltp_f.vect = *vect,
387  .sp.ltp_f.heading = heading
388  };
389  return sp;
390 }
391 
393 {
394  struct StabilizationSetpoint sp = {
395  .type = STAB_SP_RATES,
396  .format = STAB_SP_INT,
397  .r_sp.rates_i = *rates
398  };
399  return sp;
400 }
401 
403 {
404  struct StabilizationSetpoint sp = {
405  .type = STAB_SP_RATES,
406  .format = STAB_SP_FLOAT,
407  .r_sp.rates_f = *rates
408  };
409  return sp;
410 }
411 
float psi
in radians
static void float_quat_identity(struct FloatQuat *q)
initialises a quaternion to identity
void float_quat_of_eulers(struct FloatQuat *q, struct FloatEulers *e)
quat of euler roation 'ZYX'
void float_eulers_of_quat(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'ZYX'
euler angles
Roation quaternion.
angular rates
#define EULERS_BFP_OF_REAL(_ei, _ef)
Definition: pprz_algebra.h:715
#define QUAT_BFP_OF_REAL(_qi, _qf)
Definition: pprz_algebra.h:752
#define RATES_BFP_OF_REAL(_ri, _rf)
Definition: pprz_algebra.h:765
#define QUAT_FLOAT_OF_BFP(_qf, _qi)
Definition: pprz_algebra.h:745
#define RATES_FLOAT_OF_BFP(_rf, _ri)
Definition: pprz_algebra.h:759
#define EULERS_FLOAT_OF_BFP(_ef, _ei)
Definition: pprz_algebra.h:709
int32_t psi
in rad with INT32_ANGLE_FRAC
int32_t theta
in rad with INT32_ANGLE_FRAC
void int32_eulers_of_quat(struct Int32Eulers *e, struct Int32Quat *q)
#define INT32_TRIG_FRAC
static void int32_quat_identity(struct Int32Quat *q)
initialises a quaternion to identity
void int32_quat_of_eulers(struct Int32Quat *q, struct Int32Eulers *e)
Quaternion from Euler angles.
euler angles
Rotation quaternion.
angular rates
static struct Int32Eulers * stateGetNedToBodyEulers_i(void)
Get vehicle body attitude euler angles (int).
Definition: state.h:1125
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1143
Simple first order low pass filter with bilinear transform.
static void init_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, float cut_off, float Q, float sample_time, int32_t value)
Init second order low pass filter(fixed point version).
static int32_t update_second_order_low_pass_int(struct SecondOrderLowPass_int *filter, int32_t value)
Update second order low pass filter state with a new value(fixed point version).
int32_t i[2]
input history
#define MAX_PPRZ
Definition: paparazzi.h:8
#define PPRZ_ITRIG_SIN(_s, _a)
#define PPRZ_ITRIG_COS(_c, _a)
struct StabilizationSetpoint stab_sp_from_ltp_i(struct Int32Vect2 *vect, int32_t heading)
static struct Int32Eulers stab_sp_rotate_i(struct Int32Vect2 *vect, int32_t heading)
Definition: stabilization.c:79
struct FloatEulers stab_sp_to_eulers_f(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_ltp_f(struct FloatVect2 *vect, float heading)
void stabilization_filter_commands(void)
struct StabilizationSetpoint stab_sp_from_rates_i(struct Int32Rates *rates)
struct Int32Rates stab_sp_to_rates_i(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_quat_ff_rates_f(struct FloatQuat *quat, struct FloatRates *rates)
struct StabilizationSetpoint stab_sp_from_quat_f(struct FloatQuat *quat)
struct StabilizationSetpoint stab_sp_from_quat_i(struct Int32Quat *quat)
static struct FloatEulers stab_sp_rotate_f(struct FloatVect2 *vect, float heading)
Definition: stabilization.c:93
int32_t stabilization_cmd[COMMANDS_NB]
Stabilization commands.
Definition: stabilization.c:34
struct FloatRates stab_sp_to_rates_f(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_eulers_f(struct FloatEulers *eulers)
struct Int32Quat stab_sp_to_quat_i(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_eulers_i(struct Int32Eulers *eulers)
struct Int32Eulers stab_sp_to_eulers_i(struct StabilizationSetpoint *sp)
void stabilization_init(void)
Definition: stabilization.c:57
struct StabilizationSetpoint stab_sp_from_rates_f(struct FloatRates *rates)
struct FloatQuat stab_sp_to_quat_f(struct StabilizationSetpoint *sp)
General stabilization interface for rotorcrafts.
void quat_from_earth_cmd_f(struct FloatQuat *quat, struct FloatVect2 *cmd, float heading)
void quat_from_earth_cmd_i(struct Int32Quat *quat, struct Int32Vect2 *cmd, int32_t heading)
Quaternion transformation functions.
API to get/set the generic vehicle states.
Stabilization setpoint.
Definition: stabilization.h:42
@ STAB_SP_RATES
body rates
Definition: stabilization.h:47
@ STAB_SP_EULERS
LTP to Body orientation in euler angles.
Definition: stabilization.h:45
@ STAB_SP_LTP
banking and heading in LTP (NED) frame
Definition: stabilization.h:46
@ STAB_SP_QUAT_FF_RATE
LTP to Body orientation in unit quaternion with precomputed feedforward rates.
Definition: stabilization.h:48
@ STAB_SP_QUAT
LTP to Body orientation in unit quaternion.
Definition: stabilization.h:44
union StabilizationSetpoint::@278 sp
union StabilizationSetpoint::@279 r_sp
int int32_t
Typedef defining 32 bit int type.
Definition: vl53l1_types.h:83
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
float heading
Definition: wedgebug.c:258