For me, it can be useful to have conversions to/from rodrigues parameters from/to quaternions. Usualy it is called " exponential/logarithm" (from lie algebra). As it can be seen in "Sophus" library built on top of Eigen. https://github.com/strasdat/Sophus/blob/master/sophus/so3.hpp My versions of this operations looks like (the SO3 class represent 3 rodrigues params in member m_coeffs ): SO3(const QuaternionT& q_) { // forcing positive "w" to work from 0 to PI const QuaternionT& q = q_.w() >= Scalar(0) ? q_ : QuaternionT(-q_.coeffs()); const Vector3& qv = q.vec(); Scalar sinha = qv.norm(); if(sinha > Scalar(0)) { Scalar angle = Scalar(2) * atan2(sinha, q.w()); //NOTE: signed m_coeffs = qv * (angle/sinha); }else{ // if l is too small, its norm can be equal 0 but norm_inf greater 0 // probably w is much bigger that vec, use it as length m_coeffs = qv * (Scalar(2)/q.w()); ////NOTE: signed } } NOTE: it is important to keep rodrigues params inside (0 ...PI) interval for precision. Also all handmade taylor expansions of SINC is not useful and have no better precision than direct computation. QuaternionT getQuaternion() const { QuaternionT q; const Vector3 ha = m_coeffs/Scalar(2); // vector of half angle Scalar l = ha.norm(); if( l > Scalar(0) ) { Scalar ss = sin(l)/l; q = QuaternionT(cos(l), ha.x()*ss, ha.y()*ss, ha.z()*ss); }else{ // if l is too small, its norm can be equal 0 but norm_inf greater 0 q = QuaternionT(Scalar(1), ha.x(), ha.y(), ha.z()); } return q; }
UPD: more compact version of "Lie 2 Quat" conversion, with same precision QuaternionT getQuaternion() const { Scalar a = m_coeffs.norm(); Scalar ha = a * Scalar(0.5); Scalar scale = a > Scalar(0) ? sin(ha) / a : Scalar(0.5); return QuaternionT(cos(ha), x() * scale, y() * scale, z() * scale); }
Those are essentially variants of the current AngleAxis <-> Quaternion conversion methods where the angle is embedded in the norm of the rotation axis. The main question is about the API. We could start with: QuaternionBase::fromAngleAxisVector(const MatrixBase<Derived>& vec); Vector3 QuaternionBase::toAngleAxisVector(); and then think about adding a ctor and operator= as aliases to fromAngleAxisVector?
I usually know it by the name "Scaled Axis", so I'd prefer fromScaledAxis(...), etc. I don't really like adding operator= and a constructor for thi conversion, since it would hide what is happening there (this is not the only possible map from R^3 to S^3).
QuaternionBase::fromAngleAxisVector(const MatrixBase<Derived>& vec); Vector3 QuaternionBase::toAngleAxisVector(); This sounds for me very confusing. It is not common "term". Common terms (for me) from computer vision is: 1. Exponential map https://en.wikipedia.org/wiki/Rotation_matrix#Exponential_map https://en.wikipedia.org/wiki/Rotation_group_SO(3)#Exponential_map 2. Rodrigues parameters https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Rodrigues_parameters_and_Gibbs_representation 3. Lie parameters 4. Logarithm/exponent or tangent. https://pixhawk.org/_media/dev/know-how/jlblanco2010geometry3d_techrep.pdf chapter "SE(3) as a Lie group" For example openCV uses Rodrigues "term", Sophus uses SE3::exp(..) and SE3::log(..) as static member functions. Also "AngleAxis" usualy mean exactly Angle + Axis, and it is hard to discover that so named functions works with lie params. This operations and representations is common for computer vision, 3d reconstruction. Please assume this set of names: fromRodrigues toRodrigues fromExpMap toExpMap fromLie toLie exp log logarithmicMap exponentialGroup logarithm exponent fromTangent toTangent i prefer: log exp or logarithm exponent
(In reply to Christoph Hertzberg from comment #3) > I don't really like adding operator= and a > constructor for thi conversion, since it would hide what is happening there > (this is not the only possible map from R^3 to S^3). I agree, it is not "common" operation for creation of quaternion, and can be mixed up with "Euler angles" etc. i prefer some similar way that uses "FromTwoVectors" member.
I agree my naming suggestion was pretty bad. Nonetheless, I still think that we should put the emphasis on the *representation* of the input/output using names matching: FromRepresentationName fromRepresentationName toRepresentationName According to: https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation, and some other resources, choice for RepresentationName could be: - RotationVector - EulerVector plus the ScaleAxis proposal of Christoph. Among those three, I would slightly prefer RotationVector: - ScaleAxis does not convey the idea of a rotation - EulerVector might be confused with a vector storing Euler angles. - RotationVector might be confused with RotationAxis, but then fromRotationAxis would make no sense, and toRotationVector does return the rotation axis (it's just that it is not normalized). See also this old thread for an extensive discussion and proposals for the proper introduction of Lie group and algebra their exp/log maps.
I forgot to paste the link: https://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2010/04/msg00109.html
That thread is also related: https://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/05/msg00028.html
Note: - RotationVector https://en.wikipedia.org/wiki/Rotation_(mathematics) - EulerVector https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation Give correct description from google, but - ScaleAxis not.
I did say "Scaled Axis" not "Scale Axis", but admittedly that was mostly the common naming at my former group (however there are several positive google hits for that name as well). But I don't have strong feelings for that name. Given the other options I'd prefer RotationVector over EulerVector. I don't think the confusion risk with RotationAxis is too big in contrast to the danger of confusing EulerVector with EulerAngles. The bad thing is that for small angles they agree (with Euler angles in XYZ convention), get slightly different for medium angles and are completely off, when the Euler angles are near their singularities.
(In reply to Christoph Hertzberg from comment #10) I agree, EulerVector will be mixed up with Euler angles. And RotationVector sound better among 3 versions.
I am using these implementations of quaternion exp and log mapping: https://github.com/hengli/vmav-ros-pkg/blob/master/calibration/hand_eye_calibration/include/hand_eye_calibration/QuaternionMapping.h These also work for non-unit quaternions. If bug 560 is solved in 3.3, one could just add them to the API of the GeneralQuaternion interface and, if needed, add the more specialized exp/log implementations for unit quaternions that were discussed above to the UnitQuaternion interface.
(In reply to Adrian Haarbach from comment #12) Seems it little bit different functionality with additional performance loose. Don't you think it is better to use as overloaded "exp/log" functions for exact "math" interpretation of "exp/log"? P.S. did you tried the "boost::quaternion" implementation of their quaternion operations?
-- GitLab Migration Automatic Message -- This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/1244.