GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
// |
||
2 |
// Copyright (c) 2017-2020 CNRS INRIA |
||
3 |
// |
||
4 |
|||
5 |
#include "pinocchio/multibody/model.hpp" |
||
6 |
#include "pinocchio/multibody/data.hpp" |
||
7 |
#include "pinocchio/algorithm/jacobian.hpp" |
||
8 |
#include "pinocchio/algorithm/joint-configuration.hpp" |
||
9 |
#include "pinocchio/algorithm/kinematics.hpp" |
||
10 |
#include "pinocchio/algorithm/kinematics-derivatives.hpp" |
||
11 |
#include "pinocchio/parsers/sample-models.hpp" |
||
12 |
|||
13 |
#include <iostream> |
||
14 |
|||
15 |
#include <boost/test/unit_test.hpp> |
||
16 |
#include <boost/utility/binary.hpp> |
||
17 |
|||
18 |
BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE) |
||
19 |
|||
20 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
BOOST_AUTO_TEST_CASE(test_kinematics_derivatives_all) |
21 |
{ |
||
22 |
using namespace Eigen; |
||
23 |
using namespace pinocchio; |
||
24 |
|||
25 |
✓✗ | 4 |
Model model; |
26 |
✓✗ | 2 |
buildModels::humanoidRandom(model); |
27 |
|||
28 |
✓✗✓✗ |
4 |
Data data(model), data_ref(model); |
29 |
|||
30 |
✓✗✓✗ |
2 |
model.lowerPositionLimit.head<3>().fill(-1.); |
31 |
✓✗✓✗ |
2 |
model.upperPositionLimit.head<3>().fill(1.); |
32 |
✓✗ | 4 |
VectorXd q = randomConfiguration(model); |
33 |
✓✗✓✗ |
4 |
VectorXd v(VectorXd::Random(model.nv)); |
34 |
✓✗✓✗ |
4 |
VectorXd a(VectorXd::Random(model.nv)); |
35 |
|||
36 |
✓✗ | 2 |
forwardKinematics(model,data_ref,q,v,a); |
37 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data,q,v,a); |
38 |
|||
39 |
✓✓ | 56 |
for(size_t i = 1; i < (size_t)model.njoints; ++i) |
40 |
{ |
||
41 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
54 |
BOOST_CHECK(data.oMi[i].isApprox(data_ref.oMi[i])); |
42 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
54 |
BOOST_CHECK(data.v[i].isApprox(data_ref.v[i])); |
43 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
54 |
BOOST_CHECK(data.ov[i].isApprox(data_ref.oMi[i].act(data_ref.v[i]))); |
44 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
54 |
BOOST_CHECK(data.a[i].isApprox(data_ref.a[i])); |
45 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
54 |
BOOST_CHECK(data.oa[i].isApprox(data_ref.oMi[i].act(data_ref.a[i]))); |
46 |
} |
||
47 |
|||
48 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
49 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(data.J.isApprox(data_ref.J)); |
50 |
|||
51 |
✓✗ | 2 |
computeJointJacobiansTimeVariation(model, data_ref, q, v); |
52 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(data.dJ.isApprox(data_ref.dJ)); |
53 |
2 |
} |
|
54 |
|||
55 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
BOOST_AUTO_TEST_CASE(test_kinematics_derivatives_velocity) |
56 |
{ |
||
57 |
using namespace Eigen; |
||
58 |
using namespace pinocchio; |
||
59 |
|||
60 |
✓✗ | 4 |
Model model; |
61 |
✓✗ | 2 |
buildModels::humanoidRandom(model); |
62 |
|||
63 |
✓✗✓✗ |
4 |
Data data(model), data_ref(model); |
64 |
|||
65 |
✓✗✓✗ |
2 |
model.lowerPositionLimit.head<3>().fill(-1.); |
66 |
✓✗✓✗ |
2 |
model.upperPositionLimit.head<3>().fill(1.); |
67 |
✓✗ | 4 |
VectorXd q = randomConfiguration(model); |
68 |
✓✗✓✗ |
4 |
VectorXd v(VectorXd::Random(model.nv)); |
69 |
✓✗✓✗ |
4 |
VectorXd a(VectorXd::Random(model.nv)); |
70 |
|||
71 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data,q,v,a); |
72 |
|||
73 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗ |
2 |
const Model::JointIndex jointId = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoints-1); |
74 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq(6,model.nv); partial_dq.setZero(); |
75 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq_local_world_aligned(6,model.nv); partial_dq_local_world_aligned.setZero(); |
76 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq_local(6,model.nv); partial_dq_local.setZero(); |
77 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv(6,model.nv); partial_dv.setZero(); |
78 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv_local_world_aligned(6,model.nv); partial_dv_local_world_aligned.setZero(); |
79 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv_local(6,model.nv); partial_dv_local.setZero(); |
80 |
|||
81 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data,jointId,WORLD, |
82 |
partial_dq,partial_dv); |
||
83 |
|||
84 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data,jointId,LOCAL_WORLD_ALIGNED, |
85 |
partial_dq_local_world_aligned,partial_dv_local_world_aligned); |
||
86 |
|||
87 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data,jointId,LOCAL, |
88 |
partial_dq_local,partial_dv_local); |
||
89 |
|||
90 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref(6,model.nv); J_ref.setZero(); |
91 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref_local_world_aligned(6,model.nv); J_ref_local_world_aligned.setZero(); |
92 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref_local(6,model.nv); J_ref_local.setZero(); |
93 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
94 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,WORLD,J_ref); |
95 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,LOCAL_WORLD_ALIGNED,J_ref_local_world_aligned); |
96 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,LOCAL,J_ref_local); |
97 |
|||
98 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv.isApprox(J_ref)); |
99 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv_local_world_aligned.isApprox(J_ref_local_world_aligned)); |
100 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv_local.isApprox(J_ref_local)); |
101 |
|||
102 |
// Check against finite differences |
||
103 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq_fd(6,model.nv); partial_dq_fd.setZero(); |
104 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq_fd_local_world_aligned(6,model.nv); partial_dq_fd_local_world_aligned.setZero(); |
105 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dq_fd_local(6,model.nv); partial_dq_fd_local.setZero(); |
106 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv_fd(6,model.nv); partial_dv_fd.setZero(); |
107 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv_fd_local_world_aligned(6,model.nv); partial_dv_fd_local_world_aligned.setZero(); |
108 |
✓✗✓✗ |
4 |
Data::Matrix6x partial_dv_fd_local(6,model.nv); partial_dv_fd_local.setZero(); |
109 |
2 |
const double alpha = 1e-8; |
|
110 |
|||
111 |
// dvel/dv |
||
112 |
✓✗ | 4 |
Eigen::VectorXd v_plus(v); |
113 |
✓✗ | 4 |
Data data_plus(model); |
114 |
✓✗ | 2 |
forwardKinematics(model,data_ref,q,v); |
115 |
✓✗ | 2 |
SE3 oMi_rot(SE3::Identity()); |
116 |
✓✗✓✗ ✓✗ |
2 |
oMi_rot.rotation() = data_ref.oMi[jointId].rotation(); |
117 |
✓✗ | 2 |
Motion v0(data_ref.oMi[jointId].act(data_ref.v[jointId])); |
118 |
✓✗ | 2 |
Motion v0_local_world_aligned(oMi_rot.act(data_ref.v[jointId])); |
119 |
✓✗ | 2 |
Motion v0_local(data_ref.v[jointId]); |
120 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
121 |
{ |
||
122 |
✓✗ | 64 |
v_plus[k] += alpha; |
123 |
✓✗ | 64 |
forwardKinematics(model,data_plus,q,v_plus); |
124 |
|||
125 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
partial_dv_fd.col(k) = (data_plus.oMi[jointId].act(data_plus.v[jointId]) - v0).toVector()/alpha; |
126 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
partial_dv_fd_local_world_aligned.col(k) = (oMi_rot.act(data_plus.v[jointId]) - v0_local_world_aligned).toVector()/alpha; |
127 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
partial_dv_fd_local.col(k) = (data_plus.v[jointId] - v0_local).toVector()/alpha; |
128 |
✓✗ | 64 |
v_plus[k] -= alpha; |
129 |
} |
||
130 |
|||
131 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv.isApprox(partial_dv_fd,sqrt(alpha))); |
132 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv_local_world_aligned.isApprox(partial_dv_fd_local_world_aligned,sqrt(alpha))); |
133 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dv_local.isApprox(partial_dv_fd_local,sqrt(alpha))); |
134 |
|||
135 |
// dvel/dq |
||
136 |
✓✗✓✗ ✓✗ |
4 |
Eigen::VectorXd q_plus(q), v_eps(Eigen::VectorXd::Zero(model.nv)); |
137 |
✓✗ | 2 |
forwardKinematics(model,data_ref,q,v); |
138 |
✓✗ | 2 |
v0 = data_ref.oMi[jointId].act(data_ref.v[jointId]); |
139 |
|||
140 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
141 |
{ |
||
142 |
✓✗ | 64 |
v_eps[k] += alpha; |
143 |
✓✗ | 64 |
q_plus = integrate(model,q,v_eps); |
144 |
✓✗ | 64 |
forwardKinematics(model,data_plus,q_plus,v); |
145 |
|||
146 |
✓✗ | 64 |
SE3 oMi_plus_rot = data_plus.oMi[jointId]; |
147 |
✓✗✓✗ |
64 |
oMi_plus_rot.translation().setZero(); |
148 |
|||
149 |
✓✗ | 64 |
Motion v_plus_local_world_aligned = oMi_plus_rot.act(data_plus.v[jointId]); |
150 |
✓✗✓✗ ✓✗✓✗ |
64 |
SE3::Vector3 trans = data_plus.oMi[jointId].translation() - data_ref.oMi[jointId].translation(); |
151 |
✓✗✓✗ ✓✗✓✗ |
64 |
v_plus_local_world_aligned.linear() -= v_plus_local_world_aligned.angular().cross(trans); |
152 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
partial_dq_fd.col(k) = (data_plus.oMi[jointId].act(data_plus.v[jointId]) - v0).toVector()/alpha; |
153 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
partial_dq_fd_local_world_aligned.col(k) = (v_plus_local_world_aligned - v0_local_world_aligned).toVector()/alpha; |
154 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
partial_dq_fd_local.col(k) = (data_plus.v[jointId] - v0_local).toVector()/alpha; |
155 |
✓✗ | 64 |
v_eps[k] -= alpha; |
156 |
} |
||
157 |
|||
158 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dq.isApprox(partial_dq_fd,sqrt(alpha))); |
159 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dq_local_world_aligned.isApprox(partial_dq_fd_local_world_aligned,sqrt(alpha))); |
160 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(partial_dq_local.isApprox(partial_dq_fd_local,sqrt(alpha))); |
161 |
|||
162 |
2 |
} |
|
163 |
|||
164 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
BOOST_AUTO_TEST_CASE(test_kinematics_derivatives_acceleration) |
165 |
{ |
||
166 |
using namespace Eigen; |
||
167 |
using namespace pinocchio; |
||
168 |
|||
169 |
✓✗ | 4 |
Model model; |
170 |
✓✗ | 2 |
buildModels::humanoidRandom(model); |
171 |
|||
172 |
✓✗✓✗ |
4 |
Data data(model), data_ref(model); |
173 |
|||
174 |
✓✗✓✗ |
2 |
model.lowerPositionLimit.head<3>().fill(-1.); |
175 |
✓✗✓✗ |
2 |
model.upperPositionLimit.head<3>().fill(1.); |
176 |
✓✗ | 4 |
VectorXd q = randomConfiguration(model); |
177 |
✓✗✓✗ |
4 |
VectorXd v(VectorXd::Random(model.nv)); |
178 |
✓✗✓✗ |
4 |
VectorXd a(VectorXd::Random(model.nv)); |
179 |
|||
180 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data,q,v,a); |
181 |
|||
182 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗ |
2 |
const Model::JointIndex jointId = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoints-1); |
183 |
|||
184 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq(6,model.nv); v_partial_dq.setZero(); |
185 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_local(6,model.nv); v_partial_dq_local.setZero(); |
186 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_local_world_aligned(6,model.nv); v_partial_dq_local_world_aligned.setZero(); |
187 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq(6,model.nv); a_partial_dq.setZero(); |
188 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq_local_world_aligned(6,model.nv); a_partial_dq_local_world_aligned.setZero(); |
189 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq_local(6,model.nv); a_partial_dq_local.setZero(); |
190 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv(6,model.nv); a_partial_dv.setZero(); |
191 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv_local_world_aligned(6,model.nv); a_partial_dv_local_world_aligned.setZero(); |
192 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv_local(6,model.nv); a_partial_dv_local.setZero(); |
193 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da(6,model.nv); a_partial_da.setZero(); |
194 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da_local_world_aligned(6,model.nv); a_partial_da_local_world_aligned.setZero(); |
195 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da_local(6,model.nv); a_partial_da_local.setZero(); |
196 |
|||
197 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,WORLD, |
198 |
v_partial_dq, |
||
199 |
a_partial_dq,a_partial_dv,a_partial_da); |
||
200 |
|||
201 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,LOCAL_WORLD_ALIGNED, |
202 |
v_partial_dq_local_world_aligned, |
||
203 |
a_partial_dq_local_world_aligned, |
||
204 |
a_partial_dv_local_world_aligned, |
||
205 |
a_partial_da_local_world_aligned); |
||
206 |
|||
207 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,LOCAL, |
208 |
v_partial_dq_local, |
||
209 |
a_partial_dq_local,a_partial_dv_local,a_partial_da_local); |
||
210 |
|||
211 |
// Check v_partial_dq against getJointVelocityDerivatives |
||
212 |
{ |
||
213 |
✓✗ | 4 |
Data data_v(model); |
214 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data_v,q,v,a); |
215 |
|||
216 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_ref(6,model.nv); v_partial_dq_ref.setZero(); |
217 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_ref_local_world_aligned(6,model.nv); v_partial_dq_ref_local_world_aligned.setZero(); |
218 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_ref_local(6,model.nv); v_partial_dq_ref_local.setZero(); |
219 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dv_ref(6,model.nv); v_partial_dv_ref.setZero(); |
220 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dv_ref_local_world_aligned(6,model.nv); v_partial_dv_ref_local_world_aligned.setZero(); |
221 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dv_ref_local(6,model.nv); v_partial_dv_ref_local.setZero(); |
222 |
|||
223 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_v,jointId,WORLD, |
224 |
v_partial_dq_ref,v_partial_dv_ref); |
||
225 |
|||
226 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(v_partial_dq.isApprox(v_partial_dq_ref)); |
227 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da.isApprox(v_partial_dv_ref)); |
228 |
|||
229 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_v,jointId,LOCAL_WORLD_ALIGNED, |
230 |
v_partial_dq_ref_local_world_aligned,v_partial_dv_ref_local_world_aligned); |
||
231 |
|||
232 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(v_partial_dq_local_world_aligned.isApprox(v_partial_dq_ref_local_world_aligned)); |
233 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local_world_aligned.isApprox(v_partial_dv_ref_local_world_aligned)); |
234 |
|||
235 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_v,jointId,LOCAL, |
236 |
v_partial_dq_ref_local,v_partial_dv_ref_local); |
||
237 |
|||
238 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(v_partial_dq_local.isApprox(v_partial_dq_ref_local)); |
239 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local.isApprox(v_partial_dv_ref_local)); |
240 |
} |
||
241 |
|||
242 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref(6,model.nv); J_ref.setZero(); |
243 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref_local(6,model.nv); J_ref_local.setZero(); |
244 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref_local_world_aligned(6,model.nv); J_ref_local_world_aligned.setZero(); |
245 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
246 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,WORLD,J_ref); |
247 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,LOCAL_WORLD_ALIGNED,J_ref_local_world_aligned); |
248 |
✓✗ | 2 |
getJointJacobian(model,data_ref,jointId,LOCAL,J_ref_local); |
249 |
|||
250 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da.isApprox(J_ref)); |
251 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local_world_aligned.isApprox(J_ref_local_world_aligned)); |
252 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local.isApprox(J_ref_local)); |
253 |
|||
254 |
// Check against finite differences |
||
255 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da_fd(6,model.nv); a_partial_da_fd.setZero(); |
256 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da_fd_local_world_aligned(6,model.nv); a_partial_da_fd_local_world_aligned.setZero(); |
257 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da_fd_local(6,model.nv); a_partial_da_fd_local.setZero(); |
258 |
2 |
const double alpha = 1e-8; |
|
259 |
|||
260 |
✓✗✓✗ |
4 |
Eigen::VectorXd v_plus(v), a_plus(a); |
261 |
✓✗ | 4 |
Data data_plus(model); |
262 |
✓✗ | 2 |
forwardKinematics(model,data_ref,q,v,a); |
263 |
✓✗ | 2 |
SE3 oMi_rot(SE3::Identity()); |
264 |
✓✗✓✗ ✓✗ |
2 |
oMi_rot.rotation() = data_ref.oMi[jointId].rotation(); |
265 |
|||
266 |
// dacc/da |
||
267 |
✓✗ | 2 |
Motion a0(data_ref.oMi[jointId].act(data_ref.a[jointId])); |
268 |
✓✗ | 2 |
Motion a0_local_world_aligned(oMi_rot.act(data_ref.a[jointId])); |
269 |
✓✗ | 2 |
Motion a0_local(data_ref.a[jointId]); |
270 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
271 |
{ |
||
272 |
✓✗ | 64 |
a_plus[k] += alpha; |
273 |
✓✗ | 64 |
forwardKinematics(model,data_plus,q,v,a_plus); |
274 |
|||
275 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
a_partial_da_fd.col(k) = (data_plus.oMi[jointId].act(data_plus.a[jointId]) - a0).toVector()/alpha; |
276 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
a_partial_da_fd_local_world_aligned.col(k) = (oMi_rot.act(data_plus.a[jointId]) - a0_local_world_aligned).toVector()/alpha; |
277 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
a_partial_da_fd_local.col(k) = (data_plus.a[jointId] - a0_local).toVector()/alpha; |
278 |
✓✗ | 64 |
a_plus[k] -= alpha; |
279 |
} |
||
280 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da.isApprox(a_partial_da_fd,sqrt(alpha))); |
281 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local_world_aligned.isApprox(a_partial_da_fd_local_world_aligned,sqrt(alpha))); |
282 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local.isApprox(a_partial_da_fd_local,sqrt(alpha))); |
283 |
✓✗✓✗ |
2 |
motionSet::se3Action(data_ref.oMi[jointId].inverse(),a_partial_da,a_partial_da_local); |
284 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_da_local.isApprox(a_partial_da_fd_local,sqrt(alpha))); |
285 |
|||
286 |
// dacc/dv |
||
287 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv_fd(6,model.nv); a_partial_dv_fd.setZero(); |
288 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv_fd_local_world_aligned(6,model.nv); a_partial_dv_fd_local_world_aligned.setZero(); |
289 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv_fd_local(6,model.nv); a_partial_dv_fd_local.setZero(); |
290 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
291 |
{ |
||
292 |
✓✗ | 64 |
v_plus[k] += alpha; |
293 |
✓✗ | 64 |
forwardKinematics(model,data_plus,q,v_plus,a); |
294 |
|||
295 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
a_partial_dv_fd.col(k) = (data_plus.oMi[jointId].act(data_plus.a[jointId]) - a0).toVector()/alpha; a_partial_dv_fd_local_world_aligned.col(k) = (oMi_rot.act(data_plus.a[jointId]) - a0_local_world_aligned).toVector()/alpha; |
296 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
a_partial_dv_fd_local.col(k) = (data_plus.a[jointId] - a0_local).toVector()/alpha; |
297 |
✓✗ | 64 |
v_plus[k] -= alpha; |
298 |
} |
||
299 |
|||
300 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dv.isApprox(a_partial_dv_fd,sqrt(alpha))); |
301 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dv_local_world_aligned.isApprox(a_partial_dv_fd_local_world_aligned,sqrt(alpha))); |
302 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dv_local.isApprox(a_partial_dv_fd_local,sqrt(alpha))); |
303 |
✓✗✓✗ |
2 |
motionSet::se3Action(data_ref.oMi[jointId].inverse(),a_partial_dv,a_partial_dv_local); |
304 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dv_local.isApprox(a_partial_dv_fd_local,sqrt(alpha))); |
305 |
|||
306 |
// dacc/dq |
||
307 |
✓✗ | 2 |
a_partial_dq.setZero(); |
308 |
✓✗ | 2 |
a_partial_dv.setZero(); |
309 |
✓✗ | 2 |
a_partial_da.setZero(); |
310 |
|||
311 |
✓✗ | 2 |
a_partial_dq_local_world_aligned.setZero(); |
312 |
✓✗ | 2 |
a_partial_dv_local_world_aligned.setZero(); |
313 |
✓✗ | 2 |
a_partial_da_local_world_aligned.setZero(); |
314 |
|||
315 |
✓✗ | 2 |
a_partial_dq_local.setZero(); |
316 |
✓✗ | 2 |
a_partial_dv_local.setZero(); |
317 |
✓✗ | 2 |
a_partial_da_local.setZero(); |
318 |
|||
319 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq_fd(6,model.nv); a_partial_dq_fd.setZero(); |
320 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq_fd_local_world_aligned(6,model.nv); a_partial_dq_fd_local_world_aligned.setZero(); |
321 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq_fd_local(6,model.nv); a_partial_dq_fd_local.setZero(); |
322 |
|||
323 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data,q,v,a); |
324 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,WORLD, |
325 |
v_partial_dq, |
||
326 |
a_partial_dq,a_partial_dv,a_partial_da); |
||
327 |
|||
328 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,LOCAL_WORLD_ALIGNED, |
329 |
v_partial_dq_local_world_aligned, |
||
330 |
a_partial_dq_local_world_aligned, |
||
331 |
a_partial_dv_local_world_aligned, |
||
332 |
a_partial_da_local_world_aligned); |
||
333 |
|||
334 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,LOCAL, |
335 |
v_partial_dq_local, |
||
336 |
a_partial_dq_local,a_partial_dv_local,a_partial_da_local); |
||
337 |
|||
338 |
✓✗✓✗ ✓✗ |
4 |
Eigen::VectorXd q_plus(q), v_eps(Eigen::VectorXd::Zero(model.nv)); |
339 |
✓✗ | 2 |
forwardKinematics(model,data_ref,q,v,a); |
340 |
✓✗ | 2 |
a0 = data_ref.oMi[jointId].act(data_ref.a[jointId]); |
341 |
✓✗✓✗ ✓✗ |
2 |
oMi_rot.rotation() = data_ref.oMi[jointId].rotation(); |
342 |
✓✗ | 2 |
a0_local_world_aligned = oMi_rot.act(data_ref.a[jointId]); |
343 |
✓✗ | 2 |
a0_local = data_ref.a[jointId]; |
344 |
|||
345 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
346 |
{ |
||
347 |
✓✗ | 64 |
v_eps[k] += alpha; |
348 |
✓✗ | 64 |
q_plus = integrate(model,q,v_eps); |
349 |
✓✗ | 64 |
forwardKinematics(model,data_plus,q_plus,v,a); |
350 |
|||
351 |
✓✗ | 64 |
SE3 oMi_plus_rot = data_plus.oMi[jointId]; |
352 |
✓✗✓✗ |
64 |
oMi_plus_rot.translation().setZero(); |
353 |
|||
354 |
✓✗ | 64 |
Motion a_plus_local_world_aligned = oMi_plus_rot.act(data_plus.a[jointId]); |
355 |
✓✗✓✗ ✓✗✓✗ |
64 |
const SE3::Vector3 trans = data_plus.oMi[jointId].translation() - data_ref.oMi[jointId].translation(); |
356 |
✓✗✓✗ ✓✗✓✗ |
64 |
a_plus_local_world_aligned.linear() -= a_plus_local_world_aligned.angular().cross(trans); |
357 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
a_partial_dq_fd.col(k) = (data_plus.oMi[jointId].act(data_plus.a[jointId]) - a0).toVector()/alpha; |
358 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
a_partial_dq_fd_local_world_aligned.col(k) = (a_plus_local_world_aligned - a0_local_world_aligned).toVector()/alpha; |
359 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
a_partial_dq_fd_local.col(k) = (data_plus.a[jointId] - a0_local).toVector()/alpha; |
360 |
✓✗ | 64 |
v_eps[k] -= alpha; |
361 |
} |
||
362 |
|||
363 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dq.isApprox(a_partial_dq_fd,sqrt(alpha))); |
364 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dq_local_world_aligned.isApprox(a_partial_dq_fd_local_world_aligned,sqrt(alpha))); |
365 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dq_local.isApprox(a_partial_dq_fd_local,sqrt(alpha))); |
366 |
|||
367 |
2 |
} |
|
368 |
|||
369 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
BOOST_AUTO_TEST_CASE(test_kinematics_derivatives_against_classic_formula) |
370 |
{ |
||
371 |
using namespace Eigen; |
||
372 |
using namespace pinocchio; |
||
373 |
|||
374 |
✓✗ | 4 |
Model model; |
375 |
✓✗ | 2 |
buildModels::humanoidRandom(model,true); |
376 |
|||
377 |
✓✗✓✗ |
4 |
Data data(model), data_ref(model); |
378 |
|||
379 |
✓✗✓✗ |
2 |
model.lowerPositionLimit.head<3>().fill(-1.); |
380 |
✓✗✓✗ |
2 |
model.upperPositionLimit.head<3>().fill(1.); |
381 |
✓✗ | 4 |
VectorXd q = randomConfiguration(model); |
382 |
✓✗✓✗ |
4 |
VectorXd v(VectorXd::Random(model.nv)); |
383 |
✓✗✓✗ |
4 |
VectorXd a(VectorXd::Random(model.nv)); |
384 |
|||
385 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗ |
2 |
const Model::JointIndex jointId = model.existJointName("rarm4_joint")?model.getJointId("rarm4_joint"):(Model::Index)(model.njoints-1); |
386 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq(6,model.nv); v_partial_dq.setZero(); |
387 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_ref(6,model.nv); v_partial_dq_ref.setZero(); |
388 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dv_ref(6,model.nv); v_partial_dv_ref.setZero(); |
389 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dq(6,model.nv); a_partial_dq.setZero(); |
390 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_dv(6,model.nv); a_partial_dv.setZero(); |
391 |
✓✗✓✗ |
4 |
Data::Matrix6x a_partial_da(6,model.nv); a_partial_da.setZero(); |
392 |
|||
393 |
// LOCAL: da/dv == dJ/dt + dv/dq |
||
394 |
// { |
||
395 |
// Data::Matrix6x rhs(6,model.nv); rhs.setZero(); |
||
396 |
// |
||
397 |
// v_partial_dq.setZero(); |
||
398 |
// a_partial_dq.setZero(); |
||
399 |
// a_partial_dv.setZero(); |
||
400 |
// a_partial_da.setZero(); |
||
401 |
// |
||
402 |
// computeForwardKinematicsDerivatives(model,data_ref,q,v,a); |
||
403 |
// computeForwardKinematicsDerivatives(model,data,q,v,a); |
||
404 |
// |
||
405 |
// getJointAccelerationDerivatives<LOCAL>(model,data,jointId, |
||
406 |
// v_partial_dq, |
||
407 |
// a_partial_dq,a_partial_dv,a_partial_da); |
||
408 |
// |
||
409 |
// getJointJacobianTimeVariation<LOCAL>(model,data_ref,jointId,rhs); |
||
410 |
// |
||
411 |
// v_partial_dq_ref.setZero(); v_partial_dv_ref.setZero(); |
||
412 |
// getJointVelocityDerivatives<LOCAL>(model,data_ref,jointId, |
||
413 |
// v_partial_dq_ref,v_partial_dv_ref); |
||
414 |
// rhs += v_partial_dq_ref; |
||
415 |
// BOOST_CHECK(a_partial_dv.isApprox(rhs,1e-12)); |
||
416 |
// |
||
417 |
// std::cout << "a_partial_dv\n" << a_partial_dv << std::endl; |
||
418 |
// std::cout << "rhs\n" << rhs << std::endl; |
||
419 |
// } |
||
420 |
|||
421 |
// WORLD: da/dv == dJ/dt + dv/dq |
||
422 |
{ |
||
423 |
✓✗✓✗ |
4 |
Data::Matrix6x rhs(6,model.nv); rhs.setZero(); |
424 |
|||
425 |
✓✗ | 2 |
v_partial_dq.setZero(); |
426 |
✓✗ | 2 |
a_partial_dq.setZero(); |
427 |
✓✗ | 2 |
a_partial_dv.setZero(); |
428 |
✓✗ | 2 |
a_partial_da.setZero(); |
429 |
|||
430 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data_ref,q,v,a); |
431 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data,q,v,a); |
432 |
|||
433 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data,jointId,WORLD, |
434 |
v_partial_dq, |
||
435 |
a_partial_dq,a_partial_dv,a_partial_da); |
||
436 |
|||
437 |
✓✗ | 2 |
getJointJacobianTimeVariation(model,data_ref,jointId,WORLD,rhs); |
438 |
|||
439 |
✓✗✓✗ |
2 |
v_partial_dq_ref.setZero(); v_partial_dv_ref.setZero(); |
440 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_ref,jointId,WORLD, |
441 |
v_partial_dq_ref,v_partial_dv_ref); |
||
442 |
✓✗ | 2 |
rhs += v_partial_dq_ref; |
443 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dv.isApprox(rhs,1e-12)); |
444 |
|||
445 |
// std::cout << "a_partial_dv\n" << a_partial_dv << std::endl; |
||
446 |
// std::cout << "rhs\n" << rhs << std::endl; |
||
447 |
} |
||
448 |
|||
449 |
// // WORLD: da/dq == d/dt(dv/dq) |
||
450 |
// { |
||
451 |
// const double alpha = 1e-8; |
||
452 |
// Eigen::VectorXd q_plus(model.nq), v_plus(model.nv); |
||
453 |
// |
||
454 |
// Data data_plus(model); |
||
455 |
// v_plus = v + alpha * a; |
||
456 |
// q_plus = integrate(model,q,alpha*v); |
||
457 |
// |
||
458 |
// computeForwardKinematicsDerivatives(model,data_plus,q_plus,v_plus,a); |
||
459 |
// computeForwardKinematicsDerivatives(model,data_ref,q,v,a); |
||
460 |
// |
||
461 |
// Data::Matrix6x v_partial_dq_plus(6,model.nv); v_partial_dq_plus.setZero(); |
||
462 |
// Data::Matrix6x v_partial_dv_plus(6,model.nv); v_partial_dv_plus.setZero(); |
||
463 |
// |
||
464 |
// v_partial_dq_ref.setZero(); v_partial_dv_ref.setZero(); |
||
465 |
// |
||
466 |
// v_partial_dq.setZero(); |
||
467 |
// a_partial_dq.setZero(); |
||
468 |
// a_partial_dv.setZero(); |
||
469 |
// a_partial_da.setZero(); |
||
470 |
// |
||
471 |
// getJointVelocityDerivatives<WORLD>(model,data_ref,jointId, |
||
472 |
// v_partial_dq_ref,v_partial_dv_ref); |
||
473 |
// getJointVelocityDerivatives<WORLD>(model,data_plus,jointId, |
||
474 |
// v_partial_dq_plus,v_partial_dv_plus); |
||
475 |
// |
||
476 |
// getJointAccelerationDerivatives<WORLD>(model,data_ref,jointId, |
||
477 |
// v_partial_dq, |
||
478 |
// a_partial_dq,a_partial_dv,a_partial_da); |
||
479 |
// |
||
480 |
// Data::Matrix6x a_partial_dq_fd(6,model.nv); a_partial_dq_fd.setZero(); |
||
481 |
// { |
||
482 |
// Data data_fd(model); |
||
483 |
// VectorXd q_fd(model.nq), v_eps(model.nv); v_eps.setZero(); |
||
484 |
// for(int k = 0; k < model.nv; ++k) |
||
485 |
// { |
||
486 |
// v_eps[k] += alpha; |
||
487 |
// q_fd = integrate(model,q,v_eps); |
||
488 |
// forwardKinematics(model,data_fd,q_fd,v,a); |
||
489 |
// a_partial_dq_fd.col(k) = (data_fd.oMi[jointId].act(data_fd.a[jointId]) - data_ref.oa[jointId]).toVector()/alpha; |
||
490 |
// v_eps[k] = 0.; |
||
491 |
// } |
||
492 |
// } |
||
493 |
// |
||
494 |
// Data::Matrix6x rhs = (v_partial_dq_plus - v_partial_dq_ref)/alpha; |
||
495 |
// BOOST_CHECK(a_partial_dq.isApprox(rhs,sqrt(alpha))); |
||
496 |
// |
||
497 |
// std::cout << "a_partial_dq\n" << a_partial_dq << std::endl; |
||
498 |
// std::cout << "a_partial_dq_fd\n" << a_partial_dq_fd << std::endl; |
||
499 |
// std::cout << "rhs\n" << rhs << std::endl; |
||
500 |
// } |
||
501 |
|||
502 |
// LOCAL: da/dq == d/dt(dv/dq) |
||
503 |
{ |
||
504 |
2 |
const double alpha = 1e-8; |
|
505 |
✓✗✓✗ |
4 |
Eigen::VectorXd q_plus(model.nq), v_plus(model.nv); |
506 |
|||
507 |
✓✗ | 4 |
Data data_plus(model); |
508 |
✓✗✓✗ ✓✗ |
2 |
v_plus = v + alpha * a; |
509 |
✓✗✓✗ |
2 |
q_plus = integrate(model,q,alpha*v); |
510 |
|||
511 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data_plus,q_plus,v_plus,a); |
512 |
✓✗ | 2 |
computeForwardKinematicsDerivatives(model,data_ref,q,v,a); |
513 |
|||
514 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dq_plus(6,model.nv); v_partial_dq_plus.setZero(); |
515 |
✓✗✓✗ |
4 |
Data::Matrix6x v_partial_dv_plus(6,model.nv); v_partial_dv_plus.setZero(); |
516 |
|||
517 |
✓✗✓✗ |
2 |
v_partial_dq_ref.setZero(); v_partial_dv_ref.setZero(); |
518 |
|||
519 |
✓✗ | 2 |
v_partial_dq.setZero(); |
520 |
✓✗ | 2 |
a_partial_dq.setZero(); |
521 |
✓✗ | 2 |
a_partial_dv.setZero(); |
522 |
✓✗ | 2 |
a_partial_da.setZero(); |
523 |
|||
524 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_ref,jointId,LOCAL, |
525 |
v_partial_dq_ref,v_partial_dv_ref); |
||
526 |
✓✗ | 2 |
getJointVelocityDerivatives(model,data_plus,jointId,LOCAL, |
527 |
v_partial_dq_plus,v_partial_dv_plus); |
||
528 |
|||
529 |
✓✗ | 2 |
getJointAccelerationDerivatives(model,data_ref,jointId,LOCAL, |
530 |
v_partial_dq, |
||
531 |
a_partial_dq,a_partial_dv,a_partial_da); |
||
532 |
|||
533 |
✓✗✓✗ ✓✗ |
4 |
Data::Matrix6x rhs = (v_partial_dq_plus - v_partial_dq_ref)/alpha; |
534 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(a_partial_dq.isApprox(rhs,sqrt(alpha))); |
535 |
|||
536 |
// std::cout << "a_partial_dq\n" << a_partial_dq << std::endl; |
||
537 |
// std::cout << "rhs\n" << rhs << std::endl; |
||
538 |
} |
||
539 |
|||
540 |
|||
541 |
2 |
} |
|
542 |
|||
543 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
BOOST_AUTO_TEST_CASE(test_kinematics_hessians) |
544 |
{ |
||
545 |
using namespace Eigen; |
||
546 |
using namespace pinocchio; |
||
547 |
|||
548 |
✓✗ | 4 |
Model model; |
549 |
✓✗ | 2 |
buildModels::humanoidRandom(model,true); |
550 |
|||
551 |
✓✗✓✗ ✓✗ |
4 |
Data data(model), data_ref(model), data_plus(model); |
552 |
|||
553 |
✓✗✓✗ |
2 |
model.lowerPositionLimit.head<3>().fill(-1.); |
554 |
✓✗✓✗ |
2 |
model.upperPositionLimit.head<3>().fill(1.); |
555 |
✓✗ | 4 |
VectorXd q = randomConfiguration(model); |
556 |
|||
557 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗ |
2 |
const Model::JointIndex joint_id = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoints-1); |
558 |
|||
559 |
✓✗ | 2 |
computeJointJacobians(model,data,q); |
560 |
✓✗ | 2 |
computeJointKinematicHessians(model,data); |
561 |
|||
562 |
✓✗ | 4 |
Data data2(model); |
563 |
✓✗ | 2 |
computeJointKinematicHessians(model,data2,q); |
564 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
2 |
BOOST_CHECK(data2.J.isApprox(data.J)); |
565 |
|||
566 |
2 |
const Eigen::DenseIndex matrix_offset = 6 * model.nv; |
|
567 |
|||
568 |
✓✓ | 66 |
for(int k = 0; k < model.nv; ++k) |
569 |
{ |
||
570 |
✓✗✓✗ ✓✗ |
64 |
Eigen::Map<Data::Matrix6x> dJ(data.kinematic_hessians.data() + k*matrix_offset,6,model.nv); |
571 |
✓✗✓✗ ✓✗ |
64 |
Eigen::Map<Data::Matrix6x> dJ2(data2.kinematic_hessians.data() + k*matrix_offset,6,model.nv); |
572 |
|||
573 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
64 |
BOOST_CHECK(dJ2.isApprox(dJ)); |
574 |
} |
||
575 |
|||
576 |
✓✓ | 66 |
for(int i = 0; i < model.nv; ++i) |
577 |
{ |
||
578 |
✓✓ | 1120 |
for(int j = i; j < model.nv; ++j) |
579 |
{ |
||
580 |
1056 |
bool j_is_children_of_i = false; |
|
581 |
✓✓ | 8896 |
for(int parent = j; parent >= 0; parent = data.parents_fromRow[(size_t)parent]) |
582 |
{ |
||
583 |
✓✓ | 8416 |
if(parent == i) |
584 |
{ |
||
585 |
576 |
j_is_children_of_i = true; |
|
586 |
576 |
break; |
|
587 |
} |
||
588 |
} |
||
589 |
|||
590 |
✓✓ | 1056 |
if(j_is_children_of_i) |
591 |
{ |
||
592 |
✓✓ | 576 |
if(i==j) |
593 |
{ |
||
594 |
✓✗ | 64 |
Eigen::Map<Data::Motion::Vector6> SixSi( data.kinematic_hessians.data() |
595 |
64 |
+ i * matrix_offset |
|
596 |
✓✗✓✗ |
128 |
+ i * 6); |
597 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
64 |
BOOST_CHECK(SixSi.isZero()); |
598 |
} |
||
599 |
else |
||
600 |
{ |
||
601 |
✓✗ | 512 |
Eigen::Map<Data::Motion::Vector6> SixSj( data.kinematic_hessians.data() |
602 |
512 |
+ i * matrix_offset |
|
603 |
✓✗✓✗ |
1024 |
+ j * 6); |
604 |
|||
605 |
✓✗ | 512 |
Eigen::Map<Data::Motion::Vector6> SjxSi( data.kinematic_hessians.data() |
606 |
512 |
+ j * matrix_offset |
|
607 |
✓✗✓✗ |
1024 |
+ i * 6); |
608 |
|||
609 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
512 |
BOOST_CHECK(SixSj.isApprox(-SjxSi)); |
610 |
} |
||
611 |
} |
||
612 |
else |
||
613 |
{ |
||
614 |
✓✗ | 480 |
Eigen::Map<Data::Motion::Vector6> SixSj( data.kinematic_hessians.data() |
615 |
480 |
+ i * matrix_offset |
|
616 |
✓✗✓✗ |
960 |
+ j * 6); |
617 |
|||
618 |
✓✗ | 480 |
Eigen::Map<Data::Motion::Vector6> SjxSi( data.kinematic_hessians.data() |
619 |
480 |
+ j * matrix_offset |
|
620 |
✓✗✓✗ |
960 |
+ i * 6); |
621 |
|||
622 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
480 |
BOOST_CHECK(SixSj.isZero()); |
623 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
480 |
BOOST_CHECK(SjxSi.isZero()); |
624 |
} |
||
625 |
} |
||
626 |
} |
||
627 |
|||
628 |
2 |
const double eps = 1e-8; |
|
629 |
✓✗✓✗ |
4 |
Data::Matrix6x J_ref(6,model.nv), J_plus(6,model.nv); |
630 |
✓✗✓✗ |
2 |
J_ref.setZero(); J_plus.setZero(); |
631 |
|||
632 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
633 |
✓✗✓✗ |
4 |
VectorXd v_plus(VectorXd::Zero(model.nv)); |
634 |
|||
635 |
2 |
const Eigen::DenseIndex outer_offset = model.nv * 6; |
|
636 |
|||
637 |
// WORLD |
||
638 |
✓✗ | 2 |
getJointJacobian(model,data_ref,joint_id,WORLD,J_ref); |
639 |
✓✗ | 4 |
Data::Tensor3x kinematic_hessian_world = getJointKinematicHessian(model,data,joint_id,WORLD); |
640 |
✓✓ | 66 |
for(Eigen::DenseIndex k = 0; k < model.nv; ++k) |
641 |
{ |
||
642 |
✓✗ | 64 |
v_plus[k] = eps; |
643 |
✓✗ | 128 |
const VectorXd q_plus = integrate(model,q,v_plus); |
644 |
✓✗ | 64 |
computeJointJacobians(model,data_plus,q_plus); |
645 |
✓✗ | 64 |
J_plus.setZero(); |
646 |
✓✗ | 64 |
getJointJacobian(model,data_plus,joint_id,WORLD,J_plus); |
647 |
|||
648 |
✓✗✓✗ ✓✗ |
64 |
Data::Matrix6x dJ_dq_ref = (J_plus - J_ref)/eps; |
649 |
✓✗✓✗ ✓✗ |
64 |
Eigen::Map<Data::Matrix6x> dJ_dq(kinematic_hessian_world.data() + k * outer_offset,6,model.nv); |
650 |
|||
651 |
// std::cout << "k: " << k << std::endl; |
||
652 |
// std::cout << "dJ_dq:\n" << dJ_dq << std::endl; |
||
653 |
// std::cout << "dJ_dq_ref:\n" << dJ_dq_ref << std::endl; |
||
654 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
64 |
BOOST_CHECK((dJ_dq_ref-dJ_dq).isZero(sqrt(eps))); |
655 |
✓✗ | 64 |
v_plus[k] = 0.; |
656 |
} |
||
657 |
|||
658 |
// LOCAL_WORLD_ALIGNED |
||
659 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
660 |
✓✗ | 2 |
getJointJacobian(model,data_ref,joint_id,LOCAL_WORLD_ALIGNED,J_ref); |
661 |
✓✗ | 4 |
Data::Tensor3x kinematic_hessian_local_world_aligned = getJointKinematicHessian(model,data,joint_id,LOCAL_WORLD_ALIGNED); |
662 |
✓✗ | 4 |
Data::Matrix3x dt_last_fd(3,model.nv); |
663 |
✓✓ | 66 |
for(Eigen::DenseIndex k = 0; k < model.nv; ++k) |
664 |
{ |
||
665 |
✓✗ | 64 |
v_plus[k] = eps; |
666 |
✓✗ | 128 |
const VectorXd q_plus = integrate(model,q,v_plus); |
667 |
✓✗ | 64 |
computeJointJacobians(model,data_plus,q_plus); |
668 |
✓✗ | 64 |
J_plus.setZero(); |
669 |
✓✗ | 64 |
getJointJacobian(model,data_plus,joint_id,LOCAL_WORLD_ALIGNED,J_plus); |
670 |
|||
671 |
✓✗✓✗ |
64 |
SE3 tMt_plus = data_ref.oMi[joint_id].inverse() * data_plus.oMi[joint_id]; |
672 |
✓✗✓✗ |
64 |
tMt_plus.rotation().setIdentity(); |
673 |
|||
674 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
64 |
dt_last_fd.col(k) = (data_plus.oMi[joint_id].translation() - data_ref.oMi[joint_id].translation())/eps; |
675 |
|||
676 |
✓✗✓✗ ✓✗ |
64 |
Data::Matrix6x dJ_dq_ref = (J_plus - J_ref)/eps; |
677 |
✓✗✓✗ ✓✗ |
64 |
Eigen::Map<Data::Matrix6x> dJ_dq(kinematic_hessian_local_world_aligned.data() + k * outer_offset,6,model.nv); |
678 |
|||
679 |
// std::cout << "k: " << k << std::endl; |
||
680 |
// std::cout << "dJ_dq:\n" << dJ_dq << std::endl; |
||
681 |
// std::cout << "dJ_dq_ref:\n" << dJ_dq_ref << std::endl; |
||
682 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
64 |
BOOST_CHECK((dJ_dq_ref-dJ_dq).isZero(sqrt(eps))); |
683 |
✓✗ | 64 |
v_plus[k] = 0.; |
684 |
} |
||
685 |
|||
686 |
✓✗✓✗ |
4 |
Data::Matrix6x J_world(6,model.nv); J_world.setZero(); |
687 |
✓✗ | 2 |
getJointJacobian(model,data_ref,joint_id,LOCAL_WORLD_ALIGNED,J_world); |
688 |
|||
689 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
2 |
BOOST_CHECK(dt_last_fd.isApprox(J_world.topRows<3>(),sqrt(eps))); |
690 |
|||
691 |
// LOCAL |
||
692 |
✓✗ | 2 |
computeJointJacobians(model,data_ref,q); |
693 |
✓✗ | 2 |
getJointJacobian(model,data_ref,joint_id,LOCAL,J_ref); |
694 |
✓✗ | 4 |
Data::Tensor3x kinematic_hessian_local = getJointKinematicHessian(model,data,joint_id,LOCAL); |
695 |
✓✓ | 66 |
for(Eigen::DenseIndex k = 0; k < model.nv; ++k) |
696 |
{ |
||
697 |
✓✗ | 64 |
v_plus[k] = eps; |
698 |
✓✗ | 128 |
const VectorXd q_plus = integrate(model,q,v_plus); |
699 |
✓✗ | 64 |
computeJointJacobians(model,data_plus,q_plus); |
700 |
✓✗ | 64 |
J_plus.setZero(); |
701 |
✓✗ | 64 |
getJointJacobian(model,data_plus,joint_id,LOCAL,J_plus); |
702 |
|||
703 |
// const SE3 tMt_plus = data_ref.oMi[joint_id].inverse() * data_plus.oMi[joint_id]; |
||
704 |
|||
705 |
✓✗✓✗ ✓✗ |
64 |
Data::Matrix6x dJ_dq_ref = (J_plus - J_ref)/eps; |
706 |
✓✗✓✗ ✓✗ |
64 |
Eigen::Map<Data::Matrix6x> dJ_dq(kinematic_hessian_local.data() + k * outer_offset,6,model.nv); |
707 |
|||
708 |
// std::cout << "k: " << k << std::endl; |
||
709 |
// std::cout << "dJ_dq:\n" << dJ_dq << std::endl; |
||
710 |
// std::cout << "dJ_dq_ref:\n" << dJ_dq_ref << std::endl; |
||
711 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
64 |
BOOST_CHECK((dJ_dq_ref-dJ_dq).isZero(sqrt(eps))); |
712 |
✓✗ | 64 |
v_plus[k] = 0.; |
713 |
} |
||
714 |
2 |
} |
|
715 |
|||
716 |
BOOST_AUTO_TEST_SUITE_END() |
Generated by: GCOVR (Version 4.2) |