Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
33#include "generated/airframe.h"
40#include "mcu_periph/sys_time.h"
41#include "state.h"
42#include "autopilot.h"
45#include "modules/core/abi.h"
46
47// The acceleration reference is calculated with these gains. If you use GPS,
48// they are probably limited by the update rate of your GPS. The default
49// values are tuned for 4 Hz GPS updates. If you have high speed position updates, the
50// gains can be higher, depending on the speed of the inner loop.
51#ifdef GUIDANCE_INDI_POS_GAIN
53#else
55#endif
56
57#ifdef GUIDANCE_INDI_SPEED_GAIN
59#else
61#endif
62
63#ifndef GUIDANCE_INDI_ACCEL_SP_ID
64#define GUIDANCE_INDI_ACCEL_SP_ID ABI_BROADCAST
65#endif
68struct FloatVect3 indi_accel_sp = {0.0f, 0.0f, 0.0f};
71
72// FIXME make a proper structure for these variables
73struct FloatVect3 speed_sp = {0.0f, 0.0f, 0.0f};
74struct FloatVect3 sp_accel = {0.0f, 0.0f, 0.0f};
75#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
77static void guidance_indi_filter_thrust(void);
78
79#ifdef GUIDANCE_INDI_THRUST_DYNAMICS
80#warning GUIDANCE_INDI_THRUST_DYNAMICS is deprecated, use GUIDANCE_INDI_THRUST_DYNAMICS_FREQ instead.
81#warning "The thrust dynamics are now specified in continuous time with the corner frequency of the first order model!"
82#warning "define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ in rad/s"
83#warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old value."
84#endif
85
86#ifndef GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
87#ifndef STABILIZATION_INDI_ACT_FREQ_P
88#error "You need to define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ to be able to use indi vertical control"
89#else // assume that the same actuators are used for thrust as for roll (e.g. quadrotor)
90#define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ STABILIZATION_INDI_ACT_FREQ_P
91#endif
92#endif //GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
93
94
95#endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
96
97#ifndef GUIDANCE_INDI_FILTER_CUTOFF
98#ifdef STABILIZATION_INDI_FILT_CUTOFF
99#define GUIDANCE_INDI_FILTER_CUTOFF STABILIZATION_INDI_FILT_CUTOFF
100#else
101#define GUIDANCE_INDI_FILTER_CUTOFF 3.0
102#endif
103#endif
104
105float thrust_dyn = 0.f;
106float thrust_act = 0.f;
110
112
113#if GUIDANCE_INDI_USE_WLS
114#include "math/wls/wls_alloc.h"
115
116// priorities on control inputs (ax, ay, az)
117#ifndef GUIDANCE_INDI_WLS_PRIORITIES
118#define GUIDANCE_INDI_WLS_PRIORITIES {100.f, 100.f, 100.f}
119#endif
120
121// weighting of prefered control outputs (phi, theta, psi, Tx, Ty, Tz)
122#ifndef GUIDANCE_INDI_WLS_WU
123#define GUIDANCE_INDI_WLS_WU {1000.f,1000.f,10.f,1.f,1.f,1.f}
124#endif
125
126#define NU_MAX 6 // Example constant value // [dtheta, dphi, dthrust, dtx , dty]
127#define NV_MAX 3 // Example constant value (ax,ay,az)
128static float du_guidance[GUIDANCE_INDI_NU];
129static float *Bwls_gi[GUIDANCE_INDI_NV];
130
131static struct WLS_t wls_guid_p = {
133 .nv = GUIDANCE_INDI_NV,
134 .gamma_sq = 100.0,
135 .v = {0.0},
138 .u_pref = {0.0},
139 .u_min = {0.0},
140 .u_max = {0.0},
141 .PC = 0.0,
142 .SC = 0.0,
143 .iter = 0
144};
145
146#else
147
148// inverse matrix directly if not using WLS
151struct FloatVect3 control_increment; // [dtheta, dphi, dthrust]
152
153#endif
154
157
160
164float thrust_vect[3];
165
166static void guidance_indi_propagate_filters(void);
167
168//------------------------------------------------------------//
169
170#if PERIODIC_TELEMETRY
172static void send_indi_guidance(struct transport_tx *trans, struct link_device *dev)
173{
175 &sp_accel.x,
176 &sp_accel.y,
177 &sp_accel.z,
179 &du_guidance[0],
180 &du_guidance[1],
181 &du_guidance[2],
182#else
186#endif
187 &filt_accel_ned[0].o[0],
188 &filt_accel_ned[1].o[0],
189 &filt_accel_ned[2].o[0],
190 &speed_sp.x,
191 &speed_sp.y,
192 &speed_sp.z);
193}
194#endif
195
209
215{
216 /* set nav_heading to current heading */
218
221
222#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
223#ifdef GUIDANCE_INDI_THRUST_DYNAMICS
225#else
227#endif //GUIDANCE_INDI_THRUST_DYNAMICS
228#endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
229
230 float tau = 1.0 / (2.0 * M_PI * filter_cutoff);
231 float sample_time = 1.0 / PERIODIC_FREQUENCY;
232 for (int8_t i = 0; i < 3; i++) {
234 }
237}
238
247{
250
251 // set global accel sp variable FIXME clean this
253
254 //filter accel to get rid of noise and filter attitude to synchronize with accel
256
257 struct FloatVect3 a_diff = {
258 sp_accel.x - filt_accel_ned[0].o[0],
259 sp_accel.y - filt_accel_ned[1].o[0],
260 sp_accel.z - filt_accel_ned[2].o[0]
261 };
262 Bound(a_diff.x, -6.0, 6.0);
263 Bound(a_diff.y, -6.0, 6.0);
264 Bound(a_diff.z, -9.0, 9.0);
265
266 //If the thrust to specific force ratio has been defined, include vertical control
267 //else ignore the vertical acceleration error
268#ifndef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
269#ifndef STABILIZATION_ATTITUDE_INDI_FULL
270 a_diff.z = 0.0;
271#endif
272#endif
273
274#if GUIDANCE_INDI_USE_WLS
275 const float m = GUIDANCE_INDI_MASS;
276 wls_guid_p.v[0] = m*a_diff.x;
277 wls_guid_p.v[1] = m*a_diff.y;
278 wls_guid_p.v[2] = m*a_diff.z;
279
282 for (int i = 0; i < GUIDANCE_INDI_NV; i++) {
283 Bwls_gi[i] = Gmat[i];
284 }
285 wls_alloc(&wls_guid_p,Bwls_gi, 0, 0, 10);
286 for (int i = 0; i < GUIDANCE_INDI_NU; i++) {
287 du_guidance [i] = wls_guid_p.u[i];
288 }
289
293 thrust_vect[0] = du_guidance[3]; // (TX)
294 thrust_vect[1] = du_guidance[4]; // (TY)
295 thrust_vect[2] = du_guidance[5]; // (TZ)
297
298#else // !USE_WLS
299
300 // Calculate matrix of partial derivatives
302
303 RMAT_ELMT(Ga, 0, 0) = Gmat[0][0];
304 RMAT_ELMT(Ga, 1, 0) = Gmat[1][0];
305 RMAT_ELMT(Ga, 2, 0) = Gmat[2][0];
306 RMAT_ELMT(Ga, 0, 1) = Gmat[0][1];
307 RMAT_ELMT(Ga, 1, 1) = Gmat[1][1];
308 RMAT_ELMT(Ga, 2, 1) = Gmat[2][1];
309 RMAT_ELMT(Ga, 0, 2) = Gmat[0][2];
310 RMAT_ELMT(Ga, 1, 2) = Gmat[1][2];
311 RMAT_ELMT(Ga, 2, 2) = Gmat[2][2];
312 // Invert this matrix // FIXME input format
314 // Calculate roll,pitch and thrust command
316
319 guidance_euler_cmd.psi = heading_sp;
320
321 // Compute and store thust setpoint
322#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
324 //Add the increment in specific force * specific_force_to_thrust_gain to the filtered thrust
328
329#else
330 // basic quad, no side force
331 thrust_vect[0] = 0.0f;
332 thrust_vect[1] = 0.0f;
334
335 // specific force not defined, return required increment
337#endif
338
339#endif // USE_WLS
340
341 // Bound euler angles to prevent flipping
344
345 // set the quat setpoint with the calculated roll and pitch
346 struct FloatQuat q_sp;
348
349 return stab_sp_from_quat_f(&q_sp);
350}
351
353{
354 struct FloatVect3 pos_err = { 0 };
355 struct FloatVect3 accel_sp = { 0 };
356
357 struct FloatVect3 speed_fb;
358
360 // Speed feedback is included in the guidance when running in ACCEL mode
361 speed_fb.x = 0.;
362 speed_fb.y = 0.;
363 }
364 else {
365 // Generate speed feedback for acceleration, as it is estimated
367 speed_sp.x = SPEED_FLOAT_OF_BFP(gh->ref.speed.x);
368 speed_sp.y = SPEED_FLOAT_OF_BFP(gh->ref.speed.y);
369 }
370 else { // H_POS
375 }
378 }
379
381 // Speed feedback is included in the guidance when running in ACCEL mode
382 speed_fb.z = 0;
383 }
384 else {
385 // Generate speed feedback for acceleration, as it is estimated
387 speed_sp.z = SPEED_FLOAT_OF_BFP(gv->zd_ref);
388 }
389 else { // V_POS
392 }
394 }
395
396 accel_sp.x = speed_fb.x + ACCEL_FLOAT_OF_BFP(gh->ref.accel.x);
397 accel_sp.y = speed_fb.y + ACCEL_FLOAT_OF_BFP(gh->ref.accel.y);
398 accel_sp.z = speed_fb.z + ACCEL_FLOAT_OF_BFP(gv->zdd_ref);
399
400 return accel_sp;
401}
402
404{
405 struct FloatVect3 accel_sp;
406
407 // If set and valid, the ABI message overwrite the accel setpoint
408 // TODO This is not ideal, guided mode with accel setpoint would be better
412 // In 2D the vertical motion is derived from the flight plan
415 // If the input command is not updated after a timeout, switch back to flight plan control
416 if (dt > 0.5) {
417 indi_accel_sp_set_2d = false;
418 }
419 } else if (indi_accel_sp_set_3d) {
424 // If the input command is not updated after a timeout, switch back to flight plan control
425 if (dt > 0.5) {
426 indi_accel_sp_set_3d = false;
427 }
428 }
429 else {
431 }
432
433 return guidance_indi_run(&accel_sp, gh->sp.heading);
434}
435
436
437#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
442{
443 // Actuator dynamics
445
446 // same filter as for the acceleration
448}
449#endif
450
464
470{
471 if (flag == 0) {
476 } else if (flag == 1) {
482 }
483}
484
485#if GUIDANCE_INDI_USE_AS_DEFAULT
486// guidance indi control function is implementing the default functions of guidance
487
488void guidance_h_run_enter(void)
489{
491}
492
493void guidance_v_run_enter(void)
494{
495 // nothing to do
496}
497
498static struct VerticalGuidance *_gv = &guidance_v;
500
502{
504}
505
507{
509}
510
512{
514}
515
517{
518 _gv = gv;
520 return thrust_sp;
521}
522
524{
525 _gv = gv;
527 return thrust_sp;
528}
529
531{
532 _gv = gv;
534 return thrust_sp;
535}
536
537#endif
538
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
Core autopilot interface common to all firmwares.
#define UNUSED(x)
static struct uart_periph * dev
float phi
in radians
float theta
in radians
float psi
in radians
#define FLOAT_EULERS_ZERO(_e)
void float_eulers_of_quat_yxz(struct FloatEulers *e, const struct FloatQuat *q)
euler rotation 'YXZ' This function calculates from a quaternion the Euler angles with the order YXZ,...
void float_quat_of_eulers_yxz(struct FloatQuat *q, const struct FloatEulers *e)
quat from euler rotation 'YXZ' This function calculates a quaternion from Euler angles with the order...
euler angles
Roation quaternion.
#define MAT33_VECT3_MUL(_vout, _mat, _vin)
#define MAT33_INV(_minv, _m)
#define RMAT_ELMT(_rm, _row, _col)
#define POS_FLOAT_OF_BFP(_ai)
#define SPEED_FLOAT_OF_BFP(_ai)
#define ACCEL_FLOAT_OF_BFP(_ai)
static struct NedCoor_f * stateGetAccelNed_f(void)
Get acceleration in NED coordinates (float).
Definition state.h:1203
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1314
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1302
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition state.h:839
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition state.h:1049
#define GUIDANCE_INDI_ACCEL_SP_ID
QuatButterworthLowPass quat_filt
float thrust_in
struct StabilizationSetpoint guidance_indi_run_mode(bool in_flight, struct HorizontalGuidance *gh, struct VerticalGuidance *gv, enum GuidanceIndi_HMode h_mode, enum GuidanceIndi_VMode v_mode)
float guidance_indi_max_bank
bool indi_accel_sp_set_3d
float guidance_indi_pos_gain
struct FloatVect3 sp_accel
struct FloatEulers guidance_euler_cmd
struct FloatVect3 speed_sp
float thrust_act
struct FloatMat33 Ga_inv
void guidance_indi_enter(void)
Call upon entering indi guidance.
static void accel_sp_cb(uint8_t sender_id, uint8_t flag, struct FloatVect3 *accel_sp)
ABI callback that obtains the acceleration setpoint from telemetry flag: 0 -> 2D, 1 -> 3D.
abi_event accel_sp_ev
struct ThrustSetpoint thrust_sp
void guidance_indi_init(void)
Init function.
float time_of_accel_sp_3d
float filter_cutoff
#define GUIDANCE_INDI_FILTER_CUTOFF
struct FloatVect3 WEAK guidance_indi_controller(bool in_flight UNUSED, struct HorizontalGuidance *gh, struct VerticalGuidance *gv, enum GuidanceIndi_HMode h_mode, enum GuidanceIndi_VMode v_mode)
bool indi_accel_sp_set_2d
struct FloatVect3 indi_accel_sp
float thrust_vect[3]
struct FloatVect3 control_increment
struct FloatMat33 Ga
Butterworth2LowPass filt_accel_ned[3]
float guidance_indi_speed_gain
float time_of_accel_sp_2d
float thrust_dyn
static float Gmat[GUIDANCE_INDI_NV][GUIDANCE_INDI_NU]
struct StabilizationSetpoint guidance_indi_run(struct FloatVect3 *accel_sp, float heading_sp)
static void guidance_indi_propagate_filters(void)
Low pass the accelerometer measurements to remove noise from vibrations.
Butterworth2LowPass thrust_filt
static void send_indi_guidance(struct transport_tx *trans, struct link_device *dev)
A guidance mode based on Incremental Nonlinear Dynamic Inversion.
#define GUIDANCE_INDI_NV
float guidance_indi_specific_force_gain
#define GUIDANCE_INDI_NU
GuidanceIndi_VMode
@ GUIDANCE_INDI_V_ACCEL
@ GUIDANCE_INDI_V_SPEED
@ GUIDANCE_INDI_V_POS
GuidanceIndi_HMode
@ GUIDANCE_INDI_H_SPEED
@ GUIDANCE_INDI_H_ACCEL
@ GUIDANCE_INDI_H_POS
void guidance_indi_calcG(float Gmat[GUIDANCE_INDI_NV][GUIDANCE_INDI_NU], const struct FloatQuat *att)
void guidance_indi_set_wls_settings(struct WLS_t *wls, const struct FloatQuat *att, const float heading_sp)
#define GUIDANCE_INDI_POS_GAIN
#define GUIDANCE_INDI_SPEED_GAIN
static enum GuidanceOneloop_VMode _v_mode
void guidance_v_run_enter(void)
static struct VerticalGuidance * _gv
struct ThrustSetpoint guidance_v_run_pos(bool in_flight UNUSED, struct VerticalGuidance *gv)
struct ThrustSetpoint guidance_v_run_speed(bool in_flight UNUSED, struct VerticalGuidance *gv)
struct ThrustSetpoint guidance_v_run_accel(bool in_flight UNUSED, struct VerticalGuidance *gv)
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, const float tau, const float sample_time, const float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, const float value)
Update second order Butterworth low pass filter state with a new value.
Second order low pass filter structure.
uint16_t foo
Definition main_demo5.c:58
#define MAX_PPRZ
Definition paparazzi.h:8
float z
in meters
float x
in meters
float y
in meters
vector in North East Down coordinates Units: meters
Quaternion second order filter.
static struct FloatQuat update_quat_butterworth_low_pass(QuatButterworthLowPass *filter, const struct FloatQuat quat)
Update second order quaternion Butterworth low pass filter state with a new value.
static void init_quat_butterworth_low_pass(QuatButterworthLowPass *filter, const float omega, const float sample_time, const struct FloatQuat q0)
Init a second order quaternion Butterworth filter.
Quaternion second order filter model (float)
Generic interface for radio control modules.
Some helper functions to check RC sticks.
Horizontal guidance for rotorcrafts.
void guidance_h_run_enter(void)
struct StabilizationSetpoint guidance_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
struct StabilizationSetpoint guidance_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
struct StabilizationSetpoint guidance_h_run_accel(bool in_flight, struct HorizontalGuidance *gh)
#define GUIDANCE_H_MAX_BANK
Max bank controlled by guidance.
Definition guidance_h.h:64
struct VerticalGuidance guidance_v
Definition guidance_v.c:60
Vertical guidance for rotorcrafts.
struct RotorcraftNavigation nav
Definition navigation.c:51
float heading
heading setpoint (in radians)
Definition navigation.h:133
struct Stabilization stabilization
struct ThrustSetpoint th_sp_from_incr_vect_f(float th_increment[3])
struct StabilizationSetpoint stab_sp_from_quat_f(struct FloatQuat *quat)
struct ThrustSetpoint th_sp_from_thrust_i(int32_t thrust, uint8_t axis)
General stabilization interface for rotorcrafts.
#define THRUST_SP_SET_ZERO(_sp)
#define THRUST_AXIS_Z
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
API to get/set the generic vehicle states.
Stabilization setpoint.
Thrust setpoint // TODO to a setpoint header Structure to store the desired thrust vector with differ...
Architecture independent timing functions.
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:168
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.
void wls_alloc(struct WLS_t *WLS_p, float **B, float *u_guess, float *W_init, int imax)
active set algorithm for control allocation
Definition wls_alloc.c:119
int nu
Definition wls_alloc.h:67