test_Pose3.py
Go to the documentation of this file.
1 """
2 GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
3 Atlanta, Georgia 30332-0415
4 All Rights Reserved
5 
6 See LICENSE for the license information
7 
8 Pose3 unit tests.
9 Author: Frank Dellaert, Duy Nguyen Ta
10 """
11 # pylint: disable=no-name-in-module
12 import math
13 import unittest
14 
15 import numpy as np
16 from gtsam.utils.test_case import GtsamTestCase
17 
18 import gtsam
19 from gtsam import Point3, Pose3, Rot3
20 
21 
22 def numerical_derivative_pose(pose, method, delta=1e-5):
23  jacobian = np.zeros((6, 6))
24  for idx in range(6):
25  xplus = np.zeros(6)
26  xplus[idx] = delta
27  xminus = np.zeros(6)
28  xminus[idx] = -delta
29  pose_plus = pose.retract(xplus).__getattribute__(method)()
30  pose_minus = pose.retract(xminus).__getattribute__(method)()
31  jacobian[:, idx] = pose_minus.localCoordinates(pose_plus) / (2 * delta)
32  return jacobian
33 
34 
35 def numerical_derivative_2_poses(pose, other_pose, method, delta=1e-5, inputs=()):
36  jacobian = np.zeros((6, 6))
37  other_jacobian = np.zeros((6, 6))
38  for idx in range(6):
39  xplus = np.zeros(6)
40  xplus[idx] = delta
41  xminus = np.zeros(6)
42  xminus[idx] = -delta
43 
44  pose_plus = pose.retract(xplus).__getattribute__(method)(*inputs, other_pose)
45  pose_minus = pose.retract(xminus).__getattribute__(method)(*inputs, other_pose)
46  jacobian[:, idx] = pose_minus.localCoordinates(pose_plus) / (2 * delta)
47 
48  other_pose_plus = pose.__getattribute__(method)(*inputs, other_pose.retract(xplus))
49  other_pose_minus = pose.__getattribute__(method)(*inputs, other_pose.retract(xminus))
50  other_jacobian[:, idx] = other_pose_minus.localCoordinates(other_pose_plus) / (2 * delta)
51  return jacobian, other_jacobian
52 
53 
54 def numerical_derivative_pose_point(pose, point, method, delta=1e-5):
55  jacobian = np.zeros((3, 6))
56  point_jacobian = np.zeros((3, 3))
57  for idx in range(6):
58  xplus = np.zeros(6)
59  xplus[idx] = delta
60  xminus = np.zeros(6)
61  xminus[idx] = -delta
62 
63  point_plus = pose.retract(xplus).__getattribute__(method)(point)
64  point_minus = pose.retract(xminus).__getattribute__(method)(point)
65  jacobian[:, idx] = (point_plus - point_minus) / (2 * delta)
66 
67  if idx < 3:
68  xplus = np.zeros(3)
69  xplus[idx] = delta
70  xminus = np.zeros(3)
71  xminus[idx] = -delta
72  point_plus = pose.__getattribute__(method)(point + xplus)
73  point_minus = pose.__getattribute__(method)(point + xminus)
74  point_jacobian[:, idx] = (point_plus - point_minus) / (2 * delta)
75  return jacobian, point_jacobian
76 
77 
79  """Test selected Pose3 methods."""
80 
81  def test_between(self):
82  """Test between method."""
83  T2 = Pose3(Rot3.Rodrigues(0.3, 0.2, 0.1), Point3(3.5, -8.2, 4.2))
84  T3 = Pose3(Rot3.Rodrigues(-90, 0, 0), Point3(1, 2, 3))
85  expected = T2.inverse().compose(T3)
86  actual = T2.between(T3)
87  self.gtsamAssertEquals(actual, expected, 1e-6)
88 
89  #test jacobians
90  jacobian = np.zeros((6, 6), order='F')
91  jacobian_other = np.zeros((6, 6), order='F')
92  T2.between(T3, jacobian, jacobian_other)
93  jacobian_numerical, jacobian_numerical_other = numerical_derivative_2_poses(T2, T3, 'between')
94  self.gtsamAssertEquals(jacobian, jacobian_numerical)
95  self.gtsamAssertEquals(jacobian_other, jacobian_numerical_other)
96 
97  def test_inverse(self):
98  """Test between method."""
99  pose = Pose3(Rot3.Rodrigues(0, 0, -math.pi/2), Point3(2, 4, 0))
100  expected = Pose3(Rot3.Rodrigues(0, 0, math.pi/2), Point3(4, -2, 0))
101  actual = pose.inverse()
102  self.gtsamAssertEquals(actual, expected, 1e-6)
103 
104  #test jacobians
105  jacobian = np.zeros((6, 6), order='F')
106  pose.inverse(jacobian)
107  jacobian_numerical = numerical_derivative_pose(pose, 'inverse')
108  self.gtsamAssertEquals(jacobian, jacobian_numerical)
109 
110  def test_slerp(self):
111  """Test slerp method."""
112  pose0 = gtsam.Pose3()
113  pose1 = Pose3(Rot3.Rodrigues(0, 0, -math.pi/2), Point3(2, 4, 0))
114  actual_alpha_0 = pose0.slerp(0, pose1)
115  self.gtsamAssertEquals(actual_alpha_0, pose0)
116  actual_alpha_1 = pose0.slerp(1, pose1)
117  self.gtsamAssertEquals(actual_alpha_1, pose1)
118  actual_alpha_half = pose0.slerp(0.5, pose1)
119  expected_alpha_half = Pose3(Rot3.Rodrigues(0, 0, -math.pi/4), Point3(0.17157288, 2.41421356, 0))
120  self.gtsamAssertEquals(actual_alpha_half, expected_alpha_half, tol=1e-6)
121 
122  # test jacobians
123  jacobian = np.zeros((6, 6), order='F')
124  jacobian_other = np.zeros((6, 6), order='F')
125  pose0.slerp(0.5, pose1, jacobian, jacobian_other)
126  jacobian_numerical, jacobian_numerical_other = numerical_derivative_2_poses(pose0, pose1, 'slerp', inputs=[0.5])
127  self.gtsamAssertEquals(jacobian, jacobian_numerical)
128  self.gtsamAssertEquals(jacobian_other, jacobian_numerical_other)
129 
130  def test_transformTo(self):
131  """Test transformTo method."""
132  pose = Pose3(Rot3.Rodrigues(0, 0, -math.pi/2), Point3(2, 4, 0))
133  actual = pose.transformTo(Point3(3, 2, 10))
134  expected = Point3(2, 1, 10)
135  self.gtsamAssertEquals(actual, expected, 1e-6)
136 
137  #test jacobians
138  point = Point3(3, 2, 10)
139  jacobian_pose = np.zeros((3, 6), order='F')
140  jacobian_point = np.zeros((3, 3), order='F')
141  pose.transformTo(point, jacobian_pose, jacobian_point)
142  jacobian_numerical_pose, jacobian_numerical_point = numerical_derivative_pose_point(pose, point, 'transformTo')
143  self.gtsamAssertEquals(jacobian_pose, jacobian_numerical_pose)
144  self.gtsamAssertEquals(jacobian_point, jacobian_numerical_point)
145 
146  # multi-point version
147  points = np.stack([Point3(3, 2, 10), Point3(3, 2, 10)]).T
148  actual_array = pose.transformTo(points)
149  self.assertEqual(actual_array.shape, (3, 2))
150  expected_array = np.stack([expected, expected]).T
151  np.testing.assert_allclose(actual_array, expected_array, atol=1e-6)
152 
154  """Test transformFrom method."""
155  pose = Pose3(Rot3.Rodrigues(0, 0, -math.pi/2), Point3(2, 4, 0))
156  actual = pose.transformFrom(Point3(2, 1, 10))
157  expected = Point3(3, 2, 10)
158  self.gtsamAssertEquals(actual, expected, 1e-6)
159 
160  #test jacobians
161  point = Point3(3, 2, 10)
162  jacobian_pose = np.zeros((3, 6), order='F')
163  jacobian_point = np.zeros((3, 3), order='F')
164  pose.transformFrom(point, jacobian_pose, jacobian_point)
165  jacobian_numerical_pose, jacobian_numerical_point = numerical_derivative_pose_point(pose, point, 'transformFrom')
166  self.gtsamAssertEquals(jacobian_pose, jacobian_numerical_pose)
167  self.gtsamAssertEquals(jacobian_point, jacobian_numerical_point)
168 
169  # multi-point version
170  points = np.stack([Point3(2, 1, 10), Point3(2, 1, 10)]).T
171  actual_array = pose.transformFrom(points)
172  self.assertEqual(actual_array.shape, (3, 2))
173  expected_array = np.stack([expected, expected]).T
174  np.testing.assert_allclose(actual_array, expected_array, atol=1e-6)
175 
176  def test_range(self):
177  """Test range method."""
178  l1 = Point3(1, 0, 0)
179  l2 = Point3(1, 1, 0)
180  x1 = Pose3()
181 
182  xl1 = Pose3(Rot3.Ypr(0.0, 0.0, 0.0), Point3(1, 0, 0))
183  xl2 = Pose3(Rot3.Ypr(0.0, 1.0, 0.0), Point3(1, 1, 0))
184 
185  # establish range is indeed zero
186  self.assertEqual(1, x1.range(point=l1))
187 
188  # establish range is indeed sqrt2
189  self.assertEqual(math.sqrt(2.0), x1.range(point=l2))
190 
191  # establish range is indeed zero
192  self.assertEqual(1, x1.range(pose=xl1))
193 
194  # establish range is indeed sqrt2
195  self.assertEqual(math.sqrt(2.0), x1.range(pose=xl2))
196 
197  def test_adjoint(self):
198  """Test adjoint methods."""
199  T = Pose3()
200  xi = np.array([1, 2, 3, 4, 5, 6])
201  # test calling functions
202  T.AdjointMap()
203  T.Adjoint(xi)
204  T.AdjointTranspose(xi)
205  Pose3.adjointMap(xi)
206  Pose3.adjoint(xi, xi)
207  # test correctness of adjoint(x, y)
208  expected = np.dot(Pose3.adjointMap_(xi), xi)
209  actual = Pose3.adjoint_(xi, xi)
210  np.testing.assert_array_equal(actual, expected)
211 
213  """Test if serialization is working normally"""
214  expected = Pose3(Rot3.Ypr(0.0, 1.0, 0.0), Point3(1, 1, 0))
215  actual = Pose3()
216  serialized = expected.serialize()
217  actual.deserialize(serialized)
218  self.gtsamAssertEquals(expected, actual, 1e-10)
219 
221  """Test if Align method can align 2 squares."""
222  square = np.array([[0,0,0],[0,1,0],[1,1,0],[1,0,0]], float).T
223  sTt = Pose3(Rot3.Rodrigues(0, 0, -math.pi), Point3(2, 4, 0))
224  transformed = sTt.transformTo(square)
225 
226  st_pairs = []
227  for j in range(4):
228  st_pairs.append((square[:,j], transformed[:,j]))
229 
230  # Recover the transformation sTt
231  estimated_sTt = Pose3.Align(st_pairs)
232  self.gtsamAssertEquals(estimated_sTt, sTt, 1e-10)
233 
234  # Matrix version
235  estimated_sTt = Pose3.Align(square, transformed)
236  self.gtsamAssertEquals(estimated_sTt, sTt, 1e-10)
237 
238 
239 if __name__ == "__main__":
240  unittest.main()
def test_adjoint(self)
Definition: test_Pose3.py:197
def test_range(self)
Definition: test_Pose3.py:176
def test_transformTo(self)
Definition: test_Pose3.py:130
def gtsamAssertEquals(self, actual, expected, tol=1e-9)
Definition: test_case.py:18
def test_serialization(self)
Definition: test_Pose3.py:212
def numerical_derivative_pose(pose, method, delta=1e-5)
Definition: test_Pose3.py:22
T compose(const T &t1, const T &t2)
Definition: lieProxies.h:39
def numerical_derivative_2_poses(pose, other_pose, method, delta=1e-5, inputs=())
Definition: test_Pose3.py:35
def test_transformFrom(self)
Definition: test_Pose3.py:153
def numerical_derivative_pose_point(pose, point, method, delta=1e-5)
Definition: test_Pose3.py:54
def test_between(self)
Definition: test_Pose3.py:81
def test_inverse(self)
Definition: test_Pose3.py:97
def test_align_squares(self)
Definition: test_Pose3.py:220
Double_ range(const Point2_ &p, const Point2_ &q)
def test_slerp(self)
Definition: test_Pose3.py:110
Vector3 Point3
Definition: Point3.h:38


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:37:46