8

I've been trying to work out how to solve the following problem using python:

  1. We have points a, b, c, d which form a rigid body
  2. Some unknown 3D translation and rotation is applied to the rigid body
  3. We now know the coordinates for a, b, c
  4. We want to calculate coordinates for d

What I know so far:

What I can't work out is how I can calculate the rotation and translation matrices given the "new" coordinates of a, b, c.

I can see that in the general case (non-rigid body) the rotation part of this is Wahba's problem, but I think that for rigid bodies there should be some faster way of calculating it directly by working out a set of orthogonal unit vectors using the points.

lost
  • 2,210
  • 2
  • 20
  • 34
  • 2
    You could calculate the "unknown 3D translation and rotation" matrix using `affine_matrix_from_points(abc, abc_new, shear=False, scale=False)` from http://www.lfd.uci.edu/~gohlke/code/transformations.py.html#line-882 and apply it to `d` – cgohlke Apr 18 '13 at 18:46
  • Thanks - actually it looks like `superimposition_matrix` in the same will actually do this for my case I think? If you make your comment above an answer I'll accept it! – lost Apr 19 '13 at 11:04

1 Answers1

5

For a set of corresponding points that you're trying to match (with possible perturbation) I've used SVD (singular value decomposition), which appears to exist in numpy.

An example of this technique (in Python even) can be found here, but I haven't evaluated it for correctness.

What you're going for is a "basis transform" or "change of basis" which will be represented as a transformation matrix. Assuming your 3 known points are not collinear, you can create your initial basis by:

  1. Computing the vectors: x=(b-a) and y=(c-a)
  2. Normalize x (x = x / magnitude(x))
  3. Project y onto x (proj_y = x DOT y * x)
  4. Subtract the projection from y (y = y - proj_y)
  5. Normalize y
  6. Compute z = x CROSS y

That gives you an initial x,y,z coordinate basis A. Do the same for your new points, and you get a second basis B. Now you want to find transform T which will take a point in A and convert it to B (change of basis). That part is easy. You can invert A to transform the points back to the Normal basis, then use B to transform into the second one. Since A is orthonormal, you can just transpose A to get the inverse. So the "new d" is equal to d * inverse(A) * B. (Though depending on your representation, you may need to use B * inverse(A) * d.)

You need to have some familiarity with matrices to get all that. Your representation of vectors and matrices will inform you as to which order to multiply the matrices to get T (T is either inverse(A)*B or B*inverse(A)).

To compute your basis matrix from your vectors x=(x1,x2,x3), y=(y1,y2,y3), z=(z1,z2,z3) you populate it as:

| x1 y1 z1 |
| x2 y2 z2 |
| x3 y3 z3 |
Mark Ping
  • 278
  • 1
  • 6
  • 1
    Accepting this because it provides a general, high-quality answer, although the comment on my question actually solves my problem more directly. – lost Apr 25 '13 at 15:21
  • *"Assuming your three known points are not coplanar"* Rather, collinear, right? – rschwieb Jan 21 '14 at 21:08
  • Correct, fixed. I was thinking of 4 points, non-coplanar, but only 3 points are needed, as you corrected. – Mark Ping Jan 22 '14 at 04:16