bindings_explog.py
Go to the documentation of this file.
1 import unittest
2 import sys, os
3 
4 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5 
6 from test_case import PinocchioTestCase as TestCase
7 
8 import pinocchio as pin
9 import pinocchio.casadi as cpin
10 
11 import casadi
12 from casadi import SX
13 import numpy as np
14 
15 
16 class TestLogExpDerivatives(TestCase):
17  def setUp(self) -> None:
18  self.cR0 = SX.sym("R0", 3, 3)
19  self.cR1 = SX.sym("R1", 3, 3)
20  self.dv0 = SX.sym("v0", 3)
21  self.dv1 = SX.sym("v1", 3)
22  self.v_all = casadi.vertcat(self.dv0, self.dv1)
23  self.cv2 = SX.sym("v2", 3)
24  self.cdv2 = SX.sym("dv", 3) # for forming the difference
25 
26  self.cR0_i = self.cR0 @ cpin.exp3(self.dv0)
27  self.cR1_i = self.cR1 @ cpin.exp3(self.dv1)
28 
29  # SE(3) examples
30  self.cM0 = SX.sym("M0", 4, 4)
31  self.cM1 = SX.sym("M1", 4, 4)
32  self.cdw0 = SX.sym("dm0", 6)
33  self.cdw1 = SX.sym("dm1", 6)
34  self.cw2 = SX.sym("w2", 6)
35  self.cdw2 = SX.sym("dw2", 6)
36  self.cM0_i = cpin.SE3(self.cM0) * cpin.exp6(self.cdw0)
37  self.cM1_i = cpin.SE3(self.cM1) * cpin.exp6(self.cdw1)
38 
39  def test_exp3(self):
40  """Test the exp map and its derivative."""
41  dw = self.cdv2
42  exp_expr = self.cR0_i @ cpin.exp3(self.cv2 + dw)
43  repl_dargs = lambda e: casadi.substitute(
44  e, casadi.vertcat(self.dv0, dw), np.zeros(6)
45  )
46 
47  exp_eval = casadi.Function("exp", [self.cR0, self.cv2], [repl_dargs(exp_expr)])
48 
49  diff_expr = cpin.log3(exp_eval(self.cR0, self.cv2).T @ exp_expr)
50  Jexp_expr = casadi.jacobian(diff_expr, casadi.vertcat(self.dv0, dw))
51  Jexp_eval = casadi.Function(
52  "exp", [self.cR0, self.cv2], [repl_dargs(Jexp_expr)]
53  )
54 
55  w0 = np.zeros(3)
56  w1 = np.random.randn(3)
57  w2 = np.array([np.pi, 0, 0])
58  w3 = np.array([-np.pi, 0, 0])
59  R0 = pin.exp3(w0) # eye(3)
60  R1 = pin.exp3(w1)
61  R2 = pin.exp3(w2)
62  R3 = pin.exp3(w3)
63  self.assertApprox(exp_eval(R0, np.zeros(3)).full(), R0)
64  self.assertApprox(exp_eval(R0, w1).full(), R1)
65  self.assertApprox(exp_eval(R0, -w1).full(), R1.T)
66  self.assertApprox(exp_eval(R1, -w1).full(), R0)
67  self.assertApprox(exp_eval(R0, w2).full(), R2)
68 
69  J0 = pin.Jexp3(w0)
70  J1 = pin.Jexp3(w1)
71  J2 = pin.Jexp3(w2)
72  J3 = pin.Jexp3(w3)
73  # print(J0)
74  # print(Jexp_eval(R0, np.zeros(3)))
75  # print(J1)
76  # print(Jexp_eval(R0, w1))
77  # print("R1:", R1)
78  # print(Jexp_eval(R1, w1))
79  # print(Jexp_eval(R2, w1))
80  self.assertApprox(Jexp_eval(R0, w0).full(), np.hstack([R0.T, J0]))
81  self.assertApprox(Jexp_eval(R0, w1).full(), np.hstack([R1.T, J1]))
82  self.assertApprox(Jexp_eval(R0, w2).full(), np.hstack([R2.T, J2]))
83  self.assertApprox(Jexp_eval(R0, w3).full(), np.hstack([R3.T, J3]))
84  self.assertApprox(Jexp_eval(R1, w0).full(), np.hstack([R0.T, J0]))
85  self.assertApprox(Jexp_eval(R1, w2).full(), np.hstack([R2.T, J2]))
86 
87  def test_log3(self):
88  log_expr = cpin.log3(self.cR0_i.T @ self.cR1_i)
89  log_eval = casadi.Function(
90  "log",
91  [self.cR0, self.cR1],
92  [casadi.substitute(log_expr, self.v_all, np.zeros(6))],
93  )
94 
95  Jlog_expr = casadi.jacobian(log_expr, self.v_all)
96  Jlog_eval = casadi.Function(
97  "Jlog",
98  [self.cR0, self.cR1],
99  [casadi.substitute(Jlog_expr, self.v_all, np.zeros(6))],
100  )
101 
102  R0 = np.eye(3)
103  vr = np.random.randn(3)
104  R1 = pin.exp3(vr)
105  R2 = pin.exp3(np.array([np.pi, 0, 0]))
106  v3 = np.array([0, np.pi, 0])
107  R3 = pin.exp3(v3)
108 
109  self.assertApprox(log_eval(R0, R0).full().squeeze(), np.zeros(3))
110  self.assertApprox(log_eval(R0, R1).full().squeeze(), vr)
111  self.assertApprox(log_eval(R1, R1).full().squeeze(), np.zeros(3))
112  self.assertApprox(log_eval(R0, R2).full().squeeze(), np.array([np.pi, 0, 0]))
113  self.assertApprox(log_eval(R0, R3).full().squeeze(), v3)
114 
115  J0 = pin.Jlog3(R0)
116  jac_identity = np.hstack([-J0, J0])
117  self.assertApprox(Jlog_eval(R0, R0).full(), jac_identity)
118 
119  J1 = pin.Jlog3(R1)
120  self.assertApprox(Jlog_eval(R0, R1).full(), np.hstack([-R1.T @ J1, J1]))
121 
122  J2 = pin.Jlog3(R2)
123  self.assertApprox(Jlog_eval(R0, R2).full(), np.hstack([-R2.T @ J2, J2]))
124 
125  def test_log3_quat(self):
126  cquat = SX.sym("quat", 4)
127  cdv = SX.sym("dv", 3)
128  SO3 = cpin.liegroups.SO3()
129  repl_dargs = lambda e: casadi.substitute(e, cdv, np.zeros(3))
130 
131  cquat_i = SO3.integrate(cquat, cdv)
132 
133  clog = cpin.log3(cquat_i)
134  cJlog = casadi.jacobian(clog, cdv)
135  clog_eval = casadi.Function("log", [cquat], [repl_dargs(clog)])
136  cJlog_eval = casadi.Function("Jlog", [cquat], [repl_dargs(cJlog)])
137 
138  q0 = np.array([0.0, 0.0, 0.0, 1.0])
139  q1 = np.array([0.0, 1.0, 0.0, 0.0])
140  q2 = np.array([0.0, 0.0, 1.0, 0.0])
141  q3 = np.array([1.0, 0.0, 0.0, 0.0])
142 
143  self.assertApprox(clog_eval(q0).full().squeeze(), np.zeros(3))
144  self.assertApprox(cJlog_eval(q0).full().squeeze(), np.eye(3))
145 
146  clog_fun = casadi.dot(clog, clog)
147  cJlog_fun = casadi.jacobian(clog_fun, cdv)
148  clog_fun_eval = casadi.Function("normlog", [cquat], [repl_dargs(clog_fun)])
149  cJlog_fun_eval = casadi.Function("Jnormlog", [cquat], [repl_dargs(cJlog_fun)])
150 
151  self.assertApprox(clog_fun_eval(q0).full().squeeze(), np.zeros(1))
152  self.assertApprox(cJlog_fun_eval(q0).full(), np.zeros(3))
153 
154  self.assertApprox(
155  cJlog_fun_eval(q1).full(), 2 * np.pi * np.array([0.0, 1.0, 0.0])
156  )
157  self.assertApprox(
158  cJlog_fun_eval(q2).full(), 2 * np.pi * np.array([0.0, 0.0, 1.0])
159  )
160  self.assertApprox(
161  cJlog_fun_eval(q3).full(), 2 * np.pi * np.array([1.0, 0.0, 0.0])
162  )
163  print("log3 quat done")
164 
165  def test_exp6(self):
166  exp_expr = cpin.exp6(self.cw2 + self.cdw2)
167  repl_dargs = lambda e: casadi.substitute(e, self.cdw2, np.zeros(6))
168 
169  exp_eval = casadi.Function("exp6", [self.cw2], [repl_dargs(exp_expr.np)])
170 
171  diff_expr = cpin.log6(cpin.SE3(exp_eval(self.cw2)).actInv(exp_expr)).np
172  Jexp_expr = casadi.jacobian(diff_expr, self.cdw2)
173 
174  Jexp_eval = casadi.Function("exp6", [self.cw2], [repl_dargs(Jexp_expr)])
175 
176  w0 = np.zeros(6)
177  w1 = np.array([0.0, 0.0, 0.0, np.pi, 0.0, 0.0])
178  w2 = np.random.randn(6)
179  w3 = np.array([0.0, 0.0, 0.0, np.pi / 2, 0.0, 0.0])
180  M0 = pin.exp6(w0)
181  M1 = pin.exp6(w1)
182  M2 = pin.exp6(w2)
183  M3 = pin.exp6(w3)
184  self.assertApprox(exp_eval(w0).full(), M0.np)
185  self.assertApprox(exp_eval(w1).full(), M1.np)
186  self.assertApprox(exp_eval(w2).full(), M2.np)
187  self.assertApprox(exp_eval(w3).full(), M3.np)
188 
189  np.set_printoptions(precision=3)
190  J0 = pin.Jexp6(w0)
191  self.assertApprox(Jexp_eval(w0).full(), J0)
192  J1 = pin.Jexp6(w1)
193  self.assertApprox(Jexp_eval(w1).full(), J1)
194  J2 = pin.Jexp6(w2)
195  self.assertApprox(Jexp_eval(w2).full(), J2)
196 
197  def test_log6(self):
198  log_expr = cpin.log6(self.cM0_i.actInv(self.cM1_i))
199 
200  repl_dargs = lambda e: casadi.substitute(
201  e, casadi.vertcat(self.cdw0, self.cdw1), np.zeros(12)
202  )
203  log_eval = casadi.Function(
204  "log6", [self.cM0, self.cM1], [repl_dargs(log_expr.np)]
205  )
206 
207  Jlog_expr = casadi.jacobian(log_expr.np, casadi.vertcat(self.cdw0, self.cdw1))
208  Jlog_eval = casadi.Function(
209  "Jlog6", [self.cM0, self.cM1], [repl_dargs(Jlog_expr)]
210  )
211 
212  w0 = np.zeros(6)
213  M0 = pin.exp6(np.zeros(6))
214  w1 = np.array([0, 0, 0, np.pi, 0.0, 0.0])
215  M1 = pin.exp6(w1)
216  w2 = np.random.randn(6)
217  M2 = pin.exp6(w2)
218 
219  self.assertApprox(log_eval(M0.np, M0.np).full(), w0)
220  self.assertApprox(log_eval(M1.np, M1.np).full(), w0)
221  self.assertApprox(log_eval(M0.np, M1.np).full(), w1)
222  self.assertApprox(log_eval(M0.np, M2.np).full(), w2)
223 
224  J0 = pin.Jlog6(M0)
225  J1 = pin.Jlog6(M1)
226  J2 = pin.Jlog6(M2)
227  self.assertApprox(Jlog_eval(M0.np, M0.np).full(), np.hstack([-J0, J0]))
228  self.assertApprox(
229  Jlog_eval(M0.np, M1.np).full(), np.hstack([-M1.dualAction.T @ J1, J1])
230  )
231  self.assertApprox(
232  Jlog_eval(M0.np, M2.np).full(), np.hstack([-M2.dualAction.T @ J2, J2])
233  )
234 
235  def test_log6_quat(self):
236  cq0 = SX.sym("q0", 7)
237  cv0 = SX.sym("q0", 6)
238  repl_dargs = lambda e: casadi.substitute(e, cv0, np.zeros(6))
239  SE3 = cpin.liegroups.SE3()
240 
241  cq0_i = SE3.integrate(cq0, cv0)
242  clog = cpin.log6_quat(cq0_i).vector
243  clog_eval = casadi.Function("log", [cq0], [repl_dargs(clog)])
244 
245  cJlog = casadi.jacobian(clog, cv0)
246  cJlog_eval = casadi.Function("Jlog", [cq0], [repl_dargs(cJlog)])
247 
248  q0 = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0])
249  q1 = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0])
250  q2 = np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0])
251  q3 = np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0])
252  self.assertApprox(clog_eval(q0).full().squeeze(), np.zeros(6))
253  self.assertApprox(cJlog_eval(q0).full(), np.eye(6))
254 
255  print("log6 with quats")
256  print(clog_eval(q1).full())
257  print(cJlog_eval(q1).full())
258 
259  clog_fun = casadi.dot(clog, clog)
260  clog_fun = casadi.dot(clog, clog)
261  cJlog_fun = casadi.jacobian(clog_fun, cv0)
262  clog_fun_eval = casadi.Function("normlog", [cq0], [repl_dargs(clog_fun)])
263  cJlog_fun_eval = casadi.Function("Jnormlog", [cq0], [repl_dargs(cJlog_fun)])
264 
265  print(clog_fun_eval(q0).full().squeeze())
266  print(cJlog_fun_eval(q0).full())
267 
268  print(clog_fun_eval(q1).full().squeeze())
269  print(cJlog_fun_eval(q1).full())
270 
271  print(clog_fun_eval(q2).full().squeeze())
272  print(cJlog_fun_eval(q2).full())
273 
274  print(clog_fun_eval(q3).full().squeeze())
275  print(cJlog_fun_eval(q3).full())
276 
277 
278 if __name__ == "__main__":
279  unittest.main()
bindings_explog.TestLogExpDerivatives.cR0
cR0
Definition: bindings_explog.py:18
bindings_explog.TestLogExpDerivatives.cR1
cR1
Definition: bindings_explog.py:19
bindings_explog.TestLogExpDerivatives.test_exp3
def test_exp3(self)
Definition: bindings_explog.py:39
bindings_explog.TestLogExpDerivatives.test_log3
def test_log3(self)
Definition: bindings_explog.py:87
bindings_explog.TestLogExpDerivatives.cM1
cM1
Definition: bindings_explog.py:31
bindings_explog.TestLogExpDerivatives.v_all
v_all
Definition: bindings_explog.py:22
pinocchio.casadi
Definition: bindings/python/pinocchio/casadi/__init__.py:1
bindings_explog.TestLogExpDerivatives.cw2
cw2
Definition: bindings_explog.py:34
bindings_explog.TestLogExpDerivatives.test_log3_quat
def test_log3_quat(self)
Definition: bindings_explog.py:125
bindings_explog.TestLogExpDerivatives.cdv2
cdv2
Definition: bindings_explog.py:24
bindings_explog.TestLogExpDerivatives.cR0_i
cR0_i
Definition: bindings_explog.py:26
bindings_explog.TestLogExpDerivatives.test_exp6
def test_exp6(self)
Definition: bindings_explog.py:165
bindings_explog.TestLogExpDerivatives.setUp
None setUp(self)
Definition: bindings_explog.py:17
bindings_explog.TestLogExpDerivatives.cv2
cv2
Definition: bindings_explog.py:23
bindings_explog.TestLogExpDerivatives.cdw0
cdw0
Definition: bindings_explog.py:32
bindings_explog.TestLogExpDerivatives.cM0
cM0
Definition: bindings_explog.py:30
bindings_explog.TestLogExpDerivatives.dv0
dv0
Definition: bindings_explog.py:20
bindings_explog.TestLogExpDerivatives.cdw1
cdw1
Definition: bindings_explog.py:33
bindings_explog.TestLogExpDerivatives.dv1
dv1
Definition: bindings_explog.py:21
bindings_explog.TestLogExpDerivatives.test_log6
def test_log6(self)
Definition: bindings_explog.py:197
bindings_explog.TestLogExpDerivatives.test_log6_quat
def test_log6_quat(self)
Definition: bindings_explog.py:235
bindings_explog.TestLogExpDerivatives.cM1_i
cM1_i
Definition: bindings_explog.py:37
bindings_explog.TestLogExpDerivatives.cdw2
cdw2
Definition: bindings_explog.py:35
bindings_explog.TestLogExpDerivatives
Definition: bindings_explog.py:16
bindings_explog.TestLogExpDerivatives.cM0_i
cM0_i
Definition: bindings_explog.py:36
bindings_explog.TestLogExpDerivatives.cR1_i
cR1_i
Definition: bindings_explog.py:27


pinocchio
Author(s):
autogenerated on Tue Jun 25 2024 02:42:34