67 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_pos;
68 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_vel;
69 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_acc;
72 Eigen::Matrix<double, 12, 1> desired_tau;
75 std_msgs::Float64MultiArray base_pose_cmd_msg;
76 std_msgs::Float64MultiArray base_twist_cmd_msg;
78 base_pose_cmd_msg.data.resize(6);
79 base_twist_cmd_msg.data.resize(6);
82 ros::Rate loop_rate(200);
88 desired_base_pos << 0,
91 desired_base_vel.setZero();
92 desired_base_acc.setZero();
93 desired_base_ori.setZero();
95 desired_f_pos = this->
fPos;
97 for (
int i = 0; i < 4; i++)
99 desired_f_vel(i).setZero();
100 desired_f_acc(i).setZero();
103 auto start = std::chrono::steady_clock::now();
118 auto end = std::chrono::steady_clock::now();
120 std::chrono::duration<double, std::micro> diff = end - start;
122 ROS_INFO_STREAM(
"HO run-time: " << diff.count() <<
" microseconds. \n");
130 base_pose_cmd_msg.data[0] = desired_base_pos(0);
131 base_pose_cmd_msg.data[1] = desired_base_pos(1);
132 base_pose_cmd_msg.data[2] = desired_base_pos(2);
133 base_pose_cmd_msg.data[3] = desired_base_ori(0);
134 base_pose_cmd_msg.data[4] = desired_base_ori(1);
135 base_pose_cmd_msg.data[5] = desired_base_ori(2);
138 base_twist_cmd_msg.data[0] = desired_base_vel(0);
139 base_twist_cmd_msg.data[1] = desired_base_vel(1);
140 base_twist_cmd_msg.data[2] = desired_base_vel(2);
141 base_twist_cmd_msg.data[3] = 0;
142 base_twist_cmd_msg.data[4] = 0;
143 base_twist_cmd_msg.data[5] = 0;
161 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_pos;
162 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_vel;
163 Eigen::Matrix<Eigen::Vector3d, 4, 1> desired_f_acc;
166 Eigen::Matrix<double, 12, 1> desired_tau;
169 std_msgs::Float64MultiArray base_pose_cmd_msg;
170 std_msgs::Float64MultiArray base_twist_cmd_msg;
172 base_pose_cmd_msg.data.resize(6);
173 base_twist_cmd_msg.data.resize(6);
176 ros::Rate loop_rate(200);
185 desired_base_pos << 0,
188 0.05 * std::sin(timefactor*ros::Time::now().toSec()) + 0.2;
189 desired_base_vel.setZero();
190 desired_base_vel << 0,
192 timefactor * 0.05 * std::cos(timefactor*ros::Time::now().toSec());
193 desired_base_acc.setZero();
194 desired_base_acc << 0,
196 - timefactor * timefactor * 0.05 * std::sin(timefactor*ros::Time::now().toSec());
197 desired_base_ori.setZero();
199 desired_base_ori(0) = 0.3 * std::cos(timefactor*ros::Time::now().toSec());
200 desired_base_ori(2) = 0.15 * std::sin(timefactor*ros::Time::now().toSec());
202 desired_f_pos = this->
fPos;
204 for (
int i = 0; i < 4; i++)
206 desired_f_vel(i).setZero();
207 desired_f_acc(i).setZero();
213 auto start = std::chrono::steady_clock::now();
228 auto end = std::chrono::steady_clock::now();
230 std::chrono::duration<double, std::micro> diff = end - start;
232 ROS_INFO_STREAM(
"HO run-time: " << diff.count() <<
" microseconds. \n");
240 base_pose_cmd_msg.data[0] = desired_base_pos(0);
241 base_pose_cmd_msg.data[1] = desired_base_pos(1);
242 base_pose_cmd_msg.data[2] = desired_base_pos(2);
243 base_pose_cmd_msg.data[3] = desired_base_ori(0);
244 base_pose_cmd_msg.data[4] = desired_base_ori(1);
245 base_pose_cmd_msg.data[5] = desired_base_ori(2);
248 base_twist_cmd_msg.data[0] = desired_base_vel(0);
249 base_twist_cmd_msg.data[1] = desired_base_vel(1);
250 base_twist_cmd_msg.data[2] = desired_base_vel(2);
251 base_twist_cmd_msg.data[3] = 0;
252 base_twist_cmd_msg.data[4] = 0;
253 base_twist_cmd_msg.data[5] = 0;
267 const Eigen::Matrix<double, 3, 1> &_desired_base_vel,
268 const Eigen::Matrix<double, 3, 1> &_desired_base_acc,
269 const Eigen::Matrix<double, 3, 1> &_desired_base_ori,
270 const Eigen::Matrix<Eigen::Vector3d, 4, 1> &_desired_f_pos,
271 const Eigen::Matrix<Eigen::Vector3d, 4, 1> &_desired_f_vel,
272 const Eigen::Matrix<Eigen::Vector3d, 4, 1> &_desired_f_acc,
273 const Eigen::Matrix<Eigen::Vector3d, 4, 1> &_f_pos,
274 const Eigen::Matrix<Eigen::Vector3d, 4, 1> &_f_vel,
275 const Eigen::Matrix<double, 18, 1> &_q,
276 const Eigen::Matrix<double, 18, 1> &_u,
283 Eigen::Matrix<double, 12, 1> desired_tau;
285 Eigen::VectorXd x_opt;
298 std::vector<Task> tasks;
302 Eigen::Matrix<double, 18, 18> M;
303 Eigen::Matrix<double, 18, 1>
b;
304 Eigen::Matrix<double, 18, 1> g;
305 Eigen::Matrix<double, Eigen::Dynamic, 18> J_c;
306 Eigen::Matrix<double, Eigen::Dynamic, 18> dot_J_c;
309 Eigen::Matrix<double, 3, 18> J_P_fb;
310 Eigen::Matrix<double, 3, 18> J_R_fb;
311 Eigen::Matrix<double, 3, 18> J_P_fl;
312 Eigen::Matrix<double, 3, 18> J_P_fr;
313 Eigen::Matrix<double, 3, 18> J_P_rl;
314 Eigen::Matrix<double, 3, 18> J_P_rr;
316 Eigen::Matrix<double, 3, 18> dot_J_P_fb;
317 Eigen::Matrix<double, 3, 18> dot_J_R_fb;
318 Eigen::Matrix<double, 3, 18> dot_J_P_fl;
319 Eigen::Matrix<double, 3, 18> dot_J_P_fr;
320 Eigen::Matrix<double, 3, 18> dot_J_P_rl;
321 Eigen::Matrix<double, 3, 18> dot_J_P_rr;
324 Eigen::Matrix<double, 12, 1> q_r_nom;
330 Eigen::Matrix<double, 3, 3> rotationWToC;
331 Eigen::Matrix<double, 12, 1> tau_min;
332 Eigen::Matrix<double, 12, 1> tau_max;
334 std::vector<Kinematics::LegType> contact_legs;
335 std::vector<Kinematics::LegType> swing_legs;
345 Eigen::Matrix3d k_p_fb_pos = 15*Eigen::Matrix3d::Identity();
346 Eigen::Matrix3d k_d_fb_pos = 2*Eigen::Matrix3d::Identity();
347 Eigen::Matrix3d k_p_fb_rot = 30*Eigen::Matrix3d::Identity();
348 Eigen::Matrix3d k_d_fb_rot = 2*Eigen::Matrix3d::Identity();
349 Eigen::Matrix3d k_p_fl = 2*Eigen::Matrix3d::Identity();
350 Eigen::Matrix3d k_d_fl = 2*Eigen::Matrix3d::Identity();
351 Eigen::Matrix3d k_p_fr = 2*Eigen::Matrix3d::Identity();
352 Eigen::Matrix3d k_d_fr = 2*Eigen::Matrix3d::Identity();
353 Eigen::Matrix3d k_p_rl = 2*Eigen::Matrix3d::Identity();
354 Eigen::Matrix3d k_d_rl = 2*Eigen::Matrix3d::Identity();
355 Eigen::Matrix3d k_p_rr = 2*Eigen::Matrix3d::Identity();
356 Eigen::Matrix3d k_d_rr = 2*Eigen::Matrix3d::Identity();
359 Eigen::Matrix<double, 12, 12> k_p_pt = 15*Eigen::Matrix<double, 12, 12>::Identity();
360 Eigen::Matrix<double, 12, 12> k_d_pt = 4*Eigen::Matrix<double, 12, 12>::Identity();
367 for (
size_t i = 0; i < 4; i++)
383 const unsigned int n_c = contact_legs.size();
384 const unsigned int n_s = swing_legs.size();
387 const unsigned int state_dim = 18 + 3*n_c;
390 t_eom.
A_eq.resize(6, state_dim);
391 t_eom.
b_eq.resize(6, 1);
393 t_cmc.
A_eq.resize(3*n_c, state_dim);
394 t_cmc.
b_eq.resize(3*n_c, 1);
396 t_cftl.
A_ineq.resize(4*n_c + 24, state_dim);
397 t_cftl.
b_ineq.resize(4*n_c + 24, 1);
399 t_mt.
A_eq.resize(18, state_dim);
400 t_mt.
b_eq.resize(18, 1);
402 t_pt.
A_eq.resize(12, state_dim);
403 t_pt.
b_eq.resize(12, 1);
405 t_cfm.
A_eq.resize(3*n_c, state_dim);
406 t_cfm.
b_eq.resize(3*n_c, 1);
409 x_opt.resize(state_dim, 1);
411 J_c.resize(3*n_c, 18);
412 dot_J_c.resize(3*n_c, 18);
416 kindr::EulerAnglesXyz<double> base_ori(_q.segment(3,3));
418 kindr::EulerAnglesXyz<double> desired_base_ori_kindr(_desired_base_ori);
420 Eigen::Vector3d orientation_error = desired_base_ori_kindr.boxMinus(base_ori);
435 Kinematics::BodyType::base,
438 Kinematics::BodyType::base,
441 Kinematics::BodyType::foot,
444 Kinematics::BodyType::foot,
447 Kinematics::BodyType::foot,
450 Kinematics::BodyType::foot,
454 Kinematics::BodyType::base,
458 Kinematics::BodyType::base,
462 Kinematics::BodyType::foot,
466 Kinematics::BodyType::foot,
470 Kinematics::BodyType::foot,
474 Kinematics::BodyType::foot,
510 tau_max.setConstant(40);
511 tau_min.setConstant(-40);
514 t_eom.
A_eq.leftCols(18) = M.topRows(6);
515 t_eom.
A_eq.rightCols(3*n_c) = - J_c.transpose().topRows(6);
516 t_eom.
b_eq = - (
b.topRows(6) + g.topRows(6));
520 for (
size_t i = 0; i < n_c; i++)
522 t_cftl.
A_ineq.block(4*i, 0, 1, state_dim).setZero();
523 t_cftl.
A_ineq.block(4*i, 18 + 3*i, 1, 3) = (h.transpose() - n.transpose() * mu);
525 t_cftl.
A_ineq.block(4*i + 1, 0, 1, state_dim).setZero();
526 t_cftl.
A_ineq.block(4*i + 1, 18 + 3*i, 1, 3) = - (h.transpose() + n.transpose() * mu);
528 t_cftl.
A_ineq.block(4*i + 2, 0, 1, state_dim).setZero();
529 t_cftl.
A_ineq.block(4*i + 2, 18 + 3*i, 1, 3) = (l.transpose() - n.transpose() * mu);
531 t_cftl.
A_ineq.block(4*i + 3, 0, 1, state_dim).setZero();
532 t_cftl.
A_ineq.block(4*i + 3, 18 + 3*i, 1, 3) = - (l.transpose() + n.transpose() * mu);
535 t_cftl.
b_ineq.topRows(4*n_c).setZero();
540 t_cftl.
A_ineq.block(4*n_c, 0, 12, 18) = M.bottomRows(12);
541 t_cftl.
A_ineq.block(4*n_c, 18, 12, 3*n_c) = - J_c.transpose().bottomRows(12);
542 t_cftl.
b_ineq.block(4*n_c, 0, 12, 1) = tau_max - (
b.bottomRows(12) + g.bottomRows(12));
548 t_cftl.
A_ineq.block(4*n_c + 12, 0, 12, 18) = - M.bottomRows(12);
549 t_cftl.
A_ineq.block(4*n_c + 12, 18, 12, 3*n_c) = J_c.transpose().bottomRows(12);
550 t_cftl.
b_ineq.block(4*n_c + 12, 0, 12, 1) = - tau_min + (
b.bottomRows(12) + g.bottomRows(12));
553 t_cmc.
A_eq.leftCols(18) = J_c;
554 t_cmc.
A_eq.rightCols(3*n_c).setZero();
555 t_cmc.
b_eq = - dot_J_c * _u;
562 t_mt.
A_eq.block(0, 0, 3, state_dim).leftCols(18) = J_P_fb;
563 t_mt.
A_eq.block(0, 0, 3, state_dim).rightCols(3*n_c).setZero();
564 t_mt.
b_eq.block(0, 0, 3, 1) = _desired_base_acc + k_p_fb_pos * (_desired_base_pos - _q.topRows(3))
565 + k_d_fb_pos * (_desired_base_vel - _u.topRows(3)) - dot_J_P_fb * _u;
569 t_mt.
A_eq.block(3, 0, 3, state_dim).leftCols(18) = J_R_fb;
570 t_mt.
A_eq.block(3, 0, 3, state_dim).rightCols(3*n_c).setZero();
575 t_mt.
b_eq.block(3, 0, 3, 1) = k_p_fb_rot * (orientation_error)
576 + k_d_fb_rot * (- _u.segment(3,3)) - dot_J_R_fb * _u;
581 t_mt.
A_eq.block(6, 0, 3, state_dim).leftCols(18) = J_P_fl;
582 t_mt.
A_eq.block(6, 0, 3, state_dim).rightCols(3*n_c).setZero();
583 t_mt.
b_eq.block(6, 0, 3, 1) = _desired_f_acc(0) + k_p_fl * (_desired_f_pos(0) - _f_pos(0))
584 + k_d_fl * (_desired_f_vel(0) - _f_vel(0)) - dot_J_P_fl * _u;
587 t_mt.
A_eq.block(9, 0, 3, state_dim).leftCols(18) = J_P_fr;
588 t_mt.
A_eq.block(9, 0, 3, state_dim).rightCols(3*n_c).setZero();
589 t_mt.
b_eq.block(9, 0, 3, 1) = _desired_f_acc(1) + k_p_fr * (_desired_f_pos(1) - _f_pos(1))
590 + k_d_fr * (_desired_f_vel(1) - _f_vel(1)) - dot_J_P_fr * _u;
593 t_mt.
A_eq.block(12, 0, 3, state_dim).leftCols(18) = J_P_rl;
594 t_mt.
A_eq.block(12, 0, 3, state_dim).rightCols(3*n_c).setZero();
595 t_mt.
b_eq.block(12, 0, 3, 1) = _desired_f_acc(2) + k_p_rl * (_desired_f_pos(2) - _f_pos(2))
596 + k_d_rl * (_desired_f_vel(2) - _f_vel(2)) - dot_J_P_rl * _u;
599 t_mt.
A_eq.block(15, 0, 3, state_dim).leftCols(18) = J_P_rr;
600 t_mt.
A_eq.block(15, 0, 3, state_dim).rightCols(3*n_c).setZero();
601 t_mt.
b_eq.block(15, 0, 3, 1) = _desired_f_acc(3) + k_p_rr * (_desired_f_pos(3) - _f_pos(3))
602 + k_d_rr * (_desired_f_vel(3) - _f_vel(3)) - dot_J_P_rr * _u;
605 t_pt.
A_eq.leftCols(6).setZero();
606 t_pt.
A_eq.block(0, 6, 12, 12).setIdentity();
607 t_pt.
A_eq.rightCols(3*n_c).setZero();
608 t_pt.
b_eq = k_p_pt * (q_r_nom - _q.bottomRows(12)) + k_d_pt * (-_u.bottomRows(12));
611 t_cfm.
A_eq.leftCols(18).setZero();
612 t_cfm.
A_eq.rightCols(3*n_c).setIdentity();
613 t_cfm.
b_eq.setZero();
628 tasks.push_back(t_eom);
629 tasks.push_back(t_cftl);
630 tasks.push_back(t_cmc);
631 tasks.push_back(t_mt);
633 tasks.push_back(t_cfm);
635 Eigen::Matrix<Eigen::MatrixXd, 5, 1> A_ls;
636 Eigen::Matrix<Eigen::VectorXd, 5, 1> b_ls;
638 A_ls(0) = t_eom.
A_eq;
639 b_ls(0) = t_eom.
b_eq;
640 A_ls(1) = t_cmc.
A_eq;
641 b_ls(1) = t_cmc.
b_eq;
646 A_ls(4) = t_cfm.
A_eq;
647 b_ls(4) = t_cfm.
b_eq;
663 desired_tau = M.bottomRows(12) * x_opt.topRows(18) - J_c.transpose().bottomRows(12) * x_opt.bottomRows(3*n_c) +
b.bottomRows(12) + g.bottomRows(12);
680 const std::vector<Task> &_tasks,
685 Eigen::VectorXd x_opt(_state_dim);
686 Eigen::MatrixXd N(_state_dim, _state_dim);
687 Eigen::VectorXd z(_state_dim);
688 Eigen::MatrixXd stacked_A_eq;
689 Eigen::MatrixXd stacked_A_ineq;
690 Eigen::VectorXd stacked_b_ineq;
694 Eigen::MatrixXd E_ineq;
695 Eigen::VectorXd f_ineq;
698 Eigen::VectorXd stacked_v;
710 for (
Task t : _tasks)
719 if (
t.has_eq_constraint)
722 rowsA_eq =
t.A_eq.rows();
725 Eigen::MatrixXd stacked_A_eq_tmp = stacked_A_eq;
727 stacked_A_eq.resize(
t.A_eq.rows() + stacked_A_eq_tmp.rows(), _state_dim);
728 stacked_A_eq <<
t.A_eq,
738 if (
t.has_ineq_constraint)
741 rowsA_ineq =
t.A_ineq.rows();
744 Eigen::MatrixXd stacked_A_ineq_tmp = stacked_A_ineq;
746 stacked_A_ineq.resize(
t.A_ineq.rows() + stacked_A_ineq_tmp.rows(), _state_dim);
747 stacked_A_ineq <<
t.A_ineq,
751 Eigen::VectorXd stacked_b_ineq_tmp = stacked_b_ineq;
753 stacked_b_ineq.resize(
t.b_ineq.rows() + stacked_b_ineq_tmp.rows(), 1);
754 stacked_b_ineq <<
t.b_ineq,
765 v.resize(rowsA_ineq, 1);
766 xi.resize(colsN + rowsA_ineq, 1);
769 Q.resize(colsN + rowsA_ineq, colsN + rowsA_ineq);
770 c.resize(colsN + rowsA_ineq, 1);
772 if (
t.has_eq_constraint)
774 Q.topLeftCorner(colsN, colsN) = N.transpose() *
t.A_eq.transpose() *
t.A_eq * N;
775 Q.topRightCorner(colsN, rowsA_ineq).setZero();
776 Q.bottomLeftCorner(rowsA_ineq, colsN).setZero();
777 Q.bottomRightCorner(rowsA_ineq, rowsA_ineq).setIdentity();
779 c.topRows(colsN) = N.transpose() *
t.A_eq.transpose() * (
t.A_eq * x_opt -
t.b_eq);
780 c.bottomRows(rowsA_ineq).setZero();
785 Q.bottomRightCorner(rowsA_ineq, rowsA_ineq).setIdentity();
791 E_ineq.resize(stacked_A_ineq.rows() + rowsA_ineq, colsN + rowsA_ineq);
792 f_ineq.resize(stacked_A_ineq.rows() + rowsA_ineq, 1);
796 E_ineq.topLeftCorner(stacked_A_ineq.rows(), colsN) = stacked_A_ineq * N;
797 E_ineq.topRightCorner(rowsA_ineq, rowsA_ineq) = - Eigen::MatrixXd::Identity(rowsA_ineq, rowsA_ineq);
799 E_ineq.bottomRightCorner(rowsA_ineq, rowsA_ineq) = - Eigen::MatrixXd::Identity(rowsA_ineq, rowsA_ineq);
801 f_ineq.topRows(stacked_b_ineq.rows()) = stacked_b_ineq - stacked_A_ineq * x_opt;
802 f_ineq.segment(rowsA_ineq, stacked_b_ineq.rows() - rowsA_ineq) += stacked_v;
803 f_ineq.bottomRows(rowsA_ineq).setZero();
808 ROS_INFO_STREAM(
"----------------------" <<
"Task: " << count <<
"---------------------- \n" );
809 ROS_INFO_STREAM(
"Q: \n" << Q <<
"\n");
810 ROS_INFO_STREAM(
"eigenvalues(Q): \n" << Q.eigenvalues() <<
"\n");
811 ROS_INFO_STREAM(
"c: \n" <<
c <<
"\n");
812 ROS_INFO_STREAM(
"E_ineq: \n" << E_ineq <<
"\n");
813 ROS_INFO_STREAM(
"f_ineq: \n" << f_ineq <<
"\n");
817 ROS_INFO_STREAM(
"N: \n" << N <<
"\n");
818 ROS_INFO_STREAM(
"A_eq: \n" <<
t.A_eq <<
"\n");
819 ROS_INFO_STREAM(
"b_eq: \n" <<
t.b_eq <<
"\n");
820 ROS_INFO_STREAM(
"stacked_A_eq: \n" << stacked_A_eq <<
"\n");
821 ROS_INFO_STREAM(
"stacked_A_ineq: \n" << stacked_A_ineq <<
"\n");
822 ROS_INFO_STREAM(
"stacked_b_ineq: \n" << stacked_b_ineq <<
"\n");
826 if (!
SolveQP(Q,
c, E_ineq, f_ineq, xi, _solver,_v))
828 ROS_ERROR_STREAM(
"[HierarchicalOptimizationControl::HierarchicalQPOptimization] Failed to solve QP at task " << count <<
"!");
834 z = xi.topRows(colsN);
835 v = xi.bottomRows(rowsA_ineq);
838 x_opt = x_opt + N * z;
842 if (
t.has_eq_constraint)
849 if (
t.has_ineq_constraint)
851 Eigen::VectorXd stacked_v_tmp = stacked_v;
853 stacked_v.resize(v.rows() + stacked_v_tmp.rows(), 1);
861 ROS_INFO_STREAM(
"Solution at task " << count <<
" is: \n" << x_opt);
869 ROS_INFO_STREAM(
"Terminating at task " << count <<
" due to the null-space being zero. \n");
881 const Eigen::Matrix<Eigen::Matrix<double, Eigen::Dynamic, 1>, Eigen::Dynamic, 1> &_b,
884 const auto rowsA = _A.rows();
885 const auto rowsb = _b.rows();
890 ROS_ERROR(
"[HierarchicalOptimizationControl::HierarchicalLeastSquareOptimization] _A and _b does not contain equal amount of elements!");
895 const auto state_dim = _A(0).cols();
898 for (
size_t i = 0; i < rowsA; i++)
900 if (_A(i).cols() != state_dim || _A(i).rows() != _b(i).rows() )
902 ROS_ERROR_STREAM(
"[HierarchicalOptimizationControl::HierarchicalLeastSquareOptimization] State or equation dimensions failed at index: i = !" << i);
909 Eigen::Matrix<double, Eigen::Dynamic, 1> x_opt;
910 Eigen::Matrix<double, Eigen::Dynamic, 1> x_i;
911 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> N;
912 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> AN;
913 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> pinvAN;
914 Eigen::MatrixXd A_stacked;
917 x_opt.resize(state_dim, 1);
918 N.resize(state_dim, state_dim);
925 for (
size_t i = 0; i < rowsA; i++)
929 kindr::pseudoInverse(AN, pinvAN);
932 x_i = pinvAN * (_b(i) - _A(i) * x_opt);
935 x_opt = x_opt + N * x_i;
938 Eigen::MatrixXd A_stacked_tmp = A_stacked;
940 A_stacked.resize(A_stacked_tmp.rows() + _A(i).rows(), state_dim);
941 A_stacked << A_stacked_tmp,
949 ROS_INFO_STREAM(
"Solution at iteration " << i <<
" is: \n" << x_opt);
959 const Eigen::VectorXd &_c,
960 const Eigen::MatrixXd &_E_ineq,
961 const Eigen::VectorXd &_f_ineq,
962 Eigen::VectorXd &_sol,
967 if (_E_ineq.rows() != _f_ineq.rows())
969 ROS_INFO_STREAM(
"[HierarchicalOptimizationControl::SolveQP] Equality constraint dimensions does not match!");
977 lb.resize(_f_ineq.rows(), 1);
981 return this->
SolveQP(_Q, _c, _E_ineq, lb, _f_ineq, _sol, _solver, _v);
986 const Eigen::VectorXd &_c,
987 const Eigen::MatrixXd &_A,
988 const Eigen::VectorXd &_lb,
989 const Eigen::VectorXd &_ub,
990 Eigen::VectorXd &_sol,
995 drake::solvers::MathematicalProgram prog;
998 drake::solvers::MathematicalProgramResult result;
1001 auto x = prog.NewContinuousVariables(_Q.cols(),
"x");
1004 prog.AddQuadraticCost(_Q, _c,
x,
true);
1011 ROS_INFO_STREAM(
"Linear ineq, A: \n" << _A <<
"\n");
1012 ROS_INFO_STREAM(
"Linear ineq, lb: \n" << _lb <<
"\n");
1013 ROS_INFO_STREAM(
"Linear ineq, ub: \n" << _ub <<
"\n");
1016 prog.AddLinearConstraint(_A, _lb, _ub,
x);
1024 auto solver = drake::solvers::OsqpSolver();
1026 auto start = std::chrono::steady_clock::now();
1028 result = solver.Solve(prog);
1032 auto end = std::chrono::steady_clock::now();
1034 std::chrono::duration<double, std::micro> diff = end - start;
1036 ROS_INFO_STREAM(
"OSQP run-time: " << diff.count() <<
" microseconds. \n");
1038 auto details = result.get_solver_details<drake::solvers::OsqpSolver>();
1039 ROS_INFO_STREAM(
"Solver details: run_time: " << details.run_time <<
"\n");
1046 auto solver = drake::solvers::EqualityConstrainedQPSolver();
1047 result = solver.Solve(prog);
1053 auto solver = drake::solvers::ClpSolver();
1054 result = solver.Solve(prog);
1060 auto solver = drake::solvers::ScsSolver();
1061 result = solver.Solve(prog);
1067 auto solver = drake::solvers::SnoptSolver();
1068 result = solver.Solve(prog);
1074 result = Solve(prog);
1080 ROS_WARN(
"[HierarchicalOptimizationControl::SolveQP] Could not determine solver type!");
1086 if (!result.is_success())
1088 ROS_WARN(
"[HierarchicalOptimizationControl::SolveQP] Failed to solve QP!");
1094 ROS_INFO_STREAM(
"Solver id: " << result.get_solver_id() <<
"\n");
1095 ROS_INFO_STREAM(
"Solver result: " << result.get_solution_result() <<
"\n");
1096 ROS_INFO_STREAM(
"Solution result: " << result.GetSolution(
x) <<
"\n");
1097 ROS_INFO_STREAM(
"Solution result: " << result.GetSolution(
x) <<
"\n");
1109 _sol = result.GetSolution(
x);
1121 const Eigen::VectorXd &_c,
1122 const Eigen::MatrixXd &_E_eq,
1123 const Eigen::VectorXd &_f_eq,
1124 const Eigen::MatrixXd &_E_ineq,
1125 const Eigen::VectorXd &_f_ineq,
1126 Eigen::VectorXd &_sol,
1131 drake::solvers::MathematicalProgram prog;
1134 drake::solvers::MathematicalProgramResult result;
1137 auto x = prog.NewContinuousVariables(_Q.cols(),
"x");
1140 prog.AddQuadraticCost(_Q, _c,
x,
true);
1143 if (!_E_eq.isZero())
1145 prog.AddLinearEqualityConstraint(_E_eq, _f_eq,
x);
1149 if (!_E_ineq.isZero())
1151 prog.AddLinearConstraint((_E_ineq *
x).array() <= _f_ineq.array());
1159 auto solver = drake::solvers::OsqpSolver();
1160 result = solver.Solve(prog);
1165 auto solver = drake::solvers::EqualityConstrainedQPSolver();
1166 result = solver.Solve(prog);
1171 auto solver = drake::solvers::ClpSolver();
1172 result = solver.Solve(prog);
1177 auto solver = drake::solvers::ScsSolver();
1178 result = solver.Solve(prog);
1183 auto solver = drake::solvers::SnoptSolver();
1184 result = solver.Solve(prog);
1189 result = Solve(prog);
1194 ROS_WARN(
"[HierarchicalOptimizationControl::SolveQP] Could not determine solver type!");
1200 if (!result.is_success())
1202 ROS_WARN(
"[HierarchicalOptimizationControl::SolveQP] Failed to solve QP!");
1210 _sol = result.GetSolution(
x);
1223 sensor_msgs::JointState joint_state_msg;
1226 joint_state_msg.effort.resize(12);
1229 joint_state_msg.effort[0] = _desired_tau(0);
1230 joint_state_msg.effort[1] = _desired_tau(1);
1231 joint_state_msg.effort[2] = _desired_tau(2);
1234 joint_state_msg.effort[3] = _desired_tau(3);
1235 joint_state_msg.effort[4] = _desired_tau(4);
1236 joint_state_msg.effort[5] = _desired_tau(5);
1239 joint_state_msg.effort[6] = _desired_tau(6);
1240 joint_state_msg.effort[7] = _desired_tau(7);
1241 joint_state_msg.effort[8] = _desired_tau(8);
1244 joint_state_msg.effort[9] = _desired_tau(9);
1245 joint_state_msg.effort[10] = _desired_tau(10);
1246 joint_state_msg.effort[11] = _desired_tau(11);
1249 joint_state_msg.header.stamp = ros::Time::now();
1258 std::vector<double> data = _msg->data;
1260 this->
genCoord = Eigen::Map<Eigen::MatrixXd>(data.data(), 18, 1);
1266 ROS_ERROR(
"[HierarchicalOptimizationControl::OnGenCoordMsg] Could not solve forward kinematics!");
1275 std::vector<double> data = _msg->data;
1277 this->
genVel = Eigen::Map<Eigen::MatrixXd>(data.data(), 18, 1);
1279 for (
int i = 0; i < 4; i++)
1290 if (!_msg->data.size() == 4)
1292 ROS_ERROR(
"[HierarchicalOptimizationControl::OnContactStateMsg] Received contact message with wrong size!");
1307 static const double timeout = 0.01;
1317 static const double timeout = 0.01;
1327 if (!ros::isInitialized())
1334 "hierarchical_optimization_control_node",
1335 ros::init_options::NoSigintHandler
1339 this->
rosNode.reset(
new ros::NodeHandle(
"hierarchical_optimization_control_node"));
1341 ros::SubscribeOptions gen_coord_so =
1342 ros::SubscribeOptions::create<std_msgs::Float64MultiArray>(
1343 "/my_robot/gen_coord",
1350 ros::SubscribeOptions gen_vel_so =
1351 ros::SubscribeOptions::create<std_msgs::Float64MultiArray>(
1352 "/my_robot/gen_vel",
1359 ros::SubscribeOptions contact_state_so =
1360 ros::SubscribeOptions::create<std_msgs::Int8MultiArray>(
1361 "/my_robot/contact_state",
1368 ros::AdvertiseOptions joint_state_ao =
1369 ros::AdvertiseOptions::create<sensor_msgs::JointState>(
1370 "/my_robot/joint_state_cmd",
1372 ros::SubscriberStatusCallback(),
1373 ros::SubscriberStatusCallback(),
1378 ros::AdvertiseOptions base_pose_cmd_ao =
1379 ros::AdvertiseOptions::create<std_msgs::Float64MultiArray>(
1380 "/my_robot/base_pose_cmd",
1382 ros::SubscriberStatusCallback(),
1383 ros::SubscriberStatusCallback(),
1388 ros::AdvertiseOptions base_twist_cmd_ao =
1389 ros::AdvertiseOptions::create<std_msgs::Float64MultiArray>(
1390 "/my_robot/base_twist_cmd",
1392 ros::SubscriberStatusCallback(),
1393 ros::SubscriberStatusCallback(),
ros::Subscriber genVelSub
ROS Generalized Coordinates Subscriber.
std::thread rosProcessQueueThread
Thread running the rosProcessQueue.
std::unique_ptr< ros::NodeHandle > rosNode
Node used for ROS transport.
std::thread rosPublishQueueThread
Thread running the rosPublishQueue.
HierarchicalOptimizationControl()
Constructor.
Eigen::Matrix< double, 18, 1 > genCoord
Generalized Coordinates.
Kinematics kinematics
Kinematics.
bool SolveQP(const Eigen::MatrixXd &_Q, const Eigen::VectorXd &_c, const Eigen::MatrixXd &_E_ineq, const Eigen::VectorXd &_f_ineq, Eigen::VectorXd &_sol, const SolverType &_solver=SolverType::UNSPECIFIED, const int &_v=0)
The SolveQP function solves a (convex) quadratic program (QP) on the form:
void PublishTorqueMsg(const Eigen::Matrix< double, 12, 1 > &_desired_tau)
The PublishTorqueMsg function publishes a desired torque message to the ROS topic set by the joint st...
int contactState[4]
Contact State.
Eigen::Matrix< double, Eigen::Dynamic, 1 > HierarchicalQPOptimization(const int &_state_dim, const std::vector< Task > &_tasks, const SolverType &_solver=SolverType::OSQP, const int &_v=0)
The HierarchicalQPOptimization function finds the optimal solution for a set of tasks in a strictly p...
ros::CallbackQueue rosProcessQueue
ROS callbackque that helps process messages.
Eigen::Matrix< double, 18, 1 > genVel
Generalized Velocities.
void ProcessQueueThread()
The ProcessQueueThread function is a ROS helper function that processes messages.
void OnGenCoordMsg(const std_msgs::Float64MultiArrayConstPtr &_msg)
The OnGenCoordMsg function handles an incoming generalized coordinates message from ROS.
Eigen::Matrix< Eigen::Vector3d, 4, 1 > fVel
Foot-point velocities.
void InitRosQueueThreads()
The InitRosQueueThreads function is called to initialize the ROS Publish and Process Queue Threads.
Eigen::Matrix< double, 12, 1 > HierarchicalOptimization(const Eigen::Matrix< double, 3, 1 > &_desired_base_pos, const Eigen::Matrix< double, 3, 1 > &_desired_base_vel, const Eigen::Matrix< double, 3, 1 > &_desired_base_acc, const Eigen::Matrix< double, 3, 1 > &_desired_base_ori, const Eigen::Matrix< Eigen::Vector3d, 4, 1 > &_desired_f_pos, const Eigen::Matrix< Eigen::Vector3d, 4, 1 > &_desired_f_vel, const Eigen::Matrix< Eigen::Vector3d, 4, 1 > &_desired_f_acc, const Eigen::Matrix< Eigen::Vector3d, 4, 1 > &_f_pos, const Eigen::Matrix< Eigen::Vector3d, 4, 1 > &_f_vel, const Eigen::Matrix< double, 18, 1 > &_q, const Eigen::Matrix< double, 18, 1 > &_u, const int &_v=0)
The HierarchicalOptimization function finds the optimal joint torques for a desired motion plan....
void OnContactStateMsg(const std_msgs::Int8MultiArrayConstPtr &_msg)
The OnContactStateMsg function handles an incoming contact state message from ROS.
Eigen::Matrix< Eigen::Vector3d, 4, 1 > fPos
Foot-point positions.
void PublishQueueThread()
The PublishQueueThread function is a ROS helper function that publish state messages.
ros::Publisher jointStatePub
ROS Joint State Publisher.
Eigen::Matrix< double, Eigen::Dynamic, 1 > HierarchicalLeastSquareOptimization(const Eigen::Matrix< Eigen::MatrixXd, Eigen::Dynamic, 1 > &_A, const Eigen::Matrix< Eigen::Matrix< double, Eigen::Dynamic, 1 >, Eigen::Dynamic, 1 > &_b, const int &_v=0)
The HierarchicalLeastSquareOptimization function finds the optimal solution for a set of linear equal...
void InitRos()
The InitRos function is called to initialize ROS.
void OnGenVelMsg(const std_msgs::Float64MultiArrayConstPtr &_msg)
The OnGenVelMsg function handles an incoming generalized velocities message from ROS.
ros::Subscriber genCoordSub
ROS Generalized Coordinates Subscriber.
ros::CallbackQueue rosPublishQueue
ROS callbackque that helps publish messages.
virtual ~HierarchicalOptimizationControl()
Destructor.
ros::Publisher basePoseCmdPub
ROS Base Position Command Publisher.
SolverType
Drake Solver type enumerator.
ros::Subscriber contactStateSub
ROS Contact State Subscriber.
ros::Publisher baseTwistCmdPub
ROS Base Position Command Publisher.
Eigen::Matrix< double, 3, 18 > GetTranslationJacobianInW(const LegType &_leg, const BodyType &_body, const Eigen::Matrix< double, 18, 1 > &_q)
The GetTranslationJacobianInW function returns the 3x18 spatial translation Jacobian mapping generali...
Eigen::Matrix< double, Eigen::Dynamic, 18 > GetContactJacobianInW(std::vector< LegType > &_legs, const Eigen::Matrix< double, 18, 1 > &_q)
The GetContactJacobianInW function returns the (3*n_c)x18 support Jacobian mapping reaction forces at...
Eigen::Matrix< double, 18, 18 > GetMassMatrix(const Eigen::Matrix< double, 18, 1 > &_q)
The GetMassMatrix function returns the mass matrix for the floating base system.
Eigen::Matrix< double, 3, 18 > GetTranslationJacobianInCDiff(const LegType &_leg, const BodyType &_body, const Eigen::Matrix< double, 18, 1 > &_q, const Eigen::Matrix< double, 18, 1 > &_u)
The GetTranslationJacobianInCDiff function returns the time derivative of the 3x18 spatial translatio...
Eigen::Matrix< double, 3, 3 > GetRotationMatrixWToC(const double &_roll, const double &_pitch, const double &_yaw)
The GetRotationMatrixWToC function returns the Euler Angles ZYX rotation matrix from World to Control...
bool SolveForwardKinematics(const GeneralizedCoordinates &_q, FootstepPositions &_f_pos)
The SolveForwardKinematics function calculates the Forward Kinematics, i.e. maps joint angles in Join...
Eigen::Matrix< double, 18, 1 > GetGravitationalTerms(const Eigen::Matrix< double, 18, 1 > &_q)
The GetGravitationalTerms function returns the gravitational terms for the floating base system.
Eigen::Matrix< double, Eigen::Dynamic, 18 > GetContactJacobianInWDiff(std::vector< LegType > &_legs, const Eigen::Matrix< double, 18, 1 > &_q, const Eigen::Matrix< double, 18, 1 > &_u)
The GetContactJacobianInWDiff function returns the time derivative of the (3*n_c)x18 support Jacobian...
Eigen::Matrix< double, 3, 18 > GetTranslationJacobianInC(const LegType &_leg, const BodyType &_body, const Eigen::Matrix< double, 18, 1 > &_q)
The GetTranslationJacobianInC function returns the 3x18 spatial translation Jacobian mapping generali...
Eigen::Matrix< double, 3, 18 > GetRotationJacobianInC(const LegType &_leg, const BodyType &_body, const Eigen::Matrix< double, 18, 1 > &_q)
The GetRotationJacobianInC function returns the 3x18 spatial rotation Jacobian mapping generalized ve...
Eigen::Matrix< double, 3, 18 > GetRotationJacobianInCDiff(const LegType &_leg, const BodyType &_body, const Eigen::Matrix< double, 18, 1 > &_q, const Eigen::Matrix< double, 18, 1 > &_u)
The GetRotationJacobianInCDiff function returns the time derivative of the 3x18 control frame Rotatio...
LegType
Leg type enumerator.
Eigen::Matrix< double, 18, 1 > GetCoriolisAndCentrifugalTerms(const Eigen::Matrix< double, 18, 1 > &_q, const Eigen::Matrix< double, 18, 1 > &_u)
The GetCoriolisAndCentrifugalTerms function returns the coriolis and centrifugal terms for the floati...
void printGeneralizedAccelerations(const Eigen::Matrix< double, 18, 1 > &_gen_accel)
The printGeneralizedAccelerations function prints a given set of generalized accelerations to ROS usi...
void printJointTorques(const Eigen::Matrix< double, 12, 1 > &_joint_trq)
The printJointTorques function prints given joint- torques to ROS using print level INFO.
void printFootstepForces(const int *_contact_state, const Eigen::VectorXd &_F_c)
The printFootstepPositions function prints a given set of footstep forces to ROS using print level IN...
double degToRad(const double &_deg)
The degToRad function converts degrees to radians.
Eigen::Matrix< typename Matrix_TypeA::Scalar, Eigen::Dynamic, Eigen::Dynamic > SVDNullSpaceProjector(const Matrix_TypeA &_A)
The SVDNullSpaceProjector function calculates the null-space projector of a given matrix....
static constexpr double INF
Define infinity.
bool has_eq_constraint
Bool indicating whether the task has a linear equality constraint.
Eigen::MatrixXd A_ineq
Linear inequality constraint matrix A.
Eigen::VectorXd b_ineq
Linear inequality constraint vector b.
Eigen::VectorXd b_eq
Linear equality constraint vector b.
bool has_ineq_constraint
Bool indicating whether the task has a linear inequality constraint.
Eigen::MatrixXd A_eq
Linear equality constraint matrix A.