// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.com> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include"main.h"
#include <unsupported/Eigen/EulerAngles>
usingnamespace Eigen;
// Unfortunately, we need to specialize it in order to work. (We could add it in main.h test framework) template <typename Scalar, class System> bool verifyIsApprox(const Eigen::EulerAngles<Scalar, System>& a, const Eigen::EulerAngles<Scalar, System>& b)
{ return verifyIsApprox(a.angles(), b.angles());
}
// Verify that x is in the approxed range [a, b] #define VERIFY_APPROXED_RANGE(a, x, b) \ do { \
VERIFY_IS_APPROX_OR_LESS_THAN(a, x); \
VERIFY_IS_APPROX_OR_LESS_THAN(x, b); \
} while(0)
constchar X = EULER_X; constchar Y = EULER_Y; constchar Z = EULER_Z;
const Scalar ONE = Scalar(1); const Scalar HALF_PI = Scalar(EIGEN_PI / 2); const Scalar PI = Scalar(EIGEN_PI);
// It's very important calc the acceptable precision depending on the distance from the pole. const Scalar longitudeRadius = std::abs(
EulerSystem::IsTaitBryan ?
std::cos(e.beta()) :
std::sin(e.beta())
);
Scalar precision = test_precision<Scalar>() / longitudeRadius;
// When no roll(acting like polar representation), we have the best precision. // One of those cases is when the Euler angles are on the pole, and because it's singular case, // the computation returns no roll. if (ebis.beta() == 0)
precision = test_precision<Scalar>();
// Check that eabis in range
VERIFY_APPROXED_RANGE(-PI, ebis.alpha(), PI);
VERIFY_APPROXED_RANGE(betaRangeStart, ebis.beta(), betaRangeEnd);
VERIFY_APPROXED_RANGE(-PI, ebis.gamma(), PI);
// Test if ea and eabis are the same // Need to check both singular and non-singular cases // There are two singular cases. // 1. When I==K and sin(ea(1)) == 0 // 2. When I!=K and cos(ea(1)) == 0
// TODO: Make this test work well, and use range saturation function. /*// If I==K, and ea[1]==0, then there no unique solution. // The remark apply in the case where I!=K, and |ea[1]| is close to +-pi/2. if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(EIGEN_PI/2),test_precision<Scalar>())) )
VERIFY_IS_APPROX(ea, eabis);*/
// Quaternions const QuaternionType q(e);
ebis = q; const QuaternionType qbis(ebis);
VERIFY(internal::isApprox<Scalar>(std::abs(q.dot(qbis)), ONE, precision)); //VERIFY_IS_APPROX(eabis, eabis2);// Verify that the euler angles are still the same
// A suggestion for simple product test when will be supported. /*EulerAnglesType e2(PI/2, PI/2, PI/2); Matrix3 m2(e2);
VERIFY_IS_APPROX(e*e2, m*m2);*/
}
// This one for sanity, it had a problem with near pole cases in float scalar.
check_all_var(Vector3(PI*Scalar(0.8), singularBeta - Scalar(1E-6), Scalar(0.9)*PI));
}
Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
Quaternionx q1;
q1 = AngleAxisType(a, Vector3::Random().normalized());
Matrix3 m;
m = q1;
Vector3 ea = m.eulerAngles(0,1,2);
check_all_var(ea);
ea = m.eulerAngles(0,1,0);
check_all_var(ea);
// Check with purely random Quaternion:
q1.coeffs() = Quaternionx::Coefficients::Random().normalized();
m = q1;
ea = m.eulerAngles(0,1,2);
check_all_var(ea);
ea = m.eulerAngles(0,1,0);
check_all_var(ea);
// Check with random angles in range [0:pi]x[-pi:pi]x[-pi:pi].
ea = (Array3::Random() + Array3(1,0,0))*Scalar(EIGEN_PI)*Array3(0.5,1,1);
check_all_var(ea);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.