[ODE] quat to eulerXYZ

Patrick Enoch Hendrix_ at gmx.net
Sun Jun 26 03:20:51 MST 2005


these conversions work (for your physics engine maybe):

void eulerYXZfromquat( DCoordinate *euler, quat _quat )
{
     quat quat = _quat;
     double maginv = 1.0/SQRT( SQR(quat.r)+SQR(quat.x)+SQR(quat.y)+SQR 
(quat.z) );
     quat.r *= maginv;
     quat.x *= maginv;
     quat.y *= maginv;
     quat.z *= maginv;

     double asinarg = 2*(quat.y*quat.z + quat.r*quat.x);
     if (asinarg<-1)
         asinarg=-1;
     if (asinarg>1)
         asinarg=1;

     euler->x =  asin( asinarg )  *EULER_SCALE_INV;

     euler->y =  atan2(-2*(quat.x*quat.z - quat.r*quat.y),
                 quat.r*quat.r - quat.x*quat.x - quat.y*quat.y +  
quat.z*quat.z )  *EULER_SCALE_INV;

     euler->z =  atan2(-2*(quat.x*quat.y - quat.r*quat.z),
                 quat.r*quat.r - quat.x*quat.x + quat.y*quat.y -  
quat.z*quat.z )  *EULER_SCALE_INV;
};

void eulerZXYfromquat( DCoordinate *euler, quat _quat )
{
     quat quat = _quat;
     double maginv = 1.0/SQRT( SQR(quat.r)+SQR(quat.x)+SQR(quat.y)+SQR 
(quat.z) );
     quat.r *= maginv;
     quat.x *= maginv;
     quat.y *= maginv;
     quat.z *= maginv;

     double asinarg = -2*(quat.y*quat.z - quat.r*quat.x);
     if (asinarg<-1)
         asinarg=-1;
     if (asinarg>1)
         asinarg=1;

     euler->x =  asin( asinarg ) *EULER_SCALE_INV;

     euler->y =  atan2( 2*(quat.x*quat.z + quat.r*quat.y),
                         quat.r*quat.r - quat.x*quat.x -  
quat.y*quat.y + quat.z*quat.z ) *EULER_SCALE_INV;

     euler->z =  atan2( 2*(quat.x*quat.y + quat.r*quat.z),
                     quat.r*quat.r - quat.x*quat.x + quat.y*quat.y -  
quat.z*quat.z ) *EULER_SCALE_INV;

};

void eulerXYZfromquat( DCoordinate *euler, quat _quat )
{
     quat quat = _quat;
     double maginv = 1.0/SQRT( SQR(quat.r)+SQR(quat.x)+SQR(quat.y)+SQR 
(quat.z) );
     quat.r *= maginv;
     quat.x *= maginv;
     quat.y *= maginv;
     quat.z *= maginv;

     euler->x = atan2( 2*(quat.y*quat.z + quat.r*quat.x),
                     quat.r*quat.r - quat.x*quat.x - quat.y*quat.y +  
quat.z*quat.z );// *EULER_SCALE_INV;

     double asinarg = -2*(quat.x*quat.z - quat.r*quat.y);
     if (asinarg<-1)
         asinarg=-1;
     if (asinarg>1)
         asinarg=1;

     euler->y = asin( asinarg );// *EULER_SCALE_INV;

     euler->z = atan2( 2*(quat.x*quat.y + quat.r*quat.z),
                     quat.r*quat.r + quat.x*quat.x - quat.y*quat.y -  
quat.z*quat.z );// *EULER_SCALE_INV;
};

void quatfromeulerZXY( quat *quat, DCoordinate euler )
{
    const double cx(cos(0.5*euler.x*EULER_SCALE));
    const double cy(cos(0.5*euler.y*EULER_SCALE));
    const double cz(cos(0.5*euler.z*EULER_SCALE));
    const double sx(sin(0.5*euler.x*EULER_SCALE));
    const double sy(sin(0.5*euler.y*EULER_SCALE));
    const double sz(sin(0.5*euler.z*EULER_SCALE));
    quat->r =  cx*cy*cz + sx*sy*sz;
    quat->x =  sx*cy*cz + cx*sy*sz;
    quat->y =  cx*sy*cz - sx*cy*sz;
    quat->z =  cx*cy*sz - sx*sy*cz;

     double maginv = 1.0/SQRT( SQR(quat->r)+SQR(quat->x)+SQR(quat->y) 
+SQR(quat->z) );
     quat->r *= maginv;
     quat->x *= maginv;
     quat->y *= maginv;
     quat->z *= maginv;
};

Patrick


On 26. Jun 2005, at 2:36 Uhr, cr88192 wrote:

>
> ----- Original Message ----- From: "Patrick Enoch" <Hendrix_ at gmx.net>
> To: <ode at q12.org>
> Sent: Sunday, June 26, 2005 1:04 AM
> Subject: [ODE] quat to eulerXYZ
>
>
>
>> Hello all,
>>
>>
>> I am having problems with angular velocities. currently i am   
>> interfacing ODE to another program which uses eulerZXY.
>> so if i have a body with eulerZXY angular velocity, I need to  
>> convert  it to ODEs eulerXYZ.
>> i am using quaternions as the interface, which looks like this:
>>
>> prog eulerZXY at time A and B -> quats at time A and B -> ODE   
>> eulerXYZ at time A and B
>> (angular velocity is difference between eulers divided by (B-A))
>>
>> BUT:
>> when converting quats -> eulerZXY there are jumps in the  
>> conversion.  for example:
>>
>> euler ZXY (0,89,0) -> eulerXYZ (89,0,0)  (works fine)
>> euler ZXY (0,91,0) -> eulerXYZ (180,-91,180) (pretty far away  
>> from  the above)
>> (values as far as i remember. but i think the prob is clear. the  
>> difference should be small, but the resulting
>> angular velocity is very big. conversion depends on into which   
>> quadrant the rotation points, its an
>> unsteady function. )
>>
>> anyone knows a quat -> euler converter, which i can tell to give  
>> me values "near" to another triple?
>>
>>
> your case looks ugly...
>
> but, yeah, I feel doubtful ode is using euler angles for angular  
> velocity, much more likely it is a "spin vector" (or whatever they  
> are called, I don't really know).
>
> conversion may be problematic, but I doubt it is "impossible".
>
> one thing that could be possible (just off the top of my head):
> converting to quats (I guess you were allready doing this);
> transforming a point (either directly, or via a matrix);
> "undoing" the rotation.
>
> also possible would be, if using a matrix, to just grab the point  
> as one of the matrix's unit axis, then the same approach as below.
>
> "undoing" would consist of measuring the angle for each axis (eg:  
> via atan2 or such), and then counter rotating the axis for the angle.
> in the case of ZXY, the undo would probably be done in YXZ order.
>
> actually, a single point may not be sufficient, more likely it  
> would involve trying to counter-rotate the whole matrix, at each  
> step trying to re-align the matrix. ideally, at the final step the  
> matrix would have been rotated back to identity. it may be  
> necessary to try to determine what axis to try to align, eg,  
> because one or the other might lie near/at the origin wrt a 2D plane.
>
>
> herin lies another problem with eular angles, given the nature of  
> the angles themselves, there will tend to be abrupt jumps, a  
> converter for angular velocity could maybe try to determine the  
> direction for each axis, and flip it depending on sign or such.
>
> if(w[i]<0)a[i]=360-a[i]; //maybe?
>
> another problem is magnitude, what if the velocity is fairly fast,  
> this could generate an arbitrary spin?
>
> a thought that comes up is first normalizing the magnitude, so the  
> resultant angles basically tell where it was spinning, but not how  
> much. this magnitude could then be multiplied into the resultant  
> angles.
>
>
> as noted by someone else, maybe it would also be possible to just  
> set up a transformation matrix and directly transform the velocity  
> to angles?
> I don't know really, my mind has a little difficulty processing the  
> relationship between the representations (in some cases, the  
> generated point is likely to be the same, in some, no...).
>
> problably, yeah, stupid euler angles and their stupid ordering, and  
> their stupid singularities...
>
>
> all this could work, it is just a thought though.
>
> ok, I am now sort of doing my own physics api (doubtful it will be  
> able to really compare with ode, I guess probably more for personal  
> experience or something...).
> at one point I had tried converting the internal quats to eular  
> angles for the front end interface, but dropped this as it felt  
> like a bad idea (and apparently the transform doesn't work really,  
> but it was much more naive than the one above).
>
> later decree: all angles will be quats and all velocities/torques  
> will be spin vectors. if a frontend wants euler angles that is  
> another problem...
> also, jerkoff: removing, partly re-adding, and now once again  
> basing things on solid-types (also just showing the quick  
> succession of rewrites). for their annoyance, solidtypes are just  
> too useful it seems (better than trying to magically come up with  
> collision/contact info for unknown types...).
>
> I am going for a very opaque api, it is difficult to know how much  
> to expose (eg: whether or not it is safe to expose the internal  
> math functions, for example). a lot of the math is being done with  
> macros and inlines, and is currently not exposed to the "external"  
> headers.
>
> me half-thinking: the api should hide the implementation wherever  
> possible.
>
> if I wanted to switch over to using ode as the backend, for  
> example, the api/frontend shouldn't notice much. as an example: the  
> backend code is currently based primarily on doubles, the frontend  
> api provides both float and double based calls.
>
> some details are necissarily exposed though, eg, at present things  
> like the intergrator steps and whatever can be get/set as "world  
> attributes".
> quite probably, it is not possible to sufficiently generalize the  
> said api.
>
> in my case, then, it is all just a more personal fiddly project.
>
> but whatever on this...
>
>



More information about the ODE mailing list