Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
gvf_parametric.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Hector Garcia de Marina <hgarciad@ucm.es>
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
27#include <iostream>
28#include <Eigen/Dense> // https://eigen.tuxfamily.org/dox/GettingStarted.html
29
30#include "gvf_parametric.h"
31
33#ifndef GVF_PARAMETRIC_CONTROL_KROLL
34 #define GVF_PARAMETRIC_CONTROL_KROLL 1
35#endif
36
38#ifndef GVF_PARAMETRIC_CONTROL_KCLIMB
39 #define GVF_PARAMETRIC_CONTROL_KCLIMB 1
40#endif
41
43#ifndef GVF_PARAMETRIC_CONTROL_L
44 #if GVF_PARAMETRIC_CONTROL_STEP_ADAPTATION > 0
45 #define GVF_PARAMETRIC_CONTROL_L 1
46 #else
47 #define GVF_PARAMETRIC_CONTROL_L 0.1
48 #endif
49#endif
50
52#ifndef GVF_PARAMETRIC_CONTROL_BETA
53 #if GVF_PARAMETRIC_CONTROL_STEP_ADAPTATION > 0
54 #define GVF_PARAMETRIC_CONTROL_BETA 1
55 #else
56 #define GVF_PARAMETRIC_CONTROL_BETA 0.01
57 #endif
58#endif
59
60
62#ifndef GVF_PARAMETRIC_CONTROL_KPSI
63 #define GVF_PARAMETRIC_CONTROL_KPSI 1
64#endif
65
66#ifdef __cplusplus
67extern "C" {
68#endif
69
70#include "autopilot.h"
71#include "gvf_adapted_step.h"
72
73
74// Control
77
78// Time variables to check if GVF is active
80
83#if PERIODIC_TELEMETRY
103
104#if GVF_OCAML_GCS
105static void send_circle_parametric(struct transport_tx *trans, struct link_device *dev)
106{
108 uint32_t delta_T = now - gvf_parametric_t0;
109
110 if (delta_T < 200)
113 trans, dev, AC_ID,
116 }
117}
118#endif // GVF_OCAML_GCS
119
120#endif // PERIODIC TELEMETRY
121
122#ifdef __cplusplus
123}
124#endif
125
148
149void gvf_parametric_control_2D(float kx, float ky, float f1, float f2, float f1d, float f2d, float f1dd, float f2dd)
150{
151
155
156 if (gvf_parametric_control.delta_T > 300) { // We need at least two iterations for Delta_T
157 gvf_parametric_control.w = 0; // Reset w since we assume the algorithm starts
158 return;
159 }
160
161 // Carrot position
162#ifdef FIXEDWING_FIRMWARE
163 desired_x = f1;
164 desired_y = f2;
165#endif
166
167 float f_v2 = f1d * f1d + f2d * f2d;
168 float f_v = sqrtf(f_v2);
169
170 float f_d_dot_f_dd = f1d * f1dd + f2d * f2dd;
171
172 float og_f1d = f1d;
173 float og_f2d = f2d;
174
175 float og_f1dd = f1dd;
176 float og_f2dd = f2dd;
177
179 if (f_v < 1e-6) { // i.e, f'(w) = 0
180 // Use an arbitrary direction
181 f1d = 1 / sqrtf(3.);
182 f2d = 1 / sqrtf(3.);
183
184 f1dd = 0.;
185 f2dd = 0.;
186 } else {
187 f1dd = (f1dd - f_d_dot_f_dd * f1d / f_v2) / f_v2;
188 f2dd = (f2dd - f_d_dot_f_dd * f2d / f_v2) / f_v2;
189
190 f1d = f1d / f_v;
191 f2d = f2d / f_v;
192 }
193 }
194
195 float L = gvf_parametric_control.L;
197
198 Eigen::Vector3f X;
199 Eigen::Matrix3f J;
200
201 // Error signals phi_x and phi_y
203 float x = pos_enu->x;
204 float y = pos_enu->y;
205
206 float phi1 = L * (x - f1);
207 float phi2 = L * (y - f2);
208
209 gvf_parametric_telemetry.phi_errors[0] = phi1; // Error signals for the telemetry
212
213 // Chi
214 X(0) = L * beta * f1d - kx * phi1;
215 X(1) = L * beta * f2d - ky * phi2;
216 X(2) = L + beta * (kx * phi1 * f1d + ky * phi2 * f2d);
217 X *= L;
218
219 // Jacobian
220 J.setZero();
221 J(0, 0) = -kx * L;
222 J(1, 1) = -ky * L;
223 J(2, 0) = (beta * L) * (beta * f1dd + kx * f1d);
224 J(2, 1) = (beta * L) * (beta * f2dd + ky * f2d);
225 J(2, 2) = beta * beta * (kx * (phi1 * f1dd - L * f1d * f1d) + ky * (phi2 * f2dd - L * f2d * f2d));
226 J *= L;
227
228 // Guidance algorithm
230 float w_dot;
231
235 } else {
236 w_dot = (ground_speed * X(2)) / sqrtf(X(0) * X(0) + X(1) * X(1));
237 }
238
239 Eigen::Vector3f xi_dot;
242
243 xi_dot << vel_enu->x, vel_enu->y, w_dot;
244
245 Eigen::Matrix3f G;
246 Eigen::Matrix3f Gp;
247 Eigen::Matrix<float, 2, 3> Fp;
248 Eigen::Vector2f h;
249 Eigen::Matrix<float, 1, 2> ht;
250
251 G << 1, 0, 0,
252 0, 1, 0,
253 0, 0, 0;
254 Fp << 0, -1, 0,
255 1, 0, 0;
256 Gp << 0, -1, 0,
257 1, 0, 0,
258 0, 0, 0;
259
260 h << sinf(course), cosf(course);
261 ht = h.transpose();
262
263 Eigen::Matrix<float, 1, 3> Xt = X.transpose();
264 Eigen::Vector3f Xh = X / X.norm();
265 Eigen::Matrix<float, 1, 3> Xht = Xh.transpose();
266 Eigen::Matrix3f I;
267 I.setIdentity();
268
269 float aux = ht * Fp * X;
270 float heading_rate = -1 / (Xt * G * X) * Xt * Gp * (I - Xh * Xht) * J * xi_dot - (gvf_parametric_control.k_psi * aux /
271 sqrtf(Xt * G * X));
272
273 // From gvf_common.h TODO: implement d/dt of kppa and ori_err
274 gvf_c_ctrl.omega = heading_rate;
275 gvf_c_info.kappa = (f1d * f2dd - f1dd * f2d) / powf(f1d * f1d + f2d * f2d, 1.5);
276 gvf_c_info.ori_err = 1 - (Xh(0) * cosf(course) + Xh(1) * sinf(course));
277
278 // Virtual coordinate update, even if the vehicle is not in autonomous mode, the parameter w will get "closer" to
279 // the vehicle. So it is not only okei but advisable to update it.
281
282 gvf_low_level_control_2D(heading_rate);
283}
284
285#ifdef FIXEDWING_FIRMWARE
286void gvf_parametric_control_3D(float kx, float ky, float kz, float f1, float f2, float f3, float f1d, float f2d,
287 float f3d, float f1dd, float f2dd, float f3dd)
288{
292
293 if (gvf_parametric_control.delta_T > 300) { // We need at least two iterations for Delta_T
294 gvf_parametric_control.w = 0; // Reset w since we assume the algorithm starts
295 return;
296 }
297
298 // Carrot position
299 desired_x = f1;
300 desired_y = f2;
301
302 float L = gvf_parametric_control.L;
304
305 Eigen::Vector4f X;
306 Eigen::Matrix4f J;
307
308 // Additional values required for using step adaptation
309
310 float f_v2 = f1d * f1d + f2d * f2d + f3d * f3d;
311 float f_v = sqrtf(f_v2);
312
313 float f_d_dot_f_dd = f1d * f1dd + f2d * f2dd + f3d * f3dd;
314
315 float og_f1d = f1d;
316 float og_f2d = f2d;
317 float og_f3d = f3d;
318
319 float og_f1dd = f1dd;
320 float og_f2dd = f2dd;
321 float og_f3dd = f3dd;
322
324 if (f_v < 1e-6) { // i.e, f'(w) = 0
325 // Use an arbitrary direction
326 f1d = 1 / sqrtf(3.);
327 f2d = 1 / sqrtf(3.);
328 f3d = 1 / sqrtf(3.);
329
330 f1dd = 0.;
331 f2dd = 0.;
332 f3dd = 0.;
333 } else {
334 f1dd = (f1dd - f_d_dot_f_dd * f1d / f_v2) / f_v2;
335 f2dd = (f2dd - f_d_dot_f_dd * f2d / f_v2) / f_v2;
336 f3dd = (f3dd - f_d_dot_f_dd * f3d / f_v2) / f_v2;
337
338 f1d = f1d / f_v;
339 f2d = f2d / f_v;
340 f3d = f3d / f_v;
341 }
342 }
343
344 // Error signals phi_x phi_y and phi_z
346 float x = pos_enu->x;
347 float y = pos_enu->y;
348 float z = pos_enu->z;
349
350 float phi1 = L * (x - f1);
351 float phi2 = L * (y - f2);
352 float phi3 = L * (z - f3);
353
354 gvf_parametric_telemetry.phi_errors[0] = phi1 / L; // Error signals in meters for the telemetry
358
359
360 // Chi
361 X(0) = -f1d * L * L * beta - kx * phi1;
362 X(1) = -f2d * L * L * beta - ky * phi2;
363 X(2) = -f3d * L * L * beta - kz * phi3;
364 X(3) = -L * L + beta * (kx * phi1 * f1d + ky * phi2 * f2d + kz * phi3 * f3d);
365 X *= L;
366
367 // Jacobian
368 J.setZero();
369 J(0, 0) = -kx * L;
370 J(1, 1) = -ky * L;
371 J(2, 2) = -kz * L;
372 J(3, 0) = kx * f1d * beta * L;
373 J(3, 1) = ky * f2d * beta * L;
374 J(3, 2) = kz * f3d * beta * L;
375 J(0, 3) = -(beta * L) * (beta * L * f1dd - kx * f1d);
376 J(1, 3) = -(beta * L) * (beta * L * f2dd - ky * f2d);
377 J(2, 3) = -(beta * L) * (beta * L * f3dd - kz * f3d);
378 J(3, 3) = beta * beta * (kx * (phi1 * f1dd - L * f1d * f1d) + ky * (phi2 * f2dd - L * f2d * f2d)
379 + kz * (phi3 * f3dd - L * f3d * f3d));
380 J *= L;
381
382 // Guidance algorithm
384 float w_dot;
385
389 } else {
390 w_dot = (ground_speed * X(3)) / sqrtf(X(0) * X(0) + X(1) * X(1));
391 }
392
393 Eigen::Vector4f xi_dot;
396
397 xi_dot << vel_enu->x, vel_enu->y, vel_enu->z, w_dot;
398
399 Eigen::Matrix2f E;
400 Eigen::Matrix<float, 2, 4> F;
401 Eigen::Matrix<float, 2, 4> Fp;
402 Eigen::Matrix4f G;
403 Eigen::Matrix4f Gp;
404 Eigen::Matrix4f I;
405 Eigen::Vector2f h;
406 Eigen::Matrix<float, 1, 2> ht;
407
408 h << sinf(course), cosf(course);
409 ht = h.transpose();
410 I.setIdentity();
411 F << 1.0, 0.0, 0.0, 0.0,
412 0.0, 1.0, 0.0, 0.0;
413 E << 0.0, -1.0,
414 1.0, 0.0;
415 G = F.transpose() * F;
416 Fp = E * F;
417 Gp = F.transpose() * E * F;
418
419 Eigen::Matrix<float, 1, 4> Xt = X.transpose();
420 Eigen::Vector4f Xh = X / X.norm();
421 Eigen::Matrix<float, 1, 4> Xht = Xh.transpose();
422
423 float aux = ht * Fp * X;
424
425 float heading_rate = -1 / (Xt * G * X) * Xt * Gp * (I - Xh * Xht) * J * xi_dot - (gvf_parametric_control.k_psi * aux /
426 sqrtf(Xt * G * X));
427 float climbing_rate = (ground_speed * X(2)) / sqrtf(X(0) * X(0) + X(1) * X(1));
428
429 // Virtual coordinate update, even if the vehicle is not in autonomous mode, the parameter w will get "closer" to
430 // the vehicle. So it is not only okei but advisable to update it.
432
434}
435#endif // FIXED_WING FIRMWARE
436
441
static void h(const real32_T x[7], const real32_T q[4], real32_T y[6])
static int16_t course[3]
Core autopilot interface common to all firmwares.
uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
static float ground_speed
Definition follow_me.c:76
static struct uart_periph * dev
#define E
static struct EnuCoor_f * stateGetPositionEnu_f(void)
Get position in local ENU coordinates (float).
Definition state.h:848
static float stateGetHorizontalSpeedNorm_f(void)
Get norm of horizontal ground speed (float).
Definition state.h:1076
static float stateGetHorizontalSpeedDir_f(void)
Get dir of horizontal ground speed (float).
Definition state.h:1085
static struct EnuCoor_f * stateGetSpeedEnu_f(void)
Get ground speed in local ENU coordinates (float).
Definition state.h:1058
float step_adaptation(float ds, float f1d, float f2d, float f3d, float f1dd, float f2dd, float f3dd)
Compute the adapted parametric step given the wanted geometric distance.
Dynamic parametric step adaptation for the GVF algorithm.
gvf_common_ctrl gvf_c_ctrl
Definition gvf_common.c:28
gvf_common_params gvf_c_params
Definition gvf_common.c:30
void gvf_low_level_control_2D(float omega)
Definition gvf_common.c:58
gvf_common_info gvf_c_info
Definition gvf_common.c:29
void gvf_low_level_control_3D(float heading_rate, float climbing_rate)
Definition gvf_common.c:79
gvf_parametric_tra gvf_parametric_trajectory
@ ELLIPSE_3D
enum trajectories_parametric type
gvf_parametric_con gvf_parametric_control
#define GVF_PARAMETRIC_CONTROL_KCLIMB
#define GVF_PARAMETRIC_CONTROL_L
#define GVF_PARAMETRIC_CONTROL_BETA
#define GVF_PARAMETRIC_CONTROL_KROLL
static void send_gvf_parametric(struct transport_tx *trans, struct link_device *dev)
TELEMETRY -----------------------------------------------------------—.
#define GVF_PARAMETRIC_CONTROL_KPSI
uint32_t gvf_parametric_t0
void gvf_parametric_init(void)
void gvf_parametric_control_2D(float kx, float ky, float f1, float f2, float f1d, float f2d, float f1dd, float f2dd)
gvf_parametric_tel gvf_parametric_telemetry
void gvf_parametric_set_direction(int8_t s)
Guiding vector field algorithm for 2D and 3D parametric trajectories.
void gvf_parametric_control_3D(float, float, float, float, float, float, float, float, float, float, float, float)
#define GVF_PARAMETRIC_CONTROL_STEP_ADAPTATION
static uint32_t s
uint16_t foo
Definition main_demo5.c:58
float desired_x
Definition nav.c:308
float desired_y
Definition nav.c:308
float y
in meters
float x
in meters
float z
in meters
vector in East North Up coordinates Units: meters
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
static float J
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.