PX4 Firmware
PX4 Autopilot Software http://px4.io
test_bezierQuad.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2018-2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file test_bezierQuad.cpp
36  * Test for Bezier curve computation.
37  */
38 
39 #include <unit_test.h>
40 #include <float.h>
41 #include <stdlib.h>
42 #include <time.h>
43 
44 #include "../../lib/bezier/BezierQuad.hpp"
45 
46 class BezierQuadTest : public UnitTest
47 {
48 public:
49  virtual bool run_tests();
50 
51 private:
52 
53  bool _get_states_from_time();
54  bool _get_arc_length();
55  bool _set_bez_from_vel();
56 
57  float random(float min, float max);
58 
59 };
60 
61 
63 {
67 
68  return (_tests_failed == 0);
69 }
70 
72 {
73  // symmetric around 0
74  matrix::Vector3f pt0(-0.5f, 0.0f, 0.0f);
75  matrix::Vector3f ctrl(0.0f, 0.5f, 0.0f);
76  matrix::Vector3f pt1(0.5f, 0.0f, 0.0f);
77 
78  // create bezier with default t = [0,1]
79  bezier::BezierQuad_f bz(pt0, ctrl, pt1);
80 
81  matrix::Vector3f pos, vel, acc;
82  float precision = 0.00001;
83 
84  // states at time = 0
85  bz.getStates(pos, vel, acc, 0.0f);
86 
87  ut_compare_float("pos[0] not equal pt0[0]", pos(0), pt0(0), precision);
88  ut_compare_float("pos[1] not equal pt0[1]", pos(1), pt0(1), precision);
89  ut_compare_float("pos[2] not equal pt0[2]", pos(2), pt0(2), precision);
90 
91  ut_compare_float("slope not equal 1", vel(0), 1.0f, precision);
92  ut_compare_float("slope not equal 1", vel(1), 1.0f, precision);
93  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
94 
95  ut_compare_float("acc not equal 0", acc(0), 0.0f, precision);
96  ut_compare_float("acc not equal 1", acc(1), -2.0f, precision);
97  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
98 
99  // states at time = 1
100  bz.getStates(pos, vel, acc, 1.0f);
101 
102  ut_compare_float("pos[0] not equal pt1[0]", pos(0), pt1(0), precision);
103  ut_compare_float("pos[1] not equal pt1[1]", pos(1), pt1(1), precision);
104  ut_compare_float("pos[2] not equal pt1[2]", pos(2), pt1(2), precision);
105 
106  ut_compare_float("slope not equal 1", vel(0), 1.0f, precision);
107  ut_compare_float("slope not equal -1", vel(1), -1.0f, precision);
108  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
109 
110  ut_compare_float("acc not equal 0", acc(0), 0.0f, precision);
111  ut_compare_float("acc not equal 1", acc(1), -2.0f, precision);
112  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
113 
114  // states at time = 0.5
115  bz.getStates(pos, vel, acc, 0.50f);
116 
117  // pos must be equal to ctrl(0) and lower than ctrl(1)
118  ut_compare_float("pos[0] not equal ctrl[0]", pos(0), ctrl(0), precision);
119  ut_assert_true(pos(1) < ctrl(1));
120 
121  ut_compare_float("slope not equal 1", vel(0), 1.0f, precision);
122  ut_compare_float("slope not equal -1", vel(1), 0.0f, precision);
123  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
124 
125  ut_compare_float("acc not equal 0", acc(0), 0.0f, precision);
126  ut_compare_float("acc not equal -2", acc(1), -2.0f, precision);
127  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
128 
129  // acceleration
130  pt0 = matrix::Vector3f(0.0f, 0.0f, 0.0f);
131  ctrl = matrix::Vector3f(0.0f, 0.0f, 0.0f);
132  pt1 = matrix::Vector3f(1.0f, 0.0f, 0.0f);
133 
134  // create bezier with default t = [0,1]
135  bz.setBezier(pt0, ctrl, pt1, 1.0f);
136 
137  // states at time = 0.0
138  bz.getStates(pos, vel, acc, 0.0f);
139 
140  ut_compare_float("pos[0] not equal pt0[0]", pos(0), pt0(0), precision);
141  ut_compare_float("pos[1] not equal pt0[1]", pos(1), pt0(1), precision);
142  ut_compare_float("pos[2] not equal pt0[2]", pos(2), pt0(2), precision);
143 
144  ut_compare_float("slope not equal 0", vel(0), 0.0f, precision);
145  ut_compare_float("slope not equal 0", vel(1), 0.0f, precision);
146  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
147 
148  ut_compare_float("acc not equal 2", acc(0), 2.0f, precision);
149  ut_compare_float("acc not equal 0", acc(1), 0.0f, precision);
150  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
151 
152  // states at time = 1.0
153  bz.getStates(pos, vel, acc, 1.0f);
154 
155  ut_compare_float("pos[0] not equal pt1[0]", pos(0), pt1(0), precision);
156  ut_compare_float("pos[1] not equal pt1[1]", pos(1), pt1(1), precision);
157  ut_compare_float("pos[2] not equal pt1[2]", pos(2), pt1(2), precision);
158 
159  ut_compare_float("slope not equal 2", vel(0), 2.0f, precision);
160  ut_compare_float("slope not equal 0", vel(1), 0.0f, precision);
161  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
162 
163  ut_compare_float("acc not equal 2", acc(0), 2.0f, precision);
164  ut_compare_float("acc not equal 0", acc(1), 0.0f, precision);
165  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
166 
167  // states at time = 0.5
168  bz.getStates(pos, vel, acc, 0.5f);
169 
170  ut_compare_float("slope not equal 1", vel(0), 1.0f, precision);
171  ut_compare_float("slope not equal 0", vel(1), 0.0f, precision);
172  ut_compare_float("slope not equal 0", vel(2), 0.0f, precision);
173 
174  ut_compare_float("acc not equal 2", acc(0), 2.0f, precision);
175  ut_compare_float("acc not equal 0", acc(1), 0.0f, precision);
176  ut_compare_float("acc not equal 0", acc(2), 0.0f, precision);
177 
178  return true;
179 
180 }
181 
183 {
184  // create random numbers
185  srand(0); // choose a constant to make it deterministic
186 
187  float min = -50.f;
188  float max = 50.f;
189  float resolution = 0.1f;
190 
191  matrix::Vector3f pt0, pt1, ctrl;
192  float duration, arc_length, triangle_length, straigth_length;
193  float T = 100.0f;
194 
195  // loop trough different control points 100x and check if arc_length is in the expected range
196  for (int i = 0; i < 100 ; i++) {
197  // random bezier point
198  pt0 = matrix::Vector3f(random(min, max), random(min, max), random(min, max));
199  pt1 = matrix::Vector3f(random(min, max), random(min, max), random(min, max));
200  ctrl = matrix::Vector3f(random(min, max), random(min, max), random(min, max));
201 
202  // use for each test a new duration
203  duration = random(0.0f, T);
204 
205  // create bezier
206  bezier::BezierQuad_f bz(pt0, ctrl, pt1, duration);
207 
208  // compute arc length, triangle length and straigh length
209  arc_length = bz.getArcLength(resolution);
210  triangle_length = (ctrl - pt0).length() + (pt1 - ctrl).length();
211  straigth_length = (pt1 - pt0).length();
212 
213  // we also compute length from going point to point and add segment
214  float time_increment = duration / T;
215  float t = 0.0f + time_increment;
216  matrix::Vector3f p0 = pt0;
217  float sum_segments = 0.0f;
218 
219  for (int s = 0; s < (int)T; s++) {
220  matrix::Vector3f nextpt = bz.getPoint(t);
221  sum_segments = (nextpt - p0).length() + sum_segments;
222  p0 = bz.getPoint(t);
223  t = t + time_increment;
224  }
225 
226  // test comparisons
227  ut_assert_true((triangle_length >= arc_length) && (arc_length >= straigth_length)
228  && (fabsf(arc_length - sum_segments) < 1.f));
229  }
230 
231 
232  return true;
233 }
234 
236 {
237  // create random numbers
238  srand(100); // choose a constant to make it deterministic
239 
240  float low = -50.0f;
241  float max = 50.0f;
242  float precision = 0.001f;
243 
244  for (int i = 0; i < 20; i++) {
245 
246  // set velocity
247  matrix::Vector3f ctrl(random(low, max), random(low, max), random(low, max));
248  matrix::Vector3f vel0(random(low, max), random(low, max), random(low, max));
249  matrix::Vector3f vel1(random(low, max), random(low, max), random(low, max));
250  float duration = random(0.0f, 100.0f);
251 
253  bz.setBezFromVel(ctrl, vel0, vel1, duration);
254 
255  // get velocity back
256  matrix::Vector3f v0 = bz.getVelocity(0.0f);
257  matrix::Vector3f v1 = bz.getVelocity(duration);
258  ut_compare_float("", vel0(0), v0(0), precision);
259  ut_compare_float("", vel1(0), v1(0), precision);
260 
261  ut_compare_float("", vel0(1), v0(1), precision);
262  ut_compare_float("", vel1(1), v1(1), precision);
263 
264  ut_compare_float("", vel0(2), v0(2), precision);
265  ut_compare_float("", vel1(2), v1(2), precision);
266  }
267 
268  return true;
269 }
270 
271 float BezierQuadTest::random(float min, float max)
272 {
273  float s = rand() / (float)RAND_MAX;
274  return (min + s * (max - min));
275 
276 }
277 
#define ut_declare_test_c(test_function, test_class)
Definition: unit_test.h:40
int test_bezierQuad(int argc, char *argv[])
Vector3_t getVelocity(const Tp t)
Definition: BezierQuad.cpp:75
Tp getArcLength(const Tp resolution)
Definition: BezierQuad.cpp:119
Base class to be used for unit tests.
Definition: unit_test.h:54
virtual bool run_tests()
Override to run your unit tests.
int _tests_failed
The number of unit tests which failed.
Definition: unit_test.h:206
bool _get_states_from_time()
void setBezFromVel(const Vector3_t &ctrl, const Vector3_t &vel0, const Vector3_t &vel1, const Tp duration=(Tp) 1)
Definition: BezierQuad.cpp:107
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
void getStates(Vector3_t &point, Vector3_t &vel, Vector3_t &acc, const Tp t)
Definition: BezierQuad.cpp:87
float random(float min, float max)
#define ut_assert_true(test)
To assert specifically to true.
Definition: unit_test.h:127
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
Vector3_t getPoint(const Tp t)
Return point on bezier point corresponding to time t.
Definition: BezierQuad.cpp:67
Vector3< float > Vector3f
Definition: Vector3.hpp:136
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
#define ut_run_test(test)
Runs a single unit test.
Definition: unit_test.h:96
#define ut_compare_float(message, v1, v2, precision)
Used to compare two float values within a unit test.
Definition: unit_test.h:164
void setBezier(const Vector3_t &pt0, const Vector3_t &ctrl, const Vector3_t &pt1, Tp duration=(Tp) 1)
Set new bezier points and duration.
Definition: BezierQuad.cpp:48