Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
guidance_indi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Ewoud Smeur <ewoud.smeur@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 
30 #include "generated/airframe.h"
32 #include "subsystems/ins/ins_int.h"
34 #include "state.h"
35 #include "subsystems/imu.h"
40 #include "mcu_periph/sys_time.h"
41 #include "autopilot.h"
44 #include "stdio.h"
45 
48 struct FloatVect3 sp_accel = {0.0,0.0,0.0};
49 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
50 float thrust_in_specific_force_gain = GUIDANCE_INDI_SPECIFIC_FORCE_GAIN;
51 
52 #ifndef GUIDANCE_INDI_THRUST_DYNAMICS
53 #ifndef STABILIZATION_INDI_ACT_DYN_P
54 #error "You need to define GUIDANCE_INDI_THRUST_DYNAMICS to be able to use indi vertical control"
55 #else // assume that the same actuators are used for thrust as for roll (e.g. quadrotor)
56 #define GUIDANCE_INDI_THRUST_DYNAMICS STABILIZATION_INDI_ACT_DYN_P
57 #endif
58 #endif //GUIDANCE_INDI_THRUST_DYNAMICS
59 
60 #endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
61 
62 
66 float filt_accelzbody = 0;
67 float filt_accelzbodyd = 0;
69 float roll_filt = 0;
70 float roll_filtd = 0;
71 float roll_filtdd = 0;
72 float pitch_filt = 0;
73 float pitch_filtd = 0;
74 float pitch_filtdd = 0;
75 float thrust_act = 0;
76 float thrust_filt = 0;
77 float thrust_filtd = 0;
78 float thrust_filtdd = 0;
79 
80 struct FloatMat33 Ga;
83 
84 float filter_omega = 20.0;
85 float filter_zeta = 0.65;
86 
88 float thrust_in;
89 
94 void guidance_indi_enter(void) {
95  filt_accelzbody = 0;
96  filt_accelzbodyd = 0;
98  roll_filt = 0;
99  roll_filtd = 0;
100  roll_filtdd = 0;
101  pitch_filt = 0;
102  pitch_filtd = 0;
103  pitch_filtdd = 0;
107  thrust_in = 0.0;
108  thrust_act = 0;
109  thrust_filt = 0;
110  thrust_filtd = 0;
111  thrust_filtdd = 0;
112 }
113 
120 void guidance_indi_run(bool in_flight, int32_t heading) {
121 
122  //filter accel to get rid of noise
124  //filter attitude to synchronize with accel
126 
127  //Linear controller to find the acceleration setpoint from position and velocity
128  float pos_x_err = POS_FLOAT_OF_BFP(guidance_h.ref.pos.x) - stateGetPositionNed_f()->x;
129  float pos_y_err = POS_FLOAT_OF_BFP(guidance_h.ref.pos.y) - stateGetPositionNed_f()->y;
130  float pos_z_err = POS_FLOAT_OF_BFP(guidance_v_z_ref - stateGetPositionNed_i()->z);
131 
132  float speed_sp_x = pos_x_err * guidance_indi_pos_gain;
133  float speed_sp_y = pos_y_err * guidance_indi_pos_gain;
134  float speed_sp_z = pos_z_err * guidance_indi_pos_gain;
135 
136  sp_accel.x = (speed_sp_x - stateGetSpeedNed_f()->x) * guidance_indi_speed_gain;
137  sp_accel.y = (speed_sp_y - stateGetSpeedNed_f()->y) * guidance_indi_speed_gain;
138  sp_accel.z = (speed_sp_z - stateGetSpeedNed_f()->z) * guidance_indi_speed_gain;
139 
140 #ifdef GUIDANCE_INDI_RC_DEBUG
141  //for rc control horizontal, rotate from body axes to NED
142  float psi = stateGetNedToBodyEulers_f()->psi;
143  float rc_x = -(radio_control.values[RADIO_PITCH]/9600.0)*8.0;
144  float rc_y = (radio_control.values[RADIO_ROLL]/9600.0)*8.0;
145  sp_accel.x = cosf(psi) * rc_x - sinf(psi) * rc_y;
146  sp_accel.y = sinf(psi) * rc_x + cosf(psi) * rc_y;
147 
148  //for rc vertical control
149  sp_accel.z = -(radio_control.values[RADIO_THROTTLE]-4500)*5.0/9600.0;
150 #endif
151 
152  //Calculate matrix of partial derivatives
154  //Invert this matrix
155  MAT33_INV(Ga_inv, Ga);
156 
157  struct FloatVect3 a_diff = { sp_accel.x - filt_accel_ned.x, sp_accel.y -filt_accel_ned.y, sp_accel.z -filt_accel_ned.z};
158 
159  //Bound the acceleration error so that the linearization still holds
160  Bound(a_diff.x, -6.0, 6.0);
161  Bound(a_diff.y, -6.0, 6.0);
162  Bound(a_diff.z, -9.0, 9.0);
163 
164  //If the thrust to specific force ratio has been defined, include vertical control
165  //else ignore the vertical acceleration error
166 #ifndef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
167  a_diff.z = 0.0;
168 #endif
169 
170  //Calculate roll,pitch and thrust command
171  MAT33_VECT3_MUL(euler_cmd, Ga_inv, a_diff);
172 
175  //zero psi command, because a roll/pitch quat will be constructed later
177 
178 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
180 
181  //Add the increment in specific force * specific_force_to_thrust_gain to the filtered thrust
182  thrust_in = thrust_filt + euler_cmd.z*thrust_in_specific_force_gain;
183  Bound(thrust_in, 0, 9600);
184 
185 #ifdef GUIDANCE_INDI_RC_DEBUG
187  thrust_in = 0;
188  }
189 #endif
190 
191  //Overwrite the thrust command from guidance_v
192  stabilization_cmd[COMMAND_THRUST] = thrust_in;
193 #endif
194 
195  //Bound euler angles to prevent flipping
198 
199  //set the quat setpoint with the calculated roll and pitch
201 }
202 
203 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
204 
209 {
210  thrust_act = thrust_act + GUIDANCE_INDI_THRUST_DYNAMICS * (thrust_in - thrust_act);
211 
212  thrust_filt = thrust_filt + thrust_filtd / PERIODIC_FREQUENCY;
213  thrust_filtd = thrust_filtd + thrust_filtdd / PERIODIC_FREQUENCY;
215 }
216 #endif
217 
224 {
225  VECT3_ADD_SCALED(filt_accel_ned, filt_accel_ned_d, 1.0/PERIODIC_FREQUENCY);
226 
227  VECT3_ADD_SCALED(filt_accel_ned_d, filt_accel_ned_dd, 1.0/PERIODIC_FREQUENCY);
228 
232 }
233 
239 {
240  roll_filt = roll_filt + roll_filtd / PERIODIC_FREQUENCY;
241  pitch_filt = pitch_filt + pitch_filtd / PERIODIC_FREQUENCY;
242 
243  roll_filtd = roll_filtd + roll_filtdd / PERIODIC_FREQUENCY;
244  pitch_filtd = pitch_filtd + pitch_filtdd / PERIODIC_FREQUENCY;
245 
248 }
249 
256 void guidance_indi_calcG(struct FloatMat33 *Gmat) {
257 
258  struct FloatEulers *euler = stateGetNedToBodyEulers_f();
259 
260  float sphi = sinf(euler->phi);
261  float cphi = cosf(euler->phi);
262  float stheta = sinf(euler->theta);
263  float ctheta = cosf(euler->theta);
264  float spsi = sinf(euler->psi);
265  float cpsi = cosf(euler->psi);
266  //minus gravity is a guesstimate of the thrust force, thrust measurement would be better
267  float T = -9.81;
268 
269  RMAT_ELMT(*Gmat, 0, 0) = (cphi*spsi - sphi*cpsi*stheta)*T;
270  RMAT_ELMT(*Gmat, 1, 0) = (-sphi*spsi*stheta - cpsi*cphi)*T;
271  RMAT_ELMT(*Gmat, 2, 0) = -ctheta*sphi*T;
272  RMAT_ELMT(*Gmat, 0, 1) = (cphi*cpsi*ctheta)*T;
273  RMAT_ELMT(*Gmat, 1, 1) = (cphi*spsi*ctheta)*T;
274  RMAT_ELMT(*Gmat, 2, 1) = -stheta*cphi*T;
275  RMAT_ELMT(*Gmat, 0, 2) = sphi*spsi + cphi*cpsi*stheta;
276  RMAT_ELMT(*Gmat, 1, 2) = cphi*spsi*stheta - cpsi*sphi;
277  RMAT_ELMT(*Gmat, 2, 2) = cphi*ctheta;
278 }
279 
288 {
289  struct FloatQuat q_rp_cmd;
290  //this is a quaternion without yaw! add the desired yaw before you use it!
291  float_quat_of_eulers(&q_rp_cmd, indi_rp_cmd);
292 
293  /* get current heading */
294  const struct FloatVect3 zaxis = {0., 0., 1.};
295  struct FloatQuat q_yaw;
296 
297  float_quat_of_axis_angle(&q_yaw, &zaxis, stateGetNedToBodyEulers_f()->psi);
298 
299  /* roll/pitch commands applied to to current heading */
300  struct FloatQuat q_rp_sp;
301  float_quat_comp(&q_rp_sp, &q_yaw, &q_rp_cmd);
302  float_quat_normalize(&q_rp_sp);
303 
304  struct FloatQuat q_sp;
305 
306  if (in_flight) {
307  /* get current heading setpoint */
308  struct FloatQuat q_yaw_sp;
309  float_quat_of_axis_angle(&q_yaw_sp, &zaxis, ANGLE_FLOAT_OF_BFP(heading));
310 
311 
312  /* rotation between current yaw and yaw setpoint */
313  struct FloatQuat q_yaw_diff;
314  float_quat_comp_inv(&q_yaw_diff, &q_yaw_sp, &q_yaw);
315 
316  /* compute final setpoint with yaw */
317  float_quat_comp_norm_shortest(&q_sp, &q_rp_sp, &q_yaw_diff);
318  } else {
319  QUAT_COPY(q_sp, q_rp_sp);
320  }
321 
323 }
float filter_zeta
Definition: guidance_indi.c:85
float filt_accelzbody
Definition: guidance_indi.c:66
void guidance_indi_enter(void)
Call upon entering indi guidance.
Definition: guidance_indi.c:94
void float_quat_comp_inv(struct FloatQuat *a2b, struct FloatQuat *a2c, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
void float_quat_of_eulers(struct FloatQuat *q, struct FloatEulers *e)
Quaternion from Euler angles.
float y
in meters
float thrust_filtdd
Definition: guidance_indi.c:78
float phi
in radians
struct FloatMat33 Ga
Definition: guidance_indi.c:80
#define RADIO_ROLL
Definition: spektrum_arch.h:43
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1125
void float_quat_comp(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
General attitude stabilization interface for rotorcrafts.
struct FloatVect3 sp_accel
Definition: guidance_indi.c:48
float pitch_filtdd
Definition: guidance_indi.c:74
float thrust_filt
Definition: guidance_indi.c:76
float thrust_act
Definition: guidance_indi.c:75
float psi
in radians
Vertical guidance for rotorcrafts.
struct HorizontalGuidanceReference ref
reference calculated from setpoints
Definition: guidance_h.h:100
struct HorizontalGuidance guidance_h
Definition: guidance_h.c:80
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
Definition: radio_control.h:58
void guidance_indi_filter_thrust(void)
float roll_filtdd
Definition: guidance_indi.c:71
#define ANGLE_FLOAT_OF_BFP(_ai)
struct Int32Quat stab_att_sp_quat
with INT32_QUAT_FRAC
float filter_omega
Definition: guidance_indi.c:84
euler angles
float z
in meters
struct FloatVect3 filt_accel_ned_d
Definition: guidance_indi.c:64
Roation quaternion.
void guidance_indi_filter_accel(void)
low pass the accelerometer measurements with a second order filter to remove noise from vibrations ...
#define QUAT_COPY(_qo, _qi)
Definition: pprz_algebra.h:532
float theta
in radians
#define FLOAT_VECT3_ZERO(_v)
static float heading
Definition: ahrs_infrared.c:45
struct FloatVect3 filt_accel_ned_dd
Definition: guidance_indi.c:65
void guidance_indi_calcG(struct FloatMat33 *Gmat)
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition: state.h:896
Architecture independent timing functions.
float guidance_indi_pos_gain
Definition: guidance_indi.c:46
#define RADIO_PITCH
Definition: spektrum_arch.h:44
float thrust_filtd
Definition: guidance_indi.c:77
static struct NedCoor_f * stateGetAccelNed_f(void)
Get acceleration in NED coordinates (float).
Definition: state.h:1020
struct FloatMat33 Ga_inv
Definition: guidance_indi.c:81
#define QUAT_BFP_OF_REAL(_qi, _qf)
Definition: pprz_algebra.h:685
float filt_accelzbodyd
Definition: guidance_indi.c:67
void stabilization_attitude_set_setpoint_rp_quat_f(struct FloatEulers *indi_rp_cmd, bool in_flight, int32_t heading)
static void float_quat_normalize(struct FloatQuat *q)
struct RadioControl radio_control
Definition: radio_control.c:30
int32_t guidance_v_z_ref
altitude reference in meters.
Definition: guidance_v.c:121
#define RADIO_THROTTLE
Definition: spektrum_arch.h:42
struct FloatEulers guidance_euler_cmd
Definition: guidance_indi.c:87
struct FloatVect3 euler_cmd
Definition: guidance_indi.c:82
#define GUIDANCE_H_MAX_BANK
Definition: guidance_h.c:66
Inertial Measurement Unit interface.
float roll_filtd
Definition: guidance_indi.c:70
float guidance_indi_speed_gain
Definition: guidance_indi.c:47
signed long int32_t
Definition: types.h:19
Some helper functions to check RC sticks.
#define MAT33_VECT3_MUL(_vout, _mat, _vin)
Definition: pprz_algebra.h:451
API to get/set the generic vehicle states.
#define RMAT_ELMT(_rm, _row, _col)
Definition: pprz_algebra.h:593
void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect3 *uv, float angle)
Quaternion from unit vector and angle.
void float_quat_comp_norm_shortest(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions with normalization.
float filt_accelzbodydd
Definition: guidance_indi.c:68
General stabilization interface for rotorcrafts.
Horizontal guidance for rotorcrafts.
float roll_filt
Definition: guidance_indi.c:69
struct Int32Vect2 pos
with INT32_POS_FRAC
Definition: guidance_h.h:78
int32_t stabilization_cmd[COMMANDS_NB]
Stabilization commands.
Definition: stabilization.c:28
struct FloatVect3 filt_accel_ned
Definition: guidance_indi.c:63
#define VECT3_ADD_SCALED(_a, _b, _s)
Definition: pprz_algebra.h:167
float pitch_filtd
Definition: guidance_indi.c:73
#define POS_FLOAT_OF_BFP(_ai)
void guidance_indi_filter_attitude(void)
Filter the attitude, such that it corresponds to the filtered measured acceleration.
static struct NedCoor_i * stateGetPositionNed_i(void)
Get position in local NED coordinates (int).
Definition: state.h:659
#define MAT33_INV(_minv, _m)
Definition: pprz_algebra.h:477
float pitch_filt
Definition: guidance_indi.c:72
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition: state.h:704
void guidance_indi_run(bool in_flight, int32_t heading)
float thrust_in
Definition: guidance_indi.c:88
Rotorcraft attitude reference generation.
A guidance mode based on Incremental Nonlinear Dynamic Inversion Come to ICRA2016 to learn more! ...
float x
in meters
INS for rotorcrafts combining vertical and horizontal filters.