Advertisement

Help me to better understand Rotation Matrix

Started by July 20, 2017 02:14 AM
5 comments, last by MarcusAseth 7 years, 6 months ago

Hi guys, I'm trying to build my 3x3 rotation matrix algorithm for the sake of thoroughly understand it as much as I can

The code below is what I just wrote from memory in an attempt to explain it to myself and test what I understand and what I do not.

I roughly start to get it (saw it last week for the first time and kind of crashed my soul, at the time) and if I decompose it in small single pieces as I did below, it actually works and my point is being rotated to the appropriate coordinates (or almost, since the y component ends up getting 0ed out, so I think I just need to add back the p_proj_to_rA Vector to the final resoult to have it right).

This being said, I completely missed the point of building a rotation matrix out of it, even though the whole time I was convinced to be moving toward the goal :D

I mean I've made my matrix class with all the relevant operations/methods, but I just don't know how to do the final step to convert what I have below into a rotation matrix...and I do not mean the fomula, which I have in the book and I can copypaste that and have it work if I want to, what I need is to actually see how to derive that final matrix formula from what I have below, I need to understand how it correlate in a way that if I where to reason about the final rotation matrix formula in the book I could say "of course, it's obvious".

So everyone that deeply understand rotation matrix and how to end up with one(without just copy-pasting the formula from a book or using a function that just give you one) is welcome to take on the challenge of making it look obvious to me, so that I can finish my program and end up with the correct one for wathever Axis of rotation I choose :D

Or just link me wathever online resource helped you in the past :)

Thanks :)

 


	Vector p = { 1, 1, 1 };// point that needs to rotate
	Vector rA = { 0, 1, 0 }; // rotation Axis
	p.computeMagnitude(); // sqrt( x*x + y*y + z*z )
	rA.computeMagnitude();// sqrt( x*x + y*y + z*z )

	//projection of our point on the rotation axis, which corresponds to the dotProduct since rA is of lenght 1
	// Formula 1 dotProduct(p,rA) = px*rAx + py*rAy + pz*rAz
	// Formula 2 dotProduct(p,rA) = |p| * |rA| * cos(angleBetween) 

	//	    proj_rA(p) = dotProduct(p,rA) = |p| * 1 * cos(angleBetween) = |p| * cos(angleBetween)

	//Solve Formula 2 for angleBetween
	//|p| * cos(angleBetween) =      dotProduct(p,rA)
	//      cos(angleBetween) =     (dotProduct(p,rA) / |p|)
	//          angleBetween  = acos( dotProduct(p,rA) / |p| ) 

	//	    proj_rA(p) = |p| * cos(angleBetween)
	//      proj_rA(p) = |p| * cos( acos( dotProduct(p,rA) / |p| ) )
	//projection of p on rA:
	double proj_to_rA = p.magnitude * cos(Vector::angleBetween(p, rA));

	//vector p projected on rA, which is basically a longer or shorter version of rA
	Vector p_proj_to_rA = rA * proj_to_rA;

	//subtracting from p the (projection of p on rA) zeroes out the dotProduct(p,rA) so the resulting vector must be orthogonal to rA
	Vector p_perp_to_rA1 = p - p_proj_to_rA;

	//the cross product between two vector is a vector orthogonal to both of them
	//Formula 1 crossProduct(A,B) = |A|*|B|*sin(angleBetween) 
	//Formula 2 v1.y*v2.z - v1.z*v2.y, //X
	//	    v1.z*v2.x - v1.x*v2.z, //Y
	//	    v1.x*v2.y - v1.y*v2.x  //Z
	Vector p_perp_to_rA2 = Vector::crossProduct(rA, p_perp_to_rA1);

	//since rA, p_perp_to_rA1 and p_perp_to_rA2 are all perpendicular to each other, 
	//if we now only consider p_perp_to_rA1 and p_perp_to_rA2 they describe a 2d plane
	//perpendicular to rA, and we rotate stuff based on this plane
	//Now the desired point of that plane is the sum  (VectorX on p_perp_to_rA1  + VectorY on p_perp_to_rA2)
	double desiredRotation = toRad(-30);
	double X = cos(desiredRotation);
	double Y = sin(desiredRotation);
	Vector finalPoint = Vector(p_perp_to_rA1 * X) + Vector(p_perp_to_rA2 * Y);

	cout << "x,y,z{ 1, 1, 1 } -30 degree on the x,y,z{ 0, 1, 0 } Axis = " << finalPoint << endl;

	return 0;

output:

Quote

x,y,z{ 1, 1, 1 } -30 degree on the x,y,z{ 0, 1, 0 } Axis =   x,y,z{0.366025 ,0, 1.36603}

 

[redacted] I missed the part where you're doing axis+angle rotation.

Advertisement

Rotation matrix is nothing special, that is, it's a matrix, like all other matrices. I'll do this in 2D to reduce writing, but the general principle extends to matrices of any size.

Say I have a matrix (LaTeX stuff doesn't work for me, so I drop down to the less nice but working ASCII variation)


    [ a b ]
A = [ c d ]

Applying that to a vector (x, y) gives


    [ x ]   [ a b ]   [ x ]   [ a * x + b * y ]
A * [ y ] = [ c d ] * [ y ] = [ c * x + d * y ]

Nothing new, right? "x" gets applied to the first column, "y" to the second column, and you add the results.

Let's apply vector (1, 0) and vector (0, 1):


    [ 1 ]   [ a b ]   [ 1 ]   [ a ]
A * [ 0 ] = [ c d ] * [ 0 ] = [ c ]

    [ 0 ]   [ a b ]   [ 0 ]   [ b ]
A * [ 1 ] = [ c d ] * [ 1 ] = [ d ]

Now compare the result vectors with the original matrix. As you can see, the (1, 0) vector gave us the first column, and the (0, 1) vector gave us the second column. Trivially explainable from the equations right?

But wait, what if we do it the other way around? That is, in our 2D space, we decide where (1, 0) should end up after applying the matrix (giving us a and c), we decide where (0, 1) should end up after applying the matrix (giving us b and d), and we use those numbers to construct the matrix.

So where does (1, 0) end up after rotation? It's at (cos(p), sin(p)), with "p" the rotation angle. Similarly, (0, 1) ends up at (-sin(p), cos(p)). The rotation matrix is thus


[ cos(p) -sin(p) ]
[ sin(p)  cos(p) ]

This will work for any regular matrix without problem, it rests on the fact that the transformation applies to each axis individually, and is then summed (ie the set equations that define the meaning of the matrix).

A translation matrix is a bit weird in the sense that the 4th axis always uses the unit vector (0, 0, 0, 1) in the matrix application (it's not a regular axis like the x, y, and z axes), so you may want to handle that separately.

 

 

 

 

 

11 minutes ago, Alberth said:

So where does (1, 0) end up after rotation? It's at (cos(p), sin(p)), with "p" the rotation angle. Similarly, (0, 1) ends up at (-sin(p), cos(p)). The rotation matrix is thus



[ cos(p) -sin(p) ]
[ sin(p)  cos(p) ]

 

You completely lost me here xD

I guess for me that is not obvious at all, I mean, if you where to ask me how to buil that rotation matrix you wrote I won't know where to start, I think  the problem for me would become even exponentially bigger adding a third dimension.

The point I was trying to make is

  • the first column in a matrix is the position where the first unit vector ends up (after applying the matrix),
  • the second column in a matrix is where the second unit vector ends up (after the applying the matrix),
  • the third column in a matrix is where the third unit vector ends up (after the applying the matrix),
  • etc.

This reduces the problem of making any 3D matrix to knowing where the three unit vectors end up.

Maybe your problem is not so much in creating a matrix, but more in understanding how to do rotation in 3D space?

 

Matrices are just a convenient way to write a set of equations in a compact way (this is why everybody loves them), but they don't enable anything you can't already do with simple variables, and the "*" and "+" operators.

 

That's totally possible, that's why I'm going trough THIS and

" rel="external nofollow">THIS playlist right now, I think that knowledge will either solve my problem or enable me to get more out of your and everyone else explanation, therefore I'll be reading what you've wrote above more than once for sure :P

This topic is closed to new replies.

Advertisement