Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
guidance_pid.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Gautier Hattenberger <gautier.hattenberger@enac.fr>
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 
29 #include "generated/airframe.h"
30 #include "state.h"
31 
32 
33 // Keep GUIDANCE_H_XXX format for backward compatibility
34 
35 #ifndef GUIDANCE_H_AGAIN
36 #define GUIDANCE_H_AGAIN 0
37 #endif
38 
39 #ifndef GUIDANCE_H_VGAIN
40 #define GUIDANCE_H_VGAIN 0
41 #endif
42 
43 /* error if some gains are negative */
44 #if (GUIDANCE_H_PGAIN < 0) || \
45  (GUIDANCE_H_DGAIN < 0) || \
46  (GUIDANCE_H_IGAIN < 0) || \
47  (GUIDANCE_H_AGAIN < 0) || \
48  (GUIDANCE_H_VGAIN < 0)
49 #error "ALL PID_H control gains have to be positive!!!"
50 #endif
51 
52 #ifndef GUIDANCE_H_THRUST_CMD_FILTER
53 #define GUIDANCE_H_THRUST_CMD_FILTER 10
54 #endif
55 
56 #ifndef GUIDANCE_H_APPROX_FORCE_BY_THRUST
57 #define GUIDANCE_H_APPROX_FORCE_BY_THRUST FALSE
58 #endif
59 
60 // TODO configurable
61 #define MAX_POS_ERR POS_BFP_OF_REAL(16.)
62 #define MAX_SPEED_ERR SPEED_BFP_OF_REAL(16.)
63 
64 // Keep GUIDANCE_V_XXX format for backward compatibility
65 
66 /* error if some gains are negative */
67 #if (GUIDANCE_V_HOVER_KP < 0) || \
68  (GUIDANCE_V_HOVER_KD < 0) || \
69  (GUIDANCE_V_HOVER_KI < 0)
70 #error "ALL PID_V control gains must be positive!!!"
71 #endif
72 
73 /* If only GUIDANCE_V_NOMINAL_HOVER_THROTTLE is defined,
74  * disable the adaptive throttle estimation by default.
75  * Otherwise enable adaptive estimation by default.
76  */
77 #ifdef GUIDANCE_V_NOMINAL_HOVER_THROTTLE
78 # ifndef GUIDANCE_V_ADAPT_THROTTLE_ENABLED
79 # define GUIDANCE_V_ADAPT_THROTTLE_ENABLED FALSE
80 # endif
81 #else
82 # ifndef GUIDANCE_V_ADAPT_THROTTLE_ENABLED
83 # define GUIDANCE_V_ADAPT_THROTTLE_ENABLED TRUE
84 # endif
85 #endif
86 PRINT_CONFIG_VAR(GUIDANCE_V_ADAPT_THROTTLE_ENABLED)
87 
88 #ifndef GUIDANCE_V_MIN_ERR_Z
89 #define GUIDANCE_V_MIN_ERR_Z POS_BFP_OF_REAL(-10.)
90 #endif
91 
92 #ifndef GUIDANCE_V_MAX_ERR_Z
93 #define GUIDANCE_V_MAX_ERR_Z POS_BFP_OF_REAL(10.)
94 #endif
95 
96 #ifndef GUIDANCE_V_MIN_ERR_ZD
97 #define GUIDANCE_V_MIN_ERR_ZD SPEED_BFP_OF_REAL(-10.)
98 #endif
99 
100 #ifndef GUIDANCE_V_MAX_ERR_ZD
101 #define GUIDANCE_V_MAX_ERR_ZD SPEED_BFP_OF_REAL(10.)
102 #endif
103 
104 #ifndef GUIDANCE_V_MAX_SUM_ERR
105 #define GUIDANCE_V_MAX_SUM_ERR 2000000
106 #endif
107 
108 #ifndef GUIDANCE_V_MAX_CMD
109 #define GUIDANCE_V_MAX_CMD 0.9*MAX_PPRZ
110 #endif
111 
112 
113 
116 #ifndef GUIDANCE_PID_USE_AS_DEFAULT
117 #define GUIDANCE_PID_USE_AS_DEFAULT TRUE
118 #endif
119 
120 /*
121  * external variables
122  */
123 
125 
126 /*
127  * internal variables
128  */
129 
133 
137 
138 
139 #if PERIODIC_TELEMETRY
141 
142 static void send_hover_loop(struct transport_tx *trans, struct link_device *dev)
143 {
144  struct NedCoor_i *pos = stateGetPositionNed_i();
145  struct NedCoor_i *speed = stateGetSpeedNed_i();
146  struct NedCoor_i *accel = stateGetAccelNed_i();
147  pprz_msg_send_HOVER_LOOP(trans, dev, AC_ID,
148  &guidance_h.sp.pos.x,
149  &guidance_h.sp.pos.y,
150  &(pos->x), &(pos->y),
151  &(speed->x), &(speed->y),
152  &(accel->x), &(accel->y),
162 }
163 
164 static void send_vert_loop(struct transport_tx *trans, struct link_device *dev)
165 {
166  pprz_msg_send_VERT_LOOP(trans, dev, AC_ID,
168  &(stateGetPositionNed_i()->z),
169  &(stateGetSpeedNed_i()->z),
170  &(stateGetAccelNed_i()->z),
173  &gv_adapt_X,
174  &gv_adapt_P,
180 }
181 
182 #endif
183 
185 {
194  guidance_pid.kp = GUIDANCE_H_PGAIN;
195  guidance_pid.ki = GUIDANCE_H_IGAIN;
196  guidance_pid.kd = GUIDANCE_H_DGAIN;
199  guidance_pid.v_kp = GUIDANCE_V_HOVER_KP;
200  guidance_pid.v_kd = GUIDANCE_V_HOVER_KD;
201  guidance_pid.v_ki = GUIDANCE_V_HOVER_KI;
204 
205 #if PERIODIC_TELEMETRY
208 #endif
209 }
210 
211 /* with a pgain of 100 and a scale of 2,
212  * you get an angle of 5.6 degrees for 1m pos error */
213 #define GH_GAIN_SCALE 2
214 
218 static struct StabilizationSetpoint guidance_pid_h_run(bool in_flight, struct HorizontalGuidance *gh)
219 {
220  /* maximum bank angle: default 20 deg, max 40 deg*/
221  static const int32_t traj_max_bank = Min(BFP_OF_REAL(GUIDANCE_H_MAX_BANK, INT32_ANGLE_FRAC),
222  BFP_OF_REAL(RadOfDeg(40), INT32_ANGLE_FRAC));
223  static const int32_t total_max_bank = BFP_OF_REAL(RadOfDeg(45), INT32_ANGLE_FRAC);
224 
225  /* run PID */
226  int32_t pd_x =
229  int32_t pd_y =
232  guidance_pid.cmd_earth.x = pd_x +
233  ((guidance_pid.kv * gh->ref.speed.x) >> (INT32_SPEED_FRAC - GH_GAIN_SCALE)) + /* speed feedforward gain */
234  ((guidance_pid.ka * gh->ref.accel.x) >> (INT32_ACCEL_FRAC - GH_GAIN_SCALE)); /* acceleration feedforward gain */
235  guidance_pid.cmd_earth.y = pd_y +
236  ((guidance_pid.kv * gh->ref.speed.y) >> (INT32_SPEED_FRAC - GH_GAIN_SCALE)) + /* speed feedforward gain */
237  ((guidance_pid.ka * gh->ref.accel.y) >> (INT32_ACCEL_FRAC - GH_GAIN_SCALE)); /* acceleration feedforward gain */
238 
239  /* trim max bank angle from PD */
240  VECT2_STRIM(guidance_pid.cmd_earth, -traj_max_bank, traj_max_bank);
241 
242  /* Update pos & speed error integral, zero it if not in_flight.
243  * Integrate twice as fast when not only POS but also SPEED are wrong,
244  * but do not integrate POS errors when the SPEED is already catching up.
245  */
246  if (in_flight) {
247  /* ANGLE_FRAC (12) * GAIN (8) * LOOP_FREQ (9) -> INTEGRATOR HIGH RES ANGLE_FRAX (28) */
250  /* saturate it */
252  (traj_max_bank << (INT32_ANGLE_FRAC + GH_GAIN_SCALE * 2)));
253  /* add it to the command */
256  } else {
258  }
259 
260  /* compute a better approximation of force commands by taking thrust into account */
261  if (guidance_pid.approx_force_by_thrust && in_flight) {
262  static int32_t thrust_cmd_filt;
263  // FIXME strong coupling with guidance_v here !!!
264  int32_t vertical_thrust = (stabilization_cmd[COMMAND_THRUST] * guidance_v.thrust_coeff) >> INT32_TRIG_FRAC;
265  thrust_cmd_filt = (thrust_cmd_filt * GUIDANCE_H_THRUST_CMD_FILTER + vertical_thrust) /
268  thrust_cmd_filt));
270  thrust_cmd_filt));
271  }
272 
273  VECT2_STRIM(guidance_pid.cmd_earth, -total_max_bank, total_max_bank);
274 
276 }
277 
278 struct StabilizationSetpoint guidance_pid_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
279 {
280  /* compute position error */
282  /* saturate it */
284 
285  /* compute speed error */
287  /* saturate it */
289 
290  /* run PID */
291  return guidance_pid_h_run(in_flight, gh);
292 }
293 
294 struct StabilizationSetpoint guidance_pid_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
295 {
296  /* cancel position error */
298 
299  /* compute speed error */
301  /* saturate it */
303 
304  /* run PID */
305  return guidance_pid_h_run(in_flight, gh);
306 }
307 
309 {
310  struct StabilizationSetpoint sp = { 0 };
311  // TODO
312  return sp;
313 }
314 
319 #define FF_CMD_FRAC 18
320 
321 static int32_t guidance_pid_v_run(bool in_flight, struct VerticalGuidance *gv)
322 {
323  /* compute the error to our reference */
324  int32_t err_z = gv->z_ref - stateGetPositionNed_i()->z;
326  int32_t err_zd = gv->zd_ref - stateGetSpeedNed_i()->z;
328 
329  if (in_flight) {
330  guidance_pid_z_sum_err += err_z;
332  } else {
334  }
335 
336  /* our nominal command : (g + zdd)*m */
337  int32_t inv_m;
339  inv_m = gv_adapt_X >> (GV_ADAPT_X_FRAC - FF_CMD_FRAC);
340  } else {
341  /* use the fixed nominal throttle */
342  inv_m = BFP_OF_REAL(9.81 / (gv->nominal_throttle * MAX_PPRZ), FF_CMD_FRAC);
343  }
344 
345  const int32_t g_m_zdd = (int32_t)BFP_OF_REAL(9.81, FF_CMD_FRAC) -
346  (gv->zdd_ref << (FF_CMD_FRAC - INT32_ACCEL_FRAC));
347 
348  guidance_pid_v_ff_cmd = g_m_zdd / inv_m;
349  /* feed forward command */
351 
352  /* bound the nominal command to GUIDANCE_V_MAX_CMD */
354 
355 
356  /* our error feed back command */
357  /* z-axis pointing down -> positive error means we need less thrust */
359  ((-guidance_pid.v_kp * err_z) >> 7) +
360  ((-guidance_pid.v_kd * err_zd) >> 16) +
362 
364 
365  /* bound the result */
366  Bound(guidance_pid.cmd_thrust, 0, MAX_PPRZ);
367 
368  return guidance_pid.cmd_thrust;
369 }
370 
372 {
373  return guidance_pid_v_run(in_flight, gv);
374 }
375 
377 {
378  return guidance_pid_v_run(in_flight, gv);
379 }
380 
382 {
383  // TODO
384  return 0;
385 }
386 
388 {
389  /* set nav_heading to current heading */
391 }
392 
394 {
396 }
397 
403 {
404  guidance_pid.ki = igain;
406 }
407 
409 {
410  guidance_pid.v_ki = igain;
412 }
413 
414 
416 {
417  return &guidance_pid_pos_err;
418 }
419 
420 #if GUIDANCE_PID_USE_AS_DEFAULT
421 // guidance pid control function is implementing the default functions of guidance
422 
423 void guidance_h_run_enter(void)
424 {
426 }
427 
428 void guidance_v_run_enter(void)
429 {
431 }
432 
433 struct StabilizationSetpoint guidance_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
434 {
435  return guidance_pid_h_run_pos(in_flight, gh);
436 }
437 
438 struct StabilizationSetpoint guidance_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
439 {
440  return guidance_pid_h_run_speed(in_flight, gh);
441 }
442 
443 struct StabilizationSetpoint guidance_h_run_accel(bool in_flight, struct HorizontalGuidance *gh)
444 {
445  return guidance_pid_h_run_accel(in_flight, gh);
446 }
447 
448 int32_t guidance_v_run_pos(bool in_flight, struct VerticalGuidance *gv)
449 {
450  return guidance_pid_v_run_pos(in_flight, gv);
451 }
452 
453 int32_t guidance_v_run_speed(bool in_flight, struct VerticalGuidance *gv)
454 {
455  return guidance_pid_v_run_speed(in_flight, gv);
456 }
457 
458 int32_t guidance_v_run_accel(bool in_flight, struct VerticalGuidance *gv)
459 {
460  return guidance_pid_v_run_accel(in_flight, gv);
461 }
462 
463 #endif
464 
uint8_t last_wp UNUSED
#define Min(x, y)
Definition: esc_dshot.c:109
float psi
in radians
#define VECT2_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:92
#define VECT2_STRIM(_v, _min, _max)
Definition: pprz_algebra.h:110
#define INT32_POS_FRAC
#define ANGLE_BFP_OF_REAL(_af)
#define INT32_TRIG_FRAC
#define INT32_SPEED_FRAC
#define INT32_ANGLE_PI_2
#define INT32_ACCEL_FRAC
#define INT32_ANGLE_FRAC
#define BFP_OF_REAL(_vr, _frac)
#define INT_VECT2_ZERO(_v)
int32_t z
Down.
int32_t y
East.
int32_t x
North.
vector in North East Down coordinates
static struct NedCoor_i * stateGetAccelNed_i(void)
Get acceleration in NED coordinates (int).
Definition: state.h:1020
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1143
static struct NedCoor_i * stateGetPositionNed_i(void)
Get position in local NED coordinates (int).
Definition: state.h:665
static struct NedCoor_i * stateGetSpeedNed_i(void)
Get ground speed in local NED coordinates (int).
Definition: state.h:863
void guidance_v_run_enter(void)
int32_t guidance_v_run_speed(bool in_flight UNUSED, struct VerticalGuidance *gv)
int32_t guidance_v_run_pos(bool in_flight UNUSED, struct VerticalGuidance *gv)
int32_t guidance_v_run_accel(bool in_flight UNUSED, struct VerticalGuidance *gv)
void guidance_pid_set_h_igain(uint32_t igain)
settings handler
Definition: guidance_pid.c:402
#define GUIDANCE_V_MAX_SUM_ERR
Definition: guidance_pid.c:105
void guidance_pid_init(void)
Definition: guidance_pid.c:184
#define GUIDANCE_H_VGAIN
Definition: guidance_pid.c:40
int32_t guidance_pid_v_ff_cmd
feed-forward command
Definition: guidance_pid.c:135
struct StabilizationSetpoint guidance_pid_h_run_accel(bool in_flight UNUSED, struct HorizontalGuidance *gh UNUSED)
Definition: guidance_pid.c:308
struct Int32Vect2 guidance_pid_trim_att_integrator
Definition: guidance_pid.c:132
struct StabilizationSetpoint guidance_pid_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
Definition: guidance_pid.c:278
static void send_hover_loop(struct transport_tx *trans, struct link_device *dev)
Definition: guidance_pid.c:142
struct StabilizationSetpoint guidance_pid_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
Definition: guidance_pid.c:294
int32_t guidance_pid_v_fb_cmd
feed-back command
Definition: guidance_pid.c:136
#define MAX_SPEED_ERR
Definition: guidance_pid.c:62
#define GUIDANCE_V_MIN_ERR_Z
Definition: guidance_pid.c:89
void guidance_pid_set_v_igain(uint32_t igain)
Definition: guidance_pid.c:408
#define MAX_POS_ERR
Definition: guidance_pid.c:61
#define GUIDANCE_H_AGAIN
Definition: guidance_pid.c:36
#define GUIDANCE_V_MAX_CMD
Definition: guidance_pid.c:109
#define GUIDANCE_V_ADAPT_THROTTLE_ENABLED
Definition: guidance_pid.c:83
#define FF_CMD_FRAC
run vertical control loop for position and speed control
Definition: guidance_pid.c:319
static void send_vert_loop(struct transport_tx *trans, struct link_device *dev)
Definition: guidance_pid.c:164
static struct StabilizationSetpoint guidance_pid_h_run(bool in_flight, struct HorizontalGuidance *gh)
run horizontal control loop for position and speed control
Definition: guidance_pid.c:218
struct GuidancePID guidance_pid
Guidance PID structyre.
Definition: guidance_pid.c:124
static int32_t guidance_pid_v_run(bool in_flight, struct VerticalGuidance *gv)
Definition: guidance_pid.c:321
#define GH_GAIN_SCALE
Definition: guidance_pid.c:213
#define GUIDANCE_H_THRUST_CMD_FILTER
Definition: guidance_pid.c:53
#define GUIDANCE_V_MIN_ERR_ZD
Definition: guidance_pid.c:97
#define GUIDANCE_V_MAX_ERR_ZD
Definition: guidance_pid.c:101
int32_t guidance_pid_z_sum_err
accumulator for I-gain
Definition: guidance_pid.c:134
struct Int32Vect2 guidance_pid_pos_err
Definition: guidance_pid.c:130
int32_t guidance_pid_v_run_accel(bool in_flight UNUSED, struct VerticalGuidance *gv UNUSED)
Definition: guidance_pid.c:381
int32_t guidance_pid_v_run_pos(bool in_flight, struct VerticalGuidance *gv)
Definition: guidance_pid.c:371
int32_t guidance_pid_v_run_speed(bool in_flight, struct VerticalGuidance *gv)
Definition: guidance_pid.c:376
#define GUIDANCE_H_APPROX_FORCE_BY_THRUST
Definition: guidance_pid.c:57
const struct Int32Vect2 * guidance_pid_get_h_pos_err(void)
Gets the position error.
Definition: guidance_pid.c:415
void guidance_pid_v_enter(void)
Definition: guidance_pid.c:393
#define GUIDANCE_V_MAX_ERR_Z
Definition: guidance_pid.c:93
struct Int32Vect2 guidance_pid_speed_err
Definition: guidance_pid.c:131
void guidance_pid_h_enter(void)
Definition: guidance_pid.c:387
Guidance controller with PID for rotorcrafts.
int32_t v_ki
Definition: guidance_pid.h:48
int32_t cmd_thrust
Definition: guidance_pid.h:51
bool approx_force_by_thrust
Definition: guidance_pid.h:53
int32_t kv
Definition: guidance_pid.h:43
bool adapt_throttle_enabled
Definition: guidance_pid.h:54
int32_t v_kp
Definition: guidance_pid.h:46
int32_t ki
Definition: guidance_pid.h:42
struct Int32Vect2 cmd_earth
Definition: guidance_pid.h:50
int32_t kd
Definition: guidance_pid.h:41
int32_t ka
Definition: guidance_pid.h:44
int32_t kp
Definition: guidance_pid.h:40
int32_t v_kd
Definition: guidance_pid.h:47
int32_t gv_adapt_P
Covariance.
int32_t gv_adapt_X
State of the estimator.
int32_t gv_adapt_Xmeas
Measurement.
Adaptation block of the vertical guidance.
#define GV_ADAPT_X_FRAC
#define MAX_PPRZ
Definition: paparazzi.h:8
struct HorizontalGuidance guidance_h
Definition: guidance_h.c:50
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:71
struct HorizontalGuidanceSetpoint sp
setpoints
Definition: guidance_h.h:109
struct VerticalGuidance guidance_v
Definition: guidance_v.c:59
float nominal_throttle
nominal throttle for hover.
Definition: guidance_v.h:103
int32_t z_sp
altitude setpoint in meters (input).
Definition: guidance_v.h:51
int32_t zd_sp
vertical speed setpoint in meter/s (input).
Definition: guidance_v.h:57
int32_t z_ref
altitude reference in meters.
Definition: guidance_v.h:63
int32_t zd_ref
vertical speed reference in meter/s.
Definition: guidance_v.h:69
int32_t thrust_coeff
Definition: guidance_v.h:105
int32_t zdd_ref
vertical acceleration reference in meter/s^2.
Definition: guidance_v.h:75
struct RotorcraftNavigation nav
Definition: navigation.c:51
float heading
heading setpoint (in radians)
Definition: navigation.h:133
struct StabilizationSetpoint stab_sp_from_ltp_i(struct Int32Vect2 *vect, int32_t heading)
int32_t stabilization_cmd[COMMANDS_NB]
Stabilization commands.
Definition: stabilization.c:34
General stabilization interface for rotorcrafts.
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
struct Int32Vect2 pos
horizontal position setpoint in NED.
Definition: guidance_h.h:80
Stabilization setpoint.
Definition: stabilization.h:42
union StabilizationSetpoint::@278 sp
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
int int32_t
Typedef defining 32 bit int type.
Definition: vl53l1_types.h:83
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78