Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
gvf_adapted_step.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 Mael Feurgard <maelfeurgard@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
21
22#include <math.h>
23#include "std.h"
24
31#include "gvf_adapted_step.h"
32
33// Numbers with absolute values smaller than `ADAPTED_STEP_NULL_TOLERANCE` will be considered equal to 0
34#ifndef ADAPTED_STEP_NULL_TOLERANCE
35 #define ADAPTED_STEP_NULL_TOLERANCE 1e-6
36#endif
37
38// Maximum number of steps used in the root finding algorithm
39#ifndef ADAPTED_STEP_MAX_ROOTFINDING_STEPS
40 #define ADAPTED_STEP_MAX_ROOTFINDING_STEPS 1e6
41#endif
42
56static float p4_eval(float x, float a4, float a3, float a2, float a1, float a0)
57{
58 return a0 + x * (a1 + x * (a2 + x * (a3 + x * (a4))));
59}
60
76static float p4_halley(float a4, float a3, float a2, float a1, float a0, float tol, float init, int max_steps)
77{
78 float x = init;
79 float p_x = p4_eval(x, a4, a3, a2, a1, a0);
80
81 // Coefficients of the polynomial first derivative
82 float a4_d = 0.;
83 float a3_d = 4 * a4;
84 float a2_d = 3 * a3;
85 float a1_d = 2 * a2;
86 float a0_d = a1;
87
88 // Coefficients of the polynomial second derivative
89 float a4_dd = 0.;
90 float a3_dd = 0.;
91 float a2_dd = 3 * a3_d;
92 float a1_dd = 2 * a2_d;
93 float a0_dd = a1_d;
94
95 int step = 0;
96
97 while (ABS(p_x) > tol && step < max_steps) {
98 float p_xd = p4_eval(x, a4_d, a3_d, a2_d, a1_d, a0_d);
99 float p_xdd = p4_eval(x, a4_dd, a3_dd, a2_dd, a1_dd, a0_dd);
100 p_x = p4_eval(x, a4, a3, a2, a1, a0);
101 x = x - (2 * p_x * p_xd) / (2 * p_xd * p_xd - p_x * p_xdd);
102 step++;
103 }
104
105 return x;
106}
107
108float step_adaptation(float ds, float f1d, float f2d, float f3d, float f1dd, float f2dd, float f3dd)
109{
110 float a4 = (f1dd * f1dd + f2dd * f2dd + f3dd * f3dd) / 4.;
111 float a3 = (f1d * f1dd + f2d * f2dd + f3d * f3dd);
112 float a2 = (f1d * f1d + f2d * f2d + f3d * f3d);
113 float a1 = 0.;
114 float a0 = - ds * ds;
115
116
118 // fprintf(stderr,"***** Error: order 2 singularity (f' and f'' are null) *****\n");
119 // fprintf(stderr, "Falling back to 'natural' parametrization'\n");
120 return ds;
121 }
122
124 // Second derivative is null; this is a degree 2 polynomial
125 return ds / sqrtf(a2);
126 }
127
129 // First derivative is null, but not the second; immediate analytical solution
130 float output = sqrtf(ABS(ds)) / sqrtf(sqrtf(a4));
131 if (ds > 0) {
132 return output;
133 } else {
134 return - output;
135 }
136 }
137
138
139 float init;
140
141 {
142 // Compute derivative's (reduced polynomial) discriminant
143 // float a4_d = 0.; unused
144 float a3_d = 4 * a4;
145 float a2_d = 3 * a3;
146 float a1_d = 2 * a2;
147 // float a0_d = a1; // = 0; unused
148
149 float discr = a2_d * a2_d - 4 * a3_d * a1_d;
150
151 if (discr < 0) {
152 // If there are no additional roots, use the 1st order approx as starting point
153 init = ds / sqrtf(a2);
154 } else {
155 // If there are additional roots, use the closest one
156 if (ds > 0) {
157 // Positive direction
158 if (a2_d < 0) {
159 // Additional roots are on this side, use the closest to 0 for reference
160 init = (-a2_d - sqrtf(discr)) / (4 * a3_d);
161 } else {
162 // No additional roots
163 init = ds / sqrtf(a2);
164 }
165 } else {
166 if (a2_d < 0) {
167 // No additional roots
168 init = ds / sqrtf(a2);
169 } else {
170 // Additional roots are on this side, use the closest to 0 for reference
171 init = (-a2_d + sqrtf(discr)) / (4 * a3_d);
172 }
173 }
174 }
175 }
176
178
179 if (result * ds < 0) {
181 }
182
183 return result;
184}
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.
#define ADAPTED_STEP_NULL_TOLERANCE
static float p4_halley(float a4, float a3, float a2, float a1, float a0, float tol, float init, int max_steps)
Implementation of Halley's method for degree 4 polynomial root finding.
#define ADAPTED_STEP_MAX_ROOTFINDING_STEPS
static float p4_eval(float x, float a4, float a3, float a2, float a1, float a0)
Horner's method for fast degree 4 polynomial evaluation.
Dynamic parametric step adaptation for the GVF algorithm.
uint16_t foo
Definition main_demo5.c:58
uint8_t step
Definition max7456.c:141
bool init
Definition nav_gls.c:57