GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/numdiff/constraint.hxx
Date: 2025-01-30 11:01:55
Exec Total Coverage
Lines: 97 104 93.3%
Branches: 54 192 28.1%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2020-2023, University of Edinburgh, Heriot-Watt University
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
7 ///////////////////////////////////////////////////////////////////////////////
8
9 #include "crocoddyl/core/numdiff/constraint.hpp"
10
11 namespace crocoddyl {
12
13 template <typename Scalar>
14 140 ConstraintModelNumDiffTpl<Scalar>::ConstraintModelNumDiffTpl(
15 const std::shared_ptr<Base>& model)
16 : Base(model->get_state(), model->get_nu(), model->get_ng(),
17 model->get_nh()),
18 140 model_(model),
19
1/2
✓ Branch 10 taken 140 times.
✗ Branch 11 not taken.
140 e_jac_(std::sqrt(2.0 * std::numeric_limits<Scalar>::epsilon())) {}
20
21 template <typename Scalar>
22 280 ConstraintModelNumDiffTpl<Scalar>::~ConstraintModelNumDiffTpl() {}
23
24 template <typename Scalar>
25 140 void ConstraintModelNumDiffTpl<Scalar>::calc(
26 const std::shared_ptr<ConstraintDataAbstract>& data,
27 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
28
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
29 throw_pretty(
30 "Invalid argument: " << "x has wrong dimension (it should be " +
31 std::to_string(state_->get_nx()) + ")");
32 }
33
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 if (static_cast<std::size_t>(u.size()) != nu_) {
34 throw_pretty(
35 "Invalid argument: " << "u has wrong dimension (it should be " +
36 std::to_string(nu_) + ")");
37 }
38
39 140 Data* d = static_cast<Data*>(data.get());
40 140 d->data_0->g.setZero();
41 140 d->data_0->h.setZero();
42 140 model_->calc(d->data_0, x, u);
43 140 d->g = d->data_0->g;
44 140 d->h = d->data_0->h;
45 140 }
46
47 template <typename Scalar>
48 70 void ConstraintModelNumDiffTpl<Scalar>::calc(
49 const std::shared_ptr<ConstraintDataAbstract>& data,
50 const Eigen::Ref<const VectorXs>& x) {
51
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
70 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
52 throw_pretty(
53 "Invalid argument: " << "x has wrong dimension (it should be " +
54 std::to_string(state_->get_nx()) + ")");
55 }
56 70 Data* d = static_cast<Data*>(data.get());
57
58 70 d->data_0->g.setZero();
59 70 d->data_0->h.setZero();
60 70 model_->calc(d->data_0, x);
61 70 d->g = d->data_0->g;
62 70 d->h = d->data_0->h;
63 70 }
64
65 template <typename Scalar>
66 70 void ConstraintModelNumDiffTpl<Scalar>::calcDiff(
67 const std::shared_ptr<ConstraintDataAbstract>& data,
68 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
69
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
70 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
70 throw_pretty(
71 "Invalid argument: " << "x has wrong dimension (it should be " +
72 std::to_string(state_->get_nx()) + ")");
73 }
74
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
70 if (static_cast<std::size_t>(u.size()) != nu_) {
75 throw_pretty(
76 "Invalid argument: " << "u has wrong dimension (it should be " +
77 std::to_string(nu_) + ")");
78 }
79 70 Data* d = static_cast<Data*>(data.get());
80
81 70 const VectorXs& g0 = d->g;
82 70 const VectorXs& h0 = d->h;
83 70 const std::size_t ndx = model_->get_state()->get_ndx();
84 70 const std::size_t nu = model_->get_nu();
85 70 const std::size_t ng = model_->get_ng();
86 70 const std::size_t nh = model_->get_nh();
87 70 d->Gx.resize(ng, ndx);
88 70 d->Gu.resize(ng, nu);
89 70 d->Hx.resize(nh, ndx);
90 70 d->Hu.resize(nh, nu);
91 70 d->du.setZero();
92
93 70 assertStableStateFD(x);
94
95 // Computing the d constraint(x,u) / dx
96
3/6
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 70 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 70 times.
✗ Branch 15 not taken.
70 model_->get_state()->diff(model_->get_state()->zero(), x, d->dx);
97 70 d->x_norm = d->dx.norm();
98 70 d->dx.setZero();
99 70 d->xh_jac = e_jac_ * std::max(1., d->x_norm);
100
2/2
✓ Branch 2 taken 2856 times.
✓ Branch 3 taken 70 times.
2926 for (std::size_t ix = 0; ix < state_->get_ndx(); ++ix) {
101 2856 d->dx(ix) = d->xh_jac;
102
2/4
✓ Branch 5 taken 2856 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2856 times.
✗ Branch 9 not taken.
2856 model_->get_state()->integrate(x, d->dx, d->xp);
103 // call the update function
104
2/2
✓ Branch 1 taken 2856 times.
✓ Branch 2 taken 2856 times.
5712 for (size_t i = 0; i < reevals_.size(); ++i) {
105
1/2
✓ Branch 3 taken 2856 times.
✗ Branch 4 not taken.
2856 reevals_[i](d->xp, u);
106 }
107
1/2
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
2856 model_->calc(d->data_x[ix], d->xp, u);
108
3/6
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2856 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2856 times.
✗ Branch 11 not taken.
2856 d->Gx.col(ix) = (d->data_x[ix]->g - g0) / d->xh_jac;
109
3/6
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2856 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2856 times.
✗ Branch 11 not taken.
2856 d->Hx.col(ix) = (d->data_x[ix]->h - h0) / d->xh_jac;
110 2856 d->dx(ix) = 0.;
111 }
112
113 // Computing the d constraint(x,u) / du
114 70 d->uh_jac = e_jac_ * std::max(1., u.norm());
115
2/2
✓ Branch 2 taken 1428 times.
✓ Branch 3 taken 70 times.
1498 for (std::size_t iu = 0; iu < model_->get_nu(); ++iu) {
116 1428 d->du(iu) = d->uh_jac;
117
1/2
✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
1428 d->up = u + d->du;
118 // call the update function
119
2/2
✓ Branch 1 taken 1428 times.
✓ Branch 2 taken 1428 times.
2856 for (std::size_t i = 0; i < reevals_.size(); ++i) {
120
1/2
✓ Branch 3 taken 1428 times.
✗ Branch 4 not taken.
1428 reevals_[i](x, d->up);
121 }
122
1/2
✓ Branch 4 taken 1428 times.
✗ Branch 5 not taken.
1428 model_->calc(d->data_u[iu], x, d->up);
123
3/6
✓ Branch 4 taken 1428 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1428 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1428 times.
✗ Branch 11 not taken.
1428 d->Gu.col(iu) = (d->data_u[iu]->g - g0) / d->uh_jac;
124
3/6
✓ Branch 4 taken 1428 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1428 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1428 times.
✗ Branch 11 not taken.
1428 d->Hu.col(iu) = (d->data_u[iu]->h - h0) / d->uh_jac;
125 1428 d->du(iu) = 0.;
126 }
127 70 }
128
129 template <typename Scalar>
130 70 void ConstraintModelNumDiffTpl<Scalar>::calcDiff(
131 const std::shared_ptr<ConstraintDataAbstract>& data,
132 const Eigen::Ref<const VectorXs>& x) {
133
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
70 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
134 throw_pretty(
135 "Invalid argument: " << "x has wrong dimension (it should be " +
136 std::to_string(state_->get_nx()) + ")");
137 }
138 70 Data* d = static_cast<Data*>(data.get());
139
140 70 const VectorXs& g0 = d->g;
141 70 const VectorXs& h0 = d->h;
142 70 const std::size_t ndx = model_->get_state()->get_ndx();
143 70 d->Gx.resize(model_->get_ng(), ndx);
144 70 d->Hx.resize(model_->get_nh(), ndx);
145
146 70 assertStableStateFD(x);
147
148 // Computing the d constraint(x) / dx
149
3/6
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 70 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 70 times.
✗ Branch 15 not taken.
70 model_->get_state()->diff(model_->get_state()->zero(), x, d->dx);
150 70 d->x_norm = d->dx.norm();
151 70 d->dx.setZero();
152 70 d->xh_jac = e_jac_ * std::max(1., d->x_norm);
153
2/2
✓ Branch 2 taken 2856 times.
✓ Branch 3 taken 70 times.
2926 for (std::size_t ix = 0; ix < state_->get_ndx(); ++ix) {
154 // x + dx
155 2856 d->dx(ix) = d->xh_jac;
156
2/4
✓ Branch 5 taken 2856 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2856 times.
✗ Branch 9 not taken.
2856 model_->get_state()->integrate(x, d->dx, d->xp);
157 // call the update function
158
2/2
✓ Branch 1 taken 2856 times.
✓ Branch 2 taken 2856 times.
5712 for (size_t i = 0; i < reevals_.size(); ++i) {
159 2856 reevals_[i](d->xp, unone_);
160 }
161
1/2
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
2856 model_->calc(d->data_x[ix], d->xp);
162
3/6
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2856 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2856 times.
✗ Branch 11 not taken.
2856 d->Gx.col(ix) = (d->data_x[ix]->g - g0) / d->xh_jac;
163
3/6
✓ Branch 4 taken 2856 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2856 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2856 times.
✗ Branch 11 not taken.
2856 d->Hx.col(ix) = (d->data_x[ix]->h - h0) / d->xh_jac;
164 2856 d->dx(ix) = 0.;
165 }
166 70 }
167
168 template <typename Scalar>
169 std::shared_ptr<ConstraintDataAbstractTpl<Scalar> >
170 140 ConstraintModelNumDiffTpl<Scalar>::createData(
171 DataCollectorAbstract* const data) {
172 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this,
173
1/2
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
140 data);
174 }
175
176 template <typename Scalar>
177 const std::shared_ptr<ConstraintModelAbstractTpl<Scalar> >&
178 8988 ConstraintModelNumDiffTpl<Scalar>::get_model() const {
179 8988 return model_;
180 }
181
182 template <typename Scalar>
183 70 const Scalar ConstraintModelNumDiffTpl<Scalar>::get_disturbance() const {
184 70 return e_jac_;
185 }
186
187 template <typename Scalar>
188 void ConstraintModelNumDiffTpl<Scalar>::set_disturbance(
189 const Scalar disturbance) {
190 if (disturbance < 0.) {
191 throw_pretty("Invalid argument: " << "Disturbance constant is positive");
192 }
193 e_jac_ = disturbance;
194 }
195
196 template <typename Scalar>
197 70 void ConstraintModelNumDiffTpl<Scalar>::set_reevals(
198 const std::vector<ReevaluationFunction>& reevals) {
199 70 reevals_ = reevals;
200 70 }
201
202 template <typename Scalar>
203 140 void ConstraintModelNumDiffTpl<Scalar>::assertStableStateFD(
204 const Eigen::Ref<const VectorXs>& /*x*/) {
205 // do nothing in the general case
206 140 }
207
208 } // namespace crocoddyl
209