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"
36#include "../gvf_common.h"
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42#include "autopilot.h"
43
44// Control
45uint32_t gvf_parametric_t0 = 0; // We need it for calculting the time lapse delta_T
46uint32_t gvf_parametric_splines_ctr = 0; // We need it for Bézier curves splines Telemetry
48
49// Trajectory
51
52// Parameters array lenght
55
56// Error signals array lenght
58
59// Bézier
61
62#if PERIODIC_TELEMETRY
79
80#if GVF_OCAML_GCS
81static void send_circle_parametric(struct transport_tx *trans, struct link_device *dev)
82{
84 uint32_t delta_T = now - gvf_parametric_t0;
85
86 if (delta_T < 200)
90 }
91}
92#endif // GVF_OCAML_GCS
93
94#endif // PERIODIC TELEMETRY
95
96#ifdef __cplusplus
97}
98#endif
99
119
124
125void gvf_parametric_control_2D(float kx, float ky, float f1, float f2, float f1d, float f2d, float f1dd, float f2dd)
126{
127
131
132 if (gvf_parametric_control.delta_T > 300) { // We need at least two iterations for Delta_T
133 gvf_parametric_control.w = 0; // Reset w since we assume the algorithm starts
134 return;
135 }
136
137 // Carrot position
138#ifdef FIXEDWING_FIRMWARE
139 desired_x = f1;
140 desired_y = f2;
141#endif
142
143 float L = gvf_parametric_control.L;
145
146 Eigen::Vector3f X;
147 Eigen::Matrix3f J;
148
149 // Error signals phi_x and phi_y
151 float x = pos_enu->x;
152 float y = pos_enu->y;
153
154 float phi1 = L * (x - f1);
155 float phi2 = L * (y - f2);
156
157 gvf_parametric_trajectory.phi_errors[0] = phi1; // Error signals for the telemetry
160
161 // Chi
162 X(0) = L * beta * f1d - kx * phi1;
163 X(1) = L * beta * f2d - ky * phi2;
164 X(2) = L + beta * (kx * phi1 * f1d + ky * phi2 * f2d);
165 X *= L;
166
167 // Jacobian
168 J.setZero();
169 J(0, 0) = -kx * L;
170 J(1, 1) = -ky * L;
171 J(2, 0) = (beta * L) * (beta * f1dd + kx * f1d);
172 J(2, 1) = (beta * L) * (beta * f2dd + ky * f2d);
173 J(2, 2) = beta * beta * (kx * (phi1 * f1dd - L * f1d * f1d) + ky * (phi2 * f2dd - L * f2d * f2d));
174 J *= L;
175
176 // Guidance algorithm
178 float w_dot = (ground_speed * X(2)) / sqrtf(X(0) * X(0) + X(1) * X(1));
179
180 Eigen::Vector3f xi_dot;
183
184 xi_dot << vel_enu->x, vel_enu->y, w_dot;
185
186 Eigen::Matrix3f G;
187 Eigen::Matrix3f Gp;
188 Eigen::Matrix<float, 2, 3> Fp;
189 Eigen::Vector2f h;
190 Eigen::Matrix<float, 1, 2> ht;
191
192 G << 1, 0, 0,
193 0, 1, 0,
194 0, 0, 0;
195 Fp << 0, -1, 0,
196 1, 0, 0;
197 Gp << 0, -1, 0,
198 1, 0, 0,
199 0, 0, 0;
200
201 h << sinf(course), cosf(course);
202 ht = h.transpose();
203
204 Eigen::Matrix<float, 1, 3> Xt = X.transpose();
205 Eigen::Vector3f Xh = X / X.norm();
206 Eigen::Matrix<float, 1, 3> Xht = Xh.transpose();
207 Eigen::Matrix3f I;
208 I.setIdentity();
209
210 float aux = ht * Fp * X;
211 float heading_rate = -1 / (Xt * G * X) * Xt * Gp * (I - Xh * Xht) * J * xi_dot - (gvf_parametric_control.k_psi * aux /
212 sqrtf(Xt * G * X));
213
214 // From gvf_common.h TODO: implement d/dt of kppa and ori_err
215 gvf_c_omega.omega = heading_rate;
216 gvf_c_info.kappa = (f1d * f2dd - f1dd * f2d) / powf(f1d * f1d + f2d * f2d, 1.5);
217 gvf_c_info.ori_err = 1 - (Xh(0) * cosf(course) + Xh(1) * sinf(course));
218
219 // Virtual coordinate update, even if the vehicle is not in autonomous mode, the parameter w will get "closer" to
220 // the vehicle. So it is not only okei but advisable to update it.
222
224}
225
226#ifdef FIXEDWING_FIRMWARE
227void gvf_parametric_control_3D(float kx, float ky, float kz, float f1, float f2, float f3, float f1d, float f2d,
228 float f3d, float f1dd, float f2dd, float f3dd)
229{
233
234 if (gvf_parametric_control.delta_T > 300) { // We need at least two iterations for Delta_T
235 gvf_parametric_control.w = 0; // Reset w since we assume the algorithm starts
236 return;
237 }
238
239 // Carrot position
240 desired_x = f1;
241 desired_y = f2;
242
243 float L = gvf_parametric_control.L;
245
246 Eigen::Vector4f X;
247 Eigen::Matrix4f J;
248
249 // Error signals phi_x phi_y and phi_z
251 float x = pos_enu->x;
252 float y = pos_enu->y;
253 float z = pos_enu->z;
254
255 float phi1 = L * (x - f1);
256 float phi2 = L * (y - f2);
257 float phi3 = L * (z - f3);
258
259 gvf_parametric_trajectory.phi_errors[0] = phi1 / L; // Error signals in meters for the telemetry
263
264
265 // Chi
266 X(0) = -f1d * L * L * beta - kx * phi1;
267 X(1) = -f2d * L * L * beta - ky * phi2;
268 X(2) = -f3d * L * L * beta - kz * phi3;
269 X(3) = -L * L + beta * (kx * phi1 * f1d + ky * phi2 * f2d + kz * phi3 * f3d);
270 X *= L;
271
272 // Jacobian
273 J.setZero();
274 J(0, 0) = -kx * L;
275 J(1, 1) = -ky * L;
276 J(2, 2) = -kz * L;
277 J(3, 0) = kx * f1d * beta * L;
278 J(3, 1) = ky * f2d * beta * L;
279 J(3, 2) = kz * f3d * beta * L;
280 J(0, 3) = -(beta * L) * (beta * L * f1dd - kx * f1d);
281 J(1, 3) = -(beta * L) * (beta * L * f2dd - ky * f2d);
282 J(2, 3) = -(beta * L) * (beta * L * f3dd - kz * f3d);
283 J(3, 3) = beta * beta * (kx * (phi1 * f1dd - L * f1d * f1d) + ky * (phi2 * f2dd - L * f2d * f2d)
284 + kz * (phi3 * f3dd - L * f3d * f3d));
285 J *= L;
286
287 // Guidance algorithm
289 float w_dot = (ground_speed * X(3)) / sqrtf(X(0) * X(0) + X(1) * X(1));
290
291 Eigen::Vector4f xi_dot;
294
295 xi_dot << vel_enu->x, vel_enu->y, vel_enu->z, w_dot;
296
297 Eigen::Matrix2f E;
298 Eigen::Matrix<float, 2, 4> F;
299 Eigen::Matrix<float, 2, 4> Fp;
300 Eigen::Matrix4f G;
301 Eigen::Matrix4f Gp;
302 Eigen::Matrix4f I;
303 Eigen::Vector2f h;
304 Eigen::Matrix<float, 1, 2> ht;
305
306 h << sinf(course), cosf(course);
307 ht = h.transpose();
308 I.setIdentity();
309 F << 1.0, 0.0, 0.0, 0.0,
310 0.0, 1.0, 0.0, 0.0;
311 E << 0.0, -1.0,
312 1.0, 0.0;
313 G = F.transpose() * F;
314 Fp = E * F;
315 Gp = F.transpose() * E * F;
316
317 Eigen::Matrix<float, 1, 4> Xt = X.transpose();
318 Eigen::Vector4f Xh = X / X.norm();
319 Eigen::Matrix<float, 1, 4> Xht = Xh.transpose();
320
321 float aux = ht * Fp * X;
322
323 float heading_rate = -1 / (Xt * G * X) * Xt * Gp * (I - Xh * Xht) * J * xi_dot - (gvf_parametric_control.k_psi * aux /
324 sqrtf(Xt * G * X));
325 float climbing_rate = (ground_speed * X(2)) / sqrtf(X(0) * X(0) + X(1) * X(1));
326
327 // Virtual coordinate update, even if the vehicle is not in autonomous mode, the parameter w will get "closer" to
328 // the vehicle. So it is not only okei but advisable to update it.
330
332}
333#endif // FIXED_WING FIRMWARE
334
336// 2D TREFOIL KNOT
337
359
360bool gvf_parametric_2D_trefoil_wp(uint8_t wp, float w1, float w2, float ratio, float r, float alpha)
361{
364 gvf_parametric_2D_trefoil_XY(WaypointX(wp), WaypointY(wp), w1, w2, ratio, r, alpha);
365 return true;
366}
367
368// 2D CUBIC BEZIER CURVE
378
379/* @param first_wp is the first waypoint of the Bézier Spline
380 * there should be 3*GVF_PARAMETRIC_2D_BEZIER_N_SEG+1 points
381 */
383{
384 float x[3 * GVF_PARAMETRIC_2D_BEZIER_N_SEG + 1];
385 float y[3 * GVF_PARAMETRIC_2D_BEZIER_N_SEG + 1];
386 int k;
387 for (k = 0; k < 3 * GVF_PARAMETRIC_2D_BEZIER_N_SEG + 1; k++) {
388 x[k] = WaypointX(first_wp + k);
389 y[k] = WaypointY(first_wp + k);
390 }
392
393 /* Send data piecewise. Some radio modules do not allow for a big data frame.*/
394
395 // Send x points -> Indicate x with sign (+) in the first parameter
398 for (k = 0; k < 3 * GVF_PARAMETRIC_2D_BEZIER_N_SEG + 1; k++) {
400 }
401 }
402 // Send y points -> Indicate y with sign (-) in the first parameter
403 else if (gvf_parametric_splines_ctr == 1) {
405 for (k = 0; k < 3 * GVF_PARAMETRIC_2D_BEZIER_N_SEG + 1; k++) {
407 }
408 }
409 // send kx, ky, beta and anything else needed..
410 else {
415 }
418
419 // restart the spline
422 } else if (gvf_parametric_control.w < 0) {
424 }
426 return true;
427}
428
430// 3D ELLIPSE
431#ifdef FIXEDWING_FIRMWARE
432bool gvf_parametric_3D_ellipse_XYZ(float xo, float yo, float r, float zl, float zh, float alpha)
433{
434 horizontal_mode = HORIZONTAL_MODE_CIRCLE; // Circle for the 2D GCS
435
436 // Safety first! If the asked altitude is low
437 if (zl > zh) {
438 zl = zh;
439 }
440 if (zl < 1 || zh < 1) {
441 zl = 10;
442 zh = 10;
443 }
444 if (r < 1) {
445 r = 60;
446 }
447
457
458 float f1, f2, f3, f1d, f2d, f3d, f1dd, f2dd, f3dd;
459
463
464 return true;
465}
466
467bool gvf_parametric_3D_ellipse_wp(uint8_t wp, float r, float zl, float zh, float alpha)
468{
471
473 return true;
474}
475
476bool gvf_parametric_3D_ellipse_wp_delta(uint8_t wp, float r, float alt_center, float delta, float alpha)
477{
478 float zl = alt_center - delta;
479 float zh = alt_center + delta;
480
482 return true;
483}
484
485// 3D Lissajous
486
487bool gvf_parametric_3D_lissajous_XYZ(float xo, float yo, float zo, float cx, float cy, float cz, float wx, float wy,
488 float wz, float dx, float dy, float dz, float alpha)
489{
490 // Safety first! If the asked altitude is low
491 if ((zo - cz) < 1) {
492 zo = 10;
493 cz = 0;
494 }
495
512
513 float f1, f2, f3, f1d, f2d, f3d, f1dd, f2dd, f3dd;
514
518
519 return true;
520}
521
522bool gvf_parametric_3D_lissajous_wp_center(uint8_t wp, float zo, float cx, float cy, float cz, float wx, float wy,
523 float wz, float dx, float dy, float dz, float alpha)
524{
527
528 gvf_parametric_3D_lissajous_XYZ(waypoints[wp].x, waypoints[wp].y, zo, cx, cy, cz, wx, wy, wz, dx, dy, dz, alpha);
529 return true;
530}
531#endif // FIXEDWING_FIRMWARE
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.
struct point waypoints[NB_WAYPOINT]
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition common_nav.c:44
#define WaypointX(_wp)
Definition common_nav.h:45
#define WaypointY(_wp)
Definition common_nav.h:46
static float ground_speed
Definition follow_me.c:76
#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
gvf_common_omega gvf_c_omega
Definition gvf_common.c:23
gvf_common_params gvf_c_info
Definition gvf_common.c:24
gvf_parametric_con gvf_parametric_control
int gvf_parametric_elen
bool gvf_parametric_2D_bezier_wp(uint8_t first_wp)
uint32_t gvf_parametric_splines_ctr
bool gvf_parametric_2D_trefoil_XY(float xo, float yo, float w1, float w2, float ratio, float r, float alpha)
2D TRAJECTORIES
int gvf_parametric_plen_wps
static void send_gvf_parametric(struct transport_tx *trans, struct link_device *dev)
bool gvf_parametric_2D_bezier_XY(void)
bezier_t gvf_bezier_2D[GVF_PARAMETRIC_2D_BEZIER_N_SEG]
uint32_t gvf_parametric_t0
void gvf_parametric_init(void)
gvf_parametric_tra gvf_parametric_trajectory
void gvf_parametric_control_2D(float kx, float ky, float f1, float f2, float f1d, float f2d, float f1dd, float f2dd)
bool gvf_parametric_2D_trefoil_wp(uint8_t wp, float w1, float w2, float ratio, float r, float alpha)
int gvf_parametric_plen
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)
@ LISSAJOUS_3D
@ BEZIER_2D
@ TREFOIL_2D
@ ELLIPSE_3D
#define GVF_PARAMETRIC_CONTROL_KCLIMB
#define GVF_PARAMETRIC_CONTROL_L
bool gvf_parametric_3D_ellipse_XYZ(float, float, float, float, float, float)
#define GVF_PARAMETRIC_CONTROL_BETA
#define GVF_PARAMETRIC_CONTROL_KROLL
bool gvf_parametric_3D_lissajous_XYZ(float, float, float, float, float, float, float, float, float, float, float, float, float)
#define GVF_PARAMETRIC_CONTROL_KPSI
bool gvf_parametric_3D_ellipse_wp_delta(uint8_t, float, float, float, float)
bool gvf_parametric_3D_lissajous_wp_center(uint8_t, float, float, float, float, float, float, float, float, float, float, float)
enum trajectories_parametric type
bool gvf_parametric_3D_ellipse_wp(uint8_t, float, float, float, float)
void gvf_parametric_2d_bezier_splines_info(bezier_t *bezier, float *f1, float *f2, float *f1d, float *f2d, float *f1dd, float *f2dd)
gvf_par_2d_bezier_par gvf_parametric_2d_bezier_par
void create_bezier_spline(bezier_t *bezier, float *px, float *py)
#define GVF_PARAMETRIC_2D_BEZIER_N_SEG
void gvf_parametric_2d_trefoil_info(float *f1, float *f2, float *f1d, float *f2d, float *f1dd, float *f2dd)
gvf_par_2d_tre_par gvf_parametric_2d_trefoil_par
Guiding vector field algorithm for 2D and 3D complex trajectories.
void gvf_parametric_3d_ellipse_info(float *f1, float *f2, float *f3, float *f1d, float *f2d, float *f3d, float *f1dd, float *f2dd, float *f3dd)
gvf_par_3d_ell_par gvf_parametric_3d_ellipse_par
Guiding vector field algorithm for 2D and 3D complex trajectories.
gvf_par_3d_lis_par gvf_parametric_3d_lissajous_par
void gvf_parametric_3d_lissajous_info(float *f1, float *f2, float *f3, float *f1d, float *f2d, float *f3d, float *f1dd, float *f2dd, float *f3dd)
Guiding vector field algorithm for 2D and 3D complex trajectories.
void gvf_parametric_low_level_control_3D(float heading_rate USED_IN_FIXEDWING_ONLY, float climbing_rate USED_IN_FIXEDWING_ONLY)
void gvf_parametric_low_level_control_2D(float heading_rate USED_IN_FIXEDWING_ONLY)
Firmware dependent file for the guiding vector field algorithm for 2D and 3D parametric trajectories.
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
uint8_t horizontal_mode
Definition nav.c:70
#define HORIZONTAL_MODE_CIRCLE
Definition nav.h:92
float y
in meters
float x
in meters
float z
in meters
vector in East North Up coordinates Units: meters
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
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
float alpha
Definition textons.c:133
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.