Quaternion\Coord system

Started by
16 comments, last by Woodchuck 18 years, 2 months ago
Quote:Original post by haegarr
So (Q2,U2) is a local transformation given in the frame (Q1,U1), and you want the transformation being transformed into the parent frame of (Q1,U1)? So you mean a "simple" transformation concatenation?


That's it. I think.. =)


Quote:Original post by haegarr
I assume it is because U1 denotes the origin of a co-ordinate frame, and U2 denotes a translation vector. Similarly, Q1 denotes an orientation, and Q2 denotes a rotation. Say, (Q1,U1) is a frame and (Q2,U2) a transformation. Just a question of convention...


That's it! =)

Ok, so this is just concatenation. I damn don't now why I have this formula in head : R2*R1*1/R2 for matrix33.


Quote:Original post by jyk
Where the Rotate() function applies the quaternion rotation formula q*p*conjugate(q)


Ok so, what should i do with all of that.

Q2' := Q1.Conjugate*Q2*Q1 ?
U2' := U1 + Q1.Conjugate*Quat(U2)*Q1 ?

Sorry, i'm a little lost. What is the formula for rotation concatenation in term of quaternion ? What exactly do 'Rotate()' ?

[ --- English lesson --- ]
You say frame... mmh should i use this world instead of coordinate system ? Parent frame, frame... Sounds good ^^
[ --- English lesson --- ]
Advertisement
Quote:Original post by Woodchuck
Q2' := Q1.Conjugate*Q2*Q1 ?
U2' := U1 + Q1.Conjugate*Quat(U2)*Q1 ?

IMHO (say if I'm on the right trip) suggest
Q2' := Q1 * Q2
to concatenate both rotations (as I recall correct this order means that Q2 is more local, what exactly is needed here), and
U2' := U1 + Q1 * [U2,0] * conj(Q1)

Quote:Original post by Woodchuck
What is the formula for rotation concatenation in term of quaternion ? What exactly do 'Rotate()' ?

As far as I know the product of 2 (unit) quaternions is the concatenation of the represented rotations. However, you have to consider that the product isn't commutative, so that the order counts.

The Rotate() function mentioned by jyk is for rotating a vector [X,0] (notice the extension w/ zero) by a quaternion w/o the need to convert the quaternion to a matrix first:
Rotate(X;Q) := Q * [X,0] * conj(Q)

See e.g. the Matrix and Quaternion FAQ:
http://www.j3d.org/matrix_faq/matrfaq_latest.html

Quote:Original post by Woodchuck
[ --- English lesson --- ]
You say frame... mmh should i use this world instead of coordinate system ? Parent frame, frame... Sounds good ^^
[ --- English lesson --- ]

Well, I use the term frame since I've read the article "A Coordinate Free Geometry ADT". My natural language isn't english, so I can't guarantee its correctness. However, until now nowbody here in the forum has complained about it, although I've used the term nearly a thousand times ;)


I hope this helps (and even more it is correct; I'm not sure about the multiplication order).
Thank you haegarr, really thank you, This help me a lot. :D

EDIT: A more clean link about matrix and quaternion faq http://www.flipcode.com/documents/matrfaq.html#Q47
Quote:Original post by Woodchuck
EDIT: A more clean link about matrix and quaternion faq http://www.flipcode.com/documents/matrfaq.html#Q47

Please notice that your link refers to
FAQ Version 1.4 26th December 1998
but my link to
FAQ Version 1.21 30th November 2003
(but I don't claim that this is the newest version).
Quote:Original post by haegarr
Quote:Original post by Woodchuck
EDIT: A more clean link about matrix and quaternion faq http://www.flipcode.com/documents/matrfaq.html#Q47

Please notice that your link refers to
FAQ Version 1.4 26th December 1998
but my link to
FAQ Version 1.21 30th November 2003
(but I don't claim that this is the newest version).


Oh yes, that's right.
I'm sorry if this should be obvious by now, but which of the following holds afterall?

1) Is (Q1,U1) a transformation that maps the usual world axes vectors ({1,0,0}, {0,1,0}, {0,0,1}) to the world co-ordinate vectors (x1, y1, z1), and what you are looking for, is a transformation (Q,U) expressed in (Q2,U2) that maps the base vectors of (Q2, U2) to the world coordinate vectors (x1, y1, z1) ?

OR

2) (Q2, U2) is transformation expressed in (Q1,U1) coordinates and you want its equivalent in the world frame of reference?

Just out of curiosity, can you post the correct equations, if you try what the above posters suggested?
Somewhat offtopic but possibly useful info on quats:

I wrote the 'coordinate system' class that is mostly equivalent in usage to 4x4 matrix (can be multiplied, etc) but has quaternion and vector inside (quaternion for rotation, vector for translation). It's very convenient for doing things like that.

Explanations of how you can figure out what to do with quaternions:

The basic idea of this is very simple, mostly same as with 3x3 matrix for rotation and vector for translation.
Let's first define
Q rotate V = Q*V*~Q , in other words, rotation of vector by quaternion. In programming it can be written as Q.rotate(V)
This "rotate" is much like rotation_matrix*vector, in that it also does rotation, and all properties of rotation apply.
For instance,
1.) Q rotate (V1+V2) = (Q rotate V1) + (Q rotate V2)
2.) Q1 rotate (Q2 rotate V) = (Q1*Q2) rotate V
3.) (~Q) rotate (Q rotate V) = V
The "rotate" is really sorta multiplication & from now on i will assume it have same precedence. These formulas can all be derived from definition of "rotate"

Now, we can define Euclidean transform(?) i.e. rotation and translation, as
E=(Q, P)
where P is translation and Q is quaternion. We can make it behave just like 4x4 matrix. We can define E*V to mean rotation&translation of V by E just as if E would be an 4x4 matrix, define ~E as inverse transform, and define E1*E2 as concatenated rotations.

So we have:
V' = E*V = (Q rotate V) + P , where Q is rotation and P is translation.
The inverse transform can be easily found as
V' = (Q rotate V) + P
V' - P = Q rotate V
~Q rotate (V' - P) = V
~Q rotate V' - ~Q rotate P = V

That is, for
E=(Q,P)
inverse is
~E=(~Q, - (~Q rotate P))

Another thing we can be interested in is concatenation of transformations. Say V is transformed by E1 then by E2 .
(E2*E1)*V = P2+Q2 rotate (P1+Q1 rotate V) = P2 + Q2 rotate P1 + Q2*Q1 rotate V
So we have
E2*E1=(Q2*Q1,P2 + Q2 rotate P1)


There is the code i use (somewhat crude), may be more readable than math above:
// ignore the templates - them is there just so i can use it with // floats and doubles alike.// You can just assume T is double and "something<t>" // is "somethingd" to indicate that it's using double.template <class T>struct CoordSys{    Quaternion<T> orientation;    Vec3<T> position;    CoordSys()    {}    ;    CoordSys(Quaternion<T> o,Vec3<T>pos)    {        position=pos;        orientation=o;    };    //helpser    void Translate(const Vec3<T> &by)    {        position+=QuaternionToMatrix(orientation)*by;    };    void Rotate(const Quaternion<T> &by)    {        orientation=#ifndef dont_normalize            Normalized#endif            (orientation*by);    };    inline void Rotate(const Vec3<T> &axis,T angle)    {        orientation=#ifndef dont_normalize            Normalized#endif            (orientation*(Quaternion<T>(axis,angle)));    }};template<class T>CoordSys<T> operator*(const CoordSys<T> &c1,const CoordSys<T> &c2){    CoordSys<T> result;    result.orientation=#ifndef dont_normalize        Normalized#endif        (c1.orientation*c2.orientation)        ;    result.position=c1.orientation.Rotate(c2.position)+c1.position;};// transforms vector like 4x4 matrix wouldtemplate<class T>Vec3<T> operator*(const CoordSys<T> &c,const Vec3<T> &v){    return c.orientation.rotate(v) + c.position;};template<class T>CoordSys<T> Inverse(const CoordSys<T> &c1){    CoordSys<T> result;// for rotation quaternions, signs do not matter// (Q and -Q works the same). So i use minus conjugate, // because it negates real part only and is // faster than conjugate     result.orientation=MinusConjugate(c1.orientation);    result.position= -(result.orientation.rotate(c1.position));    return result;};template<class T>inline Matrix4x4<T> TransformFrom(const CoordSys<T> &c1){    Matrix4x4<T> result(QuaternionToMatrix(c1.orientation));    result.a[0][3]=c1.position.x;    result.a[1][3]=c1.position.y;    result.a[2][3]=c1.position.z;    return result;};template<class T>inline Matrix4x4<T> TransformTo(const CoordSys<T> &c1){    return TransformFrom(Inverse(c1));};

The TransformFrom and TransformTo is used to get matrix for use in openGL.
How it is related:
To find "how CoordSys C2 looks from other CoordSys C1" (i assume that's what you want), i'd just use C2*Inverse(C1)
(if it would be really really speed critical and compiler wouldn't optimize everything out, i would maybe write it manually. But in any other case it's allright to work with CoordSys and not it's implementation details)

It's especially good when there's something complicated you has to do. It could be also good if you have code that used 4x4 matrices, or have experience using them. Also it hides details of implementation of coordinate system in a way that really makes sense (you may for example have CoordSysM that is implemented as 4x4 matrix , but is exactly same in usage)
Quote:Original post by Dmytry
Somewhat offtopic but possibly useful info on quats:

I wrote the 'coordinate system' class that is mostly equivalent in usage to 4x4 matrix (can be multiplied, etc) but has quaternion and vector inside (quaternion for rotation, vector for translation). It's very convenient for doing things like that.

Explanations of how you can figure out what to do with quaternions:

The basic idea of this is very simple, mostly same as with 3x3 matrix for rotation and vector for translation.
Let's first define
Q rotate V = Q*V*~Q , in other words, rotation of vector by quaternion. In programming it can be written as Q.rotate(V)
This "rotate" is much like rotation_matrix*vector, in that it also does rotation, and all properties of rotation apply.
For instance,
1.) Q rotate (V1+V2) = (Q rotate V1) + (Q rotate V2)
2.) Q1 rotate (Q2 rotate V) = (Q1*Q2) rotate V
3.) (~Q) rotate (Q rotate V) = V
The "rotate" is really sorta multiplication & from now on i will assume it have same precedence. These formulas can all be derived from definition of "rotate"

Now, we can define Euclidean transform(?) i.e. rotation and translation, as
E=(Q, P)
where P is translation and Q is quaternion. We can make it behave just like 4x4 matrix. We can define E*V to mean rotation&translation of V by E just as if E would be an 4x4 matrix, define ~E as inverse transform, and define E1*E2 as concatenated rotations.

So we have:
V' = E*V = (Q rotate V) + P , where Q is rotation and P is translation.
The inverse transform can be easily found as
V' = (Q rotate V) + P
V' - P = Q rotate V
~Q rotate (V' - P) = V
~Q rotate V' - ~Q rotate P = V

That is, for
E=(Q,P)
inverse is
~E=(~Q, - (~Q rotate P))

Another thing we can be interested in is concatenation of transformations. Say V is transformed by E1 then by E2 .
(E2*E1)*V = P2+Q2 rotate (P1+Q1 rotate V) = P2 + Q2 rotate P1 + Q2*Q1 rotate V
So we have
E2*E1=(Q2*Q1,P2 + Q2 rotate P1)


There is the code i use (somewhat crude), may be more readable than math above:
*** Source Snippet Removed ***
The TransformFrom and TransformTo is used to get matrix for use in openGL.
How it is related:
To find "how CoordSys C2 looks from other CoordSys C1" (i assume that's what you want), i'd just use C2*Inverse(C1)
(if it would be really really speed critical and compiler wouldn't optimize everything out, i would maybe write it manually. But in any other case it's allright to work with CoordSys and not it's implementation details)

It's especially good when there's something complicated you has to do. It could be also good if you have code that used 4x4 matrices, or have experience using them. Also it hides details of implementation of coordinate system in a way that really makes sense (you may for example have CoordSysM that is implemented as 4x4 matrix , but is exactly same in usage)



That's exactly the class I wanted to do. :) 'seems I gained time... ;)

This topic is closed to new replies.

Advertisement