9#include "crocoddyl/multibody/utils/quadruped-gaits.hpp"
11#include "crocoddyl/core/costs/residual.hpp"
15SimpleQuadrupedGaitProblem::SimpleQuadrupedGaitProblem(
16 const pinocchio::Model& rmodel,
const std::string& lf_foot,
17 const std::string& rf_foot,
const std::string& lh_foot,
18 const std::string& rh_foot)
21 lf_foot_id_(rmodel_.getFrameId(
23 (pinocchio::FrameType)(pinocchio::JOINT | pinocchio::FIXED_JOINT |
25 rf_foot_id_(rmodel_.getFrameId(
27 (pinocchio::FrameType)(pinocchio::JOINT | pinocchio::FIXED_JOINT |
29 lh_foot_id_(rmodel_.getFrameId(
31 (pinocchio::FrameType)(pinocchio::JOINT | pinocchio::FIXED_JOINT |
33 rh_foot_id_(rmodel_.getFrameId(
35 (pinocchio::FrameType)(pinocchio::JOINT | pinocchio::FIXED_JOINT |
37 state_(std::make_shared<crocoddyl::StateMultibody>(
38 std::make_shared<pinocchio::Model>(rmodel_))),
40 std::make_shared<crocoddyl::ActuationModelFloatingBase>(state_)),
42 defaultstate_(rmodel_.nq + rmodel_.nv) {
43 defaultstate_.head(rmodel_.nq) = rmodel_.referenceConfigurations[
"standing"];
44 defaultstate_.tail(rmodel_.nv).setZero();
47SimpleQuadrupedGaitProblem::~SimpleQuadrupedGaitProblem() {}
49std::shared_ptr<crocoddyl::ShootingProblem>
50SimpleQuadrupedGaitProblem::createWalkingProblem(
51 const Eigen::VectorXd& x0,
const double steplength,
const double stepheight,
52 const double timestep,
const std::size_t stepknots,
53 const std::size_t supportknots) {
57 const Eigen::VectorBlock<const Eigen::VectorXd> q0 = x0.head(nq);
58 pinocchio::forwardKinematics(rmodel_, rdata_, q0);
59 pinocchio::centerOfMass(rmodel_, rdata_, q0);
60 pinocchio::updateFramePlacements(rmodel_, rdata_);
62 const pinocchio::SE3::Vector3& rf_foot_pos0 =
63 rdata_.oMf[rf_foot_id_].translation();
64 const pinocchio::SE3::Vector3& rh_foot_pos0 =
65 rdata_.oMf[rh_foot_id_].translation();
66 const pinocchio::SE3::Vector3& lf_foot_pos0 =
67 rdata_.oMf[lf_foot_id_].translation();
68 const pinocchio::SE3::Vector3& lh_foot_pos0 =
69 rdata_.oMf[lh_foot_id_].translation();
71 pinocchio::SE3::Vector3 comRef =
72 (rf_foot_pos0 + rh_foot_pos0 + lf_foot_pos0 + lh_foot_pos0) / 4;
73 comRef[2] = rdata_.com[0][2];
76 std::vector<std::shared_ptr<crocoddyl::ActionModelAbstract> > loco3d_model;
77 std::vector<std::shared_ptr<crocoddyl::ActionModelAbstract> > rh_step,
78 rf_step, lh_step, lf_step;
81 std::vector<pinocchio::FrameIndex> support_feet;
82 support_feet.push_back(lf_foot_id_);
83 support_feet.push_back(rf_foot_id_);
84 support_feet.push_back(lh_foot_id_);
85 support_feet.push_back(rh_foot_id_);
86 Eigen::Vector3d nullCoM =
87 Eigen::Vector3d::Constant(std::numeric_limits<double>::infinity());
88 std::vector<std::shared_ptr<crocoddyl::ActionModelAbstract> > doubleSupport(
89 supportknots, createSwingFootModel(timestep, support_feet, nullCoM));
91 const pinocchio::FrameIndex rh_s[] = {lf_foot_id_, rf_foot_id_, lh_foot_id_};
92 const pinocchio::FrameIndex rf_s[] = {lf_foot_id_, lh_foot_id_, rh_foot_id_};
93 const pinocchio::FrameIndex lh_s[] = {lf_foot_id_, rf_foot_id_, rh_foot_id_};
94 const pinocchio::FrameIndex lf_s[] = {rf_foot_id_, lh_foot_id_, rh_foot_id_};
96 std::vector<pinocchio::FrameIndex> rh_support(
97 rh_s, rh_s +
sizeof(rh_s) /
sizeof(rh_s[0]));
98 std::vector<pinocchio::FrameIndex> rf_support(
99 rf_s, rf_s +
sizeof(rf_s) /
sizeof(rf_s[0]));
100 std::vector<pinocchio::FrameIndex> lh_support(
101 lh_s, lh_s +
sizeof(lh_s) /
sizeof(lh_s[0]));
102 std::vector<pinocchio::FrameIndex> lf_support(
103 lf_s, lf_s +
sizeof(lf_s) /
sizeof(lf_s[0]));
105 std::vector<pinocchio::FrameIndex> rh_foot(1, rh_foot_id_);
106 std::vector<pinocchio::FrameIndex> rf_foot(1, rf_foot_id_);
107 std::vector<pinocchio::FrameIndex> lf_foot(1, lf_foot_id_);
108 std::vector<pinocchio::FrameIndex> lh_foot(1, lh_foot_id_);
110 std::vector<Eigen::Vector3d> rh_foot_pos0_v(1, rh_foot_pos0);
111 std::vector<Eigen::Vector3d> lh_foot_pos0_v(1, lh_foot_pos0);
112 std::vector<Eigen::Vector3d> rf_foot_pos0_v(1, rf_foot_pos0);
113 std::vector<Eigen::Vector3d> lf_foot_pos0_v(1, lf_foot_pos0);
116 createFootStepModels(timestep, comRef, rh_foot_pos0_v, 0.5 * steplength,
117 stepheight, stepknots, rh_support, rh_foot);
119 createFootStepModels(timestep, comRef, rf_foot_pos0_v, 0.5 * steplength,
120 stepheight, stepknots, rf_support, rf_foot);
123 rh_step = createFootStepModels(timestep, comRef, rh_foot_pos0_v, steplength,
124 stepheight, stepknots, rh_support, rh_foot);
125 rf_step = createFootStepModels(timestep, comRef, rf_foot_pos0_v, steplength,
126 stepheight, stepknots, rf_support, rf_foot);
128 lh_step = createFootStepModels(timestep, comRef, lh_foot_pos0_v, steplength,
129 stepheight, stepknots, lh_support, lh_foot);
130 lf_step = createFootStepModels(timestep, comRef, lf_foot_pos0_v, steplength,
131 stepheight, stepknots, lf_support, lf_foot);
133 loco3d_model.insert(loco3d_model.end(), doubleSupport.begin(),
134 doubleSupport.end());
135 loco3d_model.insert(loco3d_model.end(), rh_step.begin(), rh_step.end());
136 loco3d_model.insert(loco3d_model.end(), rf_step.begin(), rf_step.end());
137 loco3d_model.insert(loco3d_model.end(), doubleSupport.begin(),
138 doubleSupport.end());
139 loco3d_model.insert(loco3d_model.end(), lh_step.begin(), lh_step.end());
140 loco3d_model.insert(loco3d_model.end(), lf_step.begin(), lf_step.end());
142 return std::make_shared<crocoddyl::ShootingProblem>(x0, loco3d_model,
143 loco3d_model.back());
146std::vector<std::shared_ptr<crocoddyl::ActionModelAbstract> >
147SimpleQuadrupedGaitProblem::createFootStepModels(
148 double timestep, Eigen::Vector3d& com_pos0,
149 std::vector<Eigen::Vector3d>& feet_pos0,
double steplength,
150 double stepheight, std::size_t n_knots,
151 const std::vector<pinocchio::FrameIndex>& support_foot_ids,
152 const std::vector<pinocchio::FrameIndex>& swingFootIds) {
154 static_cast<std::size_t
>(support_foot_ids.size() + swingFootIds.size());
155 double com_percentage =
156 static_cast<double>(swingFootIds.size()) /
static_cast<double>(n_legs);
159 std::vector<std::shared_ptr<ActionModelAbstract> > foot_swing_model;
160 std::vector<pinocchio::FrameIndex> id_foot_swing_task;
161 std::vector<pinocchio::SE3> ref_foot_swing_task;
162 for (std::size_t k = 0; k < n_knots; ++k) {
164 Eigen::Vector3d dp = Eigen::Vector3d::Zero();
165 id_foot_swing_task.clear();
166 ref_foot_swing_task.clear();
167 for (std::size_t i = 0; i < swingFootIds.size(); ++i) {
169 std::size_t phaseknots = n_knots >> 1;
170 _kp1_n =
static_cast<double>(k + 1) /
static_cast<double>(n_knots);
171 double _k =
static_cast<double>(k);
172 double _phaseknots =
static_cast<double>(phaseknots);
174 dp << steplength * _kp1_n, 0., stepheight * _k / _phaseknots;
175 else if (k == phaseknots)
176 dp << steplength * _kp1_n, 0., stepheight;
178 dp << steplength * _kp1_n, 0.,
179 stepheight * (1 - (_k - _phaseknots) / _phaseknots);
180 Eigen::Vector3d tref = feet_pos0[i] + dp;
182 id_foot_swing_task.push_back(swingFootIds[i]);
183 ref_foot_swing_task.push_back(
184 pinocchio::SE3(Eigen::Matrix3d::Identity(), tref));
188 Eigen::Vector3d com_task =
189 Eigen::Vector3d(steplength * _kp1_n, 0., 0.) * com_percentage +
191 foot_swing_model.push_back(
192 createSwingFootModel(timestep, support_foot_ids, com_task,
193 id_foot_swing_task, ref_foot_swing_task));
196 foot_swing_model.push_back(createFootSwitchModel(
197 support_foot_ids, id_foot_swing_task, ref_foot_swing_task));
200 com_pos0 += Eigen::Vector3d(steplength * com_percentage, 0., 0.);
201 for (std::size_t i = 0; i < feet_pos0.size(); ++i) {
202 feet_pos0[i] += Eigen::Vector3d(steplength, 0., 0.);
204 return foot_swing_model;
207std::shared_ptr<crocoddyl::ActionModelAbstract>
208SimpleQuadrupedGaitProblem::createSwingFootModel(
209 double timestep,
const std::vector<pinocchio::FrameIndex>& support_foot_ids,
210 const Eigen::Vector3d& com_task,
211 const std::vector<pinocchio::FrameIndex>& id_foot_swing_task,
212 const std::vector<pinocchio::SE3>& ref_foot_swing_task) {
214 std::shared_ptr<crocoddyl::ContactModelMultiple> contact_model =
215 std::make_shared<crocoddyl::ContactModelMultiple>(state_,
216 actuation_->get_nu());
217 for (std::vector<pinocchio::FrameIndex>::const_iterator it =
218 support_foot_ids.begin();
219 it != support_foot_ids.end(); ++it) {
220 std::shared_ptr<crocoddyl::ContactModelAbstract> support_contact_model =
221 std::make_shared<crocoddyl::ContactModel3D>(
222 state_, *it, Eigen::Vector3d::Zero(),
223 pinocchio::ReferenceFrame::LOCAL_WORLD_ALIGNED,
224 actuation_->get_nu(), Eigen::Vector2d(0., 50.));
225 contact_model->addContact(rmodel_.frames[*it].name +
"_contact",
226 support_contact_model);
230 std::shared_ptr<crocoddyl::CostModelSum> cost_model =
231 std::make_shared<crocoddyl::CostModelSum>(state_, actuation_->get_nu());
232 if (com_task.array().allFinite()) {
233 std::shared_ptr<crocoddyl::CostModelAbstract> com_track =
234 std::make_shared<crocoddyl::CostModelResidual>(
235 state_, std::make_shared<crocoddyl::ResidualModelCoMPosition>(
236 state_, com_task, actuation_->get_nu()));
237 cost_model->addCost(
"comTrack", com_track, 1e6);
239 if (!id_foot_swing_task.empty() && !ref_foot_swing_task.empty()) {
240 for (std::size_t i = 0; i < id_foot_swing_task.size(); ++i) {
241 const pinocchio::FrameIndex
id = id_foot_swing_task[i];
242 std::shared_ptr<crocoddyl::CostModelAbstract> foot_track =
243 std::make_shared<crocoddyl::CostModelResidual>(
245 std::make_shared<crocoddyl::ResidualModelFrameTranslation>(
246 state_,
id, ref_foot_swing_task[i].translation(),
247 actuation_->get_nu()));
248 cost_model->addCost(rmodel_.frames[
id].name +
"_footTrack", foot_track,
252 Eigen::VectorXd state_weights(2 * rmodel_.nv);
253 state_weights.head<3>().fill(0.);
254 state_weights.segment<3>(3).fill(pow(500., 2));
255 state_weights.segment(6, rmodel_.nv - 6).fill(pow(0.01, 2));
256 state_weights.segment(rmodel_.nv, 6).fill(pow(10., 2));
257 state_weights.segment(rmodel_.nv + 6, rmodel_.nv - 6).fill(pow(1., 2));
258 std::shared_ptr<crocoddyl::ActivationModelAbstract> state_activation =
259 std::make_shared<crocoddyl::ActivationModelWeightedQuad>(state_weights);
260 std::shared_ptr<crocoddyl::CostModelAbstract> state_reg =
261 std::make_shared<crocoddyl::CostModelResidual>(
262 state_, state_activation,
263 std::make_shared<crocoddyl::ResidualModelState>(
264 state_, defaultstate_, actuation_->get_nu()));
265 std::shared_ptr<crocoddyl::CostModelAbstract> ctrl_reg =
266 std::make_shared<crocoddyl::CostModelResidual>(
267 state_, std::make_shared<crocoddyl::ResidualModelControl>(
268 state_, actuation_->get_nu()));
269 cost_model->addCost(
"stateReg", state_reg, 1e1);
270 cost_model->addCost(
"ctrlReg", ctrl_reg, 1e-1);
274 std::shared_ptr<crocoddyl::DifferentialActionModelAbstract> dmodel =
275 std::make_shared<crocoddyl::DifferentialActionModelContactFwdDynamics>(
276 state_, actuation_, contact_model, cost_model);
277 return std::make_shared<crocoddyl::IntegratedActionModelEuler>(dmodel,
281std::shared_ptr<ActionModelAbstract>
282SimpleQuadrupedGaitProblem::createFootSwitchModel(
283 const std::vector<pinocchio::FrameIndex>& support_foot_ids,
284 const std::vector<pinocchio::FrameIndex>& id_foot_swing_task,
285 const std::vector<pinocchio::SE3>& ref_foot_swing_task,
286 bool pseudo_impulse) {
287 if (pseudo_impulse) {
288 return createPseudoImpulseModel(support_foot_ids, id_foot_swing_task,
289 ref_foot_swing_task);
291 return createImpulseModel(support_foot_ids, id_foot_swing_task,
292 ref_foot_swing_task);
296std::shared_ptr<crocoddyl::ActionModelAbstract>
297SimpleQuadrupedGaitProblem::createPseudoImpulseModel(
298 const std::vector<pinocchio::FrameIndex>& support_foot_ids,
299 const std::vector<pinocchio::FrameIndex>& id_foot_swing_task,
300 const std::vector<pinocchio::SE3>& ref_foot_swing_task) {
302 std::shared_ptr<crocoddyl::ContactModelMultiple> contact_model =
303 std::make_shared<crocoddyl::ContactModelMultiple>(state_,
304 actuation_->get_nu());
305 for (std::vector<pinocchio::FrameIndex>::const_iterator it =
306 support_foot_ids.begin();
307 it != support_foot_ids.end(); ++it) {
308 std::shared_ptr<crocoddyl::ContactModelAbstract> support_contact_model =
309 std::make_shared<crocoddyl::ContactModel3D>(
310 state_, *it, Eigen::Vector3d::Zero(),
311 pinocchio::ReferenceFrame::LOCAL_WORLD_ALIGNED,
312 actuation_->get_nu(), Eigen::Vector2d(0., 50.));
313 contact_model->addContact(rmodel_.frames[*it].name +
"_contact",
314 support_contact_model);
318 std::shared_ptr<crocoddyl::CostModelSum> cost_model =
319 std::make_shared<crocoddyl::CostModelSum>(state_, actuation_->get_nu());
320 if (!id_foot_swing_task.empty() && !ref_foot_swing_task.empty()) {
321 for (std::size_t i = 0; i < id_foot_swing_task.size(); ++i) {
322 const pinocchio::FrameIndex
id = id_foot_swing_task[i];
323 std::shared_ptr<crocoddyl::CostModelAbstract> foot_track =
324 std::make_shared<crocoddyl::CostModelResidual>(
326 std::make_shared<crocoddyl::ResidualModelFrameTranslation>(
327 state_,
id, ref_foot_swing_task[i].translation(),
328 actuation_->get_nu()));
329 std::shared_ptr<crocoddyl::CostModelAbstract> impulse_foot_vel =
330 std::make_shared<crocoddyl::CostModelResidual>(
332 std::make_shared<crocoddyl::ResidualModelFrameVelocity>(
333 state_,
id, pinocchio::Motion::Zero(),
334 pinocchio::ReferenceFrame::LOCAL, actuation_->get_nu()));
335 cost_model->addCost(rmodel_.frames[
id].name +
"_footTrack", foot_track,
337 cost_model->addCost(rmodel_.frames[
id].name +
"_impulseVel",
338 impulse_foot_vel, 1e6);
341 Eigen::VectorXd state_weights(2 * rmodel_.nv);
342 state_weights.head<3>().fill(0.);
343 state_weights.segment<3>(3).fill(pow(500., 2));
344 state_weights.segment(6, rmodel_.nv - 6).fill(pow(0.01, 2));
345 state_weights.segment(rmodel_.nv, rmodel_.nv).fill(pow(10., 2));
346 std::shared_ptr<crocoddyl::ActivationModelAbstract> state_activation =
347 std::make_shared<crocoddyl::ActivationModelWeightedQuad>(state_weights);
348 std::shared_ptr<crocoddyl::CostModelAbstract> state_reg =
349 std::make_shared<crocoddyl::CostModelResidual>(
350 state_, state_activation,
351 std::make_shared<crocoddyl::ResidualModelState>(
352 state_, defaultstate_, actuation_->get_nu()));
353 std::shared_ptr<crocoddyl::CostModelAbstract> ctrl_reg =
354 std::make_shared<crocoddyl::CostModelResidual>(
355 state_, std::make_shared<crocoddyl::ResidualModelControl>(
356 state_, actuation_->get_nu()));
357 cost_model->addCost(
"stateReg", state_reg, 1e1);
358 cost_model->addCost(
"ctrlReg", ctrl_reg, 1e-3);
362 std::shared_ptr<crocoddyl::DifferentialActionModelAbstract> dmodel =
363 std::make_shared<crocoddyl::DifferentialActionModelContactFwdDynamics>(
364 state_, actuation_, contact_model, cost_model);
365 return std::make_shared<crocoddyl::IntegratedActionModelEuler>(dmodel, 0.);
368std::shared_ptr<ActionModelAbstract>
369SimpleQuadrupedGaitProblem::createImpulseModel(
370 const std::vector<pinocchio::FrameIndex>& support_foot_ids,
371 const std::vector<pinocchio::FrameIndex>& id_foot_swing_task,
372 const std::vector<pinocchio::SE3>& ref_foot_swing_task) {
374 std::shared_ptr<crocoddyl::ImpulseModelMultiple> impulse_model =
375 std::make_shared<crocoddyl::ImpulseModelMultiple>(state_);
376 for (std::vector<pinocchio::FrameIndex>::const_iterator it =
377 support_foot_ids.begin();
378 it != support_foot_ids.end(); ++it) {
379 std::shared_ptr<crocoddyl::ImpulseModelAbstract> support_contact_model =
380 std::make_shared<crocoddyl::ImpulseModel3D>(
381 state_, *it, pinocchio::ReferenceFrame::LOCAL_WORLD_ALIGNED);
382 impulse_model->addImpulse(rmodel_.frames[*it].name +
"_impulse",
383 support_contact_model);
387 std::shared_ptr<crocoddyl::CostModelSum> cost_model =
388 std::make_shared<crocoddyl::CostModelSum>(state_, 0);
389 if (!id_foot_swing_task.empty() && !ref_foot_swing_task.empty()) {
390 for (std::size_t i = 0; i < id_foot_swing_task.size(); ++i) {
391 const pinocchio::FrameIndex
id = id_foot_swing_task[i];
392 std::shared_ptr<crocoddyl::CostModelAbstract> foot_track =
393 std::make_shared<crocoddyl::CostModelResidual>(
395 std::make_shared<crocoddyl::ResidualModelFrameTranslation>(
396 state_,
id, ref_foot_swing_task[i].translation(), 0));
397 cost_model->addCost(rmodel_.frames[
id].name +
"_footTrack", foot_track,
401 Eigen::VectorXd state_weights(2 * rmodel_.nv);
402 state_weights.head<6>().fill(1.);
403 state_weights.segment(6, rmodel_.nv - 6).fill(pow(10., 2));
404 state_weights.segment(rmodel_.nv, rmodel_.nv).fill(pow(10., 2));
405 std::shared_ptr<crocoddyl::ActivationModelAbstract> state_activation =
406 std::make_shared<crocoddyl::ActivationModelWeightedQuad>(state_weights);
407 std::shared_ptr<crocoddyl::CostModelAbstract> state_reg =
408 std::make_shared<crocoddyl::CostModelResidual>(
409 state_, state_activation,
410 std::make_shared<crocoddyl::ResidualModelState>(state_, defaultstate_,
412 cost_model->addCost(
"stateReg", state_reg, 1e1);
416 return std::make_shared<crocoddyl::ActionModelImpulseFwdDynamics>(
417 state_, impulse_model, cost_model);
420const Eigen::VectorXd& SimpleQuadrupedGaitProblem::get_defaultState()
const {
421 return defaultstate_;