1

For context, I am trying to apply the same rotations from one set of 3D points to another set of 3D points. Concretely, I am trying to model the movements of human joints from a video on a 3D human body model.

From what I gathered, I need to calculate the Euler angle between two 3D points around the third 3D point (they all represent joint locations in the video), so I can apply the same rotation to my 3D model.

So, my problem boils down to that I want to calculate the Euler angles between X, Y and Z axes (in radians) between these two 3D points:

(224, 129, 76)
(225, 129, 78)

rotating around this 3D point:

(181, 151, 67)

How do I do this? I am aiming to implement this in software.

  • Welcome to MSE. Your question is phrased as an isolated problem, without any further information or context. This does not match many users' quality standards, so it may attract downvotes, or be closed. To prevent that, please [edit] the question. This will help you recognize and resolve the issues. Concretely: please provide context, and include your work and thoughts on the problem. These changes can help in formulating more appropriate answers. – José Carlos Santos Jan 23 '23 at 11:44
  • @JoséCarlosSantos I added context to my question. I hope it is better now, but if you have any further suggestions feel free to notify me. – Jack Gordon Jan 23 '23 at 12:21
  • Yes, it is better now. – José Carlos Santos Jan 23 '23 at 12:22
  • @Jack You might find this post helpful – Ben Grossmann Jan 23 '23 at 15:39
  • @Jack What exactly do you mean when you say "the Euler angle between two 3D points"? It is apparent that you want to describe the rotation (about the given center) that takes the first point to the second. Do you want the 3 Euler angles associated with that rotation, or do you want the single angle by which this rotation rotates about its axis? – Ben Grossmann Jan 23 '23 at 15:41
  • @BenGrossmann I want the 3 Euler angles (around the X, Y and Z axis) associated with that rotation. I'll edit my original question to reflect this. – Jack Gordon Jan 24 '23 at 12:16
  • @JackGordon In that case, you should be able to follow the top answer to the post I linked, using the vectors $$ (224, 129, 76) - (181, 151, 67)\ (225, 129, 78) - (181, 151, 67) $$ to get the matrix of the corresponding rotation about the origin and applying that same rotation about the new center $(181,151,67)$. – Ben Grossmann Jan 24 '23 at 14:07
  • @BenGrossmann thank you for sharing that answer. I read through it multiple times, but I found it quite convoluted, primarily because its use case is for rotating around the z-axis, then around the x-axis (with no y-axis rotation involved) and the writing style was terse. Could you guide me through my particular example, with (brief) explanations on why I'm doing what I'm doing? – Jack Gordon Jan 26 '23 at 13:35
  • @Jack I'll try to put an explanation together – Ben Grossmann Jan 26 '23 at 15:52
  • By the way, can we presume that the two points are the same distance away from the center of the rotation? – Ben Grossmann Jan 26 '23 at 16:07
  • @Jack A key point here is that a rotation is not uniquely determined by the destination of a single point. For example, consider the case where a rotation about the origin moves the point $(1,0,0)$ to the point $(0,1,0)$. We could just apply the $90^\circ$ rotation about the $z$-axis to bring it straight there, but we could also apply any rotation about the $y$-axis after doing so, or equivalently apply any rotation about the $x$-axis before doing so. It turns out that we are missing exactly one "parameter" of information that would be necessary to make that determination. – Ben Grossmann Jan 26 '23 at 18:25
  • @Jack One way to make it so that we end up with a unique rotation is to add the heuristic that the rotation angle needs to be as small as possible (given that the rotation maps point 1 to point 2). It so happens that this corresponds to taking the approach described here, in the second answer from the top. – Ben Grossmann Jan 26 '23 at 18:35
  • @Jack I've decided that the approach I initially suggested isn't really suited to your problem. If you're interested in what I had in mind anyway, I've left my answer over here. – Ben Grossmann Jan 26 '23 at 18:41

1 Answers1

0

Denote the two points as $$ P_1:(x_1,y_1,z_1), \quad P_2: (x_2,y_2,z_2) $$ and the center as $P_0: (x_0,y_0,z_0)$. First of all, note that the rotation matrix corresponding to the rotation about $P_0$ will take the vector $v_1 = P_1 - P_0$ to the vector $v_2 = P_2 - P_0$.

Note that a suitable rotation will only exist if $\|v_1\| = \|v_2\|$, i.e. both points are equidistant from the center of the rotation. If that is the case, then it suffices to find rotation matrix $R$ satisfying $Rv_1 = v_2$. Once this is done, the desired affine rotation is the same rotation about $P_0$, that is, $$ T(v) = R(v - P_0) + P_0 = Rv + (I-R)P_0, $$ corresponding to the homogeneous coordinates transformation matrix $$ \pmatrix{R & (I-R)P_0\\0 & 1}. $$


There are infinitely many choices for a rotation (about the center) from $v_1$ to $v_2$. However, I will suppose that we want the rotation by the smallest possible angle that achieves this result. I will also assume that $v_1$ and $v_2$ are linearly independent; the edge cases of $v_1 = \pm v_2$ can be handled separately.

I claim (without proof, for now) that the rotation that achieves this is the smaller of the two rotations along the axis orthogonal to both $v_1$ and $v_2$. In particular, it is the counterclockwise rotation by angle $$ \theta = \arccos\left(\frac{v_1 \cdot v_2}{\|v_1\|\,\|v_2\|}\right) $$ about the axis $v_1 \times v_2$. Let $u = (x_u,y_u,z_u)$ denote the unit vector parallel to $v_1 \times v_2$, $u = \frac{v_1\times v_2}{\|v_1 \times v_2\|}$. With Rodrigues' rotation formula, we find that this rotation has the matrix $R = I + \sin\theta K + (1-\cos \theta) K^2$, where $K$ denotes the "cross-product matrix" for the vector $u$, $$ K = \pmatrix{ 0 & -z_u & y_u\\ z_u&0&x_u\\ -y_u&x_u&0}. $$ From there, the $z$-$x$-$Z$ extrinsic Euler angles for the rotation can be obtained using the formulas given here: \begin{align} \phi &= \operatorname{arctan2}\left(R_{31}, R_{32}\right),\\ \theta &= \arccos\left(R_{33}\right),\\ \psi &= -\operatorname{arctan2}\left(R_{13}, R_{23}\right). \end{align}


As it turns out, we can neatly rewrite the formula for $R$ using the fact that $u = \frac 1{\sin\theta}v_1 \times v_2$. I claim (again, without proof for now) that if $v_1,v_2$ are normalized to have length $1$, then $$ R = (v_1^\top v_2) I + (v_2v_1^\top - v_1v_2^\top) + (1 + v_1^\top v_2)(v_1 \times v_2)(v_1 \times v_2)^\top. $$ Another nice reformulation: $$ M = \pmatrix{v_1 & v_2 & v_1\times v_2}, \\ R = (v_1^\top v_2) I + M\pmatrix{0&-1&0\\1&0&0\\0&0&1 + v_1^\top v_2}M^\top. $$

Ben Grossmann
  • 225,327
  • Thank you. I think I got what I needed from the middle paragraph. I think I need to: 1) Calculate theta; 2) Calculate vector u; 3) Plug in vector u coordinates in matrix K; 4) calculate R; 5) obtain my x, y and z axis rotation angles from the formulas at the end of that middle paragraph. – Jack Gordon Jan 27 '23 at 09:33
  • I have a follow-up question: what happens if v_1 and v_2 aren't equidistant from the center of rotation? Then it wouldn't be just rotation, but rather rotation and scaling of a vector? How much does that complicate the situation? – Jack Gordon Jan 27 '23 at 09:34
  • As a follow-up to my previous question, I think that it may be the case that v_1 and v_2 aren't equidistant from each other. The reason for this is because my 3D human joint coordinates may be inaccurate and I can't guarantee that both v_1 and v_2 reside on the same sphere. In that case, I'd like to find the point closest to v_2 that is on the sphere which contains v_1. How could I do that? – Jack Gordon Jan 27 '23 at 09:50
  • @JackGordon I think you mean equidistant from the center in that second comment. Note that for $v_1,v_2$, the center of rotation is necessarily the origin. If you want to take the specific approach of finding the point "closest to $v_2$ that is on the sphere containing $v_1$", then that amounts to simply rescaling $v_2$ that it has the same length as $v_1$, i.e. replacing $v_2$ with $\frac{|v_1|}{|v_2|} \cdot v_2$. I think that is a reasonable solution here – Ben Grossmann Jan 27 '23 at 14:44
  • @JackGordon If you want to find the best rotation given multiple pairs of reference points before and after the rotation, then you're looking for a solution to Wahba's problem. As the link describes, the matrix of the rotation can be obtained in a straightforward fashion, and from there you could go from a rotation matrix to Euler angles as I did in my answer. – Ben Grossmann Jan 27 '23 at 14:46
  • OK, thank you so much. I am currently implementing another solution, but thank you for elaborating on this. Will come back to this if needed. – Jack Gordon Jan 30 '23 at 07:47
  • Hello, I have implemented your answer in code. However, it gives me strange results, as I explain below. I double-checked if I implemented everything right by calculating by hand (using the values in my original post) and printing out the variables in my code. It seems that my implementation is correct.

    I have some questions for you:

    1. Can I somehow get the rotation around the x, y and z axis, instead of the z, x and Z axis? What is Z axis anyway?
    2. I noticed I get a large angle for the rotation about the z axis (over 100 degrees). Do you have any ideas why is that?
    – Jack Gordon Mar 08 '23 at 14:38
  • @JackGordon If you don't know what the "$Z$-axis$ is", then in what sense have you implemented my answer in code? – Ben Grossmann Mar 08 '23 at 14:43
  • @JackGordon If you want to stick to extrinsic Euler angles, then this writeup that I found online seems to give you what you're looking for starting from the matrix of the rotation – Ben Grossmann Mar 08 '23 at 14:45
  • I implemented your answer as I described in my first comment to your answer. I mistakenly thought that the angles I obtain at the end of your 2nd paragraph are the rotation angels around the x, y and z axis, respectively, but I was mistaken. – Jack Gordon Mar 08 '23 at 14:45
  • @JackGordon Ok, so it makes sense that you're getting strange results. The $Z$-axis, by the way, is the new z-axis within the rotated coordinate system – Ben Grossmann Mar 08 '23 at 14:48
  • Oh, OK. That makes sense. I'll look into the writeup you posted (not sure when, but eventually I will) and I'll try to obtain the rotation angles around the x, y and z axis. Thank you for being so responsive. It really helps me out a lot. – Jack Gordon Mar 08 '23 at 14:50
  • @Jack Glad to help. You might find some of the posts on this SO thread to be helpful – Ben Grossmann Mar 08 '23 at 15:02