quaternion exponential logarithm

Submitted by Michael Norel

Assigned to Nobody

Link to original bugzilla bug (#1244)
Version: 3.3 (current stable)

Description

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;  
}  

Depends on

#1312 (closed)

Blocking

#814 (closed)

Edited by Eigen Bugzilla