PX4 Firmware
PX4 Autopilot Software http://px4.io
ControlMathTest.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 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 #include <gtest/gtest.h>
35 #include <ControlMath.hpp>
36 #include <px4_platform_common/defines.h>
37 
38 using namespace matrix;
39 using namespace ControlMath;
40 
41 
42 TEST(ControlMathTest, ThrottleAttitudeMapping)
43 {
44  /* expected: zero roll, zero pitch, zero yaw, full thr mag
45  * reason: thrust pointing full upward */
46  Vector3f thr{0.0f, 0.0f, -1.0f};
47  float yaw = 0.0f;
49  thrustToAttitude(thr, yaw, att);
50  EXPECT_EQ(att.roll_body, 0);
51  EXPECT_EQ(att.pitch_body, 0);
52  EXPECT_EQ(att.yaw_body, 0);
53  EXPECT_EQ(att.thrust_body[2], -1.f);
54 
55  /* expected: same as before but with 90 yaw
56  * reason: only yaw changed */
57  yaw = M_PI_2_F;
58  thrustToAttitude(thr, yaw, att);
59  EXPECT_EQ(att.roll_body, 0);
60  EXPECT_EQ(att.pitch_body, 0);
61  EXPECT_EQ(att.yaw_body, M_PI_2_F);
62  EXPECT_EQ(att.thrust_body[2], -1.f);
63 
64  /* expected: same as before but roll 180
65  * reason: thrust points straight down and order Euler
66  * order is: 1. roll, 2. pitch, 3. yaw */
67  thr = Vector3f(0.0f, 0.0f, 1.0f);
68  thrustToAttitude(thr, yaw, att);
69  EXPECT_NEAR(att.roll_body, -M_PI_F, 1e-4);
70  EXPECT_EQ(att.pitch_body, 0);
71  EXPECT_EQ(att.yaw_body, M_PI_2_F);
72  EXPECT_EQ(att.thrust_body[2], -1.f);
73 }
74 
75 TEST(ControlMathTest, ConstrainXYPriorities)
76 {
77  const float max = 5.0f;
78  // v0 already at max
79  Vector2f v0(max, 0);
80  Vector2f v1(v0(1), -v0(0));
81 
82  Vector2f v_r = constrainXY(v0, v1, max);
83  EXPECT_EQ(v_r(0), max);
84  EXPECT_EQ(v_r(1), 0);
85 
86  // norm of v1 exceeds max but v0 is zero
87  v0.zero();
88  v_r = constrainXY(v0, v1, max);
89  EXPECT_EQ(v_r(1), -max);
90  EXPECT_EQ(v_r(0), 0);
91 
92  v0 = Vector2f(0.5f, 0.5f);
93  v1 = Vector2f(0.5f, -0.5f);
94  v_r = constrainXY(v0, v1, max);
95  const float diff = Vector2f(v_r - (v0 + v1)).length();
96  EXPECT_EQ(diff, 0);
97 
98  // v0 and v1 exceed max and are perpendicular
99  v0 = Vector2f(4.0f, 0.0f);
100  v1 = Vector2f(0.0f, -4.0f);
101  v_r = constrainXY(v0, v1, max);
102  EXPECT_EQ(v_r(0), v0(0));
103  EXPECT_GT(v_r(0), 0);
104  const float remaining = sqrtf(max * max - (v0(0) * v0(0)));
105  EXPECT_EQ(v_r(1), -remaining);
106 }
107 
108 TEST(ControlMathTest, CrossSphereLine)
109 {
110  /* Testing 9 positions (+) around waypoints (o):
111  *
112  * Far + + +
113  *
114  * Near + + +
115  * On trajectory --+----o---------+---------o----+--
116  * prev curr
117  *
118  * Expected targets (1, 2, 3):
119  * Far + + +
120  *
121  *
122  * On trajectory -------1---------2---------3-------
123  *
124  *
125  * Near + + +
126  * On trajectory -------o---1---------2-----3-------
127  *
128  *
129  * On trajectory --+----o----1----+--------2/3---+-- */
130  const Vector3f prev = Vector3f(0.0f, 0.0f, 0.0f);
131  const Vector3f curr = Vector3f(0.0f, 0.0f, 2.0f);
132  Vector3f res;
133  bool retval = false;
134 
135  // on line, near, before previous waypoint
136  retval = cross_sphere_line(Vector3f(0.0f, 0.0f, -0.5f), 1.0f, prev, curr, res);
137  EXPECT_TRUE(retval);
138  EXPECT_EQ(res, Vector3f(0.f, 0.f, 0.5f));
139 
140  // on line, near, before target waypoint
141  retval = cross_sphere_line(Vector3f(0.0f, 0.0f, 1.0f), 1.0f, prev, curr, res);
142  EXPECT_TRUE(retval);
143  EXPECT_EQ(res, Vector3f(0.f, 0.f, 2.f));
144 
145  // on line, near, after target waypoint
146  retval = cross_sphere_line(Vector3f(0.0f, 0.0f, 2.5f), 1.0f, prev, curr, res);
147  EXPECT_TRUE(retval);
148  EXPECT_EQ(res, Vector3f(0.f, 0.f, 2.f));
149 
150  // near, before previous waypoint
151  retval = cross_sphere_line(Vector3f(0.0f, 0.5f, -0.5f), 1.0f, prev, curr, res);
152  EXPECT_TRUE(retval);
153  EXPECT_EQ(res, Vector3f(0.f, 0.f, 0.366025388f));
154 
155  // near, before target waypoint
156  retval = cross_sphere_line(Vector3f(0.0f, 0.5f, 1.0f), 1.0f, prev, curr, res);
157  EXPECT_TRUE(retval);
158  EXPECT_EQ(res, Vector3f(0.f, 0.f, 1.866025448f));
159 
160  // near, after target waypoint
161  retval = ControlMath::cross_sphere_line(matrix::Vector3f(0.0f, 0.5f, 2.5f), 1.0f, prev, curr, res);
162  EXPECT_TRUE(retval);
163  EXPECT_EQ(res, Vector3f(0.f, 0.f, 2.f));
164 
165  // far, before previous waypoint
166  retval = ControlMath::cross_sphere_line(matrix::Vector3f(0.0f, 2.0f, -0.5f), 1.0f, prev, curr, res);
167  EXPECT_FALSE(retval);
168  EXPECT_EQ(res, Vector3f());
169 
170  // far, before target waypoint
171  retval = ControlMath::cross_sphere_line(matrix::Vector3f(0.0f, 2.0f, 1.0f), 1.0f, prev, curr, res);
172  EXPECT_FALSE(retval);
173  EXPECT_EQ(res, Vector3f(0.f, 0.f, 1.f));
174 
175  // far, after target waypoint
176  retval = ControlMath::cross_sphere_line(matrix::Vector3f(0.0f, 2.0f, 2.5f), 1.0f, prev, curr, res);
177  EXPECT_FALSE(retval);
178  EXPECT_EQ(res, Vector3f(0.f, 0.f, 2.f));
179 }
bool cross_sphere_line(const Vector3f &sphere_c, const float sphere_r, const Vector3f &line_a, const Vector3f &line_b, Vector3f &res)
This method was used for smoothing the corners along two lines.
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
Vector2< float > Vector2f
Definition: Vector2.hpp:69
void zero()
Definition: Matrix.hpp:421
void thrustToAttitude(const Vector3f &thr_sp, const float yaw_sp, vehicle_attitude_setpoint_s &att_sp)
Converts thrust vector and yaw set-point to a desired attitude.
Definition: ControlMath.cpp:47
Vector3< float > Vector3f
Definition: Vector3.hpp:136
Vector2f constrainXY(const Vector2f &v0, const Vector2f &v1, const float &max)
Outputs the sum of two vectors but respecting the limits and priority.
Dual< Scalar, N > max(const Dual< Scalar, N > &a, const Dual< Scalar, N > &b)
Definition: Dual.hpp:224
TEST(ControlMathTest, ThrottleAttitudeMapping)
Simple functions for vector manipulation that do not fit into matrix lib.
#define M_PI_F
Definition: ashtech.cpp:44