GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/numdiff/actuation.hxx
Date: 2025-06-03 08:14:12
Exec Total Coverage
Lines: 0 88 0.0%
Functions: 0 21 0.0%
Branches: 0 296 0.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, University of Edinburgh, LAAS-CNRS,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include "crocoddyl/core/numdiff/actuation.hpp"
11
12 namespace crocoddyl {
13
14 template <typename Scalar>
15 ActuationModelNumDiffTpl<Scalar>::ActuationModelNumDiffTpl(
16 std::shared_ptr<Base> model)
17 : Base(model->get_state(), model->get_nu()),
18 model_(model),
19 e_jac_(sqrt(Scalar(2.0) * std::numeric_limits<Scalar>::epsilon())) {}
20
21 template <typename Scalar>
22 void ActuationModelNumDiffTpl<Scalar>::calc(
23 const std::shared_ptr<ActuationDataAbstract>& data,
24 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
25 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
26 throw_pretty("Invalid argument: "
27 << "x has wrong dimension (it should be " +
28 std::to_string(model_->get_state()->get_nx()) + ")");
29 }
30 if (static_cast<std::size_t>(u.size()) != nu_) {
31 throw_pretty(
32 "Invalid argument: " << "u has wrong dimension (it should be " +
33 std::to_string(nu_) + ")");
34 }
35 Data* d = static_cast<Data*>(data.get());
36 model_->calc(d->data_0, x, u);
37 data->tau = d->data_0->tau;
38 }
39
40 template <typename Scalar>
41 void ActuationModelNumDiffTpl<Scalar>::calc(
42 const std::shared_ptr<ActuationDataAbstract>& data,
43 const Eigen::Ref<const VectorXs>& x) {
44 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
45 throw_pretty("Invalid argument: "
46 << "x has wrong dimension (it should be " +
47 std::to_string(model_->get_state()->get_nx()) + ")");
48 }
49 Data* d = static_cast<Data*>(data.get());
50 model_->calc(d->data_0, x);
51 data->tau = d->data_0->tau;
52 }
53
54 template <typename Scalar>
55 void ActuationModelNumDiffTpl<Scalar>::calcDiff(
56 const std::shared_ptr<ActuationDataAbstract>& data,
57 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
58 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
59 throw_pretty("Invalid argument: "
60 << "x has wrong dimension (it should be " +
61 std::to_string(model_->get_state()->get_nx()) + ")");
62 }
63 if (static_cast<std::size_t>(u.size()) != nu_) {
64 throw_pretty(
65 "Invalid argument: " << "u has wrong dimension (it should be " +
66 std::to_string(nu_) + ")");
67 }
68 Data* d = static_cast<Data*>(data.get());
69 const VectorXs& tau0 = d->data_0->tau;
70 d->du.setZero();
71
72 // Computing the d actuation(x,u) / dx
73 model_->get_state()->diff(model_->get_state()->zero(), x, d->dx);
74 d->x_norm = d->dx.norm();
75 d->dx.setZero();
76 d->xh_jac = e_jac_ * std::max(Scalar(1.), d->x_norm);
77 for (std::size_t ix = 0; ix < model_->get_state()->get_ndx(); ++ix) {
78 d->dx(ix) = d->xh_jac;
79 model_->get_state()->integrate(x, d->dx, d->xp);
80 model_->calc(d->data_x[ix], d->xp, u);
81 d->dtau_dx.col(ix) = (d->data_x[ix]->tau - tau0) / d->xh_jac;
82 d->dx(ix) = Scalar(0.);
83 }
84
85 // Computing the d actuation(x,u) / du
86 d->uh_jac = e_jac_ * std::max(Scalar(1.), u.norm());
87 for (unsigned iu = 0; iu < model_->get_nu(); ++iu) {
88 d->du(iu) = d->uh_jac;
89 model_->calc(d->data_u[iu], x, u + d->du);
90 d->dtau_du.col(iu) = (d->data_u[iu]->tau - tau0) / d->uh_jac;
91 d->du(iu) = Scalar(0.);
92 }
93 }
94
95 template <typename Scalar>
96 void ActuationModelNumDiffTpl<Scalar>::calcDiff(
97 const std::shared_ptr<ActuationDataAbstract>& data,
98 const Eigen::Ref<const VectorXs>& x) {
99 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
100 throw_pretty("Invalid argument: "
101 << "x has wrong dimension (it should be " +
102 std::to_string(model_->get_state()->get_nx()) + ")");
103 }
104 Data* d = static_cast<Data*>(data.get());
105 const VectorXs& tau0 = d->data_0->tau;
106 d->dx.setZero();
107
108 // Computing the d actuation(x,u) / dx
109 model_->get_state()->diff(model_->get_state()->zero(), x, d->dx);
110 d->x_norm = d->dx.norm();
111 d->dx.setZero();
112 d->xh_jac = e_jac_ * std::max(Scalar(1.), d->x_norm);
113 for (std::size_t ix = 0; ix < model_->get_state()->get_ndx(); ++ix) {
114 d->dx(ix) = d->xh_jac;
115 model_->get_state()->integrate(x, d->dx, d->xp);
116 model_->calc(d->data_x[ix], d->xp);
117 d->dtau_dx.col(ix) = (d->data_x[ix]->tau - tau0) / d->xh_jac;
118 d->dx(ix) = Scalar(0.);
119 }
120 }
121
122 template <typename Scalar>
123 void ActuationModelNumDiffTpl<Scalar>::commands(
124 const std::shared_ptr<ActuationDataAbstract>& data,
125 const Eigen::Ref<const VectorXs>& x,
126 const Eigen::Ref<const VectorXs>& tau) {
127 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
128 throw_pretty("Invalid argument: "
129 << "x has wrong dimension (it should be " +
130 std::to_string(model_->get_state()->get_nx()) + ")");
131 }
132 if (static_cast<std::size_t>(tau.size()) != model_->get_state()->get_nv()) {
133 throw_pretty("Invalid argument: "
134 << "tau has wrong dimension (it should be " +
135 std::to_string(model_->get_state()->get_nv()) + ")");
136 }
137 Data* d = static_cast<Data*>(data.get());
138 model_->commands(d->data_0, x, tau);
139 data->u = d->data_0->u;
140 }
141
142 template <typename Scalar>
143 void ActuationModelNumDiffTpl<Scalar>::torqueTransform(
144 const std::shared_ptr<ActuationDataAbstract>& data,
145 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
146 if (static_cast<std::size_t>(x.size()) != model_->get_state()->get_nx()) {
147 throw_pretty("Invalid argument: "
148 << "x has wrong dimension (it should be " +
149 std::to_string(model_->get_state()->get_nx()) + ")");
150 }
151 if (static_cast<std::size_t>(u.size()) != nu_) {
152 throw_pretty(
153 "Invalid argument: " << "u has wrong dimension (it should be " +
154 std::to_string(nu_) + ")");
155 }
156 Data* d = static_cast<Data*>(data.get());
157 model_->torqueTransform(d->data_0, x, u);
158 d->Mtau = d->data_0->Mtau;
159 }
160
161 template <typename Scalar>
162 std::shared_ptr<ActuationDataAbstractTpl<Scalar> >
163 ActuationModelNumDiffTpl<Scalar>::createData() {
164 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
165 }
166
167 template <typename Scalar>
168 template <typename NewScalar>
169 ActuationModelNumDiffTpl<NewScalar> ActuationModelNumDiffTpl<Scalar>::cast()
170 const {
171 typedef ActuationModelNumDiffTpl<NewScalar> ReturnType;
172 ReturnType res(model_->template cast<NewScalar>());
173 return res;
174 }
175
176 template <typename Scalar>
177 const std::shared_ptr<ActuationModelAbstractTpl<Scalar> >&
178 ActuationModelNumDiffTpl<Scalar>::get_model() const {
179 return model_;
180 }
181
182 template <typename Scalar>
183 const Scalar ActuationModelNumDiffTpl<Scalar>::get_disturbance() const {
184 return e_jac_;
185 }
186
187 template <typename Scalar>
188 void ActuationModelNumDiffTpl<Scalar>::set_disturbance(
189 const Scalar disturbance) {
190 if (disturbance < Scalar(0.)) {
191 throw_pretty("Invalid argument: " << "Disturbance constant is positive");
192 }
193 e_jac_ = disturbance;
194 }
195
196 } // namespace crocoddyl
197