test/EulerAngles.cpp File Reference
#include "main.h"
#include <unsupported/Eigen/EulerAngles>

Macros

#define VERIFY_APPROXED_RANGE(a, x, b)
 

Functions

template<typename Scalar , class System >
bool verifyIsApprox (const Eigen::EulerAngles< Scalar, System > &a, const Eigen::EulerAngles< Scalar, System > &b)
 
template<typename Scalar , class EulerSystem >
void verify_euler (const EulerAngles< Scalar, EulerSystem > &e)
 
template<signed char A, signed char B, signed char C, typename Scalar >
void verify_euler_vec (const Matrix< Scalar, 3, 1 > &ea)
 
template<signed char A, signed char B, signed char C, typename Scalar >
void verify_euler_all_neg (const Matrix< Scalar, 3, 1 > &ea)
 
template<typename Scalar >
void check_all_var (const Matrix< Scalar, 3, 1 > &ea)
 
template<typename Scalar >
void check_singular_cases (const Scalar &singularBeta)
 
template<typename Scalar >
void eulerangles_manual ()
 
template<typename Scalar >
void eulerangles_rand ()
 
 EIGEN_DECLARE_TEST (EulerAngles)
 

Variables

const char X = EULER_X
 
const char Y = EULER_Y
 
const char Z = EULER_Z
 

Macro Definition Documentation

◆ VERIFY_APPROXED_RANGE

#define VERIFY_APPROXED_RANGE (   a,
  x,
  b 
)
Value:
do { \
VERIFY_IS_APPROX_OR_LESS_THAN(a, x); \
VERIFY_IS_APPROX_OR_LESS_THAN(x, b); \
} while (0)
Scalar * b
Definition: benchVecAdd.cpp:17
const Scalar * a
Definition: level2_cplx_impl.h:32
list x
Definition: plotDoE.py:28

Function Documentation

◆ check_all_var()

template<typename Scalar >
void check_all_var ( const Matrix< Scalar, 3, 1 > &  ea)
146  {
147  verify_euler_all_neg<X, Y, Z>(ea);
148  verify_euler_all_neg<X, Y, X>(ea);
149  verify_euler_all_neg<X, Z, Y>(ea);
150  verify_euler_all_neg<X, Z, X>(ea);
151 
152  verify_euler_all_neg<Y, Z, X>(ea);
153  verify_euler_all_neg<Y, Z, Y>(ea);
154  verify_euler_all_neg<Y, X, Z>(ea);
155  verify_euler_all_neg<Y, X, Y>(ea);
156 
157  verify_euler_all_neg<Z, X, Y>(ea);
158  verify_euler_all_neg<Z, X, Z>(ea);
159  verify_euler_all_neg<Z, Y, X>(ea);
160  verify_euler_all_neg<Z, Y, Z>(ea);
161 }

Referenced by check_singular_cases(), eulerangles_manual(), and eulerangles_rand().

◆ check_singular_cases()

template<typename Scalar >
void check_singular_cases ( const Scalar singularBeta)
164  {
165  typedef Matrix<Scalar, 3, 1> Vector3;
166  const Scalar PI = Scalar(EIGEN_PI);
167 
169  check_all_var(Vector3(PI / 4, singularBeta, PI / 3));
170  check_all_var(Vector3(PI / 4, singularBeta - epsilon, PI / 3));
171  check_all_var(Vector3(PI / 4, singularBeta - Scalar(1.5) * epsilon, PI / 3));
172  check_all_var(Vector3(PI / 4, singularBeta - 2 * epsilon, PI / 3));
173  check_all_var(Vector3(PI * Scalar(0.8), singularBeta - epsilon, Scalar(0.9) * PI));
174  check_all_var(Vector3(PI * Scalar(-0.9), singularBeta + epsilon, PI * Scalar(0.3)));
175  check_all_var(Vector3(PI * Scalar(-0.6), singularBeta + Scalar(1.5) * epsilon, PI * Scalar(0.3)));
176  check_all_var(Vector3(PI * Scalar(-0.5), singularBeta + 2 * epsilon, PI * Scalar(0.4)));
177  check_all_var(Vector3(PI * Scalar(0.9), singularBeta + epsilon, Scalar(0.8) * PI));
178  }
179 
180  // This one for sanity, it had a problem with near pole cases in float scalar.
181  check_all_var(Vector3(PI * Scalar(0.8), singularBeta - Scalar(1E-6), Scalar(0.9) * PI));
182 }
#define EIGEN_PI
Definition: MathFunctions.h:16
SCALAR Scalar
Definition: bench_gemm.cpp:45
double E
Elastic modulus.
Definition: TwenteMeshGluing.cpp:68
double epsilon
Definition: osc_ring_sarah_asymptotics.h:43
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
void check_all_var(const Matrix< Scalar, 3, 1 > &ea)
Definition: test/EulerAngles.cpp:146

References check_all_var(), Global_Physical_Variables::E, EIGEN_PI, and oomph::SarahBL::epsilon.

Referenced by eulerangles_manual().

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( EulerAngles  )
263  {
264  // Simple cast test
265  EulerAnglesXYZd onesEd(1, 1, 1);
266  EulerAnglesXYZf onesEf = onesEd.cast<float>();
267  VERIFY_IS_APPROX(onesEd, onesEf.cast<double>());
268 
269  // Simple Construction from Vector3 test
270  VERIFY_IS_APPROX(onesEd, EulerAnglesXYZd(Vector3d::Ones()));
271 
272  CALL_SUBTEST_1(eulerangles_manual<float>());
273  CALL_SUBTEST_2(eulerangles_manual<double>());
274 
275  for (int i = 0; i < g_repeat; i++) {
276  CALL_SUBTEST_3(eulerangles_rand<float>());
277  CALL_SUBTEST_4(eulerangles_rand<double>());
278  }
279 
280  // TODO: Add tests for auto diff
281  // TODO: Add tests for complex numbers
282 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define VERIFY_IS_APPROX(a, b)
Definition: integer_types.cpp:13
static int g_repeat
Definition: main.h:191
#define CALL_SUBTEST_3(FUNC)
Definition: split_test_helper.h:16
#define CALL_SUBTEST_1(FUNC)
Definition: split_test_helper.h:4
#define CALL_SUBTEST_2(FUNC)
Definition: split_test_helper.h:10
#define CALL_SUBTEST_4(FUNC)
Definition: split_test_helper.h:22

References CALL_SUBTEST_1, CALL_SUBTEST_2, CALL_SUBTEST_3, CALL_SUBTEST_4, Eigen::g_repeat, i, and VERIFY_IS_APPROX.

◆ eulerangles_manual()

template<typename Scalar >
void eulerangles_manual ( )
185  {
186  typedef Matrix<Scalar, 3, 1> Vector3;
188  const Vector3 Zero = Vector3::Zero();
189  const Scalar PI = Scalar(EIGEN_PI);
190 
192 
193  // singular cases
194  check_singular_cases(PI / 2);
195  check_singular_cases(-PI / 2);
196 
199 
202 
203  // non-singular cases
204  VectorX alpha = VectorX::LinSpaced(20, Scalar(-0.99) * PI, PI);
205  VectorX beta = VectorX::LinSpaced(20, Scalar(-0.49) * PI, Scalar(0.49) * PI);
206  VectorX gamma = VectorX::LinSpaced(20, Scalar(-0.99) * PI, PI);
207  for (int i = 0; i < alpha.size(); ++i) {
208  for (int j = 0; j < beta.size(); ++j) {
209  for (int k = 0; k < gamma.size(); ++k) {
210  check_all_var(Vector3(alpha(i), beta(j), gamma(k)));
211  }
212  }
213  }
214 }
RealScalar alpha
Definition: level1_cplx_impl.h:151
Scalar beta
Definition: level2_cplx_impl.h:36
char char char int int * k
Definition: level2_impl.h:374
Mdouble gamma(Mdouble gamma_in)
This is the gamma function returns the true value for the half integer value.
Definition: ExtendedMath.cc:116
double Zero
Definition: pseudosolid_node_update_elements.cc:35
Matrix< Scalar, Dynamic, 1 > VectorX
Definition: sparse_lu.cpp:43
void check_singular_cases(const Scalar &singularBeta)
Definition: test/EulerAngles.cpp:164
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References alpha, beta, check_all_var(), check_singular_cases(), EIGEN_PI, mathsFunc::gamma(), i, j, k, and oomph::PseudoSolidHelper::Zero.

◆ eulerangles_rand()

template<typename Scalar >
void eulerangles_rand ( )
217  {
218  typedef Matrix<Scalar, 3, 3> Matrix3;
219  typedef Matrix<Scalar, 3, 1> Vector3;
220  typedef Array<Scalar, 3, 1> Array3;
221  typedef Quaternion<Scalar> Quaternionx;
222  typedef AngleAxis<Scalar> AngleAxisType;
223 
224  Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
225  Quaternionx q1;
226  q1 = AngleAxisType(a, Vector3::Random().normalized());
227  Matrix3 m;
228  m = q1;
229 
230  Vector3 ea = m.eulerAngles(0, 1, 2);
231  check_all_var(ea);
232  ea = m.eulerAngles(0, 1, 0);
233  check_all_var(ea);
234 
235  // Check with purely random Quaternion:
236  q1.coeffs() = Quaternionx::Coefficients::Random().normalized();
237  m = q1;
238  ea = m.eulerAngles(0, 1, 2);
239  check_all_var(ea);
240  ea = m.eulerAngles(0, 1, 0);
241  check_all_var(ea);
242 
243  // Check with random angles in range [0:pi]x[-pi:pi]x[-pi:pi].
244  ea = (Array3::Random() + Array3(1, 0, 0)) * Scalar(EIGEN_PI) * Array3(0.5, 1, 1);
245  check_all_var(ea);
246 
247  ea[2] = ea[0] = internal::random<Scalar>(0, Scalar(EIGEN_PI));
248  check_all_var(ea);
249 
250  ea[0] = ea[1] = internal::random<Scalar>(0, Scalar(EIGEN_PI));
251  check_all_var(ea);
252 
253  ea[1] = 0;
254  check_all_var(ea);
255 
256  ea.head(2).setZero();
257  check_all_var(ea);
258 
259  ea.setZero();
260  check_all_var(ea);
261 }
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Definition: AngleAxis.h:52
General-purpose arrays with easy API for coefficient-wise operations.
Definition: Array.h:48
The quaternion class used to represent 3D orientations and rotations.
Definition: Eigen/Eigen/src/Geometry/Quaternion.h:285
int * m
Definition: level2_cplx_impl.h:294

References a, check_all_var(), EIGEN_PI, and m.

◆ verify_euler()

template<typename Scalar , class EulerSystem >
void verify_euler ( const EulerAngles< Scalar, EulerSystem > &  e)
36  {
37  typedef EulerAngles<Scalar, EulerSystem> EulerAnglesType;
38  typedef Matrix<Scalar, 3, 3> Matrix3;
39  typedef Matrix<Scalar, 3, 1> Vector3;
40  typedef Quaternion<Scalar> QuaternionType;
41  typedef AngleAxis<Scalar> AngleAxisType;
42 
43  const Scalar ONE = Scalar(1);
44  const Scalar HALF_PI = Scalar(EIGEN_PI / 2);
45  const Scalar PI = Scalar(EIGEN_PI);
46 
47  // It's very important calc the acceptable precision depending on the distance from the pole.
48  const Scalar longitudeRadius = std::abs(EulerSystem::IsTaitBryan ? std::cos(e.beta()) : std::sin(e.beta()));
49  Scalar precision = test_precision<Scalar>() / longitudeRadius;
50 
51  Scalar betaRangeStart, betaRangeEnd;
52  if (EulerSystem::IsTaitBryan) {
53  betaRangeStart = -HALF_PI;
54  betaRangeEnd = HALF_PI;
55  } else {
56  if (!EulerSystem::IsBetaOpposite) {
57  betaRangeStart = 0;
58  betaRangeEnd = PI;
59  } else {
60  betaRangeStart = -PI;
61  betaRangeEnd = 0;
62  }
63  }
64 
65  const Vector3 I_ = EulerAnglesType::AlphaAxisVector();
66  const Vector3 J_ = EulerAnglesType::BetaAxisVector();
67  const Vector3 K_ = EulerAnglesType::GammaAxisVector();
68 
69  // Is approx checks
70  VERIFY(e.isApprox(e));
72  VERIFY_IS_NOT_APPROX(e, EulerAnglesType(e.alpha() + ONE, e.beta() + ONE, e.gamma() + ONE));
73 
74  const Matrix3 m(e);
75  VERIFY_IS_APPROX(Scalar(m.determinant()), ONE);
76 
77  EulerAnglesType ebis(m);
78 
79  // When no roll(acting like polar representation), we have the best precision.
80  // One of those cases is when the Euler angles are on the pole, and because it's singular case,
81  // the computation returns no roll.
82  if (ebis.beta() == 0) precision = test_precision<Scalar>();
83 
84  // Check that eabis in range
85  VERIFY_APPROXED_RANGE(-PI, ebis.alpha(), PI);
86  VERIFY_APPROXED_RANGE(betaRangeStart, ebis.beta(), betaRangeEnd);
87  VERIFY_APPROXED_RANGE(-PI, ebis.gamma(), PI);
88 
89  const Matrix3 mbis(AngleAxisType(ebis.alpha(), I_) * AngleAxisType(ebis.beta(), J_) *
90  AngleAxisType(ebis.gamma(), K_));
91  VERIFY_IS_APPROX(Scalar(mbis.determinant()), ONE);
92  VERIFY_IS_APPROX(mbis, ebis.toRotationMatrix());
93  /*std::cout << "===================\n" <<
94  "e: " << e << std::endl <<
95  "eabis: " << eabis.transpose() << std::endl <<
96  "m: " << m << std::endl <<
97  "mbis: " << mbis << std::endl <<
98  "X: " << (m * Vector3::UnitX()).transpose() << std::endl <<
99  "X: " << (mbis * Vector3::UnitX()).transpose() << std::endl;*/
100  VERIFY(m.isApprox(mbis, precision));
101 
102  // Test if ea and eabis are the same
103  // Need to check both singular and non-singular cases
104  // There are two singular cases.
105  // 1. When I==K and sin(ea(1)) == 0
106  // 2. When I!=K and cos(ea(1)) == 0
107 
108  // TODO: Make this test work well, and use range saturation function.
109  /*// If I==K, and ea[1]==0, then there no unique solution.
110  // The remark apply in the case where I!=K, and |ea[1]| is close to +-pi/2.
111  if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(EIGEN_PI/2),test_precision<Scalar>())) )
112  VERIFY_IS_APPROX(ea, eabis);*/
113 
114  // Quaternions
115  const QuaternionType q(e);
116  ebis = q;
117  const QuaternionType qbis(ebis);
118  VERIFY(internal::isApprox<Scalar>(std::abs(q.dot(qbis)), ONE, precision));
119  // VERIFY_IS_APPROX(eabis, eabis2);// Verify that the euler angles are still the same
120 
121  // A suggestion for simple product test when will be supported.
122  /*EulerAnglesType e2(PI/2, PI/2, PI/2);
123  Matrix3 m2(e2);
124  VERIFY_IS_APPROX(e*e2, m*m2);*/
125 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar cos(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:136
AnnoyingScalar sin(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:137
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Represents a rotation in a 3 dimensional space as three Euler angles.
Definition: unsupported/Eigen/src/EulerAngles/EulerAngles.h:103
#define VERIFY_IS_NOT_APPROX(a, b)
Definition: integer_types.cpp:15
#define VERIFY(a)
Definition: main.h:362
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:2019
#define VERIFY_APPROXED_RANGE(a, x, b)
Definition: test/EulerAngles.cpp:25

References abs(), cos(), e(), EIGEN_PI, Eigen::EulerSystem< _AlphaAxis, _BetaAxis, _GammaAxis >::IsBetaOpposite, Eigen::EulerSystem< _AlphaAxis, _BetaAxis, _GammaAxis >::IsTaitBryan, m, Eigen::numext::q, sin(), VERIFY, VERIFY_APPROXED_RANGE, VERIFY_IS_APPROX, and VERIFY_IS_NOT_APPROX.

Referenced by verify_euler_vec().

◆ verify_euler_all_neg()

template<signed char A, signed char B, signed char C, typename Scalar >
void verify_euler_all_neg ( const Matrix< Scalar, 3, 1 > &  ea)
133  {
134  verify_euler_vec<+A, +B, +C>(ea);
135  verify_euler_vec<+A, +B, -C>(ea);
136  verify_euler_vec<+A, -B, +C>(ea);
137  verify_euler_vec<+A, -B, -C>(ea);
138 
139  verify_euler_vec<-A, +B, +C>(ea);
140  verify_euler_vec<-A, +B, -C>(ea);
141  verify_euler_vec<-A, -B, +C>(ea);
142  verify_euler_vec<-A, -B, -C>(ea);
143 }
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:48
Definition: matrices.h:74
void verify_euler_vec(const Matrix< Scalar, 3, 1 > &ea)
Definition: test/EulerAngles.cpp:128

References verify_euler_vec().

◆ verify_euler_vec()

template<signed char A, signed char B, signed char C, typename Scalar >
void verify_euler_vec ( const Matrix< Scalar, 3, 1 > &  ea)
128  {
129  verify_euler(EulerAngles<Scalar, EulerSystem<A, B, C> >(ea[0], ea[1], ea[2]));
130 }
Represents a fixed Euler rotation system.
Definition: EulerSystem.h:121
void verify_euler(const EulerAngles< Scalar, EulerSystem > &e)
Definition: test/EulerAngles.cpp:36

References verify_euler().

Referenced by verify_euler_all_neg().

◆ verifyIsApprox()

template<typename Scalar , class System >
bool verifyIsApprox ( const Eigen::EulerAngles< Scalar, System > &  a,
const Eigen::EulerAngles< Scalar, System > &  b 
)
20  {
21  return verifyIsApprox(a.angles(), b.angles());
22 }
bool verifyIsApprox(const Eigen::EulerAngles< Scalar, System > &a, const Eigen::EulerAngles< Scalar, System > &b)
Definition: test/EulerAngles.cpp:20

References a, b, and Eigen::verifyIsApprox().

Variable Documentation

◆ X

const char X = EULER_X

◆ Y

◆ Z

const char Z = EULER_Z