GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: unittest/rpy.cpp Lines: 186 186 100.0 %
Date: 2024-04-26 13:14:21 Branches: 762 1518 50.2 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2019-2020 INRIA
3
//
4
5
#include <pinocchio/math/rpy.hpp>
6
#include <pinocchio/math/quaternion.hpp>
7
#include <pinocchio/spatial/skew.hpp>
8
9
#include <boost/variant.hpp> // to avoid C99 warnings
10
11
#include <boost/test/unit_test.hpp>
12
#include <boost/utility/binary.hpp>
13
14
BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
15
16
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
4
BOOST_AUTO_TEST_CASE(test_rpyToMatrix)
17
{
18
2
  double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
19
2
  double p = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/M_PI)) - (M_PI/2);
20
2
  double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
21
22
✓✗
2
  Eigen::Matrix3d R = pinocchio::rpy::rpyToMatrix(r, p, y);
23
24
✓✗✓✗
2
  Eigen::Matrix3d Raa = (Eigen::AngleAxisd(y, Eigen::Vector3d::UnitZ())
25
✓✗✓✗
✓✗
4
                            * Eigen::AngleAxisd(p, Eigen::Vector3d::UnitY())
26
✓✗✓✗
✓✗
6
                            * Eigen::AngleAxisd(r, Eigen::Vector3d::UnitX())
27
✓✗
2
                            ).toRotationMatrix();
28
29
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(R.isApprox(Raa));
30
31
✓✗
2
  Eigen::Vector3d v;
32
✓✗✓✗
✓✗
2
  v << r, p, y;
33
34
✓✗
2
  Eigen::Matrix3d Rv = pinocchio::rpy::rpyToMatrix(v);
35
36
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(Rv.isApprox(Raa));
37
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(Rv.isApprox(R));
38
2
}
39
40
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
4
BOOST_AUTO_TEST_CASE(test_matrixToRpy)
41
{
42
  #ifdef NDEBUG
43
    const int n = 1e5;
44
  #else
45
2
    const int n = 1e2;
46
  #endif
47
✓✓
202
  for(int k = 0; k < n ; ++k)
48
  {
49
✓✗
200
    Eigen::Quaterniond quat;
50
✓✗
200
    pinocchio::quaternion::uniformRandom(quat);
51
✓✗
200
    const Eigen::Matrix3d R = quat.toRotationMatrix();
52
53
✓✗
200
    const Eigen::Vector3d v = pinocchio::rpy::matrixToRpy(R);
54
✓✗
200
    Eigen::Matrix3d Rprime = pinocchio::rpy::rpyToMatrix(v);
55
56
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
200
    BOOST_CHECK(Rprime.isApprox(R));
57
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[0] && v[0] <= M_PI);
58
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI/2 <= v[1] && v[1] <= M_PI/2);
59
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[2] && v[2] <= M_PI);
60
  }
61
62
#ifdef NDEBUG
63
  const int n2 = 1e3;
64
#else
65
2
  const int n2 = 1e2;
66
#endif
67
68
  // Test singular case theta = pi/2
69
✓✓
202
  for(int k = 0; k < n2 ; ++k)
70
  {
71
200
    double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
72
200
    double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
73
✓✗
200
    Eigen::Matrix3d Rp;
74
✓✗✓✗
✓✗
200
    Rp <<  0.0, 0.0, 1.0,
75
✓✗✓✗
✓✗
200
           0.0, 1.0, 0.0,
76
✓✗✓✗
✓✗
200
          -1.0, 0.0, 0.0;
77
✓✗✓✗
✓✗
200
    const Eigen::Matrix3d R = Eigen::AngleAxisd(y, Eigen::Vector3d::UnitZ()).toRotationMatrix()
78
✓✗
200
                            * Rp
79
✓✗✓✗
✓✗✓✗
✓✗
400
                            * Eigen::AngleAxisd(r, Eigen::Vector3d::UnitX()).toRotationMatrix();
80
81
✓✗
200
    const Eigen::Vector3d v = pinocchio::rpy::matrixToRpy(R);
82
✓✗
200
    Eigen::Matrix3d Rprime = pinocchio::rpy::rpyToMatrix(v);
83
84
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
200
    BOOST_CHECK(Rprime.isApprox(R));
85
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[0] && v[0] <= M_PI);
86
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI/2 <= v[1] && v[1] <= M_PI/2);
87
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[2] && v[2] <= M_PI);
88
  }
89
90
  // Test singular case theta = -pi/2
91
✓✓
202
  for(int k = 0; k < n2 ; ++k)
92
  {
93
200
    double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
94
200
    double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
95
✓✗
200
    Eigen::Matrix3d Rp;
96
✓✗✓✗
✓✗
200
    Rp << 0.0, 0.0, -1.0,
97
✓✗✓✗
✓✗
200
          0.0, 1.0,  0.0,
98
✓✗✓✗
✓✗
200
          1.0, 0.0,  0.0;
99
✓✗✓✗
✓✗
200
    const Eigen::Matrix3d R = Eigen::AngleAxisd(y, Eigen::Vector3d::UnitZ()).toRotationMatrix()
100
✓✗
200
                            * Rp
101
✓✗✓✗
✓✗✓✗
✓✗
400
                            * Eigen::AngleAxisd(r, Eigen::Vector3d::UnitX()).toRotationMatrix();
102
103
✓✗
200
    const Eigen::Vector3d v = pinocchio::rpy::matrixToRpy(R);
104
✓✗
200
    Eigen::Matrix3d Rprime = pinocchio::rpy::rpyToMatrix(v);
105
106
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
200
    BOOST_CHECK(Rprime.isApprox(R));
107
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[0] && v[0] <= M_PI);
108
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI/2 <= v[1] && v[1] <= M_PI/2);
109
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
200
    BOOST_CHECK(-M_PI <= v[2] && v[2] <= M_PI);
110
  }
111
2
}
112
113
114
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
4
BOOST_AUTO_TEST_CASE(test_computeRpyJacobian)
115
{
116
  // Check identity at zero
117
✓✗✓✗
2
  Eigen::Vector3d rpy(Eigen::Vector3d::Zero());
118
✓✗
2
  Eigen::Matrix3d j0 = pinocchio::rpy::computeRpyJacobian(rpy);
119
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(j0.isIdentity());
120
✓✗
2
  Eigen::Matrix3d jL = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL);
121
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(jL.isIdentity());
122
✓✗
2
  Eigen::Matrix3d jW = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::WORLD);
123
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(jW.isIdentity());
124
✓✗
2
  Eigen::Matrix3d jA = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL_WORLD_ALIGNED);
125
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(jA.isIdentity());
126
127
  // Check correct identities between different versions
128
2
  double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
129
2
  double p = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/M_PI)) - (M_PI/2);
130
2
  double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
131
✓✗
2
  rpy = Eigen::Vector3d(r, p, y);
132
✓✗
2
  Eigen::Matrix3d R = pinocchio::rpy::rpyToMatrix(rpy);
133
✓✗
2
  j0 = pinocchio::rpy::computeRpyJacobian(rpy);
134
✓✗
2
  jL = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL);
135
✓✗
2
  jW = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::WORLD);
136
✓✗
2
  jA = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL_WORLD_ALIGNED);
137
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(j0 == jL);
138
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(jW == jA);
139
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jW.isApprox(R*jL));
140
141
  // Check against analytical formulas
142
✓✗✓✗
2
  Eigen::Vector3d jL0Expected = Eigen::Vector3d::UnitX();
143
✓✗✓✗
✓✗✓✗
✓✗✓✗
2
  Eigen::Vector3d jL1Expected = Eigen::AngleAxisd(r, Eigen::Vector3d::UnitX()).toRotationMatrix().transpose().col(1);
144
✓✗✓✗
2
  Eigen::Vector3d jL2Expected = (Eigen::AngleAxisd(p, Eigen::Vector3d::UnitY())
145
✓✗✓✗
✓✗
4
                               * Eigen::AngleAxisd(r, Eigen::Vector3d::UnitX())
146
✓✗✓✗
✓✗✓✗
2
                                ).toRotationMatrix().transpose().col(2);
147
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jL.col(0).isApprox(jL0Expected));
148
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jL.col(1).isApprox(jL1Expected));
149
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jL.col(2).isApprox(jL2Expected));
150
151
✓✗✓✗
2
  Eigen::Vector3d jW0Expected = (Eigen::AngleAxisd(y, Eigen::Vector3d::UnitZ())
152
✓✗✓✗
✓✗
4
                               * Eigen::AngleAxisd(p, Eigen::Vector3d::UnitY())
153
✓✗✓✗
✓✗
2
                                ).toRotationMatrix().col(0);
154
✓✗✓✗
✓✗✓✗
✓✗
2
  Eigen::Vector3d jW1Expected = Eigen::AngleAxisd(y, Eigen::Vector3d::UnitZ()).toRotationMatrix().col(1);
155
✓✗✓✗
2
  Eigen::Vector3d jW2Expected = Eigen::Vector3d::UnitZ();
156
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jW.col(0).isApprox(jW0Expected));
157
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jW.col(1).isApprox(jW1Expected));
158
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jW.col(2).isApprox(jW2Expected));
159
160
  // Check against finite differences
161
✓✗✓✗
2
  Eigen::Vector3d rpydot = Eigen::Vector3d::Random();
162
2
  double const eps = 1e-7;
163
2
  double const tol = 1e-5;
164
165
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d dRdr = (pinocchio::rpy::rpyToMatrix(r + eps, p, y) - R) / eps;
166
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d dRdp = (pinocchio::rpy::rpyToMatrix(r, p + eps, y) - R) / eps;
167
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d dRdy = (pinocchio::rpy::rpyToMatrix(r, p, y + eps) - R) / eps;
168
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
2
  Eigen::Matrix3d Rdot = dRdr * rpydot[0] + dRdp * rpydot[1] + dRdy * rpydot[2];
169
170
✓✗✓✗
2
  Eigen::Vector3d omegaL = jL * rpydot;
171
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(Rdot.isApprox(R * pinocchio::skew(omegaL), tol));
172
173
✓✗✓✗
2
  Eigen::Vector3d omegaW = jW * rpydot;
174
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(Rdot.isApprox(pinocchio::skew(omegaW) * R, tol));
175
2
}
176
177
178
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
4
BOOST_AUTO_TEST_CASE(test_computeRpyJacobianInverse)
179
{
180
  // Check correct identities between different versions
181
2
  double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
182
2
  double p = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/M_PI)) - (M_PI/2);
183
2
  p *= 0.999; // ensure we are not too close to a singularity
184
2
  double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
185
✓✗
2
  Eigen::Vector3d rpy(r, p, y);
186
187
✓✗
2
  Eigen::Matrix3d j0 = pinocchio::rpy::computeRpyJacobian(rpy);
188
✓✗
2
  Eigen::Matrix3d j0inv = pinocchio::rpy::computeRpyJacobianInverse(rpy);
189
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(j0inv.isApprox(j0.inverse()));
190
191
✓✗
2
  Eigen::Matrix3d jL = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL);
192
✓✗
2
  Eigen::Matrix3d jLinv = pinocchio::rpy::computeRpyJacobianInverse(rpy, pinocchio::LOCAL);
193
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jLinv.isApprox(jL.inverse()));
194
195
✓✗
2
  Eigen::Matrix3d jW = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::WORLD);
196
✓✗
2
  Eigen::Matrix3d jWinv = pinocchio::rpy::computeRpyJacobianInverse(rpy, pinocchio::WORLD);
197
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jWinv.isApprox(jW.inverse()));
198
199
✓✗
2
  Eigen::Matrix3d jA = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL_WORLD_ALIGNED);
200
✓✗
2
  Eigen::Matrix3d jAinv = pinocchio::rpy::computeRpyJacobianInverse(rpy, pinocchio::LOCAL_WORLD_ALIGNED);
201
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(jAinv.isApprox(jA.inverse()));
202
2
}
203
204
205
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
4
BOOST_AUTO_TEST_CASE(test_computeRpyJacobianTimeDerivative)
206
{
207
  // Check zero at zero velocity
208
2
  double r = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
209
2
  double p = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/M_PI)) - (M_PI/2);
210
2
  double y = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/(2*M_PI))) - M_PI;
211
✓✗
2
  Eigen::Vector3d rpy(r, p, y);
212
✓✗✓✗
2
  Eigen::Vector3d rpydot(Eigen::Vector3d::Zero());
213
✓✗
2
  Eigen::Matrix3d dj0 = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot);
214
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(dj0.isZero());
215
✓✗
2
  Eigen::Matrix3d djL = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::LOCAL);
216
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djL.isZero());
217
✓✗
2
  Eigen::Matrix3d djW = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::WORLD);
218
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djW.isZero());
219
✓✗
2
  Eigen::Matrix3d djA = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::LOCAL_WORLD_ALIGNED);
220
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djA.isZero());
221
222
  // Check correct identities between different versions
223
✓✗✓✗
2
  rpydot = Eigen::Vector3d::Random();
224
✓✗
2
  dj0 = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot);
225
✓✗
2
  djL = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::LOCAL);
226
✓✗
2
  djW = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::WORLD);
227
✓✗
2
  djA = pinocchio::rpy::computeRpyJacobianTimeDerivative(rpy, rpydot, pinocchio::LOCAL_WORLD_ALIGNED);
228
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(dj0 == djL);
229
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djW == djA);
230
231
✓✗
2
  Eigen::Matrix3d R = pinocchio::rpy::rpyToMatrix(rpy);
232
✓✗
2
  Eigen::Matrix3d jL = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::LOCAL);
233
✓✗
2
  Eigen::Matrix3d jW = pinocchio::rpy::computeRpyJacobian(rpy, pinocchio::WORLD);
234
✓✗✓✗
2
  Eigen::Vector3d omegaL = jL * rpydot;
235
✓✗✓✗
2
  Eigen::Vector3d omegaW = jW * rpydot;
236
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(omegaW.isApprox(R*omegaL));
237
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(djW.isApprox(pinocchio::skew(omegaW)*R*jL + R*djL));
238
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✗✓
2
  BOOST_CHECK(djW.isApprox(R*pinocchio::skew(omegaL)*jL + R*djL));
239
240
  // Check against finite differences
241
2
  double const eps = 1e-7;
242
2
  double const tol = 1e-5;
243
✓✗
2
  Eigen::Vector3d rpyEps = rpy;
244
245
✓✗
2
  rpyEps[0] += eps;
246
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djLdr = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::LOCAL) - jL) / eps;
247
✓✗✓✗
2
  rpyEps[0] = rpy[0];
248
✓✗
2
  rpyEps[1] += eps;
249
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djLdp = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::LOCAL) - jL) / eps;
250
✓✗✓✗
2
  rpyEps[1] = rpy[1];
251
✓✗
2
  rpyEps[2] += eps;
252
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djLdy = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::LOCAL) - jL) / eps;
253
✓✗✓✗
2
  rpyEps[2] = rpy[2];
254
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
2
  Eigen::Matrix3d djLf = djLdr * rpydot[0] + djLdp * rpydot[1] + djLdy * rpydot[2];
255
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djL.isApprox(djLf, tol));
256
257
✓✗
2
  rpyEps[0] += eps;
258
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djWdr = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::WORLD) - jW) / eps;
259
✓✗✓✗
2
  rpyEps[0] = rpy[0];
260
✓✗
2
  rpyEps[1] += eps;
261
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djWdp = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::WORLD) - jW) / eps;
262
✓✗✓✗
2
  rpyEps[1] = rpy[1];
263
✓✗
2
  rpyEps[2] += eps;
264
✓✗✓✗
✓✗✓✗
2
  Eigen::Matrix3d djWdy = (pinocchio::rpy::computeRpyJacobian(rpyEps, pinocchio::WORLD) - jW) / eps;
265
✓✗✓✗
2
  rpyEps[2] = rpy[2];
266
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗✓✗
✓✗
2
  Eigen::Matrix3d djWf = djWdr * rpydot[0] + djWdp * rpydot[1] + djWdy * rpydot[2];
267
✓✗✓✗
✓✗✓✗
✓✗✓✗
✗✓
2
  BOOST_CHECK(djW.isApprox(djWf, tol));
268
2
}
269
270
BOOST_AUTO_TEST_SUITE_END()