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, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
34#include "generated/airframe.h"
41#include "mcu_periph/sys_time.h"
42#include "state.h"
43#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;
111
114struct FloatVect3 control_increment; // [dtheta, dphi, dthrust]
115
118
121
125
126static void guidance_indi_propagate_filters(struct FloatEulers *eulers);
127static void guidance_indi_calcG(struct FloatMat33 *Gmat);
128static void guidance_indi_calcG_yxz(struct FloatMat33 *Gmat, struct FloatEulers *euler_yxz);
129
130#if PERIODIC_TELEMETRY
132static void send_indi_guidance(struct transport_tx *trans, struct link_device *dev)
133{
135 &sp_accel.x,
136 &sp_accel.y,
137 &sp_accel.z,
141 &filt_accel_ned[0].o[0],
142 &filt_accel_ned[1].o[0],
143 &filt_accel_ned[2].o[0],
144 &speed_sp.x,
145 &speed_sp.y,
146 &speed_sp.z);
147}
148#endif
149
163
169{
170 /* set nav_heading to current heading */
172
175
176#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
177#ifdef GUIDANCE_INDI_THRUST_DYNAMICS
179#else
181#endif //GUIDANCE_INDI_THRUST_DYNAMICS
182#endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
183
184 float tau = 1.0 / (2.0 * M_PI * filter_cutoff);
185 float sample_time = 1.0 / PERIODIC_FREQUENCY;
186 for (int8_t i = 0; i < 3; i++) {
188 }
192}
193
202{
203 struct FloatEulers eulers_yxz;
206
207 // set global accel sp variable FIXME clean this
209
210 //filter accel to get rid of noise and filter attitude to synchronize with accel
212
213 // FIXME the ABI message overwrite the accel setpoint
214 // it update should be replaced by a call to the run function
215 // If the acceleration setpoint is set over ABI message
219 // In 2D the vertical motion is derived from the flight plan
222 // If the input command is not updated after a timeout, switch back to flight plan control
223 if (dt > 0.5) {
224 indi_accel_sp_set_2d = false;
225 }
226 } else if (indi_accel_sp_set_3d) {
231 // If the input command is not updated after a timeout, switch back to flight plan control
232 if (dt > 0.5) {
233 indi_accel_sp_set_3d = false;
234 }
235 }
236 // else, don't change sp_accel
237
238#if GUIDANCE_INDI_RC_DEBUG
239#warning "GUIDANCE_INDI_RC_DEBUG lets you control the accelerations via RC, but disables autonomous flight!"
240 //for rc control horizontal, rotate from body axes to NED
241 float psi = stateGetNedToBodyEulers_f()->psi;
242 float rc_x = -(radio_control.values[RADIO_PITCH] / 9600.0) * 8.0;
243 float rc_y = (radio_control.values[RADIO_ROLL] / 9600.0) * 8.0;
244 sp_accel.x = cosf(psi) * rc_x - sinf(psi) * rc_y;
245 sp_accel.y = sinf(psi) * rc_x + cosf(psi) * rc_y;
246
247 //for rc vertical control
248 sp_accel.z = -(radio_control.values[RADIO_THROTTLE] - 4500) * 8.0 / 9600.0;
249#endif
250
251 //Calculate matrix of partial derivatives
253
254 //Invert this matrix
256
258
259 //Bound the acceleration error so that the linearization still holds
260 Bound(a_diff.x, -6.0, 6.0);
261 Bound(a_diff.y, -6.0, 6.0);
262 Bound(a_diff.z, -9.0, 9.0);
263
264 //If the thrust to specific force ratio has been defined, include vertical control
265 //else ignore the vertical acceleration error
266#ifndef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
267#ifndef STABILIZATION_ATTITUDE_INDI_FULL
268 a_diff.z = 0.0;
269#endif
270#endif
271
272 //Calculate roll,pitch and thrust command
274
278
279 // Compute and store thust setpoint
280#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
282 //Add the increment in specific force * specific_force_to_thrust_gain to the filtered thrust
284 Bound(thrust_in, 0, 9600);
285#if GUIDANCE_INDI_RC_DEBUG
287 thrust_in = 0;
288 }
289#endif
290 // return required thrust
292
293#else
294 float thrust_vect[3];
295 thrust_vect[0] = 0.0f; // Fill for quadplanes
296 thrust_vect[1] = 0.0f;
298
299 // specific force not defined, return required increment
301#endif
302
303 //Bound euler angles to prevent flipping
306
307 //set the quat setpoint with the calculated roll and pitch
308 struct FloatQuat q_sp;
310
311 return stab_sp_from_quat_f(&q_sp);
312}
313
315{
316 struct FloatVect3 pos_err = { 0 };
317 struct FloatVect3 accel_sp = { 0 };
318
319 struct FloatVect3 speed_fb;
320
321
323 // Speed feedback is included in the guidance when running in ACCEL mode
324 speed_fb.x = 0.;
325 speed_fb.y = 0.;
326 }
327 else {
328 // Generate speed feedback for acceleration, as it is estimated
330 speed_sp.x = SPEED_FLOAT_OF_BFP(gh->ref.speed.x);
331 speed_sp.y = SPEED_FLOAT_OF_BFP(gh->ref.speed.y);
332 }
333 else { // H_POS
338 }
341 }
342
344 // Speed feedback is included in the guidance when running in ACCEL mode
345 speed_fb.z = 0;
346 }
347 else {
348 // Generate speed feedback for acceleration, as it is estimated
350 speed_sp.z = SPEED_FLOAT_OF_BFP(gv->zd_ref);
351 }
352 else { // V_POS
355 }
357 }
358
359 accel_sp.x = speed_fb.x + ACCEL_FLOAT_OF_BFP(gh->ref.accel.x);
360 accel_sp.y = speed_fb.y + ACCEL_FLOAT_OF_BFP(gh->ref.accel.y);
361 accel_sp.z = speed_fb.z + ACCEL_FLOAT_OF_BFP(gv->zdd_ref);
362
363 return guidance_indi_run(&accel_sp, gh->sp.heading);
364}
365
366#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
371{
372 // Actuator dynamics
374
375 // same filter as for the acceleration
377}
378#endif
379
395
404{
405
406 float sphi = sinf(euler_yxz->phi);
407 float cphi = cosf(euler_yxz->phi);
408 float stheta = sinf(euler_yxz->theta);
409 float ctheta = cosf(euler_yxz->theta);
410 //minus gravity is a guesstimate of the thrust force, thrust measurement would be better
411 float T = -9.81;
412
413 RMAT_ELMT(*Gmat, 0, 0) = ctheta * cphi * T;
414 RMAT_ELMT(*Gmat, 1, 0) = 0;
415 RMAT_ELMT(*Gmat, 2, 0) = -stheta * cphi * T;
416 RMAT_ELMT(*Gmat, 0, 1) = -stheta * sphi * T;
417 RMAT_ELMT(*Gmat, 1, 1) = -cphi * T;
418 RMAT_ELMT(*Gmat, 2, 1) = -ctheta * sphi * T;
419 RMAT_ELMT(*Gmat, 0, 2) = stheta * cphi;
420 RMAT_ELMT(*Gmat, 1, 2) = -sphi;
421 RMAT_ELMT(*Gmat, 2, 2) = ctheta * cphi;
422}
423
432{
433
434 struct FloatEulers *euler = stateGetNedToBodyEulers_f();
435
436 float sphi = sinf(euler->phi);
437 float cphi = cosf(euler->phi);
438 float stheta = sinf(euler->theta);
439 float ctheta = cosf(euler->theta);
440 float spsi = sinf(euler->psi);
441 float cpsi = cosf(euler->psi);
442 //minus gravity is a guesstimate of the thrust force, thrust measurement would be better
443 float T = -9.81;
444
445 RMAT_ELMT(*Gmat, 0, 0) = (cphi * spsi - sphi * cpsi * stheta) * T;
446 RMAT_ELMT(*Gmat, 1, 0) = (-sphi * spsi * stheta - cpsi * cphi) * T;
447 RMAT_ELMT(*Gmat, 2, 0) = -ctheta * sphi * T;
448 RMAT_ELMT(*Gmat, 0, 1) = (cphi * cpsi * ctheta) * T;
449 RMAT_ELMT(*Gmat, 1, 1) = (cphi * spsi * ctheta) * T;
450 RMAT_ELMT(*Gmat, 2, 1) = -stheta * cphi * T;
451 RMAT_ELMT(*Gmat, 0, 2) = sphi * spsi + cphi * cpsi * stheta;
452 RMAT_ELMT(*Gmat, 1, 2) = cphi * spsi * stheta - cpsi * sphi;
453 RMAT_ELMT(*Gmat, 2, 2) = cphi * ctheta;
454}
455
461{
462 if (flag == 0) {
467 } else if (flag == 1) {
473 }
474}
475
476#if GUIDANCE_INDI_USE_AS_DEFAULT
477// guidance indi control function is implementing the default functions of guidance
478
479void guidance_h_run_enter(void)
480{
482}
483
484void guidance_v_run_enter(void)
485{
486 // nothing to do
487}
488
489static struct VerticalGuidance *_gv = &guidance_v;
491
493{
495}
496
498{
500}
501
503{
505}
506
508{
509 _gv = gv;
511 return thrust_sp;
512}
513
515{
516 _gv = gv;
518 return thrust_sp;
519}
520
522{
523 _gv = gv;
525 return thrust_sp;
526}
527
528#endif
529
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:67
Core autopilot interface common to all firmwares.
#define UNUSED(x)
float phi
in radians
float theta
in radians
float psi
in radians
void float_eulers_of_quat_yxz(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'YXZ' This function calculates from a quaternion the Euler angles with the order YXZ,...
#define FLOAT_EULERS_ZERO(_e)
void float_quat_of_eulers_yxz(struct FloatQuat *q, 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:1195
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1306
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1294
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
Butterworth2LowPass roll_filt
float thrust_in
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
static void guidance_indi_calcG(struct FloatMat33 *Gmat)
struct FloatVect3 speed_sp
static void guidance_indi_calcG_yxz(struct FloatMat33 *Gmat, struct FloatEulers *euler_yxz)
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.
Butterworth2LowPass pitch_filt
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 StabilizationSetpoint guidance_indi_run_mode(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
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
struct StabilizationSetpoint guidance_indi_run(struct FloatVect3 *accel_sp, float heading_sp)
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.
float guidance_indi_specific_force_gain
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
#define GUIDANCE_INDI_POS_GAIN
void guidance_indi_propagate_filters(void)
Low pass the accelerometer measurements to remove noise from vibrations.
#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, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, 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
float z
in meters
float x
in meters
float y
in meters
vector in North East Down coordinates Units: meters
struct RadioControl radio_control
Generic interface for radio control modules.
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
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.
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
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:138
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_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.