From 126cc04d1d42f453864a8b649b4e2e3ea1675891 Mon Sep 17 00:00:00 2001 From: Don Cross Date: Sun, 15 Dec 2019 20:29:41 -0500 Subject: [PATCH] Python: Implemented CombineRotation. --- generate/template/astronomy.py | 45 ++++++++++++++++++++++++++++++++++ generate/test.py | 23 +++++++++++++++++ source/python/README.md | 19 ++++++++++++++ source/python/astronomy.py | 45 ++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+) diff --git a/generate/template/astronomy.py b/generate/template/astronomy.py index 256f8a65..75edefa3 100644 --- a/generate/template/astronomy.py +++ b/generate/template/astronomy.py @@ -3044,6 +3044,51 @@ def InverseRotation(rotation): [rotation.rot[0][2], rotation.rot[1][2], rotation.rot[2][2]] ]) + +def CombineRotation(a, b): + """Creates a rotation based on applying one rotation followed by another. + + Given two rotation matrices, returns a combined rotation matrix that is + equivalent to rotating based on the first matrix, followed by the second. + + Parameters + ---------- + a : RotationMatrix + The first rotation to apply. + + b : RotationMatrix + The second rotation to apply. + + Returns + ------- + RotationMatrix + The combined rotation matrix. + """ + # Use matrix multiplication: c = b*a. + # We put 'b' on the left and 'a' on the right because, + # just like when you use a matrix M to rotate a vector V, + # you put the M on the left in the product M*V. + # We can think of this as 'b' rotating all the 3 column vectors in 'a'. + + return RotationMatrix([ + [ + b.rot[0][0]*a.rot[0][0] + b.rot[1][0]*a.rot[0][1] + b.rot[2][0]*a.rot[0][2], + b.rot[0][1]*a.rot[0][0] + b.rot[1][1]*a.rot[0][1] + b.rot[2][1]*a.rot[0][2], + b.rot[0][2]*a.rot[0][0] + b.rot[1][2]*a.rot[0][1] + b.rot[2][2]*a.rot[0][2] + ], + [ + b.rot[0][0]*a.rot[1][0] + b.rot[1][0]*a.rot[1][1] + b.rot[2][0]*a.rot[1][2], + b.rot[0][1]*a.rot[1][0] + b.rot[1][1]*a.rot[1][1] + b.rot[2][1]*a.rot[1][2], + b.rot[0][2]*a.rot[1][0] + b.rot[1][2]*a.rot[1][1] + b.rot[2][2]*a.rot[1][2] + ], + [ + b.rot[0][0]*a.rot[2][0] + b.rot[1][0]*a.rot[2][1] + b.rot[2][0]*a.rot[2][2], + b.rot[0][1]*a.rot[2][0] + b.rot[1][1]*a.rot[2][1] + b.rot[2][1]*a.rot[2][2], + b.rot[0][2]*a.rot[2][0] + b.rot[1][2]*a.rot[2][1] + b.rot[2][2]*a.rot[2][2] + ] + ]) + + def RotateVector(rotation, vector): """Applies a rotation to a vector, yielding a rotated vector. diff --git a/generate/test.py b/generate/test.py index 23d63408..c4274be1 100755 --- a/generate/test.py +++ b/generate/test.py @@ -750,8 +750,31 @@ def Rotation_MatrixInverse(): b = astronomy.InverseRotation(a) CompareMatrices('Rotation_MatrixInverse', b, v, 0) +def Rotation_MatrixMultiply(): + a = astronomy.RotationMatrix([ + [1, 4, 7], + [2, 5, 8], + [3, 6, 9] + ]) + + b = astronomy.RotationMatrix([ + [10, 13, 16], + [11, 14, 17], + [12, 15, 18] + ]) + + v = astronomy.RotationMatrix([ + [84, 201, 318], + [90, 216, 342], + [96, 231, 366] + ]) + + c = astronomy.CombineRotation(b, a) + CompareMatrices('Rotation_MatrixMultiply', c, v, 0) + def Test_Rotation(): Rotation_MatrixInverse() + Rotation_MatrixMultiply() print('Python Test_Rotation: PASS') return 0 diff --git a/source/python/README.md b/source/python/README.md index 3ce1aed1..0a070750 100644 --- a/source/python/README.md +++ b/source/python/README.md @@ -510,6 +510,25 @@ Otherwise, returns `Body.Invalid`. --- + +### CombineRotation(a, b) + +**Creates a rotation based on applying one rotation followed by another.** + +Given two rotation matrices, returns a combined rotation matrix that is +equivalent to rotating based on the first matrix, followed by the second. +b : RotationMatrix + The second rotation to apply. + +| Type | Parameter | Description | +| --- | --- | --- | +| [`RotationMatrix`](#RotationMatrix) | `a` | The first rotation to apply. | + +### Returns: RotationMatrix +The combined rotation matrix. + +--- + ### Ecliptic(equ) diff --git a/source/python/astronomy.py b/source/python/astronomy.py index 2b6d0cc7..ebbf02a4 100644 --- a/source/python/astronomy.py +++ b/source/python/astronomy.py @@ -5105,6 +5105,51 @@ def InverseRotation(rotation): [rotation.rot[0][2], rotation.rot[1][2], rotation.rot[2][2]] ]) + +def CombineRotation(a, b): + """Creates a rotation based on applying one rotation followed by another. + + Given two rotation matrices, returns a combined rotation matrix that is + equivalent to rotating based on the first matrix, followed by the second. + + Parameters + ---------- + a : RotationMatrix + The first rotation to apply. + + b : RotationMatrix + The second rotation to apply. + + Returns + ------- + RotationMatrix + The combined rotation matrix. + """ + # Use matrix multiplication: c = b*a. + # We put 'b' on the left and 'a' on the right because, + # just like when you use a matrix M to rotate a vector V, + # you put the M on the left in the product M*V. + # We can think of this as 'b' rotating all the 3 column vectors in 'a'. + + return RotationMatrix([ + [ + b.rot[0][0]*a.rot[0][0] + b.rot[1][0]*a.rot[0][1] + b.rot[2][0]*a.rot[0][2], + b.rot[0][1]*a.rot[0][0] + b.rot[1][1]*a.rot[0][1] + b.rot[2][1]*a.rot[0][2], + b.rot[0][2]*a.rot[0][0] + b.rot[1][2]*a.rot[0][1] + b.rot[2][2]*a.rot[0][2] + ], + [ + b.rot[0][0]*a.rot[1][0] + b.rot[1][0]*a.rot[1][1] + b.rot[2][0]*a.rot[1][2], + b.rot[0][1]*a.rot[1][0] + b.rot[1][1]*a.rot[1][1] + b.rot[2][1]*a.rot[1][2], + b.rot[0][2]*a.rot[1][0] + b.rot[1][2]*a.rot[1][1] + b.rot[2][2]*a.rot[1][2] + ], + [ + b.rot[0][0]*a.rot[2][0] + b.rot[1][0]*a.rot[2][1] + b.rot[2][0]*a.rot[2][2], + b.rot[0][1]*a.rot[2][0] + b.rot[1][1]*a.rot[2][1] + b.rot[2][1]*a.rot[2][2], + b.rot[0][2]*a.rot[2][0] + b.rot[1][2]*a.rot[2][1] + b.rot[2][2]*a.rot[2][2] + ] + ]) + + def RotateVector(rotation, vector): """Applies a rotation to a vector, yielding a rotated vector.