From 8e198d68352933b0e436ad9dee8799dc13892b73 Mon Sep 17 00:00:00 2001 From: Tal Hadad Date: Sun, 19 Jun 2016 20:42:45 +0300 Subject: Complete docs and add ostream operator for EulerAngles. --- doc/Doxyfile.in | 5 +- unsupported/Eigen/EulerAngles | 7 +-- unsupported/Eigen/src/EulerAngles/EulerAngles.h | 79 +++++++++++++++++++------ unsupported/Eigen/src/EulerAngles/EulerSystem.h | 37 ++++++------ unsupported/doc/examples/EulerAngles.cpp | 46 ++++++++++++++ 5 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 unsupported/doc/examples/EulerAngles.cpp diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 0c3673f89..a90d3852a 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1608,7 +1608,10 @@ EXPAND_AS_DEFINED = EIGEN_MAKE_TYPEDEFS \ EIGEN_MATHFUNC_IMPL \ _EIGEN_GENERIC_PUBLIC_INTERFACE \ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY \ - EIGEN_EMPTY + EIGEN_EMPTY \ + EIGEN_EULER_ANGLES_TYPEDEFS \ + EIGEN_EULER_ANGLES_SINGLE_TYPEDEF \ + EIGEN_EULER_SYSTEM_TYPEDEF # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros diff --git a/unsupported/Eigen/EulerAngles b/unsupported/Eigen/EulerAngles index a595b5f2c..521fa3f76 100644 --- a/unsupported/Eigen/EulerAngles +++ b/unsupported/Eigen/EulerAngles @@ -24,14 +24,13 @@ namespace Eigen { * * Euler angles are a way to represent 3D rotation. * - * !TODO! More about the purpose of this module and examples. - * - * See EulerAngles for more information. - * + * In order to use this module in your code, include this header: * \code * #include * \endcode * + * See \ref EulerAngles for more information. + * */ } diff --git a/unsupported/Eigen/src/EulerAngles/EulerAngles.h b/unsupported/Eigen/src/EulerAngles/EulerAngles.h index 911ba4d09..13a0da1ab 100644 --- a/unsupported/Eigen/src/EulerAngles/EulerAngles.h +++ b/unsupported/Eigen/src/EulerAngles/EulerAngles.h @@ -18,6 +18,8 @@ namespace Eigen struct ei_eulerangles_assign_impl;*/ /** \class EulerAngles + * + * \ingroup EulerAngles_Module * * \brief Represents a rotation in a 3 dimensional space as three Euler angles. * @@ -29,7 +31,7 @@ namespace Eigen * - then, rotate the axes system over the gamma axis(which was rotated in the two stages above) in angle gamma * * \note This class support only intrinsic Euler angles for simplicity, - * see EulerSystem how to easily overcome it for extrinsic systems. + * see EulerSystem how to easily overcome this for extrinsic systems. * * ### Rotation representation and conversions ### * @@ -52,17 +54,48 @@ namespace Eigen * and this class take care for the math. * Additionally, some axes related computation is done in compile time. * + * #### Euler angles ranges in conversions #### + * + * When converting some rotation to Euler angles, there are some ways you can guarantee + * the Euler angles ranges. + * + * #### implicit ranges #### + * When using implicit ranges, all angles are guarantee to be in the range [-PI, +PI], + * unless you convert from some other Euler angles. + * In this case, the range is __undefined__ (might be even less than -PI or greater than +2*PI). + * \sa EulerAngles(const MatrixBase&) + * \sa EulerAngles(const RotationBase&) + * + * #### explicit ranges #### + * When using explicit ranges, all angles are guarantee to be in the range you choose. + * In the range Boolean parameter, you're been ask whether you prefer the positive range or not: + * - _true_ - force the range between [0, +2*PI] + * - _false_ - force the range between [-PI, +PI] + * + * ##### compile time ranges ##### + * This is when you have compile time ranges and you prefer to + * use template parameter. (e.g. for performance) + * \sa FromRotation() + * + * ##### run-time time ranges ##### + * Run-time ranges are also supported. + * \sa EulerAngles(const MatrixBase&, bool, bool, bool) + * \sa EulerAngles(const RotationBase&, bool, bool, bool) + * * ### Convenient user typedefs ### * * Convenient typedefs for EulerAngles exist for float and double scalar, * in a form of EulerAngles{A}{B}{C}{scalar}, - * e.g. EulerAnglesXYZd, EulerAnglesZYZf. + * e.g. \ref EulerAnglesXYZd, \ref EulerAnglesZYZf. * - * !TODO! Add examples - * - * Only for positive axes{+x,+y,+z} euler systems are have convenient typedef. + * Only for positive axes{+x,+y,+z} Euler systems are have convenient typedef. * If you need negative axes{-x,-y,-z}, it is recommended to create you own typedef with - * a word that represent what you need, e.g. EulerAnglesUTM (!TODO! make it more clear with example code). + * a word that represent what you need. + * + * ### Example ### + * + * \include EulerAngles.cpp + * Output: \verbinclude EulerAngles.out * * ### Additional reading ### * @@ -80,12 +113,14 @@ namespace Eigen public: /** the scalar type of the angles */ typedef _Scalar Scalar; + + /** the EulerSystem to use, which represents the axes of rotation. */ typedef _System System; - typedef Matrix Matrix3; - typedef Matrix Vector3; - typedef Quaternion QuaternionType; - typedef AngleAxis AngleAxisType; + typedef Matrix Matrix3; /*!< the equivalent rotation matrix type */ + typedef Matrix Vector3; /*!< the equivalent 3 dimension vector type */ + typedef Quaternion QuaternionType; /*!< the equivalent quaternion type */ + typedef AngleAxis AngleAxisType; /*!< the equivalent angle-axis type */ /** \returns the axis vector of the first (alpha) rotation */ static Vector3 AlphaAxisVector() { @@ -125,7 +160,7 @@ namespace Eigen /** Constructs and initialize Euler angles from a 3x3 rotation matrix \p m, * with options to choose for each angle the requested range. * - * If possitive range is true, then the specified angle will be in the range [0, +2*PI]. + * If positive range is true, then the specified angle will be in the range [0, +2*PI]. * Otherwise, the specified angle will be in the range [-PI, +PI]. * * \param m The 3x3 rotation matrix to convert @@ -146,7 +181,7 @@ namespace Eigen /** Constructs and initialize Euler angles from a rotation \p rot. * * \note All angles will be in the range [-PI, PI], unless \p rot is an EulerAngles. - * If rot is an EulerAngles, expected EulerAngles range is undefined. + * If rot is an EulerAngles, expected EulerAngles range is __undefined__. * (Use other functions here for enforcing range if this effect is desired) */ template @@ -155,7 +190,7 @@ namespace Eigen /** Constructs and initialize Euler angles from a rotation \p rot, * with options to choose for each angle the requested range. * - * If possitive range is true, then the specified angle will be in the range [0, +2*PI]. + * If positive range is true, then the specified angle will be in the range [0, +2*PI]. * Otherwise, the specified angle will be in the range [-PI, +PI]. * * \param rot The 3x3 rotation matrix to convert @@ -214,7 +249,7 @@ namespace Eigen /** Constructs and initialize Euler angles from a 3x3 rotation matrix \p m, * with options to choose for each angle the requested range (__only in compile time__). * - * If possitive range is true, then the specified angle will be in the range [0, +2*PI]. + * If positive range is true, then the specified angle will be in the range [0, +2*PI]. * Otherwise, the specified angle will be in the range [-PI, +PI]. * * \param m The 3x3 rotation matrix to convert @@ -232,14 +267,15 @@ namespace Eigen EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived, 3, 3) EulerAngles e; - System::CalcEulerAngles(e, m); + System::template CalcEulerAngles< + PositiveRangeAlpha, PositiveRangeBeta, PositiveRangeGamma, _Scalar>(e, m); return e; } /** Constructs and initialize Euler angles from a rotation \p rot, * with options to choose for each angle the requested range (__only in compile time__). * - * If possitive range is true, then the specified angle will be in the range [0, +2*PI]. + * If positive range is true, then the specified angle will be in the range [0, +2*PI]. * Otherwise, the specified angle will be in the range [-PI, +PI]. * * \param rot The 3x3 rotation matrix to convert @@ -252,7 +288,7 @@ namespace Eigen bool PositiveRangeBeta, bool PositiveRangeGamma, typename Derived> - static EulerAngles& FromRotation(const RotationBase& rot) + static EulerAngles FromRotation(const RotationBase& rot) { return FromRotation(rot.toRotationMatrix()); } @@ -305,10 +341,17 @@ namespace Eigen AngleAxisType(beta(), BetaAxisVector()) * AngleAxisType(gamma(), GammaAxisVector()); } + + friend std::ostream& operator<<(std::ostream& s, const EulerAngles& eulerAngles) + { + s << eulerAngles.angles().transpose(); + return s; + } }; #define EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(AXES, SCALAR_TYPE, SCALAR_POSTFIX) \ - typedef EulerAngles EulerSystem##AXES##SCALAR_POSTFIX; + /** \ingroup EulerAngles_Module */ \ + typedef EulerAngles EulerAngles##AXES##SCALAR_POSTFIX; #define EIGEN_EULER_ANGLES_TYPEDEFS(SCALAR_TYPE, SCALAR_POSTFIX) \ EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(XYZ, SCALAR_TYPE, SCALAR_POSTFIX) \ diff --git a/unsupported/Eigen/src/EulerAngles/EulerSystem.h b/unsupported/Eigen/src/EulerAngles/EulerSystem.h index dbca3e174..82243e643 100644 --- a/unsupported/Eigen/src/EulerAngles/EulerSystem.h +++ b/unsupported/Eigen/src/EulerAngles/EulerSystem.h @@ -40,17 +40,17 @@ namespace Eigen #define EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1] - /** \brief Representation of a fixed signed rotation axis for EulerAngles. + /** \brief Representation of a fixed signed rotation axis for EulerSystem. + * + * \ingroup EulerAngles_Module * * Values here represent: * - The axis of the rotation: X, Y or Z. - * - The sign (i.e. direction of the rotation along the axis): possitive(+) or negative(-) + * - The sign (i.e. direction of the rotation along the axis): positive(+) or negative(-) * * Therefore, this could express all the axes {+X,+Y,+Z,-X,-Y,-Z} * * For positive axis, use +EULER_{axis}, and for negative axis use -EULER_{axis}. - * - * !TODO! Add examples */ enum EulerAxis { @@ -60,6 +60,8 @@ namespace Eigen }; /** \class EulerSystem + * + * \ingroup EulerAngles_Module * * \brief Represents a fixed Euler rotation system. * @@ -69,8 +71,8 @@ namespace Eigen * - Build an Euler system, and then pass it as a template parameter to EulerAngles. * - Query some compile time data about an Euler system. (e.g. Whether it's tait bryan) * - * Euler rotation is a set of three rotation on fixed axes. (see EulerAngles) - * This meta-class store constantly those signed axes. (see EulerAxis) + * Euler rotation is a set of three rotation on fixed axes. (see \ref EulerAngles) + * This meta-class store constantly those signed axes. (see \ref EulerAxis) * * ### Types of Euler systems ### * @@ -78,35 +80,31 @@ namespace Eigen * signed axes{+X,+Y,+Z,-X,-Y,-Z} are supported: * - all axes X, Y, Z in each valid order (see below what order is valid) * - rotation over the axis is supported both over the positive and negative directions. - * - both tait bryan and classic Euler angles (i.e. the opposite). + * - both tait bryan and proper/classic Euler angles (i.e. the opposite). * * Since EulerSystem support both positive and negative directions, * you may call this rotation distinction in other names: - * - right handed or left handed - * - counterclockwise or clockwise + * - _right handed_ or _left handed_ + * - _counterclockwise_ or _clockwise_ * * Notice all axed combination are valid, and would trigger a static assertion. * Same unsigned axes can't be neighbors, e.g. {X,X,Y} is invalid. * This yield two and only two classes: - * - tait bryan - all unsigned axes are distinct, e.g. {X,Y,Z} - * - proper/classic Euler angles - The first and the third unsigned axes is equal, + * - _tait bryan_ - all unsigned axes are distinct, e.g. {X,Y,Z} + * - _proper/classic Euler angles_ - The first and the third unsigned axes is equal, * and the second is different, e.g. {X,Y,X} * - * !TODO! Add some example code. - * * ### Intrinsic vs extrinsic Euler systems ### * * Only intrinsic Euler systems are supported for simplicity. * If you want to use extrinsic Euler systems, * just use the equal intrinsic opposite order for axes and angles. - * I.E axes (A,B,C) becomes (C,B,A), and angles (a,b,c) becomes (c,b,a). - * !TODO! Make it more clear and add some example code. + * I.e axes (A,B,C) becomes (C,B,A), and angles (a,b,c) becomes (c,b,a). * * ### Convenient user typedefs ### * * Convenient typedefs for EulerSystem exist (only for positive axes Euler systems), - * in a form of EulerSystem{A}{B}{C}, e.g. EulerSystemXYZd. - * !TODO! Make it more clear + * in a form of EulerSystem{A}{B}{C}, e.g. \ref EulerSystemXYZ. * * ### Additional reading ### * @@ -248,10 +246,10 @@ namespace Eigen } template< - typename Scalar, bool PositiveRangeAlpha, bool PositiveRangeBeta, - bool PositiveRangeGamma> + bool PositiveRangeGamma, + typename Scalar> static void CalcEulerAngles( EulerAngles& res, const typename EulerAngles::Matrix3& mat) @@ -296,6 +294,7 @@ namespace Eigen }; #define EIGEN_EULER_SYSTEM_TYPEDEF(A, B, C) \ + /** \ingroup EulerAngles_Module */ \ typedef EulerSystem EulerSystem##A##B##C; EIGEN_EULER_SYSTEM_TYPEDEF(X,Y,Z) diff --git a/unsupported/doc/examples/EulerAngles.cpp b/unsupported/doc/examples/EulerAngles.cpp new file mode 100644 index 000000000..1ef6aee18 --- /dev/null +++ b/unsupported/doc/examples/EulerAngles.cpp @@ -0,0 +1,46 @@ +#include +#include + +using namespace Eigen; + +int main() +{ + // A common Euler system by many armies around the world, + // where the first one is the azimuth(the angle from the north - + // the same angle that is show in compass) + // and the second one is elevation(the angle from the horizon) + // and the third one is roll(the angle between the horizontal body + // direction and the plane ground surface) + // Keep remembering we're using radian angles here! + typedef EulerSystem<-EULER_Z, EULER_Y, EULER_X> MyArmySystem; + typedef EulerAngles MyArmyAngles; + + MyArmyAngles vehicleAngles( + 3.14/*PI*/ / 2, /* heading to east, notice that this angle is counter-clockwise */ + -0.3, /* going down from a mountain */ + 0.1); /* slightly rolled to the right */ + + // Some Euler angles representation that our plane use. + EulerAnglesZYZd planeAngles(0.78474, 0.5271, -0.513794); + + MyArmyAngles planeAnglesInMyArmyAngles = MyArmyAngles::FromRotation(planeAngles); + + std::cout << "vehicle angles(MyArmy): " << vehicleAngles << std::endl; + std::cout << "plane angles(ZYZ): " << planeAngles << std::endl; + std::cout << "plane angles(MyArmy): " << planeAnglesInMyArmyAngles << std::endl; + + // Now lets rotate the plane a little bit + std::cout << "==========================================================\n"; + std::cout << "rotating plane now!\n"; + std::cout << "==========================================================\n"; + + Quaterniond planeRotated = AngleAxisd(-0.342, Vector3d::UnitY()) * planeAngles; + + planeAngles = planeRotated; + planeAnglesInMyArmyAngles = MyArmyAngles::FromRotation(planeRotated); + + std::cout << "new plane angles(ZYZ): " << planeAngles << std::endl; + std::cout << "new plane angles(MyArmy): " << planeAnglesInMyArmyAngles << std::endl; + + return 0; +} -- cgit v1.2.3