From 9f988f7b5714f19ca5a62874d63bc06a697dc877 Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 23 Aug 2024 15:09:11 +0200 Subject: [PATCH 1/7] Fixed incorrect documentation of to_euler: * to_euler() contained the doc string of from_euler. --- kornia/geometry/quaternion.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index 3d4d190cbf..3b0613a372 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -281,10 +281,7 @@ def from_euler(cls, roll: Tensor, pitch: Tensor, yaw: Tensor) -> "Quaternion": return cls(q) def to_euler(self) -> Tuple[Tensor, Tensor, Tensor]: - """Create a quaternion from euler angles. - - Args: - matrix: the rotation matrix to convert of shape :math:`(B, 3, 3)`. + """Convert the quaternion to a triple of Euler angles (roll, pitch, yaw). Example: >>> q = Quaternion(tensor([2., 0., 1., 1.])) From 481546f5c97dc9fb8a105b4b249e26203af2af97 Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 23 Aug 2024 15:09:43 +0200 Subject: [PATCH 2/7] Fixed typo in from_euler: * 'euler' -> 'Euler' --- kornia/geometry/quaternion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index 3b0613a372..ff2bb0f8be 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -262,7 +262,7 @@ def from_matrix(cls, matrix: Tensor) -> "Quaternion": @classmethod def from_euler(cls, roll: Tensor, pitch: Tensor, yaw: Tensor) -> "Quaternion": - """Create a quaternion from euler angles. + """Create a quaternion from Euler angles. Args: roll: the roll euler angle. From 4b8528b64da3bd9fdf5d6c4890cd021f474f802a Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 23 Aug 2024 15:12:05 +0200 Subject: [PATCH 3/7] Added to_axis_angle() method: * Given existence of from_axis_angle(), and conversion to to_euler(), and matrix(), a method for conversion to axis angle representation is missing. --- kornia/geometry/quaternion.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index ff2bb0f8be..f97421624f 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -13,7 +13,7 @@ normalize_quaternion, quaternion_from_euler, quaternion_to_rotation_matrix, - rotation_matrix_to_quaternion, + rotation_matrix_to_quaternion, quaternion_to_axis_angle, ) from kornia.geometry.linalg import batched_dot_product @@ -311,6 +311,17 @@ def from_axis_angle(cls, axis_angle: Tensor) -> "Quaternion": """ return cls(axis_angle_to_quaternion(axis_angle)) + def to_axis_angle(self) -> Tensor: + """Convert the quaternion to a rotation matrix of shape :math:`(B, 3, 3)`. + + Example: + >>> q = Quaternion.identity() + >>> axis_angle = q.to_axis_angle() + >>> axis_angle + tensor([0., 0., 0.], grad_fn=) + """ + return quaternion_to_axis_angle(self.q) + @classmethod def identity( cls, batch_size: Optional[int] = None, device: Optional[Device] = None, dtype: Dtype = None From 671c4b6fe9493a042cffca9ebaf84336de944fb3 Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 23 Aug 2024 15:15:30 +0200 Subject: [PATCH 4/7] to_axis_angle() uses self.data * Consistently with other functions, use self.data instead of self.q --- kornia/geometry/quaternion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index f97421624f..df49398001 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -320,7 +320,7 @@ def to_axis_angle(self) -> Tensor: >>> axis_angle tensor([0., 0., 0.], grad_fn=) """ - return quaternion_to_axis_angle(self.q) + return quaternion_to_axis_angle(self.data) @classmethod def identity( From 7be8b1534d6f5c1dc4c94ca5245e1a46e5b1e21f Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 23 Aug 2024 15:47:07 +0200 Subject: [PATCH 5/7] added test for to_axis_angle() --- tests/geometry/test_quaternion.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/geometry/test_quaternion.py b/tests/geometry/test_quaternion.py index 1bb98bac9f..0e21efc70c 100644 --- a/tests/geometry/test_quaternion.py +++ b/tests/geometry/test_quaternion.py @@ -208,6 +208,28 @@ def test_axis_angle(self, device, dtype, batch_size): q2 = q2.to(device, dtype) self.assert_close(q1, q2) + @pytest.mark.parametrize("batch_size", (None, 1, 2, 5)) + def test_to_axis_angle(self, device, dtype, batch_size): + + # batch_s = 5 + # random_coefs = Quaternion.random(batch_s).data + random_coefs = torch.tensor([[2.5398e-04, -2.2677e-01, -8.3897e-01, 4.9467e-01], + [-1.7005e-01, -1.0974e-01, 3.7635e-01, -9.0410e-01], + [9.1273e-01, 4.8935e-02, -6.2994e-03, 4.0558e-01], + [-9.8316e-01, 5.4078e-03, 1.4471e-01, 1.1145e-01], + [4.5794e-02, -7.0831e-01, 6.7577e-01, 1.9883e-01]], device=device, dtype=dtype) + + q = Quaternion(random_coefs) + axis_angle_actual = q.to_axis_angle() + + axis_angle_expected = torch.tensor([[-0.7123, -2.6353, 1.5538], + [0.3118, -1.0693, 2.5687], + [0.1008, -0.0130, 0.8356], + [-0.0109, -0.2911, -0.2242], + [-2.1626, 2.0632, 0.6071]], device=device, dtype=dtype) + + self.assert_close(axis_angle_expected, axis_angle_actual, 1e-4, 1e-4) + @pytest.mark.parametrize("batch_size", (None, 1, 2, 5)) def test_slerp(self, device, dtype, batch_size): for axis in torch.tensor([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]): From 03802a874086040dec4b088e4edaa500848dd884 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:56:37 +0000 Subject: [PATCH 6/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- kornia/geometry/quaternion.py | 3 ++- tests/geometry/test_quaternion.py | 33 ++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index df49398001..8de935f53c 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -12,8 +12,9 @@ euler_from_quaternion, normalize_quaternion, quaternion_from_euler, + quaternion_to_axis_angle, quaternion_to_rotation_matrix, - rotation_matrix_to_quaternion, quaternion_to_axis_angle, + rotation_matrix_to_quaternion, ) from kornia.geometry.linalg import batched_dot_product diff --git a/tests/geometry/test_quaternion.py b/tests/geometry/test_quaternion.py index 0e21efc70c..46a2ce48b3 100644 --- a/tests/geometry/test_quaternion.py +++ b/tests/geometry/test_quaternion.py @@ -210,23 +210,34 @@ def test_axis_angle(self, device, dtype, batch_size): @pytest.mark.parametrize("batch_size", (None, 1, 2, 5)) def test_to_axis_angle(self, device, dtype, batch_size): - # batch_s = 5 # random_coefs = Quaternion.random(batch_s).data - random_coefs = torch.tensor([[2.5398e-04, -2.2677e-01, -8.3897e-01, 4.9467e-01], - [-1.7005e-01, -1.0974e-01, 3.7635e-01, -9.0410e-01], - [9.1273e-01, 4.8935e-02, -6.2994e-03, 4.0558e-01], - [-9.8316e-01, 5.4078e-03, 1.4471e-01, 1.1145e-01], - [4.5794e-02, -7.0831e-01, 6.7577e-01, 1.9883e-01]], device=device, dtype=dtype) + random_coefs = torch.tensor( + [ + [2.5398e-04, -2.2677e-01, -8.3897e-01, 4.9467e-01], + [-1.7005e-01, -1.0974e-01, 3.7635e-01, -9.0410e-01], + [9.1273e-01, 4.8935e-02, -6.2994e-03, 4.0558e-01], + [-9.8316e-01, 5.4078e-03, 1.4471e-01, 1.1145e-01], + [4.5794e-02, -7.0831e-01, 6.7577e-01, 1.9883e-01], + ], + device=device, + dtype=dtype, + ) q = Quaternion(random_coefs) axis_angle_actual = q.to_axis_angle() - axis_angle_expected = torch.tensor([[-0.7123, -2.6353, 1.5538], - [0.3118, -1.0693, 2.5687], - [0.1008, -0.0130, 0.8356], - [-0.0109, -0.2911, -0.2242], - [-2.1626, 2.0632, 0.6071]], device=device, dtype=dtype) + axis_angle_expected = torch.tensor( + [ + [-0.7123, -2.6353, 1.5538], + [0.3118, -1.0693, 2.5687], + [0.1008, -0.0130, 0.8356], + [-0.0109, -0.2911, -0.2242], + [-2.1626, 2.0632, 0.6071], + ], + device=device, + dtype=dtype, + ) self.assert_close(axis_angle_expected, axis_angle_actual, 1e-4, 1e-4) From e90f5e89621bcf289e0731cf8274f0ad521ea14d Mon Sep 17 00:00:00 2001 From: tjelinek Date: Fri, 30 Aug 2024 10:37:53 +0200 Subject: [PATCH 7/7] Fix docs in Quaternion.to_axis_angle() --- kornia/geometry/quaternion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kornia/geometry/quaternion.py b/kornia/geometry/quaternion.py index df49398001..a62f0191f4 100644 --- a/kornia/geometry/quaternion.py +++ b/kornia/geometry/quaternion.py @@ -312,7 +312,7 @@ def from_axis_angle(cls, axis_angle: Tensor) -> "Quaternion": return cls(axis_angle_to_quaternion(axis_angle)) def to_axis_angle(self) -> Tensor: - """Convert the quaternion to a rotation matrix of shape :math:`(B, 3, 3)`. + """Converts the quaternion to an axis-angle representation. Example: >>> q = Quaternion.identity()