GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: unittest/rnea-second-order-derivatives.cpp Lines: 144 144 100.0 %
Date: 2024-01-23 21:41:47 Branches: 334 644 51.9 %

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/rnea-second-order-derivatives.hpp"
10
#include "pinocchio/algorithm/rnea-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_rnea_derivatives_SO) {
21
  using namespace Eigen;
22
  using namespace pinocchio;
23
24
4
  Model model;
25
2
  buildModels::humanoidRandom(model);
26
27

4
  Data data(model), data_fd(model);
28
29

2
  model.lowerPositionLimit.head<3>().fill(-1.);
30

2
  model.upperPositionLimit.head<3>().fill(1.);
31
32
4
  VectorXd q = randomConfiguration(model);
33

4
  VectorXd v(VectorXd::Random(model.nv));
34

4
  VectorXd a(VectorXd::Random(model.nv));
35
36
  // check with only q non-zero
37
4
  Data::Tensor3x dtau2_dq(model.nv, model.nv, model.nv);
38
4
  Data::Tensor3x dtau2_dv(model.nv, model.nv, model.nv);
39
4
  Data::Tensor3x dtau2_dqdv(model.nv, model.nv, model.nv);
40
4
  Data::Tensor3x dtau2_dadq(model.nv, model.nv, model.nv);
41
2
  dtau2_dq.setZero();
42
2
  dtau2_dv.setZero();
43
2
  dtau2_dqdv.setZero();
44
2
  dtau2_dadq.setZero();
45
46

2
  ComputeRNEASecondOrderDerivatives(model, data, q, VectorXd::Zero(model.nv),
47
2
                           VectorXd::Zero(model.nv), dtau2_dq, dtau2_dv,
48
                           dtau2_dqdv, dtau2_dadq);
49
50
4
  Data::Tensor3x dtau2_dq_fd(model.nv, model.nv, model.nv);
51
4
  Data::Tensor3x dtau2_dv_fd(model.nv, model.nv, model.nv);
52
4
  Data::Tensor3x dtau2_dqdv_fd(model.nv, model.nv, model.nv);
53
4
  Data::Tensor3x dtau2_dadq_fd(model.nv, model.nv, model.nv);
54
2
  dtau2_dq_fd.setZero();
55
2
  dtau2_dv_fd.setZero();
56
2
  dtau2_dqdv_fd.setZero();
57
2
  dtau2_dadq_fd.setZero();
58
59

4
  MatrixXd drnea_dq_plus(MatrixXd::Zero(model.nv, model.nv));
60

4
  MatrixXd drnea_dv_plus(MatrixXd::Zero(model.nv, model.nv));
61

4
  MatrixXd drnea_da_plus(MatrixXd::Zero(model.nv, model.nv));
62
63

4
  MatrixXd temp1(MatrixXd::Zero(model.nv, model.nv));
64

4
  MatrixXd temp2(MatrixXd::Zero(model.nv, model.nv));
65
66

4
  VectorXd v_eps(VectorXd::Zero(model.nv));
67
4
  VectorXd q_plus(model.nq);
68
4
  VectorXd v_plus(model.nv);
69
70

4
  MatrixXd rnea_partial_dq(MatrixXd::Zero(model.nv, model.nv));
71

4
  MatrixXd rnea_partial_dv(MatrixXd::Zero(model.nv, model.nv));
72

4
  MatrixXd rnea_partial_da(MatrixXd::Zero(model.nv, model.nv));
73
74

2
  computeRNEADerivatives(model, data, q, VectorXd::Zero(model.nv),
75
2
                         VectorXd::Zero(model.nv), rnea_partial_dq,
76
                         rnea_partial_dv, rnea_partial_da);
77
78
2
  const double alpha = 1e-7;
79
80
66
  for (int k = 0; k < model.nv; ++k) {
81
64
    v_eps[k] += alpha;
82
64
    q_plus = integrate(model, q, v_eps);
83

64
    computeRNEADerivatives(model, data_fd, q_plus, VectorXd::Zero(model.nv),
84
64
                           VectorXd::Zero(model.nv), drnea_dq_plus,
85
                           drnea_dv_plus, drnea_da_plus);
86

64
    temp1 = (drnea_dq_plus - rnea_partial_dq) / alpha;
87
2112
    for (int ii = 0; ii < model.nv; ii++) {
88
67584
      for (int jj = 0; jj < model.nv; jj++) {
89

65536
        dtau2_dq_fd(jj, ii, k) = temp1(jj, ii);
90
      }
91
    }
92
64
    v_eps[k] -= alpha;
93
  }
94
95


2
  Map<VectorXd> mq(dtau2_dq.data(), dtau2_dq.size());
96


2
  Map<VectorXd> mq_fd(dtau2_dq_fd.data(), dtau2_dq_fd.size());
97



2
  BOOST_CHECK(mq.isApprox(mq_fd, sqrt(alpha)));
98
99
  // Check with q and a non zero
100
2
  dtau2_dq.setZero();
101
2
  dtau2_dv.setZero();
102
2
  dtau2_dqdv.setZero();
103
2
  dtau2_dadq.setZero();
104

2
  ComputeRNEASecondOrderDerivatives(model, data, q, VectorXd::Zero(model.nv), a,
105
                           dtau2_dq, dtau2_dv, dtau2_dqdv, dtau2_dadq);
106
107
2
  rnea_partial_dq.setZero();
108
2
  rnea_partial_dv.setZero();
109
2
  rnea_partial_da.setZero();
110
111
2
  dtau2_dq_fd.setZero();
112
2
  dtau2_dadq_fd.setZero();
113
2
  drnea_dq_plus.setZero();
114
2
  drnea_dv_plus.setZero();
115
2
  drnea_da_plus.setZero();
116
117

2
  computeRNEADerivatives(model, data, q, VectorXd::Zero(model.nv), a,
118
                         rnea_partial_dq, rnea_partial_dv, rnea_partial_da);
119
120
66
  for (int k = 0; k < model.nv; ++k) {
121
64
    v_eps[k] += alpha;
122
64
    q_plus = integrate(model, q, v_eps);
123

64
    computeRNEADerivatives(model, data_fd, q_plus, VectorXd::Zero(model.nv), a,
124
                           drnea_dq_plus, drnea_dv_plus, drnea_da_plus);
125

64
    temp1 = (drnea_dq_plus - rnea_partial_dq) / alpha;
126

64
    temp2 = (drnea_da_plus - rnea_partial_da) / alpha;
127
64
    temp2.triangularView<Eigen::StrictlyLower>() =
128

128
        temp2.transpose().triangularView<Eigen::StrictlyLower>();
129
2112
    for (int ii = 0; ii < model.nv; ii++) {
130
67584
      for (int jj = 0; jj < model.nv; jj++) {
131

65536
        dtau2_dq_fd(jj, ii, k) = temp1(jj, ii);
132

65536
        dtau2_dadq_fd(jj, ii, k) = temp2(jj, ii);
133
      }
134
    }
135
64
    v_eps[k] -= alpha;
136
  }
137


2
  Map<VectorXd> maq(dtau2_dadq.data(), dtau2_dadq.size());
138


2
  Map<VectorXd> maq_fd(dtau2_dadq_fd.data(), dtau2_dadq_fd.size());
139
140



2
  BOOST_CHECK(mq.isApprox(mq_fd, sqrt(alpha)));
141



2
  BOOST_CHECK(maq.isApprox(maq_fd, sqrt(alpha)));
142
143
  // Check with q,v and a non zero
144
2
  dtau2_dq.setZero();
145
2
  dtau2_dv.setZero();
146
2
  dtau2_dqdv.setZero();
147
2
  dtau2_dadq.setZero();
148
2
  ComputeRNEASecondOrderDerivatives(model, data, q, v, a, dtau2_dq, dtau2_dv, dtau2_dqdv,
149
                           dtau2_dadq);
150
151
2
  rnea_partial_dq.setZero();
152
2
  rnea_partial_dv.setZero();
153
2
  rnea_partial_da.setZero();
154
2
  computeRNEADerivatives(model, data, q, v, a, rnea_partial_dq, rnea_partial_dv,
155
                         rnea_partial_da);
156
157
2
  dtau2_dq_fd.setZero();
158
2
  dtau2_dadq_fd.setZero();
159
2
  drnea_dq_plus.setZero();
160
2
  drnea_dv_plus.setZero();
161
2
  drnea_da_plus.setZero();
162
163
66
  for (int k = 0; k < model.nv; ++k) {
164
64
    v_eps[k] += alpha;
165
64
    q_plus = integrate(model, q, v_eps);
166
64
    computeRNEADerivatives(model, data_fd, q_plus, v, a, drnea_dq_plus,
167
                           drnea_dv_plus, drnea_da_plus);
168

64
    temp1 = (drnea_dq_plus - rnea_partial_dq) / alpha;
169

64
    temp2 = (drnea_da_plus - rnea_partial_da) / alpha;
170
64
    temp2.triangularView<Eigen::StrictlyLower>() =
171

128
        temp2.transpose().triangularView<Eigen::StrictlyLower>();
172
2112
    for (int ii = 0; ii < model.nv; ii++) {
173
67584
      for (int jj = 0; jj < model.nv; jj++) {
174

65536
        dtau2_dq_fd(jj, ii, k) = temp1(jj, ii);
175

65536
        dtau2_dadq_fd(jj, ii, k) = temp2(jj, ii);
176
      }
177
    }
178
64
    v_eps[k] -= alpha;
179
  }
180
2
  dtau2_dv_fd.setZero();
181
2
  dtau2_dqdv_fd.setZero();
182
66
  for (int k = 0; k < model.nv; ++k) {
183
64
    v_eps[k] += alpha;
184

64
    v_plus = v + v_eps;
185
64
    computeRNEADerivatives(model, data_fd, q, v_plus, a, drnea_dq_plus,
186
                           drnea_dv_plus, drnea_da_plus);
187

64
    temp1 = (drnea_dv_plus - rnea_partial_dv) / alpha;
188

64
    temp2 = (drnea_dq_plus - rnea_partial_dq) / alpha;
189
2112
    for (int ii = 0; ii < model.nv; ii++) {
190
67584
      for (int jj = 0; jj < model.nv; jj++) {
191

65536
        dtau2_dv_fd(jj, ii, k) = temp1(jj, ii);
192

65536
        dtau2_dqdv_fd(jj, ii, k) = temp2(jj, ii);
193
      }
194
    }
195
64
    v_eps[k] -= alpha;
196
  }
197


2
  Map<VectorXd> mv(dtau2_dv.data(), dtau2_dv.size());
198


2
  Map<VectorXd> mv_fd(dtau2_dv_fd.data(), dtau2_dv_fd.size());
199
200


2
  Map<VectorXd> mqv(dtau2_dqdv.data(), dtau2_dqdv.size());
201


2
  Map<VectorXd> mqv_fd(dtau2_dqdv_fd.data(), dtau2_dqdv_fd.size());
202
203



2
  BOOST_CHECK(mq.isApprox(mq_fd, sqrt(alpha)));
204



2
  BOOST_CHECK(maq.isApprox(maq_fd, sqrt(alpha)));
205



2
  BOOST_CHECK(mv.isApprox(mv_fd, sqrt(alpha)));
206



2
  BOOST_CHECK(mqv.isApprox(mqv_fd, sqrt(alpha)));
207
208
4
  Data data2(model);
209
2
  ComputeRNEASecondOrderDerivatives(model, data2, q, v, a);
210
211


2
  Map<VectorXd> mq2(data2.d2tau_dqdq.data(), (data2.d2tau_dqdq).size());
212


2
  Map<VectorXd> mv2(data2.d2tau_dvdv.data(), (data2.d2tau_dvdv).size());
213


2
  Map<VectorXd> mqv2(data2.d2tau_dqdv.data(), (data2.d2tau_dqdv).size());
214


2
  Map<VectorXd> maq2(data2.d2tau_dadq.data(), (data2.d2tau_dadq).size());
215
216



2
  BOOST_CHECK(mq.isApprox(mq2, sqrt(alpha)));
217



2
  BOOST_CHECK(mv.isApprox(mv2, sqrt(alpha)));
218



2
  BOOST_CHECK(mqv.isApprox(mqv2, sqrt(alpha)));
219



2
  BOOST_CHECK(maq.isApprox(maq2, sqrt(alpha)));
220
2
}
221
222
BOOST_AUTO_TEST_SUITE_END()