se3.py
Go to the documentation of this file.
1 import sympy
2 import sys
3 import unittest
4 import sophus
5 import functools
6 
7 
8 class Se3:
9  """ 3 dimensional group of rigid body transformations """
10 
11  def __init__(self, so3, t):
12  """ internally represented by a unit quaternion q and a translation
13  3-vector """
14  assert isinstance(so3, sophus.So3)
15  assert isinstance(t, sympy.Matrix)
16  assert t.shape == (3, 1), t.shape
17 
18  self.so3 = so3
19  self.t = t
20 
21  @staticmethod
22  def exp(v):
23  """ exponential map """
24  upsilon = v[0:3, :]
25  omega = sophus.Vector3(v[3], v[4], v[5])
26  so3 = sophus.So3.exp(omega)
27  Omega = sophus.So3.hat(omega)
28  Omega_sq = Omega * Omega
29  theta = sympy.sqrt(sophus.squared_norm(omega))
30  V = (sympy.Matrix.eye(3) +
31  (1 - sympy.cos(theta)) / (theta**2) * Omega +
32  (theta - sympy.sin(theta)) / (theta**3) * Omega_sq)
33  return Se3(so3, V * upsilon)
34 
35  def log(self):
36 
37  omega = self.so3.log()
38  theta = sympy.sqrt(sophus.squared_norm(omega))
39  Omega = sophus.So3.hat(omega)
40 
41  half_theta = 0.5 * theta
42 
43  V_inv = sympy.Matrix.eye(3) - 0.5 * Omega + (1 - theta * sympy.cos(
44  half_theta) / (2 * sympy.sin(half_theta))) / (theta * theta) *\
45  (Omega * Omega)
46  upsilon = V_inv * self.t
47  return upsilon.col_join(omega)
48 
49  def __repr__(self):
50  return "Se3: [" + repr(self.so3) + " " + repr(self.t)
51 
52  def inverse(self):
53  invR = self.so3.inverse()
54  return Se3(invR, invR * (-1 * self.t))
55 
56  @staticmethod
57  def hat(v):
58  """ R^6 => R^4x4 """
59  """ returns 4x4-matrix representation ``Omega`` """
60  upsilon = sophus.Vector3(v[0], v[1], v[2])
61  omega = sophus.Vector3(v[3], v[4], v[5])
62  return sophus.So3.hat(omega).\
63  row_join(upsilon).\
64  col_join(sympy.Matrix.zeros(1, 4))
65 
66  @staticmethod
67  def vee(Omega):
68  """ R^4x4 => R^6 """
69  """ returns 6-vector representation of Lie algebra """
70  """ This is the inverse of the hat-operator """
71 
72  head = sophus.Vector3(Omega[0,3], Omega[1,3], Omega[2,3])
73  tail = sophus.So3.vee(Omega[0:3,0:3])
74  upsilon_omega = \
75  sophus.Vector6(head[0], head[1], head[2], tail[0], tail[1], tail[2])
76  return upsilon_omega
77 
78 
79  def matrix(self):
80  """ returns matrix representation """
81  R = self.so3.matrix()
82  return (R.row_join(self.t)).col_join(sympy.Matrix(1, 4, [0, 0, 0, 1]))
83 
84  def __mul__(self, right):
85  """ left-multiplication
86  either rotation concatenation or point-transform """
87  if isinstance(right, sympy.Matrix):
88  assert right.shape == (3, 1), right.shape
89  return self.so3 * right + self.t
90  elif isinstance(right, Se3):
91  r = self.so3 * right.so3
92  t = self.t + self.so3 * right.t
93  return Se3(r, t)
94  assert False, "unsupported type: {0}".format(type(right))
95 
96  def __getitem__(self, key):
97  """ We use the following convention [q0, q1, q2, q3, t0, t1, t2] """
98  assert (key >= 0 and key < 7)
99  if key < 4:
100  return self.so3[key]
101  else:
102  return self.t[key - 4]
103 
104  @staticmethod
106  return sympy.Matrix(7, 6, lambda r, c:
107  sympy.diff(Se3.exp(x)[r], x[c]))
108 
109  @staticmethod
111  return sympy.Matrix([[0.0, 0.0, 0.0, 0.5, 0.0, 0.0],
112  [0.0, 0.0, 0.0, 0.0, 0.5, 0.0],
113  [0.0, 0.0, 0.0, 0.0, 0.0, 0.5],
114  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
115  [1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
116  [0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
117  [0.0, 0.0, 1.0, 0.0, 0.0, 0.0]])
118 
120  v = Se3.exp(x)
121  return sympy.Matrix(7, 6, lambda r, c:
122  sympy.diff((self * Se3.exp(x))[r], x[c])). \
123  subs(x[0], 0).subs(x[1], 0).subs(x[2], 0).\
124  subs(x[3], 0).subs(x[4], 0).limit(x[5], 0)
125 
126  @staticmethod
128  return Se3.calc_Dx_exp_x(x).subs(x[0], 0).subs(x[1], 0).subs(x[2], 0).\
129  subs(x[3], 0).subs(x[4], 0).limit(x[5], 0)
130 
131  @staticmethod
132  def Dxi_x_matrix(x, i):
133  if i < 4:
134  return sophus.So3.Dxi_x_matrix(x, i).\
135  row_join(sympy.Matrix.zeros(3, 1)).\
136  col_join(sympy.Matrix.zeros(1, 4))
137  M = sympy.Matrix.zeros(4, 4)
138  M[i - 4, 3] = 1
139  return M
140 
141  @staticmethod
142  def calc_Dxi_x_matrix(x, i):
143  return sympy.Matrix(4, 4, lambda r, c:
144  sympy.diff(x.matrix()[r, c], x[i]))
145 
146  @staticmethod
147  def Dxi_exp_x_matrix(x, i):
148  T = Se3.exp(x)
149  Dx_exp_x = Se3.calc_Dx_exp_x(x)
150  l = [Dx_exp_x[j, i] * Se3.Dxi_x_matrix(T, j) for j in range(0, 7)]
151  return functools.reduce((lambda a, b: a + b), l)
152 
153  @staticmethod
155  return sympy.Matrix(4, 4, lambda r, c:
156  sympy.diff(Se3.exp(x).matrix()[r, c], x[i]))
157 
158  @staticmethod
160  v = sophus.ZeroVector6()
161  v[i] = 1
162  return Se3.hat(v)
163 
164  @staticmethod
166  return sympy.Matrix(4, 4, lambda r, c:
167  sympy.diff(Se3.exp(x).matrix()[r, c], x[i])
168  ).subs(x[0], 0).subs(x[1], 0).subs(x[2], 0).\
169  subs(x[3], 0).subs(x[4], 0).limit(x[5], 0)
170 
171 
172 class TestSe3(unittest.TestCase):
173  def setUp(self):
174  upsilon0, upsilon1, upsilon2, omega0, omega1, omega2 = sympy.symbols(
175  'upsilon[0], upsilon[1], upsilon[2], omega[0], omega[1], omega[2]',
176  real=True)
177  x, v0, v1, v2 = sympy.symbols('q.w() q.x() q.y() q.z()', real=True)
178  p0, p1, p2 = sympy.symbols('p0 p1 p2', real=True)
179  t0, t1, t2 = sympy.symbols('t[0] t[1] t[2]', real=True)
180  v = sophus.Vector3(v0, v1, v2)
181  self.upsilon_omega = sophus.Vector6(
182  upsilon0, upsilon1, upsilon2, omega0, omega1, omega2)
183  self.t = sophus.Vector3(t0, t1, t2)
184  self.a = Se3(sophus.So3(sophus.Quaternion(x, v)), self.t)
185  self.p = sophus.Vector3(p0, p1, p2)
186 
187  def test_exp_log(self):
188  for v in [sophus.Vector6(0., 1, 0.5, 2., 1, 0.5),
189  sophus.Vector6(0.1, 0.1, 0.1, 0., 1, 0.5),
190  sophus.Vector6(0.01, 0.2, 0.03, 0.01, 0.2, 0.03)]:
191  w = Se3.exp(v).log()
192  for i in range(0, 3):
193  self.assertAlmostEqual(v[i], w[i])
194 
195  def test_matrix(self):
196  T_foo_bar = Se3.exp(self.upsilon_omega)
197  Tmat_foo_bar = T_foo_bar.matrix()
198  point_bar = self.p
199  p1_foo = T_foo_bar * point_bar
200  p2_foo = sophus.proj(Tmat_foo_bar * sophus.unproj(point_bar))
201  self.assertEqual(sympy.simplify(p1_foo - p2_foo),
202  sophus.ZeroVector3())
203 
204  def test_derivatives(self):
205  self.assertEqual(sympy.simplify(
206  Se3.calc_Dx_exp_x_at_0(self.upsilon_omega) -
207  Se3.Dx_exp_x_at_0()),
208  sympy.Matrix.zeros(7, 6))
209 
210  for i in range(0, 7):
211  self.assertEqual(sympy.simplify(Se3.calc_Dxi_x_matrix(self.a, i) -
212  Se3.Dxi_x_matrix(self.a, i)),
213  sympy.Matrix.zeros(4, 4))
214  for i in range(0, 6):
215  self.assertEqual(sympy.simplify(
216  Se3.Dxi_exp_x_matrix(self.upsilon_omega, i) -
217  Se3.calc_Dxi_exp_x_matrix(self.upsilon_omega, i)),
218  sympy.Matrix.zeros(4, 4))
219  self.assertEqual(sympy.simplify(
220  Se3.Dxi_exp_x_matrix_at_0(i) -
221  Se3.calc_Dxi_exp_x_matrix_at_0(self.upsilon_omega, i)),
222  sympy.Matrix.zeros(4, 4))
223 
224  def test_codegen(self):
225  stream = sophus.cse_codegen(self.a.calc_Dx_exp_x(self.upsilon_omega))
226  filename = "cpp_gencode/Se3_Dx_exp_x.cpp"
227  # set to true to generate codegen files
228  if False:
229  file = open(filename, "w")
230  for line in stream:
231  file.write(line)
232  file.close()
233  else:
234  file = open(filename, "r")
235  file_lines = file.readlines()
236  for i, line in enumerate(stream):
237  self.assertEqual(line, file_lines[i])
238  file.close()
239  stream.close
240 
241  stream = sophus.cse_codegen(self.a.calc_Dx_this_mul_exp_x_at_0(
242  self.upsilon_omega))
243  filename = "cpp_gencode/Se3_Dx_this_mul_exp_x_at_0.cpp"
244  # set to true to generate codegen files
245  if False:
246  file = open(filename, "w")
247  for line in stream:
248  file.write(line)
249  file.close()
250  else:
251  file = open(filename, "r")
252  file_lines = file.readlines()
253  for i, line in enumerate(stream):
254  self.assertEqual(line, file_lines[i])
255  file.close()
256  stream.close
257 
258 
259 if __name__ == '__main__':
260  unittest.main()
sophus.se3.Se3.t
t
Definition: se3.py:19
sophus.se3.Se3.so3
so3
Definition: se3.py:18
sophus.se3.Se3.matrix
def matrix(self)
Definition: se3.py:79
sophus.se3.Se3.inverse
def inverse(self)
Definition: se3.py:52
sophus.se3.Se3.calc_Dx_exp_x_at_0
def calc_Dx_exp_x_at_0(x)
Definition: se3.py:127
sophus.se3.Se3.calc_Dx_this_mul_exp_x_at_0
def calc_Dx_this_mul_exp_x_at_0(self, x)
Definition: se3.py:119
sophus.se3.Se3.calc_Dxi_x_matrix
def calc_Dxi_x_matrix(x, i)
Definition: se3.py:142
sophus.se3.Se3.__init__
def __init__(self, so3, t)
Definition: se3.py:11
sophus.so3.So3
Definition: so3.py:8
sophus.se3.Se3.calc_Dx_exp_x
def calc_Dx_exp_x(x)
Definition: se3.py:105
sophus.se3.Se3.__repr__
def __repr__(self)
Definition: se3.py:49
sophus.se3.Se3.log
def log(self)
Definition: se3.py:35
sophus.se3.TestSe3.upsilon_omega
upsilon_omega
Definition: se3.py:181
sophus.se3.TestSe3
Definition: se3.py:172
sophus.se3.Se3.__getitem__
def __getitem__(self, key)
Definition: se3.py:96
sophus.quaternion.Quaternion
Definition: quaternion.py:9
sophus.se3.Se3
Definition: se3.py:8
sophus.se3.Se3.vee
def vee(Omega)
Definition: se3.py:67
sophus.cse_codegen
Definition: cse_codegen.py:1
sophus.se3.TestSe3.test_matrix
def test_matrix(self)
Definition: se3.py:195
sophus.se3.Se3.calc_Dxi_exp_x_matrix_at_0
def calc_Dxi_exp_x_matrix_at_0(x, i)
Definition: se3.py:165
sophus.se3.Se3.exp
def exp(v)
Definition: se3.py:22
sophus.se3.Se3.hat
def hat(v)
Definition: se3.py:57
sophus.se3.TestSe3.test_derivatives
def test_derivatives(self)
Definition: se3.py:204
sophus.se3.TestSe3.test_codegen
def test_codegen(self)
Definition: se3.py:224
sophus.se3.TestSe3.test_exp_log
def test_exp_log(self)
Definition: se3.py:187
sophus.se3.TestSe3.setUp
def setUp(self)
Definition: se3.py:173
sophus.se3.TestSe3.t
t
Definition: se3.py:183
sophus.se3.Se3.Dxi_exp_x_matrix_at_0
def Dxi_exp_x_matrix_at_0(i)
Definition: se3.py:159
sophus.se3.TestSe3.p
p
Definition: se3.py:185
sophus.se3.Se3.Dx_exp_x_at_0
def Dx_exp_x_at_0()
Definition: se3.py:110
sophus.se3.Se3.__mul__
def __mul__(self, right)
Definition: se3.py:84
sophus.se3.Se3.Dxi_exp_x_matrix
def Dxi_exp_x_matrix(x, i)
Definition: se3.py:147
sophus.se3.Se3.Dxi_x_matrix
def Dxi_x_matrix(x, i)
Definition: se3.py:132
sophus.se3.TestSe3.a
a
Definition: se3.py:184
sophus.se3.Se3.calc_Dxi_exp_x_matrix
def calc_Dxi_exp_x_matrix(x, i)
Definition: se3.py:154


sophus
Author(s): Hauke Strasdat
autogenerated on Wed Mar 2 2022 01:01:48