turbotrig_test.cpp
Go to the documentation of this file.
1 /*
2  *
3  * BSD 3-Clause License
4  *
5  * Copyright (c) 2017, James Jackson BYU MAGICC Lab, Provo UT
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * * Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "math.h"
35 #include "common.h"
36 #include <stdio.h>
37 
39 {
40  turbomath::Vector(-0.0376278050814, 0.471775699711, -0.336572370974),
41  turbomath::Vector(0.842139998851, -0.113277302409, -0.435361598132),
42  turbomath::Vector(0.402876930871, -0.998517068538, 0.956603957591),
43  turbomath::Vector(0.366004030077, -0.966554559399, 0.236455814495),
44  turbomath::Vector(0.170963581611, -0.892193316086, -0.360102936987),
45  turbomath::Vector(-0.675191763273, -0.794118513048, 0.561367212903),
46  turbomath::Vector(-0.0299477253533, 0.0938177650483, 0.525814272724),
47  turbomath::Vector(-0.676191678521, -0.0780862208203, -0.272955681219),
48  turbomath::Vector(-0.435749833209, -0.673810649938, -0.896559097382),
49  turbomath::Vector(0.709083915552, -0.135067363969, -0.385492450532),
50  turbomath::Vector(-0.38728558039, -0.502219301225, 0.323557018529),
51  turbomath::Vector(-0.186870345154, 0.554827454101, 0.921567682061),
52  turbomath::Vector(-0.142106787605, -0.764876359963, 0.00303689980819),
53  turbomath::Vector(-0.677798963582, -0.664595954482, 0.339274533414),
54  turbomath::Vector(-0.700464041114, 0.325731535871, -0.621492014391),
55  turbomath::Vector(-0.604865828708, 0.270639620454, 0.188624833185),
56  turbomath::Vector(0.464205180183, -0.461504601245, -0.578708441515),
57  turbomath::Vector(0.498899172115, -0.582342366402, -0.694758083436),
58  turbomath::Vector(0.0710544604541, -0.63603887083, -0.521799692437),
59  turbomath::Vector(-0.372025413205, 0.83531212357, 0.232484576742),
60  turbomath::Vector(0.790872496361, -0.89600683592, 0.783984438621),
61  turbomath::Vector(0.236462609786, -0.636362560394, 0.203951290805),
62  turbomath::Vector(0.831924307534, -0.482532468579, 0.0600026189612),
63  turbomath::Vector(0.0562194856302, -0.605799189029, -0.556494338297),
64  turbomath::Vector(-0.85014432598, 0.0632157037573, 0.0272188414114)
65 };
66 
67 
69 {
70  turbomath::Quaternion(0.10377420365, -0.583993115868, -0.731526280531, -0.0530049846003),
71  turbomath::Quaternion(-0.00228103177408, -0.506936771567, 0.976002181169, 0.90368722061),
72  turbomath::Quaternion(-0.280191704748, 0.141235897077, 0.770363502952, 0.306427689307),
73  turbomath::Quaternion(0.964538929753, -0.849755381903, 0.36374459234, 0.694507794584),
74  turbomath::Quaternion(0.0176390041681, -0.960155080148, 0.340078582124, -0.119639355159),
75  turbomath::Quaternion(-0.213139865459, -0.91618752978, -0.192746623826, -0.761937711418),
76  turbomath::Quaternion(-0.491440057128, -0.468120646081, -0.0682240789086, -0.779728041272),
77  turbomath::Quaternion(0.00414757516987, -0.980357614738, 0.243315557667, 0.487816606638),
78  turbomath::Quaternion(-0.593742280674, 0.245648066311, 0.682367014935, -0.0659175648814),
79  turbomath::Quaternion(-0.322464011587, 0.706588950729, -0.966024250287, -0.50354344519),
80  turbomath::Quaternion(-0.537023302971, -0.496355850419, -0.326843736039, 0.456606813517),
81  turbomath::Quaternion(-0.581585485434, 0.225766708322, -0.121402082687, 0.160333514827),
82  turbomath::Quaternion(-0.422711480811, 0.894994456476, 0.392582496229, 0.0035135659771),
83  turbomath::Quaternion(0.326380783544, 0.551413227108, 0.89489801397, 0.87883243747),
84  turbomath::Quaternion(0.83500683695, -0.263875030319, -0.1783391105, 0.453727091163),
85  turbomath::Quaternion(-0.30389938019, -0.0744317276089, -0.436917072268, 0.907173926266),
86  turbomath::Quaternion(-0.320066655494, -0.349065285706, 0.0336903431161, 0.573906603454),
87  turbomath::Quaternion(-0.103624452083, -0.82874783662, -0.635967208274, 0.562138574765),
88  turbomath::Quaternion(0.90735669209, -0.611711092446, 0.732474120503, 0.866697480004),
89  turbomath::Quaternion(0.626137839218, 0.41320663394, -0.821473642241, -0.344696411875),
90  turbomath::Quaternion(0.266650461152, -0.784707647527, 0.324347257562, -0.724904312141),
91  turbomath::Quaternion(0.964177603528, -0.378173605577, 0.767349174766, 0.560290218637),
92  turbomath::Quaternion(0.0812716046369, 0.745067180353, -0.476875959113, -0.245887902551),
93  turbomath::Quaternion(-0.177027678376, 0.214558558928, -0.992910369554, 0.592964390132),
94  turbomath::Quaternion(0.0979109306209, 0.121890109199, 0.126418158551, 0.242200145606)
95 };
96 
97 
98 TEST(turbotrig_test, atan_test)
99 {
100  for (float i = -200.0; i <= 200.0; i += 0.001)
101  {
102  EXPECT_NEAR(turbomath::atan(i), atan(i), 0.0001);
103  }
104 }
105 
106 TEST(turbotrig_test, sin_cos_test)
107 {
108  for (float i = -200.0; i <= 200.0; i += 0.001)
109  {
110  EXPECT_NEAR(turbomath::sin(i), sin(i), 0.0002);
111  EXPECT_NEAR(turbomath::cos(i), cos(i), 0.0002);
112  }
113 }
114 
115 
116 TEST(turbotrig_test, atan2_test)
117 {
118  for (float i = -100.0; i <= 100.0; i += 0.1)
119  {
120  for (float j = -1.0; j <= 1.0; j += 0.001)
121  {
122  if (fabs(j) > 0.0001)
123  {
124  EXPECT_NEAR(turbomath::atan2(i, j), atan2(i, j), 0.001);
125  }
126  }
127  }
128 }
129 
130 TEST(turbotrig_test, asin_test)
131 {
132  for (float i = -1.0; i <= 1.0; i += 0.001)
133  {
134  if (fabs(i) < 0.95)
135  EXPECT_NEAR(turbomath::asin(i), asin(i), 0.0001);
136  else
137  EXPECT_NEAR(turbomath::asin(i), asin(i), 0.2);
138  }
139 }
140 
141 TEST(turbotrig_test, fast_alt_test)
142 {
143 
144  //out of bounds
145  EXPECT_EQ(turbomath::alt(69681), 0.0);
146  EXPECT_EQ(turbomath::alt(10700), 0.0);
147 
148  //all valid int values
149  float trueResult = 0.0;
150  for (int i = 69682; i < 106597; i++)
151  {
152  trueResult = static_cast<float>((1.0 - pow(static_cast<float>(i)/101325,
153  0.190284)) * 145366.45) * static_cast<float>(0.3048);
154  EXPECT_NEAR(turbomath::alt(i), trueResult, .15);
155  //arbitrarily chose <= .15m since fast_alt isn't accurate enough for EXPECT_CLOSE,
156  //but being within .15 meters of the correct result seems pretty good to me
157  }
158 }
159 
160 
161 TEST(turbovec_test, vector_test)
162 {
163  for (int i = 0; i < 24; i++)
164  {
165  turbomath::Vector vec1 = random_vectors[i];
166  turbomath::Vector vec2 = random_vectors[i + 1];
167  Eigen::Vector3f eig2, eig1;
168  eig1 << vec1.x, vec1.y, vec1.z;
169  eig2 << vec2.x, vec2.y, vec2.z;
170 
171  // Test data type
172  EXPECT_VEC3_SUPERCLOSE(vec1, eig1);
173  EXPECT_VEC3_SUPERCLOSE(vec2, eig2);
174 
175  // Test norming operations
177  EXPECT_SUPERCLOSE(vec1.norm(), eig1.norm());
178  EXPECT_SUPERCLOSE(vec1.sqrd_norm(), eig1.squaredNorm());
179  turbomath::Vector vec3 = vec1;
180  Eigen::Vector3f eig3 = eig1;
181 
182  vec3.normalize();
183  eig3.normalize();
184  EXPECT_VEC3_SUPERCLOSE(vec3, eig3);
185  EXPECT_SUPERCLOSE(vec3.norm(), 1.0);
186 
187  // Test add, subtract and multiply
188  EXPECT_VEC3_SUPERCLOSE((vec1 + vec2), (eig1 + eig2));
189  EXPECT_VEC3_SUPERCLOSE((vec1 - vec2), (eig1 - eig2));
190 
191  EXPECT_VEC3_SUPERCLOSE((vec1*5.0f), (eig1*5.0f));
192  EXPECT_VEC3_SUPERCLOSE((vec1*-10.0f), (eig1*-10.0f));
193 
194  vec1 *= -3.0f;
195  EXPECT_VEC3_SUPERCLOSE(vec1, (eig1*-3.0f));
196  eig1 *= -3.0f;
197  EXPECT_VEC3_SUPERCLOSE(vec1, eig1);
198 
199  EXPECT_VEC3_SUPERCLOSE((vec1/-10.0f), (eig1/-10.0f));
200  vec1 /= -3.0f;
201  EXPECT_VEC3_SUPERCLOSE(vec1, (eig1/-3.0f));
202  eig1 /= -3.0f;
203 
204  // Test Vector Dot Product
205  EXPECT_SUPERCLOSE(vec1.dot(vec2), eig1.transpose() * eig2);
206 
207  // Test Vector Cross Product
208  EXPECT_VEC3_SUPERCLOSE(vec1.cross(vec2), eig1.cross(eig2));
209  }
210 }
211 
212 
213 TEST(turbovec_test, quaternion_test)
214 {
215 
216  for (int i = 0; i < 24; i++)
217  {
218  turbomath::Quaternion quat1 = random_quaternions[i].normalize();
219  turbomath::Quaternion quat2 = random_quaternions[i+1].normalize();
220 
221  Eigen::Quaternionf eig1(quat1.w, quat1.x, quat1.y, quat1.z);
222  Eigen::Quaternionf eig2(quat2.w, quat2.x, quat2.y, quat2.z);
223 
224  EXPECT_QUAT_SUPERCLOSE(quat1, eig1);
225  EXPECT_QUAT_SUPERCLOSE(quat2, eig2);
226 
227  // Check normalization
228  EXPECT_SUPERCLOSE(quat1.x*quat1.x + quat1.y*quat1.y + quat1.z*quat1.z + quat1.w*quat1.w, 1.0f);
229  EXPECT_SUPERCLOSE(quat2.x*quat2.x + quat2.y*quat2.y + quat2.z*quat2.z + quat2.w*quat2.w, 1.0f);
230 
231  // Test Quaternion Operators
232  ASSERT_QUAT_SUPERCLOSE((quat1*quat2), (eig2*eig1));
233  ASSERT_QUAT_SUPERCLOSE(quat1.inverse(), eig1.inverse());
234 
235 
236  // Test Quaternion Rotate
237  turbomath::Vector vec1 = random_vectors[i];
238  Eigen::Vector3f veig1;
239  veig1 << vec1.x, vec1.y, vec1.z;
240 
241 
242  // Test rotate_vector by rotating vector to new frame
243  turbomath::Vector vec2 = quat1.rotate(vec1);
244  Eigen::Vector3f veig2 = veig1.transpose()*eig1.toRotationMatrix();
245  EXPECT_VEC3_SUPERCLOSE(vec2, veig2); // compare with eigen
246 
247  // And rotate back
248  turbomath::Vector vec3 = quat1.inverse() * vec2;
249  EXPECT_VEC3_SUPERCLOSE(vec3, veig1);
250 
251  // Convert to and from euler angles
252  float p, t, s;
253  quat1.get_RPY(&p, &t, &s);
254 
255  turbomath::Quaternion quat3(p, t, s);
256  Eigen::Vector3f ihat(1, 0, 0);
257  Eigen::Vector3f jhat(0, 1, 0);
258  Eigen::Vector3f khat(0, 0, 1);
259 
260  Eigen::Quaternionf eig3 = Eigen::AngleAxisf(s, khat) * Eigen::AngleAxisf(t, jhat) * Eigen::AngleAxisf(p, ihat);
261 
262  EXPECT_QUAT_SUPERCLOSE(quat3, eig3);
263  EXPECT_SUPERCLOSE(quat1.w, quat3.w);
264  EXPECT_SUPERCLOSE(quat1.x, quat3.x);
265  EXPECT_SUPERCLOSE(quat1.y, quat3.y);
266  EXPECT_SUPERCLOSE(quat1.z, quat3.z);
267  }
268 }
269 
270 TEST(turbovec_test, quat_from_two_vectors_test)
271 {
272  // Test the "quat_from_two_vectors"
273  turbomath::Vector vec1(1.0f, 0.0f, 0.0f);
274  turbomath::Quaternion quat1(1.0f/sqrt(2.0f), 0.0f, 0.0f, 1.0f/sqrt(2.0f));
275  turbomath::Vector vec2 = quat1.rotate(vec1);
276  turbomath::Quaternion quat_test;
277  quat_test.from_two_unit_vectors(vec2, vec1);
278 
279  ASSERT_TURBOQUAT_SUPERCLOSE(quat1, quat_test);
280 
281 
282  // A bunch of random (off-axes tests)
283  for (int i = 0; i < 25; i++)
284  {
285  turbomath::Vector vec3 = random_vectors[i].normalize();
286  turbomath::Quaternion quat2 = random_quaternions[i].normalize();
287 
288  // Manually rotate this vector with the quaternion
289  turbomath::Vector vec4 = quat2.rotate(vec3);
290 
291  // Extract the "shortest-arc" rotation
292  quat_test.from_two_unit_vectors(vec4, vec3);
293 
294  // Try rotating that same vector with this new quaternion
295  turbomath::Vector vec5 = quat_test.rotate(vec3);
296 
297  // Make sure that the vectors are the same
298  ASSERT_SUPERCLOSE(vec5.x, vec4.x);
299  ASSERT_SUPERCLOSE(vec5.y, vec4.y);
300  ASSERT_SUPERCLOSE(vec5.z, vec4.z);
301  }
302 }
float dot(const Vector &v) const
Definition: turbomath.cpp:156
#define ASSERT_SUPERCLOSE(x, y)
Definition: test/common.h:54
Vector cross(const Vector &v) const
Definition: turbomath.cpp:162
float atan(float x)
Definition: turbomath.cpp:460
float cos(float x)
Definition: turbomath.cpp:422
float sqrd_norm() const
Definition: turbomath.cpp:64
float sin(float x)
Definition: turbomath.cpp:427
float atan2(float y, float x)
Definition: turbomath.cpp:488
TEST(turbotrig_test, atan_test)
XmlRpcServer s
Vector & normalize()
Definition: turbomath.cpp:70
float alt(float press)
Definition: turbomath.cpp:549
float fabs(float x)
Definition: turbomath.cpp:571
#define EXPECT_SUPERCLOSE(x, y)
Definition: test/common.h:49
void get_RPY(float *roll, float *pitch, float *yaw) const
Definition: turbomath.cpp:305
#define ASSERT_TURBOQUAT_SUPERCLOSE(q, q2)
Definition: test/common.h:35
#define ASSERT_QUAT_SUPERCLOSE(q, q_eig)
Definition: test/common.h:26
Vector normalized() const
Definition: turbomath.cpp:80
Quaternion & from_two_unit_vectors(const Vector &u, const Vector &v)
Definition: turbomath.cpp:247
float asin(float x)
Definition: turbomath.cpp:528
turbomath::Quaternion random_quaternions[25]
#define EXPECT_VEC3_SUPERCLOSE(vec, eig)
Definition: test/common.h:14
turbomath::Vector random_vectors[25]
Quaternion & normalize()
Definition: turbomath.cpp:185
Quaternion inverse() const
Definition: turbomath.cpp:234
#define EXPECT_QUAT_SUPERCLOSE(q, q_eig)
Definition: test/common.h:18
float norm() const
Definition: turbomath.cpp:58
Vector rotate(const Vector &v) const
Definition: turbomath.cpp:222


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 19:59:26