9 """ 3 dimensional group of orthogonal matrices with determinant 1 """
12 """ internally represented by a unit quaternion q """
17 """ exponential map """
18 theta_sq = sophus.squared_norm(v)
19 theta = sympy.sqrt(theta_sq)
22 sympy.cos(0.5 * theta),
23 sympy.sin(0.5 * theta) / theta * v))
26 """ logarithmic map"""
27 n = sympy.sqrt(sophus.squared_norm(self.
q.vec))
28 return 2 * sympy.atan(n / self.
q.real) / n * self.
q.vec
31 return "So3:" + repr(self.
q)
34 return So3(self.
q.conj())
38 return sympy.Matrix([[0, -o[2], o[1]],
44 It takes the 3x3-matrix representation ``Omega`` and maps it to the
45 corresponding vector representation of Lie algebra.
47 This is the inverse of the hat-operator, see above.
49 Precondition: ``Omega`` must have the following structure:
57 v = sophus.Vector3(Omega.row(2).col(1), Omega.row(0).col(2), Omega.row(1).col(0))
61 """ returns matrix representation """
62 return sympy.Matrix([[
63 1 - 2 * self.
q.vec[1]**2 - 2 * self.
q.vec[2]**2,
64 2 * self.
q.vec[0] * self.
q.vec[1] -
65 2 * self.
q.vec[2] * self.
q[3],
66 2 * self.
q.vec[0] * self.
q.vec[2] +
67 2 * self.
q.vec[1] * self.
q[3]
69 2 * self.
q.vec[0] * self.
q.vec[1] +
70 2 * self.
q.vec[2] * self.
q[3],
71 1 - 2 * self.
q.vec[0]**2 - 2 * self.
q.vec[2]**2,
72 2 * self.
q.vec[1] * self.
q.vec[2] -
73 2 * self.
q.vec[0] * self.
q[3]
75 2 * self.
q.vec[0] * self.
q.vec[2] -
76 2 * self.
q.vec[1] * self.
q[3],
77 2 * self.
q.vec[1] * self.
q.vec[2] +
78 2 * self.
q.vec[0] * self.
q[3],
79 1 - 2 * self.
q.vec[0]**2 - 2 * self.
q.vec[1]**2
83 """ left-multiplication
84 either rotation concatenation or point-transform """
85 if isinstance(right, sympy.Matrix):
86 assert right.shape == (3, 1), right.shape
88 elif isinstance(right, So3):
89 return So3(self.
q * right.q)
90 assert False,
"unsupported type: {0}".format(type(right))
97 return sympy.Matrix(4, 3,
lambda r, c:
98 sympy.diff(So3.exp(x)[r], x[c]))
102 return sympy.Matrix([[0.5, 0.0, 0.0],
109 return So3.calc_Dx_exp_x(x).subs(x[0], 0).subs(x[1], 0).limit(x[2], 0)
112 return sympy.Matrix(4, 3,
lambda r, c:
113 sympy.diff((self * So3.exp(x))[r], x[c]))\
114 .subs(x[0], 0).subs(x[1], 0).limit(x[2], 0)
117 return sympy.Matrix(3, 4,
lambda r, c:
118 sympy.diff((self * So3.exp(x))[c], x[r, 0]))\
119 .subs(x[0], 0).subs(x[1], 0).limit(x[2], 0)
124 return sympy.Matrix([[0, 2 * x[1], 2 * x[2]],
125 [2 * x[1], -4 * x[0], -2 * x[3]],
126 [2 * x[2], 2 * x[3], -4 * x[0]]])
128 return sympy.Matrix([[-4 * x[1], 2 * x[0], 2 * x[3]],
129 [2 * x[0], 0, 2 * x[2]],
130 [-2 * x[3], 2 * x[2], -4 * x[1]]])
132 return sympy.Matrix([[-4 * x[2], -2 * x[3], 2 * x[0]],
133 [2 * x[3], -4 * x[2], 2 * x[1]],
134 [2 * x[0], 2 * x[1], 0]])
136 return sympy.Matrix([[0, -2 * x[2], 2 * x[1]],
137 [2 * x[2], 0, -2 * x[0]],
138 [-2 * x[1], 2 * x[0], 0]])
142 return sympy.Matrix(3, 3,
lambda r, c:
143 sympy.diff(x.matrix()[r, c], x[i]))
148 Dx_exp_x = So3.calc_Dx_exp_x(x)
149 l = [Dx_exp_x[j, i] * So3.Dxi_x_matrix(R, j)
for j
in [0, 1, 2, 3]]
150 return functools.reduce((
lambda a, b: a + b), l)
154 return sympy.Matrix(3, 3,
lambda r, c:
155 sympy.diff(So3.exp(x).
matrix()[r, c], x[i]))
159 v = sophus.ZeroVector3()
165 return sympy.Matrix(3, 3,
lambda r, c:
166 sympy.diff(So3.exp(x).
matrix()[r, c], x[i])
167 ).subs(x[0], 0).subs(x[1], 0).limit(x[2], 0)
172 omega0, omega1, omega2 = sympy.symbols(
173 'omega[0], omega[1], omega[2]', real=
True)
174 x, v0, v1, v2 = sympy.symbols(
'q.w() q.x() q.y() q.z()', real=
True)
175 p0, p1, p2 = sympy.symbols(
'p0 p1 p2', real=
True)
176 v = sophus.Vector3(v0, v1, v2)
177 self.
omega = sophus.Vector3(omega0, omega1, omega2)
179 self.
p = sophus.Vector3(p0, p1, p2)
182 for o
in [sophus.Vector3(0., 1, 0.5),
183 sophus.Vector3(0.1, 0.1, 0.1),
184 sophus.Vector3(0.01, 0.2, 0.03)]:
186 for i
in range(0, 3):
187 self.assertAlmostEqual(o[i], w[i])
190 R_foo_bar = So3.exp(self.
omega)
191 Rmat_foo_bar = R_foo_bar.matrix()
193 p1_foo = R_foo_bar * point_bar
194 p2_foo = Rmat_foo_bar * point_bar
195 self.assertEqual(sympy.simplify(p1_foo - p2_foo),
196 sophus.ZeroVector3())
199 self.assertEqual(sympy.simplify(So3.calc_Dx_exp_x_at_0(self.
omega) -
200 So3.Dx_exp_x_at_0()),
201 sympy.Matrix.zeros(4, 3))
203 for i
in [0, 1, 2, 3]:
204 self.assertEqual(sympy.simplify(So3.calc_Dxi_x_matrix(self.
a, i) -
205 So3.Dxi_x_matrix(self.
a, i)),
206 sympy.Matrix.zeros(3, 3))
208 self.assertEqual(sympy.simplify(
209 So3.Dxi_exp_x_matrix(self.
omega, i) -
210 So3.calc_Dxi_exp_x_matrix(self.
omega, i)),
211 sympy.Matrix.zeros(3, 3))
212 self.assertEqual(sympy.simplify(
213 So3.Dxi_exp_x_matrix_at_0(i) -
214 So3.calc_Dxi_exp_x_matrix_at_0(self.
omega, i)),
215 sympy.Matrix.zeros(3, 3))
219 filename =
"cpp_gencode/So3_Dx_exp_x.cpp"
222 file = open(filename,
"w")
227 file = open(filename,
"r")
228 file_lines = file.readlines()
229 for i, line
in enumerate(stream):
230 self.assertEqual(line, file_lines[i])
235 self.
a.calc_Dx_this_mul_exp_x_at_0(self.
omega))
236 filename =
"cpp_gencode/So3_Dx_this_mul_exp_x_at_0.cpp"
239 file = open(filename,
"w")
244 file = open(filename,
"r")
245 file_lines = file.readlines()
246 for i, line
in enumerate(stream):
247 self.assertEqual(line, file_lines[i])
252 if __name__ ==
'__main__':