How to rotate a vector about an Arbitrary Axis in 3D to align two vectors?
Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
What I'm trying to do...
Say I have two vectors. I want to align these vectors so that they one of my vectors is pointing directly at the other. For example, imagine there is this point and I want to position my camera so that my camera's center is directly aligned with said point.
From my understanding to do this, I would calculate the cross product between the two vectors and use that as an arbitrary axis of rotation.
From there I would need an angle $theta,$ which can be determined by taking the dot product between the two vectors and dividing by the product of their magnitudes. Then I would solve for $theta$ using $cos^-1$
$$theta=cos^-1$$
I'm stuck on how to determine the appropriate rotation matrix which to rotate about.
Also, I'm not sure if my process is correct I was looking online to figure this out.
linear-algebra matrices vectors linear-transformations rotations
add a comment |Â
up vote
0
down vote
favorite
What I'm trying to do...
Say I have two vectors. I want to align these vectors so that they one of my vectors is pointing directly at the other. For example, imagine there is this point and I want to position my camera so that my camera's center is directly aligned with said point.
From my understanding to do this, I would calculate the cross product between the two vectors and use that as an arbitrary axis of rotation.
From there I would need an angle $theta,$ which can be determined by taking the dot product between the two vectors and dividing by the product of their magnitudes. Then I would solve for $theta$ using $cos^-1$
$$theta=cos^-1$$
I'm stuck on how to determine the appropriate rotation matrix which to rotate about.
Also, I'm not sure if my process is correct I was looking online to figure this out.
linear-algebra matrices vectors linear-transformations rotations
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
What I'm trying to do...
Say I have two vectors. I want to align these vectors so that they one of my vectors is pointing directly at the other. For example, imagine there is this point and I want to position my camera so that my camera's center is directly aligned with said point.
From my understanding to do this, I would calculate the cross product between the two vectors and use that as an arbitrary axis of rotation.
From there I would need an angle $theta,$ which can be determined by taking the dot product between the two vectors and dividing by the product of their magnitudes. Then I would solve for $theta$ using $cos^-1$
$$theta=cos^-1$$
I'm stuck on how to determine the appropriate rotation matrix which to rotate about.
Also, I'm not sure if my process is correct I was looking online to figure this out.
linear-algebra matrices vectors linear-transformations rotations
What I'm trying to do...
Say I have two vectors. I want to align these vectors so that they one of my vectors is pointing directly at the other. For example, imagine there is this point and I want to position my camera so that my camera's center is directly aligned with said point.
From my understanding to do this, I would calculate the cross product between the two vectors and use that as an arbitrary axis of rotation.
From there I would need an angle $theta,$ which can be determined by taking the dot product between the two vectors and dividing by the product of their magnitudes. Then I would solve for $theta$ using $cos^-1$
$$theta=cos^-1$$
I'm stuck on how to determine the appropriate rotation matrix which to rotate about.
Also, I'm not sure if my process is correct I was looking online to figure this out.
linear-algebra matrices vectors linear-transformations rotations
edited Jul 26 at 20:07
saulspatz
10.4k21323
10.4k21323
asked Jul 26 at 20:04
Markus T.
31
31
add a comment |Â
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
0
down vote
accepted
I'm guessing you're intending to program this. So an implementation of @EmilioNovati's reference is illustrated below in C. You give it a rotation axis and a $theta$, and then one function gives you the corresponding quaternion, and then another gives you the $3mboxx3$ rotation matrix corresponding to that quaternion. And a third just conveniently multiplies a vector times a matrix to do the rotation for you. Here's the code, followed by a sample animation using it for rotation calculations...
/* ---
* Point and line datatype structs
* ---------------------------------- */
#define POINT struct point_struct /* "typedef" for point_struct*/
#define LINE struct line_struct /* "typedef" for line_struct*/
#define QUAT struct quaternion_struct /* "typedef" for quaternion_struct */
POINT double x, y, z; ; /* 3d pts */
LINE POINT pt1, pt2; ; /* for vectors, pt1=tail, pt2=head */
QUAT double q0, q1, q2, q3; ; /* quat = q0 + q1*i + q2*j + q3*k */
/***************************************************************************
** +===================================================================+ **
** | Low-level quaternion functions, etc | **
** +===================================================================+ **
***************************************************************************/
/* ==========================================================================
* Function: qrotate ( LINE axis, double theta )
* Purpose: returns quaternion corresponding to rotation
* through theta (**in radians**) around axis
* --------------------------------------------------------------------------
* Arguments: axis (I) LINE axis around which rotation by theta
* is to occur
* theta (I) double theta rotation **in radians**
* --------------------------------------------------------------------------
* Returns: ( QUAT ) quaternion corresponding to rotation
* through theta around axis
* --------------------------------------------------------------------------
* Notes: o Rotation direction determined by right-hand screw rule
* (when subsequent qmultiply() is called with istranspose=0)
* ======================================================================= */
/* --- entry point --- */
QUAT qrotate ( LINE axis, double theta )
/* --- allocations and declarations --- */
QUAT q = cos(0.5*theta), 0.,0.,0. ; /* constructed quaternion */
double x = axis.pt2.x - axis.pt1.x, /* length of x-component of axis */
y = axis.pt2.y - axis.pt1.y, /* length of y-component of axis */
z = axis.pt2.z - axis.pt1.z; /* length of z-component of axis */
double r = sqrt((x*x)+(y*y)+(z*z)); /* length of axis */
double qsin = sin(0.5*theta); /* for q1,q2,q3 components */
/* --- construct quaternion and return it to caller */
if ( r >= 0.0000001 ) /* error check */
q.q1 = qsin*x/r; /* i-component */
q.q2 = qsin*y/r; /* j-component */
q.q3 = qsin*z/r; /* k-component */
return ( q );
/* --- end-of-function qrotate() --- */
/* ==========================================================================
* Function: qmatrix ( QUAT q )
* Purpose: returns 3x3 rotation matrix corresponding to quaternion q
* ( can just be called as qmatrix(qrotate(axis,theta))
* for rotation matrix around axis through theta )
* --------------------------------------------------------------------------
* Arguments: q (I) QUAT q for which a rotation matrix
* is to be constructed
* --------------------------------------------------------------------------
* Returns: ( double * ) 3x3 rotation matrix, stored row-wise
* --------------------------------------------------------------------------
* Notes: o The matrix constructed from input q = q0+q1*i+q2*j+q3*k is:
* (q0 +q1 -q2 -q3 ) 2(q1q2-q0q3) 2(q1q3+q0q2)
* Q = 2(q2q1+q0q3) (q0 -q1 +q2 -q3 ) 2(q2q3-q0q1)
* 2(q3q1-q0q2) 2(q3q2+q0q1) (q0 -q1 -q2 +q3 )
* o The returned matrix is stored row-wise, i.e., explicitly
* --------- first row ----------
* qmatrix[0] = (q0 +q1 -q2 -q3 )
* [1] = 2(q1q2-q0q3)
* [2] = 2(q1q3+q0q2)
* --------- second row ---------
* [3] = 2(q2q1+q0q3)
* [4] = (q0 -q1 +q2 -q3 )
* [5] = 2(q2q3-q0q1)
* --------- third row ----------
* [6] = 2(q3q1-q0q2)
* [7] = 2(q3q2+q0q1)
* [8] = (q0 -q1 -q2 +q3 )
* o qmatrix maintains a static buffer of 128 3x3 matrices
* returned to the caller one at a time. So you may issue
* 128 qmatrix() calls and continue using all returned matrices.
* The 129th call re-uses the memory used by the 1st call, etc.
* ======================================================================= */
/* --- entry point --- */
double *qmatrix ( QUAT q )
/* --- allocations and declarations --- */
static double Qbuff[128][9]; /* up to 128 calls before wrap-around*/
static int ibuff = (-1); /* Qbuff[ibuff] index 0<=ibuff<=63 */
double *Q = NULL; /* returned ptr Q=Qbuff[ibuff] */
double q0=q.q0, q1=q.q1, q2=q.q2, q3=q.q3; /* input quaternion components */
double q02=q0*q0, q12=q1*q1, q22=q2*q2, q32=q3*q3; /* components squared */
/* --- first maintain Qbuff[ibuff] buffer --- */
if ( ++ibuff > 127 ) ibuff=0; /* wrap Qbuff[ibuff] index */
Q = Qbuff[ibuff]; /* ptr to current 3x3 buffer */
/* --- just do the algebra described in the above comments --- */
Q[0] = (q02+q12-q22-q32);
Q[1] = 2.*(q1*q2-q0*q3);
Q[2] = 2.*(q1*q3+q0*q2);
Q[3] = 2.*(q2*q1+q0*q3);
Q[4] = (q02-q12+q22-q32);
Q[5] = 2.*(q2*q3-q0*q1);
Q[6] = 2.*(q3*q1-q0*q2);
Q[7] = 2.*(q3*q2+q0*q1);
Q[8] = (q02-q12-q22+q32);
/* --- return constructed quaternion to caller */
return ( Q );
/* --- end-of-function qmatrix() --- */
/* ==========================================================================
* Function: qmultiply ( double *Q, POINT u, int istranspose )
* Purpose: returns Q*u (u a column vector) if istranspose=0,
* or u*Q (u a row vector) if istranspose=1.
* --------------------------------------------------------------------------
* Arguments: Q (I) double *Q to rotation matrix returned
* by qmatrix (or by some similar construction)
* u (I) POINT u to column vector (or to row vector
* if istranspose=1) to be multiplied by Q
* (or to multiply Q if istranspose=1)
* istranspose (I) int istranspose=0 to return Q*u (u a col vec),
* or istranspose=1 to return u*q (u a row vec)
* --------------------------------------------------------------------------
* Returns: ( POINT ) Q*u (istranspose=0), or u*Q (istranspose=1)
* --------------------------------------------------------------------------
* Notes: o Q assumed to be a 3x3 matrix stored row-wise
* ======================================================================= */
/* --- entry point --- */
POINT qmultiply ( double *Q, POINT u, int istranspose )
/* --- allocations and declarations --- */
POINT Qu = 0.,0.,0. ; /* Q*u (or u*Q if istranspose=1) */
double x=u.x, y=u.y, z=u.z; /* x(i),y(j),z(k)-components of u */
/* --- Q*u --- */
if ( !istranspose )
Qu.x = Q[0]*x + Q[1]*y + Q[2]*z; /* first row of Q * column vector u */
Qu.y = Q[3]*x + Q[4]*y + Q[5]*z; /* second row of Q * column vector u */
Qu.z = Q[6]*x + Q[7]*y + Q[8]*z; /* third row of Q * column vector u */
/* --- end-of-if(!istranspose) --- */
/* --- u*Q --- */
if ( istranspose )
Qu.x = x*Q[0] + y*Q[3] + z*Q[6]; /* row vector u * first column of Q */
Qu.y = x*Q[1] + y*Q[4] + z*Q[7]; /* row vector u * second column of Q */
Qu.z = x*Q[2] + y*Q[5] + z*Q[8]; /* row vector u * third column of Q */
/* --- end-of-if(istranspose) --- */
/* --- return product to caller --- */
return ( Qu );
/* --- end-of-function qmultiply() --- */
And here's a sample animation that uses the above functions to perform the frame-by-frame rotations...
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
add a comment |Â
up vote
0
down vote
Yes, the rotation axis is oriented by the vector orthogonal to the two vectors, but we have to use a normalized vector $$vec u=fracvec a times vec bvec b$$, and the angle $theta$ of rotation is obtained from the inner product of the two vectors as you have done.
The matrix that represents the rotation around the axis $vec u$ of angle $theta$ is given here.
add a comment |Â
up vote
0
down vote
If you look at
https://wikimedia.org/api/rest_v1/media/math/render/svg/f259f80a746ee20d481f9b7f600031084358a27c
formula from wikipedia(I don't have enough rep to include the image)
we obtain the general formula for a rotation matrix about an axis defined by the vector $(u_x,u_y,u_z)$. As you said, we obtain the angle between two vectors $v$ and $w$ with $fracvcdot wv$ and plug that in for theta. Then we take $vtimes w$ to be the vector $u$.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
I'm guessing you're intending to program this. So an implementation of @EmilioNovati's reference is illustrated below in C. You give it a rotation axis and a $theta$, and then one function gives you the corresponding quaternion, and then another gives you the $3mboxx3$ rotation matrix corresponding to that quaternion. And a third just conveniently multiplies a vector times a matrix to do the rotation for you. Here's the code, followed by a sample animation using it for rotation calculations...
/* ---
* Point and line datatype structs
* ---------------------------------- */
#define POINT struct point_struct /* "typedef" for point_struct*/
#define LINE struct line_struct /* "typedef" for line_struct*/
#define QUAT struct quaternion_struct /* "typedef" for quaternion_struct */
POINT double x, y, z; ; /* 3d pts */
LINE POINT pt1, pt2; ; /* for vectors, pt1=tail, pt2=head */
QUAT double q0, q1, q2, q3; ; /* quat = q0 + q1*i + q2*j + q3*k */
/***************************************************************************
** +===================================================================+ **
** | Low-level quaternion functions, etc | **
** +===================================================================+ **
***************************************************************************/
/* ==========================================================================
* Function: qrotate ( LINE axis, double theta )
* Purpose: returns quaternion corresponding to rotation
* through theta (**in radians**) around axis
* --------------------------------------------------------------------------
* Arguments: axis (I) LINE axis around which rotation by theta
* is to occur
* theta (I) double theta rotation **in radians**
* --------------------------------------------------------------------------
* Returns: ( QUAT ) quaternion corresponding to rotation
* through theta around axis
* --------------------------------------------------------------------------
* Notes: o Rotation direction determined by right-hand screw rule
* (when subsequent qmultiply() is called with istranspose=0)
* ======================================================================= */
/* --- entry point --- */
QUAT qrotate ( LINE axis, double theta )
/* --- allocations and declarations --- */
QUAT q = cos(0.5*theta), 0.,0.,0. ; /* constructed quaternion */
double x = axis.pt2.x - axis.pt1.x, /* length of x-component of axis */
y = axis.pt2.y - axis.pt1.y, /* length of y-component of axis */
z = axis.pt2.z - axis.pt1.z; /* length of z-component of axis */
double r = sqrt((x*x)+(y*y)+(z*z)); /* length of axis */
double qsin = sin(0.5*theta); /* for q1,q2,q3 components */
/* --- construct quaternion and return it to caller */
if ( r >= 0.0000001 ) /* error check */
q.q1 = qsin*x/r; /* i-component */
q.q2 = qsin*y/r; /* j-component */
q.q3 = qsin*z/r; /* k-component */
return ( q );
/* --- end-of-function qrotate() --- */
/* ==========================================================================
* Function: qmatrix ( QUAT q )
* Purpose: returns 3x3 rotation matrix corresponding to quaternion q
* ( can just be called as qmatrix(qrotate(axis,theta))
* for rotation matrix around axis through theta )
* --------------------------------------------------------------------------
* Arguments: q (I) QUAT q for which a rotation matrix
* is to be constructed
* --------------------------------------------------------------------------
* Returns: ( double * ) 3x3 rotation matrix, stored row-wise
* --------------------------------------------------------------------------
* Notes: o The matrix constructed from input q = q0+q1*i+q2*j+q3*k is:
* (q0 +q1 -q2 -q3 ) 2(q1q2-q0q3) 2(q1q3+q0q2)
* Q = 2(q2q1+q0q3) (q0 -q1 +q2 -q3 ) 2(q2q3-q0q1)
* 2(q3q1-q0q2) 2(q3q2+q0q1) (q0 -q1 -q2 +q3 )
* o The returned matrix is stored row-wise, i.e., explicitly
* --------- first row ----------
* qmatrix[0] = (q0 +q1 -q2 -q3 )
* [1] = 2(q1q2-q0q3)
* [2] = 2(q1q3+q0q2)
* --------- second row ---------
* [3] = 2(q2q1+q0q3)
* [4] = (q0 -q1 +q2 -q3 )
* [5] = 2(q2q3-q0q1)
* --------- third row ----------
* [6] = 2(q3q1-q0q2)
* [7] = 2(q3q2+q0q1)
* [8] = (q0 -q1 -q2 +q3 )
* o qmatrix maintains a static buffer of 128 3x3 matrices
* returned to the caller one at a time. So you may issue
* 128 qmatrix() calls and continue using all returned matrices.
* The 129th call re-uses the memory used by the 1st call, etc.
* ======================================================================= */
/* --- entry point --- */
double *qmatrix ( QUAT q )
/* --- allocations and declarations --- */
static double Qbuff[128][9]; /* up to 128 calls before wrap-around*/
static int ibuff = (-1); /* Qbuff[ibuff] index 0<=ibuff<=63 */
double *Q = NULL; /* returned ptr Q=Qbuff[ibuff] */
double q0=q.q0, q1=q.q1, q2=q.q2, q3=q.q3; /* input quaternion components */
double q02=q0*q0, q12=q1*q1, q22=q2*q2, q32=q3*q3; /* components squared */
/* --- first maintain Qbuff[ibuff] buffer --- */
if ( ++ibuff > 127 ) ibuff=0; /* wrap Qbuff[ibuff] index */
Q = Qbuff[ibuff]; /* ptr to current 3x3 buffer */
/* --- just do the algebra described in the above comments --- */
Q[0] = (q02+q12-q22-q32);
Q[1] = 2.*(q1*q2-q0*q3);
Q[2] = 2.*(q1*q3+q0*q2);
Q[3] = 2.*(q2*q1+q0*q3);
Q[4] = (q02-q12+q22-q32);
Q[5] = 2.*(q2*q3-q0*q1);
Q[6] = 2.*(q3*q1-q0*q2);
Q[7] = 2.*(q3*q2+q0*q1);
Q[8] = (q02-q12-q22+q32);
/* --- return constructed quaternion to caller */
return ( Q );
/* --- end-of-function qmatrix() --- */
/* ==========================================================================
* Function: qmultiply ( double *Q, POINT u, int istranspose )
* Purpose: returns Q*u (u a column vector) if istranspose=0,
* or u*Q (u a row vector) if istranspose=1.
* --------------------------------------------------------------------------
* Arguments: Q (I) double *Q to rotation matrix returned
* by qmatrix (or by some similar construction)
* u (I) POINT u to column vector (or to row vector
* if istranspose=1) to be multiplied by Q
* (or to multiply Q if istranspose=1)
* istranspose (I) int istranspose=0 to return Q*u (u a col vec),
* or istranspose=1 to return u*q (u a row vec)
* --------------------------------------------------------------------------
* Returns: ( POINT ) Q*u (istranspose=0), or u*Q (istranspose=1)
* --------------------------------------------------------------------------
* Notes: o Q assumed to be a 3x3 matrix stored row-wise
* ======================================================================= */
/* --- entry point --- */
POINT qmultiply ( double *Q, POINT u, int istranspose )
/* --- allocations and declarations --- */
POINT Qu = 0.,0.,0. ; /* Q*u (or u*Q if istranspose=1) */
double x=u.x, y=u.y, z=u.z; /* x(i),y(j),z(k)-components of u */
/* --- Q*u --- */
if ( !istranspose )
Qu.x = Q[0]*x + Q[1]*y + Q[2]*z; /* first row of Q * column vector u */
Qu.y = Q[3]*x + Q[4]*y + Q[5]*z; /* second row of Q * column vector u */
Qu.z = Q[6]*x + Q[7]*y + Q[8]*z; /* third row of Q * column vector u */
/* --- end-of-if(!istranspose) --- */
/* --- u*Q --- */
if ( istranspose )
Qu.x = x*Q[0] + y*Q[3] + z*Q[6]; /* row vector u * first column of Q */
Qu.y = x*Q[1] + y*Q[4] + z*Q[7]; /* row vector u * second column of Q */
Qu.z = x*Q[2] + y*Q[5] + z*Q[8]; /* row vector u * third column of Q */
/* --- end-of-if(istranspose) --- */
/* --- return product to caller --- */
return ( Qu );
/* --- end-of-function qmultiply() --- */
And here's a sample animation that uses the above functions to perform the frame-by-frame rotations...
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
add a comment |Â
up vote
0
down vote
accepted
I'm guessing you're intending to program this. So an implementation of @EmilioNovati's reference is illustrated below in C. You give it a rotation axis and a $theta$, and then one function gives you the corresponding quaternion, and then another gives you the $3mboxx3$ rotation matrix corresponding to that quaternion. And a third just conveniently multiplies a vector times a matrix to do the rotation for you. Here's the code, followed by a sample animation using it for rotation calculations...
/* ---
* Point and line datatype structs
* ---------------------------------- */
#define POINT struct point_struct /* "typedef" for point_struct*/
#define LINE struct line_struct /* "typedef" for line_struct*/
#define QUAT struct quaternion_struct /* "typedef" for quaternion_struct */
POINT double x, y, z; ; /* 3d pts */
LINE POINT pt1, pt2; ; /* for vectors, pt1=tail, pt2=head */
QUAT double q0, q1, q2, q3; ; /* quat = q0 + q1*i + q2*j + q3*k */
/***************************************************************************
** +===================================================================+ **
** | Low-level quaternion functions, etc | **
** +===================================================================+ **
***************************************************************************/
/* ==========================================================================
* Function: qrotate ( LINE axis, double theta )
* Purpose: returns quaternion corresponding to rotation
* through theta (**in radians**) around axis
* --------------------------------------------------------------------------
* Arguments: axis (I) LINE axis around which rotation by theta
* is to occur
* theta (I) double theta rotation **in radians**
* --------------------------------------------------------------------------
* Returns: ( QUAT ) quaternion corresponding to rotation
* through theta around axis
* --------------------------------------------------------------------------
* Notes: o Rotation direction determined by right-hand screw rule
* (when subsequent qmultiply() is called with istranspose=0)
* ======================================================================= */
/* --- entry point --- */
QUAT qrotate ( LINE axis, double theta )
/* --- allocations and declarations --- */
QUAT q = cos(0.5*theta), 0.,0.,0. ; /* constructed quaternion */
double x = axis.pt2.x - axis.pt1.x, /* length of x-component of axis */
y = axis.pt2.y - axis.pt1.y, /* length of y-component of axis */
z = axis.pt2.z - axis.pt1.z; /* length of z-component of axis */
double r = sqrt((x*x)+(y*y)+(z*z)); /* length of axis */
double qsin = sin(0.5*theta); /* for q1,q2,q3 components */
/* --- construct quaternion and return it to caller */
if ( r >= 0.0000001 ) /* error check */
q.q1 = qsin*x/r; /* i-component */
q.q2 = qsin*y/r; /* j-component */
q.q3 = qsin*z/r; /* k-component */
return ( q );
/* --- end-of-function qrotate() --- */
/* ==========================================================================
* Function: qmatrix ( QUAT q )
* Purpose: returns 3x3 rotation matrix corresponding to quaternion q
* ( can just be called as qmatrix(qrotate(axis,theta))
* for rotation matrix around axis through theta )
* --------------------------------------------------------------------------
* Arguments: q (I) QUAT q for which a rotation matrix
* is to be constructed
* --------------------------------------------------------------------------
* Returns: ( double * ) 3x3 rotation matrix, stored row-wise
* --------------------------------------------------------------------------
* Notes: o The matrix constructed from input q = q0+q1*i+q2*j+q3*k is:
* (q0 +q1 -q2 -q3 ) 2(q1q2-q0q3) 2(q1q3+q0q2)
* Q = 2(q2q1+q0q3) (q0 -q1 +q2 -q3 ) 2(q2q3-q0q1)
* 2(q3q1-q0q2) 2(q3q2+q0q1) (q0 -q1 -q2 +q3 )
* o The returned matrix is stored row-wise, i.e., explicitly
* --------- first row ----------
* qmatrix[0] = (q0 +q1 -q2 -q3 )
* [1] = 2(q1q2-q0q3)
* [2] = 2(q1q3+q0q2)
* --------- second row ---------
* [3] = 2(q2q1+q0q3)
* [4] = (q0 -q1 +q2 -q3 )
* [5] = 2(q2q3-q0q1)
* --------- third row ----------
* [6] = 2(q3q1-q0q2)
* [7] = 2(q3q2+q0q1)
* [8] = (q0 -q1 -q2 +q3 )
* o qmatrix maintains a static buffer of 128 3x3 matrices
* returned to the caller one at a time. So you may issue
* 128 qmatrix() calls and continue using all returned matrices.
* The 129th call re-uses the memory used by the 1st call, etc.
* ======================================================================= */
/* --- entry point --- */
double *qmatrix ( QUAT q )
/* --- allocations and declarations --- */
static double Qbuff[128][9]; /* up to 128 calls before wrap-around*/
static int ibuff = (-1); /* Qbuff[ibuff] index 0<=ibuff<=63 */
double *Q = NULL; /* returned ptr Q=Qbuff[ibuff] */
double q0=q.q0, q1=q.q1, q2=q.q2, q3=q.q3; /* input quaternion components */
double q02=q0*q0, q12=q1*q1, q22=q2*q2, q32=q3*q3; /* components squared */
/* --- first maintain Qbuff[ibuff] buffer --- */
if ( ++ibuff > 127 ) ibuff=0; /* wrap Qbuff[ibuff] index */
Q = Qbuff[ibuff]; /* ptr to current 3x3 buffer */
/* --- just do the algebra described in the above comments --- */
Q[0] = (q02+q12-q22-q32);
Q[1] = 2.*(q1*q2-q0*q3);
Q[2] = 2.*(q1*q3+q0*q2);
Q[3] = 2.*(q2*q1+q0*q3);
Q[4] = (q02-q12+q22-q32);
Q[5] = 2.*(q2*q3-q0*q1);
Q[6] = 2.*(q3*q1-q0*q2);
Q[7] = 2.*(q3*q2+q0*q1);
Q[8] = (q02-q12-q22+q32);
/* --- return constructed quaternion to caller */
return ( Q );
/* --- end-of-function qmatrix() --- */
/* ==========================================================================
* Function: qmultiply ( double *Q, POINT u, int istranspose )
* Purpose: returns Q*u (u a column vector) if istranspose=0,
* or u*Q (u a row vector) if istranspose=1.
* --------------------------------------------------------------------------
* Arguments: Q (I) double *Q to rotation matrix returned
* by qmatrix (or by some similar construction)
* u (I) POINT u to column vector (or to row vector
* if istranspose=1) to be multiplied by Q
* (or to multiply Q if istranspose=1)
* istranspose (I) int istranspose=0 to return Q*u (u a col vec),
* or istranspose=1 to return u*q (u a row vec)
* --------------------------------------------------------------------------
* Returns: ( POINT ) Q*u (istranspose=0), or u*Q (istranspose=1)
* --------------------------------------------------------------------------
* Notes: o Q assumed to be a 3x3 matrix stored row-wise
* ======================================================================= */
/* --- entry point --- */
POINT qmultiply ( double *Q, POINT u, int istranspose )
/* --- allocations and declarations --- */
POINT Qu = 0.,0.,0. ; /* Q*u (or u*Q if istranspose=1) */
double x=u.x, y=u.y, z=u.z; /* x(i),y(j),z(k)-components of u */
/* --- Q*u --- */
if ( !istranspose )
Qu.x = Q[0]*x + Q[1]*y + Q[2]*z; /* first row of Q * column vector u */
Qu.y = Q[3]*x + Q[4]*y + Q[5]*z; /* second row of Q * column vector u */
Qu.z = Q[6]*x + Q[7]*y + Q[8]*z; /* third row of Q * column vector u */
/* --- end-of-if(!istranspose) --- */
/* --- u*Q --- */
if ( istranspose )
Qu.x = x*Q[0] + y*Q[3] + z*Q[6]; /* row vector u * first column of Q */
Qu.y = x*Q[1] + y*Q[4] + z*Q[7]; /* row vector u * second column of Q */
Qu.z = x*Q[2] + y*Q[5] + z*Q[8]; /* row vector u * third column of Q */
/* --- end-of-if(istranspose) --- */
/* --- return product to caller --- */
return ( Qu );
/* --- end-of-function qmultiply() --- */
And here's a sample animation that uses the above functions to perform the frame-by-frame rotations...
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
add a comment |Â
up vote
0
down vote
accepted
up vote
0
down vote
accepted
I'm guessing you're intending to program this. So an implementation of @EmilioNovati's reference is illustrated below in C. You give it a rotation axis and a $theta$, and then one function gives you the corresponding quaternion, and then another gives you the $3mboxx3$ rotation matrix corresponding to that quaternion. And a third just conveniently multiplies a vector times a matrix to do the rotation for you. Here's the code, followed by a sample animation using it for rotation calculations...
/* ---
* Point and line datatype structs
* ---------------------------------- */
#define POINT struct point_struct /* "typedef" for point_struct*/
#define LINE struct line_struct /* "typedef" for line_struct*/
#define QUAT struct quaternion_struct /* "typedef" for quaternion_struct */
POINT double x, y, z; ; /* 3d pts */
LINE POINT pt1, pt2; ; /* for vectors, pt1=tail, pt2=head */
QUAT double q0, q1, q2, q3; ; /* quat = q0 + q1*i + q2*j + q3*k */
/***************************************************************************
** +===================================================================+ **
** | Low-level quaternion functions, etc | **
** +===================================================================+ **
***************************************************************************/
/* ==========================================================================
* Function: qrotate ( LINE axis, double theta )
* Purpose: returns quaternion corresponding to rotation
* through theta (**in radians**) around axis
* --------------------------------------------------------------------------
* Arguments: axis (I) LINE axis around which rotation by theta
* is to occur
* theta (I) double theta rotation **in radians**
* --------------------------------------------------------------------------
* Returns: ( QUAT ) quaternion corresponding to rotation
* through theta around axis
* --------------------------------------------------------------------------
* Notes: o Rotation direction determined by right-hand screw rule
* (when subsequent qmultiply() is called with istranspose=0)
* ======================================================================= */
/* --- entry point --- */
QUAT qrotate ( LINE axis, double theta )
/* --- allocations and declarations --- */
QUAT q = cos(0.5*theta), 0.,0.,0. ; /* constructed quaternion */
double x = axis.pt2.x - axis.pt1.x, /* length of x-component of axis */
y = axis.pt2.y - axis.pt1.y, /* length of y-component of axis */
z = axis.pt2.z - axis.pt1.z; /* length of z-component of axis */
double r = sqrt((x*x)+(y*y)+(z*z)); /* length of axis */
double qsin = sin(0.5*theta); /* for q1,q2,q3 components */
/* --- construct quaternion and return it to caller */
if ( r >= 0.0000001 ) /* error check */
q.q1 = qsin*x/r; /* i-component */
q.q2 = qsin*y/r; /* j-component */
q.q3 = qsin*z/r; /* k-component */
return ( q );
/* --- end-of-function qrotate() --- */
/* ==========================================================================
* Function: qmatrix ( QUAT q )
* Purpose: returns 3x3 rotation matrix corresponding to quaternion q
* ( can just be called as qmatrix(qrotate(axis,theta))
* for rotation matrix around axis through theta )
* --------------------------------------------------------------------------
* Arguments: q (I) QUAT q for which a rotation matrix
* is to be constructed
* --------------------------------------------------------------------------
* Returns: ( double * ) 3x3 rotation matrix, stored row-wise
* --------------------------------------------------------------------------
* Notes: o The matrix constructed from input q = q0+q1*i+q2*j+q3*k is:
* (q0 +q1 -q2 -q3 ) 2(q1q2-q0q3) 2(q1q3+q0q2)
* Q = 2(q2q1+q0q3) (q0 -q1 +q2 -q3 ) 2(q2q3-q0q1)
* 2(q3q1-q0q2) 2(q3q2+q0q1) (q0 -q1 -q2 +q3 )
* o The returned matrix is stored row-wise, i.e., explicitly
* --------- first row ----------
* qmatrix[0] = (q0 +q1 -q2 -q3 )
* [1] = 2(q1q2-q0q3)
* [2] = 2(q1q3+q0q2)
* --------- second row ---------
* [3] = 2(q2q1+q0q3)
* [4] = (q0 -q1 +q2 -q3 )
* [5] = 2(q2q3-q0q1)
* --------- third row ----------
* [6] = 2(q3q1-q0q2)
* [7] = 2(q3q2+q0q1)
* [8] = (q0 -q1 -q2 +q3 )
* o qmatrix maintains a static buffer of 128 3x3 matrices
* returned to the caller one at a time. So you may issue
* 128 qmatrix() calls and continue using all returned matrices.
* The 129th call re-uses the memory used by the 1st call, etc.
* ======================================================================= */
/* --- entry point --- */
double *qmatrix ( QUAT q )
/* --- allocations and declarations --- */
static double Qbuff[128][9]; /* up to 128 calls before wrap-around*/
static int ibuff = (-1); /* Qbuff[ibuff] index 0<=ibuff<=63 */
double *Q = NULL; /* returned ptr Q=Qbuff[ibuff] */
double q0=q.q0, q1=q.q1, q2=q.q2, q3=q.q3; /* input quaternion components */
double q02=q0*q0, q12=q1*q1, q22=q2*q2, q32=q3*q3; /* components squared */
/* --- first maintain Qbuff[ibuff] buffer --- */
if ( ++ibuff > 127 ) ibuff=0; /* wrap Qbuff[ibuff] index */
Q = Qbuff[ibuff]; /* ptr to current 3x3 buffer */
/* --- just do the algebra described in the above comments --- */
Q[0] = (q02+q12-q22-q32);
Q[1] = 2.*(q1*q2-q0*q3);
Q[2] = 2.*(q1*q3+q0*q2);
Q[3] = 2.*(q2*q1+q0*q3);
Q[4] = (q02-q12+q22-q32);
Q[5] = 2.*(q2*q3-q0*q1);
Q[6] = 2.*(q3*q1-q0*q2);
Q[7] = 2.*(q3*q2+q0*q1);
Q[8] = (q02-q12-q22+q32);
/* --- return constructed quaternion to caller */
return ( Q );
/* --- end-of-function qmatrix() --- */
/* ==========================================================================
* Function: qmultiply ( double *Q, POINT u, int istranspose )
* Purpose: returns Q*u (u a column vector) if istranspose=0,
* or u*Q (u a row vector) if istranspose=1.
* --------------------------------------------------------------------------
* Arguments: Q (I) double *Q to rotation matrix returned
* by qmatrix (or by some similar construction)
* u (I) POINT u to column vector (or to row vector
* if istranspose=1) to be multiplied by Q
* (or to multiply Q if istranspose=1)
* istranspose (I) int istranspose=0 to return Q*u (u a col vec),
* or istranspose=1 to return u*q (u a row vec)
* --------------------------------------------------------------------------
* Returns: ( POINT ) Q*u (istranspose=0), or u*Q (istranspose=1)
* --------------------------------------------------------------------------
* Notes: o Q assumed to be a 3x3 matrix stored row-wise
* ======================================================================= */
/* --- entry point --- */
POINT qmultiply ( double *Q, POINT u, int istranspose )
/* --- allocations and declarations --- */
POINT Qu = 0.,0.,0. ; /* Q*u (or u*Q if istranspose=1) */
double x=u.x, y=u.y, z=u.z; /* x(i),y(j),z(k)-components of u */
/* --- Q*u --- */
if ( !istranspose )
Qu.x = Q[0]*x + Q[1]*y + Q[2]*z; /* first row of Q * column vector u */
Qu.y = Q[3]*x + Q[4]*y + Q[5]*z; /* second row of Q * column vector u */
Qu.z = Q[6]*x + Q[7]*y + Q[8]*z; /* third row of Q * column vector u */
/* --- end-of-if(!istranspose) --- */
/* --- u*Q --- */
if ( istranspose )
Qu.x = x*Q[0] + y*Q[3] + z*Q[6]; /* row vector u * first column of Q */
Qu.y = x*Q[1] + y*Q[4] + z*Q[7]; /* row vector u * second column of Q */
Qu.z = x*Q[2] + y*Q[5] + z*Q[8]; /* row vector u * third column of Q */
/* --- end-of-if(istranspose) --- */
/* --- return product to caller --- */
return ( Qu );
/* --- end-of-function qmultiply() --- */
And here's a sample animation that uses the above functions to perform the frame-by-frame rotations...
I'm guessing you're intending to program this. So an implementation of @EmilioNovati's reference is illustrated below in C. You give it a rotation axis and a $theta$, and then one function gives you the corresponding quaternion, and then another gives you the $3mboxx3$ rotation matrix corresponding to that quaternion. And a third just conveniently multiplies a vector times a matrix to do the rotation for you. Here's the code, followed by a sample animation using it for rotation calculations...
/* ---
* Point and line datatype structs
* ---------------------------------- */
#define POINT struct point_struct /* "typedef" for point_struct*/
#define LINE struct line_struct /* "typedef" for line_struct*/
#define QUAT struct quaternion_struct /* "typedef" for quaternion_struct */
POINT double x, y, z; ; /* 3d pts */
LINE POINT pt1, pt2; ; /* for vectors, pt1=tail, pt2=head */
QUAT double q0, q1, q2, q3; ; /* quat = q0 + q1*i + q2*j + q3*k */
/***************************************************************************
** +===================================================================+ **
** | Low-level quaternion functions, etc | **
** +===================================================================+ **
***************************************************************************/
/* ==========================================================================
* Function: qrotate ( LINE axis, double theta )
* Purpose: returns quaternion corresponding to rotation
* through theta (**in radians**) around axis
* --------------------------------------------------------------------------
* Arguments: axis (I) LINE axis around which rotation by theta
* is to occur
* theta (I) double theta rotation **in radians**
* --------------------------------------------------------------------------
* Returns: ( QUAT ) quaternion corresponding to rotation
* through theta around axis
* --------------------------------------------------------------------------
* Notes: o Rotation direction determined by right-hand screw rule
* (when subsequent qmultiply() is called with istranspose=0)
* ======================================================================= */
/* --- entry point --- */
QUAT qrotate ( LINE axis, double theta )
/* --- allocations and declarations --- */
QUAT q = cos(0.5*theta), 0.,0.,0. ; /* constructed quaternion */
double x = axis.pt2.x - axis.pt1.x, /* length of x-component of axis */
y = axis.pt2.y - axis.pt1.y, /* length of y-component of axis */
z = axis.pt2.z - axis.pt1.z; /* length of z-component of axis */
double r = sqrt((x*x)+(y*y)+(z*z)); /* length of axis */
double qsin = sin(0.5*theta); /* for q1,q2,q3 components */
/* --- construct quaternion and return it to caller */
if ( r >= 0.0000001 ) /* error check */
q.q1 = qsin*x/r; /* i-component */
q.q2 = qsin*y/r; /* j-component */
q.q3 = qsin*z/r; /* k-component */
return ( q );
/* --- end-of-function qrotate() --- */
/* ==========================================================================
* Function: qmatrix ( QUAT q )
* Purpose: returns 3x3 rotation matrix corresponding to quaternion q
* ( can just be called as qmatrix(qrotate(axis,theta))
* for rotation matrix around axis through theta )
* --------------------------------------------------------------------------
* Arguments: q (I) QUAT q for which a rotation matrix
* is to be constructed
* --------------------------------------------------------------------------
* Returns: ( double * ) 3x3 rotation matrix, stored row-wise
* --------------------------------------------------------------------------
* Notes: o The matrix constructed from input q = q0+q1*i+q2*j+q3*k is:
* (q0 +q1 -q2 -q3 ) 2(q1q2-q0q3) 2(q1q3+q0q2)
* Q = 2(q2q1+q0q3) (q0 -q1 +q2 -q3 ) 2(q2q3-q0q1)
* 2(q3q1-q0q2) 2(q3q2+q0q1) (q0 -q1 -q2 +q3 )
* o The returned matrix is stored row-wise, i.e., explicitly
* --------- first row ----------
* qmatrix[0] = (q0 +q1 -q2 -q3 )
* [1] = 2(q1q2-q0q3)
* [2] = 2(q1q3+q0q2)
* --------- second row ---------
* [3] = 2(q2q1+q0q3)
* [4] = (q0 -q1 +q2 -q3 )
* [5] = 2(q2q3-q0q1)
* --------- third row ----------
* [6] = 2(q3q1-q0q2)
* [7] = 2(q3q2+q0q1)
* [8] = (q0 -q1 -q2 +q3 )
* o qmatrix maintains a static buffer of 128 3x3 matrices
* returned to the caller one at a time. So you may issue
* 128 qmatrix() calls and continue using all returned matrices.
* The 129th call re-uses the memory used by the 1st call, etc.
* ======================================================================= */
/* --- entry point --- */
double *qmatrix ( QUAT q )
/* --- allocations and declarations --- */
static double Qbuff[128][9]; /* up to 128 calls before wrap-around*/
static int ibuff = (-1); /* Qbuff[ibuff] index 0<=ibuff<=63 */
double *Q = NULL; /* returned ptr Q=Qbuff[ibuff] */
double q0=q.q0, q1=q.q1, q2=q.q2, q3=q.q3; /* input quaternion components */
double q02=q0*q0, q12=q1*q1, q22=q2*q2, q32=q3*q3; /* components squared */
/* --- first maintain Qbuff[ibuff] buffer --- */
if ( ++ibuff > 127 ) ibuff=0; /* wrap Qbuff[ibuff] index */
Q = Qbuff[ibuff]; /* ptr to current 3x3 buffer */
/* --- just do the algebra described in the above comments --- */
Q[0] = (q02+q12-q22-q32);
Q[1] = 2.*(q1*q2-q0*q3);
Q[2] = 2.*(q1*q3+q0*q2);
Q[3] = 2.*(q2*q1+q0*q3);
Q[4] = (q02-q12+q22-q32);
Q[5] = 2.*(q2*q3-q0*q1);
Q[6] = 2.*(q3*q1-q0*q2);
Q[7] = 2.*(q3*q2+q0*q1);
Q[8] = (q02-q12-q22+q32);
/* --- return constructed quaternion to caller */
return ( Q );
/* --- end-of-function qmatrix() --- */
/* ==========================================================================
* Function: qmultiply ( double *Q, POINT u, int istranspose )
* Purpose: returns Q*u (u a column vector) if istranspose=0,
* or u*Q (u a row vector) if istranspose=1.
* --------------------------------------------------------------------------
* Arguments: Q (I) double *Q to rotation matrix returned
* by qmatrix (or by some similar construction)
* u (I) POINT u to column vector (or to row vector
* if istranspose=1) to be multiplied by Q
* (or to multiply Q if istranspose=1)
* istranspose (I) int istranspose=0 to return Q*u (u a col vec),
* or istranspose=1 to return u*q (u a row vec)
* --------------------------------------------------------------------------
* Returns: ( POINT ) Q*u (istranspose=0), or u*Q (istranspose=1)
* --------------------------------------------------------------------------
* Notes: o Q assumed to be a 3x3 matrix stored row-wise
* ======================================================================= */
/* --- entry point --- */
POINT qmultiply ( double *Q, POINT u, int istranspose )
/* --- allocations and declarations --- */
POINT Qu = 0.,0.,0. ; /* Q*u (or u*Q if istranspose=1) */
double x=u.x, y=u.y, z=u.z; /* x(i),y(j),z(k)-components of u */
/* --- Q*u --- */
if ( !istranspose )
Qu.x = Q[0]*x + Q[1]*y + Q[2]*z; /* first row of Q * column vector u */
Qu.y = Q[3]*x + Q[4]*y + Q[5]*z; /* second row of Q * column vector u */
Qu.z = Q[6]*x + Q[7]*y + Q[8]*z; /* third row of Q * column vector u */
/* --- end-of-if(!istranspose) --- */
/* --- u*Q --- */
if ( istranspose )
Qu.x = x*Q[0] + y*Q[3] + z*Q[6]; /* row vector u * first column of Q */
Qu.y = x*Q[1] + y*Q[4] + z*Q[7]; /* row vector u * second column of Q */
Qu.z = x*Q[2] + y*Q[5] + z*Q[8]; /* row vector u * third column of Q */
/* --- end-of-if(istranspose) --- */
/* --- return product to caller --- */
return ( Qu );
/* --- end-of-function qmultiply() --- */
And here's a sample animation that uses the above functions to perform the frame-by-frame rotations...
answered Jul 26 at 20:48
John Forkosh
304110
304110
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
add a comment |Â
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
Thanks for the explanation! My mathematical background isn't enough to understand this completely, but it is a good jump off point for me to learn from. If this works with what I'm doing I will mark it as correct!
â Markus T.
Jul 26 at 21:53
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
@MarkusT. Yeah, I noticed your other "community" is stackoverflow, and figured you're likely heading in this direction (but for this type of stuff, python might not be your best choice:)
â John Forkosh
Jul 26 at 22:40
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
I thought about that, but If I only need to call the quaternion once wouldn't it not be that bad? The plan is that I'm given a vector and I need to move a robotic arm to that position based on the quaternion. In that regard would I really need to iterate through the program that much?
â Markus T.
Jul 26 at 23:16
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
@MarkusT. Sure, if you're only doing it a few times, python (or an abacus, for that matter:) "wouldn't be that bad".
â John Forkosh
Jul 27 at 8:46
add a comment |Â
up vote
0
down vote
Yes, the rotation axis is oriented by the vector orthogonal to the two vectors, but we have to use a normalized vector $$vec u=fracvec a times vec bvec b$$, and the angle $theta$ of rotation is obtained from the inner product of the two vectors as you have done.
The matrix that represents the rotation around the axis $vec u$ of angle $theta$ is given here.
add a comment |Â
up vote
0
down vote
Yes, the rotation axis is oriented by the vector orthogonal to the two vectors, but we have to use a normalized vector $$vec u=fracvec a times vec bvec b$$, and the angle $theta$ of rotation is obtained from the inner product of the two vectors as you have done.
The matrix that represents the rotation around the axis $vec u$ of angle $theta$ is given here.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Yes, the rotation axis is oriented by the vector orthogonal to the two vectors, but we have to use a normalized vector $$vec u=fracvec a times vec bvec b$$, and the angle $theta$ of rotation is obtained from the inner product of the two vectors as you have done.
The matrix that represents the rotation around the axis $vec u$ of angle $theta$ is given here.
Yes, the rotation axis is oriented by the vector orthogonal to the two vectors, but we have to use a normalized vector $$vec u=fracvec a times vec bvec b$$, and the angle $theta$ of rotation is obtained from the inner product of the two vectors as you have done.
The matrix that represents the rotation around the axis $vec u$ of angle $theta$ is given here.
answered Jul 26 at 20:28
Emilio Novati
50.2k43170
50.2k43170
add a comment |Â
add a comment |Â
up vote
0
down vote
If you look at
https://wikimedia.org/api/rest_v1/media/math/render/svg/f259f80a746ee20d481f9b7f600031084358a27c
formula from wikipedia(I don't have enough rep to include the image)
we obtain the general formula for a rotation matrix about an axis defined by the vector $(u_x,u_y,u_z)$. As you said, we obtain the angle between two vectors $v$ and $w$ with $fracvcdot wv$ and plug that in for theta. Then we take $vtimes w$ to be the vector $u$.
add a comment |Â
up vote
0
down vote
If you look at
https://wikimedia.org/api/rest_v1/media/math/render/svg/f259f80a746ee20d481f9b7f600031084358a27c
formula from wikipedia(I don't have enough rep to include the image)
we obtain the general formula for a rotation matrix about an axis defined by the vector $(u_x,u_y,u_z)$. As you said, we obtain the angle between two vectors $v$ and $w$ with $fracvcdot wv$ and plug that in for theta. Then we take $vtimes w$ to be the vector $u$.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
If you look at
https://wikimedia.org/api/rest_v1/media/math/render/svg/f259f80a746ee20d481f9b7f600031084358a27c
formula from wikipedia(I don't have enough rep to include the image)
we obtain the general formula for a rotation matrix about an axis defined by the vector $(u_x,u_y,u_z)$. As you said, we obtain the angle between two vectors $v$ and $w$ with $fracvcdot wv$ and plug that in for theta. Then we take $vtimes w$ to be the vector $u$.
If you look at
https://wikimedia.org/api/rest_v1/media/math/render/svg/f259f80a746ee20d481f9b7f600031084358a27c
formula from wikipedia(I don't have enough rep to include the image)
we obtain the general formula for a rotation matrix about an axis defined by the vector $(u_x,u_y,u_z)$. As you said, we obtain the angle between two vectors $v$ and $w$ with $fracvcdot wv$ and plug that in for theta. Then we take $vtimes w$ to be the vector $u$.
answered Jul 26 at 21:16
Alex
1
1
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmath.stackexchange.com%2fquestions%2f2863768%2fhow-to-rotate-a-vector-about-an-arbitrary-axis-in-3d-to-align-two-vectors%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password