Line |
Branch |
Exec |
Source |
1 |
|
|
#ifndef __quadruped_walkgen_quadruped_hxx__ |
2 |
|
|
#define __quadruped_walkgen_quadruped_hxx__ |
3 |
|
|
|
4 |
|
|
#include "crocoddyl/core/utils/exception.hpp" |
5 |
|
|
|
6 |
|
|
namespace quadruped_walkgen { |
7 |
|
|
template <typename Scalar> |
8 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::ActionModelQuadrupedTpl( |
9 |
|
|
typename Eigen::Matrix<Scalar, 3, 1> offset_CoM) |
10 |
|
|
: crocoddyl::ActionModelAbstractTpl<Scalar>( |
11 |
|
✗ |
boost::make_shared<crocoddyl::StateVectorTpl<Scalar> >(12), 12, 24) { |
12 |
|
|
// Relative forces to compute the norm mof the command |
13 |
|
✗ |
relative_forces = false; |
14 |
|
✗ |
uref_.setZero(); |
15 |
|
|
|
16 |
|
|
// Model parameters |
17 |
|
✗ |
mu = Scalar(1); |
18 |
|
✗ |
dt_ = Scalar(0.02); |
19 |
|
✗ |
mass = Scalar(2.50000279); |
20 |
|
✗ |
min_fz_in_contact = Scalar(0.0); |
21 |
|
✗ |
max_fz = Scalar(25.); |
22 |
|
|
|
23 |
|
|
// Matrix model initialization |
24 |
|
✗ |
g.setZero(); |
25 |
|
✗ |
g[8] = Scalar(-9.81) * dt_; |
26 |
|
✗ |
gI.setZero(); |
27 |
|
✗ |
gI.diagonal() << Scalar(3.09249e-2), Scalar(5.106100e-2), Scalar(6.939757e-2); |
28 |
|
✗ |
A.setIdentity(); |
29 |
|
✗ |
A.topRightCorner(6, 6) << Eigen::Matrix<Scalar, 6, 6>::Identity() * dt_; |
30 |
|
✗ |
B.setZero(); |
31 |
|
✗ |
lever_arms.setZero(); |
32 |
|
✗ |
I_inv.setZero(); |
33 |
|
|
|
34 |
|
|
// Weight vectors initialization |
35 |
|
✗ |
force_weights_.setConstant(0.2); |
36 |
|
✗ |
state_weights_ << Scalar(1.), Scalar(1.), Scalar(150.), Scalar(35.), |
37 |
|
✗ |
Scalar(30.), Scalar(8.), Scalar(20.), Scalar(20.), Scalar(15.), |
38 |
|
✗ |
Scalar(4.), Scalar(4.), Scalar(8.); |
39 |
|
✗ |
friction_weight_ = Scalar(10); |
40 |
|
|
|
41 |
|
|
// UpperBound vector |
42 |
|
✗ |
ub.setZero(); |
43 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
44 |
|
✗ |
ub(6 * i + 5) = max_fz; |
45 |
|
|
} |
46 |
|
|
|
47 |
|
|
// Temporary vector used |
48 |
|
✗ |
Fa_x_u.setZero(); |
49 |
|
✗ |
rub_max_.setZero(); |
50 |
|
✗ |
Arr.setZero(); |
51 |
|
✗ |
r.setZero(); |
52 |
|
✗ |
lever_tmp.setZero(); |
53 |
|
✗ |
R_tmp.setZero(); |
54 |
|
|
|
55 |
|
|
// Used for shoulder height weight |
56 |
|
✗ |
pshoulder_0 << Scalar(0.1946), Scalar(0.1946), Scalar(-0.1946), |
57 |
|
✗ |
Scalar(-0.1946), Scalar(0.14695), Scalar(-0.14695), Scalar(0.14695), |
58 |
|
✗ |
Scalar(-0.14695); |
59 |
|
✗ |
sh_hlim = Scalar(0.27); |
60 |
|
✗ |
sh_weight = Scalar(10.); |
61 |
|
✗ |
sh_ub_max_.setZero(); |
62 |
|
✗ |
psh.setZero(); |
63 |
|
✗ |
gait.setZero(); |
64 |
|
|
|
65 |
|
|
// Implicit integration |
66 |
|
|
// V+ = V + dt*B*u ; P+ = P + dt*V+ != explicit : P+ = P + dt*V |
67 |
|
✗ |
implicit_integration = true; |
68 |
|
✗ |
offset_com = offset_CoM; // x, y, z offset |
69 |
|
|
} |
70 |
|
|
|
71 |
|
|
template <typename Scalar> |
72 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::~ActionModelQuadrupedTpl() {} |
73 |
|
|
|
74 |
|
|
template <typename Scalar> |
75 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::calc( |
76 |
|
|
const boost::shared_ptr<crocoddyl::ActionDataAbstractTpl<Scalar> >& data, |
77 |
|
|
const Eigen::Ref<const typename MathBase::VectorXs>& x, |
78 |
|
|
const Eigen::Ref<const typename MathBase::VectorXs>& u) { |
79 |
|
✗ |
if (static_cast<std::size_t>(x.size()) != state_->get_nx()) { |
80 |
|
✗ |
throw_pretty("Invalid argument: " |
81 |
|
|
<< "x has wrong dimension (it should be " + |
82 |
|
|
std::to_string(state_->get_nx()) + ")"); |
83 |
|
|
} |
84 |
|
✗ |
if (static_cast<std::size_t>(u.size()) != nu_) { |
85 |
|
✗ |
throw_pretty("Invalid argument: " |
86 |
|
|
<< "u has wrong dimension (it should be " + |
87 |
|
|
std::to_string(nu_) + ")"); |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
ActionDataQuadrupedTpl<Scalar>* d = |
91 |
|
✗ |
static_cast<ActionDataQuadrupedTpl<Scalar>*>(data.get()); |
92 |
|
|
|
93 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
94 |
|
✗ |
if (gait(i, 0) != 0) { |
95 |
|
|
// Compute pdistance of the shoulder wrt contact point |
96 |
|
✗ |
psh.block(0, i, 3, 1) << x[0] - offset_com(0, 0) + pshoulder_0(0, i) - |
97 |
|
✗ |
pshoulder_0(1, i) * x[5] - lever_arms(0, i), |
98 |
|
✗ |
x[1] - offset_com(1, 0) + pshoulder_0(1, i) + |
99 |
|
✗ |
pshoulder_0(0, i) * x[5] - lever_arms(1, i), |
100 |
|
✗ |
x[2] - offset_com(2, 0) + pshoulder_0(1, i) * x[3] - |
101 |
|
✗ |
pshoulder_0(0, i) * x[4]; |
102 |
|
|
} else { |
103 |
|
|
// Compute pdistance of the shoulder wrt contact point |
104 |
|
✗ |
psh.block(0, i, 3, 1).setZero(); |
105 |
|
|
} |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
// Discrete dynamic : A*x + B*u + g |
109 |
|
✗ |
d->xnext << A.diagonal().cwiseProduct(x) + g; |
110 |
|
✗ |
d->xnext.template tail<6>() = |
111 |
|
✗ |
d->xnext.template tail<6>() + B.block(6, 0, 6, 12) * u; |
112 |
|
|
|
113 |
|
|
// Explicit : d->xnext.template head<6>() = d->xnext.template head<6>() + |
114 |
|
|
// A.topRightCorner(6,6).diagonal().cwiseProduct(d->xnext.tail(6)) ; |
115 |
|
✗ |
if (implicit_integration) { |
116 |
|
✗ |
d->xnext.template head<6>() = |
117 |
|
✗ |
d->xnext.template head<6>() + |
118 |
|
✗ |
A.topRightCorner(6, 6).diagonal().cwiseProduct(d->xnext.tail(6)); |
119 |
|
|
} else { |
120 |
|
✗ |
d->xnext.template head<6>() = |
121 |
|
✗ |
d->xnext.template head<6>() + |
122 |
|
✗ |
A.topRightCorner(6, 6).diagonal().cwiseProduct(x.tail(6)); |
123 |
|
|
} |
124 |
|
|
|
125 |
|
|
// Residual cost on the state and force norm |
126 |
|
✗ |
d->r.template head<12>() = state_weights_.cwiseProduct(x - xref_); |
127 |
|
✗ |
d->r.template tail<12>() = force_weights_.cwiseProduct(u - uref_); |
128 |
|
|
|
129 |
|
|
// Friction cone |
130 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
131 |
|
✗ |
Fa_x_u.segment(6 * i, 6) << u(3 * i) - mu * u(3 * i + 2), |
132 |
|
✗ |
-u(3 * i) - mu * u(3 * i + 2), u(3 * i + 1) - mu * u(3 * i + 2), |
133 |
|
✗ |
-u(3 * i + 1) - mu * u(3 * i + 2), -u(3 * i + 2), u(3 * i + 2); |
134 |
|
|
} |
135 |
|
✗ |
rub_max_ = (Fa_x_u - ub).cwiseMax(0.); |
136 |
|
|
|
137 |
|
|
// Shoulder height weight |
138 |
|
✗ |
sh_ub_max_ << psh.block(0, 0, 3, 1).squaredNorm() - sh_hlim * sh_hlim, |
139 |
|
✗ |
psh.block(0, 1, 3, 1).squaredNorm() - sh_hlim * sh_hlim, |
140 |
|
✗ |
psh.block(0, 2, 3, 1).squaredNorm() - sh_hlim * sh_hlim, |
141 |
|
✗ |
psh.block(0, 3, 3, 1).squaredNorm() - sh_hlim * sh_hlim; |
142 |
|
✗ |
sh_ub_max_ = sh_ub_max_.cwiseMax(Scalar(0.)); |
143 |
|
|
|
144 |
|
|
// Cost computation |
145 |
|
|
// d->cost = 0.5 * d->r.transpose() * d->r + friction_weight_ * |
146 |
|
|
// Scalar(0.5) * rub_max_.squaredNorm() + sh_weight |
147 |
|
|
// * Scalar(0.5) * sh_ub_max_.squaredNorm() ; |
148 |
|
|
|
149 |
|
✗ |
d->cost = 0.5 * d->r.transpose() * d->r + |
150 |
|
✗ |
friction_weight_ * Scalar(0.5) * rub_max_.squaredNorm() + |
151 |
|
✗ |
sh_weight * Scalar(0.5) * sh_ub_max_.sum(); |
152 |
|
|
} |
153 |
|
|
|
154 |
|
|
template <typename Scalar> |
155 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::calcDiff( |
156 |
|
|
const boost::shared_ptr<crocoddyl::ActionDataAbstractTpl<Scalar> >& data, |
157 |
|
|
const Eigen::Ref<const typename MathBase::VectorXs>& x, |
158 |
|
|
const Eigen::Ref<const typename MathBase::VectorXs>& u) { |
159 |
|
✗ |
if (static_cast<std::size_t>(x.size()) != state_->get_nx()) { |
160 |
|
✗ |
throw_pretty("Invalid argument: " |
161 |
|
|
<< "x has wrong dimension (it should be " + |
162 |
|
|
std::to_string(state_->get_nx()) + ")"); |
163 |
|
|
} |
164 |
|
✗ |
if (static_cast<std::size_t>(u.size()) != nu_) { |
165 |
|
✗ |
throw_pretty("Invalid argument: " |
166 |
|
|
<< "u has wrong dimension (it should be " + |
167 |
|
|
std::to_string(nu_) + ")"); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
ActionDataQuadrupedTpl<Scalar>* d = |
171 |
|
✗ |
static_cast<ActionDataQuadrupedTpl<Scalar>*>(data.get()); |
172 |
|
|
|
173 |
|
|
// Cost derivatives : Lx |
174 |
|
✗ |
d->Lx = (state_weights_.array() * d->r.template head<12>().array()).matrix(); |
175 |
|
|
|
176 |
|
|
// Hessian : Lxx |
177 |
|
✗ |
d->Lxx.block(0, 0, 6, 6).setZero(); |
178 |
|
✗ |
d->Lxx.diagonal() = |
179 |
|
✗ |
(state_weights_.array() * state_weights_.array()).matrix(); |
180 |
|
✗ |
for (int j = 0; j < 4; j = j + 1) { |
181 |
|
✗ |
if (sh_ub_max_[j] > Scalar(0.)) { |
182 |
|
✗ |
d->Lx(0, 0) += sh_weight * psh(0, j); |
183 |
|
✗ |
d->Lx(1, 0) += sh_weight * psh(1, j); |
184 |
|
✗ |
d->Lx(2, 0) += sh_weight * psh(2, j); |
185 |
|
✗ |
d->Lx(3, 0) += sh_weight * pshoulder_0(1, j) * psh(2, j); |
186 |
|
✗ |
d->Lx(4, 0) += -sh_weight * pshoulder_0(0, j) * psh(2, j); |
187 |
|
✗ |
d->Lx(5, 0) += sh_weight * (-pshoulder_0(1, j) * psh(0, j) + |
188 |
|
✗ |
pshoulder_0(0, j) * psh(1, j)); |
189 |
|
|
|
190 |
|
✗ |
d->Lxx(0, 0) += sh_weight; |
191 |
|
✗ |
d->Lxx(1, 1) += sh_weight; |
192 |
|
✗ |
d->Lxx(2, 2) += sh_weight; |
193 |
|
✗ |
d->Lxx(3, 3) += sh_weight * pshoulder_0(1, j) * pshoulder_0(1, j); |
194 |
|
✗ |
d->Lxx(3, 3) += sh_weight * pshoulder_0(0, j) * pshoulder_0(0, j); |
195 |
|
✗ |
d->Lxx(5, 5) += sh_weight * (pshoulder_0(1, j) * pshoulder_0(1, j) + |
196 |
|
✗ |
pshoulder_0(0, j) * pshoulder_0(0, j)); |
197 |
|
|
|
198 |
|
✗ |
d->Lxx(0, 5) += -sh_weight * pshoulder_0(1, j); |
199 |
|
✗ |
d->Lxx(5, 0) += -sh_weight * pshoulder_0(1, j); |
200 |
|
|
|
201 |
|
✗ |
d->Lxx(1, 5) += sh_weight * pshoulder_0(0, j); |
202 |
|
✗ |
d->Lxx(5, 1) += sh_weight * pshoulder_0(0, j); |
203 |
|
|
|
204 |
|
✗ |
d->Lxx(2, 3) += sh_weight * pshoulder_0(1, j); |
205 |
|
✗ |
d->Lxx(2, 4) += -sh_weight * pshoulder_0(0, j); |
206 |
|
✗ |
d->Lxx(3, 2) += sh_weight * pshoulder_0(1, j); |
207 |
|
✗ |
d->Lxx(4, 2) += -sh_weight * pshoulder_0(0, j); |
208 |
|
|
|
209 |
|
✗ |
d->Lxx(3, 4) += -sh_weight * pshoulder_0(1, j) * pshoulder_0(0, j); |
210 |
|
✗ |
d->Lxx(4, 3) += -sh_weight * pshoulder_0(1, j) * pshoulder_0(0, j); |
211 |
|
|
} |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
// Cost derivative : Lu |
215 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
216 |
|
✗ |
r = friction_weight_ * rub_max_.segment(6 * i, 6); |
217 |
|
✗ |
d->Lu.block(i * 3, 0, 3, 1) << r(0) - r(1), r(2) - r(3), |
218 |
|
✗ |
-mu * (r(0) + r(1) + r(2) + r(3)) - r(4) + r(5); |
219 |
|
|
} |
220 |
|
✗ |
d->Lu = d->Lu + |
221 |
|
✗ |
(force_weights_.array() * d->r.template tail<12>().array()).matrix(); |
222 |
|
|
|
223 |
|
|
// Hessian : Luu |
224 |
|
|
// Matrix friction cone hessian (20x12) |
225 |
|
✗ |
Arr.diagonal() = |
226 |
|
✗ |
((Fa_x_u - ub).array() >= 0.).matrix().template cast<Scalar>(); |
227 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
228 |
|
✗ |
r = friction_weight_ * Arr.diagonal().segment(6 * i, 6); |
229 |
|
✗ |
d->Luu.block(3 * i, 3 * i, 3, 3) << r(0) + r(1), 0.0, mu * (r(1) - r(0)), |
230 |
|
✗ |
0.0, r(2) + r(3), mu * (r(3) - r(2)), mu * (r(1) - r(0)), |
231 |
|
✗ |
mu * (r(3) - r(2)), mu * mu * (r(0) + r(1) + r(2) + r(3)) + r(4) + r(5); |
232 |
|
|
} |
233 |
|
✗ |
d->Luu.diagonal() = |
234 |
|
✗ |
d->Luu.diagonal() + |
235 |
|
✗ |
(force_weights_.array() * force_weights_.array()).matrix(); |
236 |
|
|
|
237 |
|
|
// Dynamic derivatives |
238 |
|
✗ |
d->Fx << A; |
239 |
|
✗ |
d->Fu << B; |
240 |
|
✗ |
if (implicit_integration) { |
241 |
|
✗ |
d->Fu.block(0, 0, 6, 12) << dt_ * B.block(6, 0, 6, 12); |
242 |
|
|
} |
243 |
|
|
} |
244 |
|
|
|
245 |
|
|
template <typename Scalar> |
246 |
|
|
boost::shared_ptr<crocoddyl::ActionDataAbstractTpl<Scalar> > |
247 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::createData() { |
248 |
|
✗ |
return boost::make_shared<ActionDataQuadrupedTpl<Scalar> >(this); |
249 |
|
|
} |
250 |
|
|
|
251 |
|
|
//////////////////////////////// |
252 |
|
|
// get & set parameters //////// |
253 |
|
|
//////////////////////////////// |
254 |
|
|
|
255 |
|
|
template <typename Scalar> |
256 |
|
|
const typename Eigen::Matrix<Scalar, 12, 1>& |
257 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::get_force_weights() const { |
258 |
|
✗ |
return force_weights_; |
259 |
|
|
} |
260 |
|
|
template <typename Scalar> |
261 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_force_weights( |
262 |
|
|
const typename MathBase::VectorXs& weights) { |
263 |
|
✗ |
if (static_cast<std::size_t>(weights.size()) != state_->get_nx()) { |
264 |
|
✗ |
throw_pretty("Invalid argument: " |
265 |
|
|
<< "Weights vector has wrong dimension (it should be " + |
266 |
|
|
std::to_string(state_->get_nx()) + ")"); |
267 |
|
|
} |
268 |
|
✗ |
force_weights_ = weights; |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
template <typename Scalar> |
272 |
|
|
const typename Eigen::Matrix<Scalar, 12, 1>& |
273 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::get_state_weights() const { |
274 |
|
✗ |
return state_weights_; |
275 |
|
|
} |
276 |
|
|
template <typename Scalar> |
277 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_state_weights( |
278 |
|
|
const typename MathBase::VectorXs& weights) { |
279 |
|
✗ |
if (static_cast<std::size_t>(weights.size()) != state_->get_nx()) { |
280 |
|
✗ |
throw_pretty("Invalid argument: " |
281 |
|
|
<< "Weights vector has wrong dimension (it should be " + |
282 |
|
|
std::to_string(state_->get_nx()) + ")"); |
283 |
|
|
} |
284 |
|
✗ |
state_weights_ = weights; |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
template <typename Scalar> |
288 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_friction_weight() const { |
289 |
|
✗ |
return friction_weight_; |
290 |
|
|
} |
291 |
|
|
template <typename Scalar> |
292 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_friction_weight( |
293 |
|
|
const Scalar& weight) { |
294 |
|
✗ |
friction_weight_ = weight; |
295 |
|
|
} |
296 |
|
|
|
297 |
|
|
template <typename Scalar> |
298 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_mu() const { |
299 |
|
✗ |
return mu; |
300 |
|
|
} |
301 |
|
|
template <typename Scalar> |
302 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_mu(const Scalar& mu_coeff) { |
303 |
|
✗ |
mu = mu_coeff; |
304 |
|
|
} |
305 |
|
|
|
306 |
|
|
template <typename Scalar> |
307 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_mass() const { |
308 |
|
✗ |
return mass; |
309 |
|
|
} |
310 |
|
|
template <typename Scalar> |
311 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_mass(const Scalar& m) { |
312 |
|
|
// The model need to be updated after this changed |
313 |
|
✗ |
mass = m; |
314 |
|
|
} |
315 |
|
|
|
316 |
|
|
template <typename Scalar> |
317 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_dt() const { |
318 |
|
✗ |
return dt_; |
319 |
|
|
} |
320 |
|
|
template <typename Scalar> |
321 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_dt(const Scalar& dt) { |
322 |
|
|
// The model need to be updated after this changed |
323 |
|
✗ |
dt_ = dt; |
324 |
|
✗ |
g[8] = Scalar(-9.81) * dt_; |
325 |
|
✗ |
A.topRightCorner(6, 6) << Eigen::Matrix<Scalar, 6, 6>::Identity() * dt_; |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
template <typename Scalar> |
329 |
|
|
const typename Eigen::Matrix<Scalar, 3, 3>& |
330 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::get_gI() const { |
331 |
|
✗ |
return gI; |
332 |
|
|
} |
333 |
|
|
template <typename Scalar> |
334 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_gI( |
335 |
|
|
const typename MathBase::Matrix3s& inertia_matrix) { |
336 |
|
|
// The model need to be updated after this changed |
337 |
|
✗ |
if (static_cast<std::size_t>(inertia_matrix.size()) != 9) { |
338 |
|
✗ |
throw_pretty("Invalid argument: " |
339 |
|
|
<< "gI has wrong dimension : 3x3"); |
340 |
|
|
} |
341 |
|
✗ |
gI = inertia_matrix; |
342 |
|
|
} |
343 |
|
|
|
344 |
|
|
template <typename Scalar> |
345 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_min_fz_contact() const { |
346 |
|
|
// The model need to be updated after this changed |
347 |
|
✗ |
return min_fz_in_contact; |
348 |
|
|
} |
349 |
|
|
template <typename Scalar> |
350 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_min_fz_contact(const Scalar& min_fz) { |
351 |
|
|
// The model need to be updated after this changed |
352 |
|
✗ |
min_fz_in_contact = min_fz; |
353 |
|
|
} |
354 |
|
|
|
355 |
|
|
template <typename Scalar> |
356 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_max_fz_contact() const { |
357 |
|
|
// The model need to be updated after this changed |
358 |
|
✗ |
return max_fz; |
359 |
|
|
} |
360 |
|
|
template <typename Scalar> |
361 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_max_fz_contact( |
362 |
|
|
const Scalar& max_fz_) { |
363 |
|
|
// The model need to be updated after this changed |
364 |
|
✗ |
max_fz = max_fz_; |
365 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
366 |
|
✗ |
ub(6 * i + 5) = max_fz; |
367 |
|
|
} |
368 |
|
|
} |
369 |
|
|
|
370 |
|
|
/////////////////////////// |
371 |
|
|
//// get A & B matrix ///// |
372 |
|
|
/////////////////////////// |
373 |
|
|
template <typename Scalar> |
374 |
|
|
const typename Eigen::Matrix<Scalar, 12, 12>& |
375 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::get_A() const { |
376 |
|
✗ |
return A; |
377 |
|
|
} |
378 |
|
|
template <typename Scalar> |
379 |
|
|
const typename Eigen::Matrix<Scalar, 12, 12>& |
380 |
|
✗ |
ActionModelQuadrupedTpl<Scalar>::get_B() const { |
381 |
|
✗ |
return B; |
382 |
|
|
} |
383 |
|
|
|
384 |
|
|
template <typename Scalar> |
385 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_shoulder_hlim() const { |
386 |
|
✗ |
return sh_hlim; |
387 |
|
|
} |
388 |
|
|
template <typename Scalar> |
389 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_shoulder_hlim(const Scalar& hlim) { |
390 |
|
|
// The model need to be updated after this changed |
391 |
|
✗ |
sh_hlim = hlim; |
392 |
|
|
} |
393 |
|
|
|
394 |
|
|
template <typename Scalar> |
395 |
|
✗ |
const Scalar& ActionModelQuadrupedTpl<Scalar>::get_shoulder_weight() const { |
396 |
|
✗ |
return sh_weight; |
397 |
|
|
} |
398 |
|
|
template <typename Scalar> |
399 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_shoulder_weight( |
400 |
|
|
const Scalar& weight) { |
401 |
|
|
// The model need to be updated after this changed |
402 |
|
✗ |
sh_weight = weight; |
403 |
|
|
} |
404 |
|
|
|
405 |
|
|
// to modify the cost on the command : || fz - m*g/nb contact ||^2 |
406 |
|
|
// --> set to True |
407 |
|
|
template <typename Scalar> |
408 |
|
✗ |
const bool& ActionModelQuadrupedTpl<Scalar>::get_relative_forces() const { |
409 |
|
✗ |
return relative_forces; |
410 |
|
|
} |
411 |
|
|
template <typename Scalar> |
412 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_relative_forces( |
413 |
|
|
const bool& rel_forces) { |
414 |
|
✗ |
relative_forces = rel_forces; |
415 |
|
✗ |
uref_.setZero(); |
416 |
|
✗ |
if (relative_forces) { |
417 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
418 |
|
✗ |
if (gait[i] == 1) { |
419 |
|
✗ |
uref_[3 * i + 2] = (Scalar(9.81) * mass) / (gait.sum()); |
420 |
|
|
} |
421 |
|
|
} |
422 |
|
|
} |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
// To set implicit integration |
426 |
|
|
template <typename Scalar> |
427 |
|
✗ |
const bool& ActionModelQuadrupedTpl<Scalar>::get_implicit_integration() const { |
428 |
|
✗ |
return implicit_integration; |
429 |
|
|
} |
430 |
|
|
template <typename Scalar> |
431 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::set_implicit_integration( |
432 |
|
|
const bool& implicit) { |
433 |
|
✗ |
implicit_integration = implicit; |
434 |
|
|
} |
435 |
|
|
|
436 |
|
|
//////////////////////// |
437 |
|
|
// Update current model |
438 |
|
|
//////////////////////// |
439 |
|
|
|
440 |
|
|
template <typename Scalar> |
441 |
|
✗ |
void ActionModelQuadrupedTpl<Scalar>::update_model( |
442 |
|
|
const Eigen::Ref<const typename MathBase::MatrixXs>& l_feet, |
443 |
|
|
const Eigen::Ref<const typename MathBase::MatrixXs>& xref, |
444 |
|
|
const Eigen::Ref<const typename MathBase::MatrixXs>& S) { |
445 |
|
✗ |
if (static_cast<std::size_t>(l_feet.size()) != 12) { |
446 |
|
✗ |
throw_pretty("Invalid argument: " |
447 |
|
|
<< "l_feet matrix has wrong dimension (it should be : 3x4)"); |
448 |
|
|
} |
449 |
|
✗ |
if (static_cast<std::size_t>(xref.size()) != state_->get_nx()) { |
450 |
|
✗ |
throw_pretty("Invalid argument: " |
451 |
|
|
<< "Weights vector has wrong dimension (it should be " + |
452 |
|
|
std::to_string(state_->get_nx()) + ")"); |
453 |
|
|
} |
454 |
|
✗ |
if (static_cast<std::size_t>(S.size()) != 4) { |
455 |
|
✗ |
throw_pretty("Invalid argument: " |
456 |
|
|
<< "S vector has wrong dimension (it should be 4x1)"); |
457 |
|
|
} |
458 |
|
|
|
459 |
|
✗ |
xref_ = xref; |
460 |
|
✗ |
gait = S; |
461 |
|
|
|
462 |
|
|
// Set ref u vector according to nb of contact |
463 |
|
✗ |
uref_.setZero(); |
464 |
|
✗ |
if (relative_forces) { |
465 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
466 |
|
✗ |
if (gait[i] == 1) { |
467 |
|
✗ |
uref_[3 * i + 2] = (Scalar(9.81) * mass) / (gait.sum()); |
468 |
|
|
} |
469 |
|
|
} |
470 |
|
|
} |
471 |
|
|
|
472 |
|
✗ |
R_tmp << cos(xref(5, 0)), -sin(xref(5, 0)), 0, sin(xref(5, 0)), |
473 |
|
✗ |
cos(xref(5, 0)), 0, 0, 0, 1.0; |
474 |
|
|
|
475 |
|
✗ |
I_inv = (R_tmp.transpose() * gI * R_tmp).inverse(); // I_inv |
476 |
|
✗ |
lever_arms.block(0, 0, 2, 4) = l_feet.block(0, 0, 2, 4); |
477 |
|
|
|
478 |
|
✗ |
for (int i = 0; i < 4; i = i + 1) { |
479 |
|
✗ |
if (S(i, 0) != 0) { |
480 |
|
|
// set limit for normal force, (foot in contact with the ground) |
481 |
|
✗ |
ub(6 * i + 4) = -min_fz_in_contact; |
482 |
|
|
|
483 |
|
|
// B update |
484 |
|
✗ |
B.block(6, 3 * i, 3, 3).diagonal() << dt_ / mass, dt_ / mass, dt_ / mass; |
485 |
|
✗ |
lever_tmp = lever_arms.block(0, i, 3, 1) - xref.block(0, 0, 3, 1); |
486 |
|
✗ |
R_tmp << 0.0, -lever_tmp[2], lever_tmp[1], lever_tmp[2], 0.0, |
487 |
|
✗ |
-lever_tmp[0], -lever_tmp[1], lever_tmp[0], 0.0; |
488 |
|
✗ |
B.block(9, 3 * i, 3, 3) << dt_ * I_inv * R_tmp; |
489 |
|
|
} else { |
490 |
|
|
// set limit for normal force at 0.0 |
491 |
|
✗ |
ub(6 * i + 4) = Scalar(0.0); |
492 |
|
✗ |
B.block(6, 3 * i, 3, 3).setZero(); |
493 |
|
✗ |
B.block(9, 3 * i, 3, 3).setZero(); |
494 |
|
|
}; |
495 |
|
|
}; |
496 |
|
|
} |
497 |
|
|
} // namespace quadruped_walkgen |
498 |
|
|
|
499 |
|
|
#endif |
500 |
|
|
|