3 #include "ros/console.h"
9 #define _USE_MATH_DEFINES
14 using drake::solvers::MatrixXDecisionVariable;
16 using drake::symbolic::sin;
18 using drake::symbolic::cos;
28 decision_variables.
position = prog.NewContinuousVariables(n_steps, 3,
"position");
30 decision_variables.
theta = prog.NewContinuousVariables(n_steps/n_legs + 1, 1,
"theta");
32 decision_variables.
lin_sin = prog.NewContinuousVariables(n_steps/n_legs + 1, 1,
"sin_theta");
34 decision_variables.
lin_cos = prog.NewContinuousVariables(n_steps/n_legs + 1, 1,
"cos_theta");
36 decision_variables.
bin_sin = prog.NewBinaryVariables(n_steps/n_legs + 1, 5,
"sin_selection");
38 decision_variables.
bin_cos = prog.NewBinaryVariables(n_steps/n_legs + 1, 5,
"cos_selection");
40 decision_variables.
stone = prog.NewBinaryVariables(n_steps, n_stones,
"stone");
44 return decision_variables;
51 MatrixXDecisionVariable &theta = decision_variables.
theta;
54 Eigen::Vector4d sequence_offset(1, 0, 0, 0);
58 double angle_divided = 2*M_PI/n_legs;
60 double phis[] = {0.5*angle_divided, -0.5*angle_divided, 1.5*angle_divided, -1.5*angle_divided};
66 double angle_front_left = theta_0 + phis[
front_left];
68 double angle_front_right = theta_0 + phis[
front_right];
70 double angle_rear_left = theta_0 + phis[
rear_left];
72 double angle_rear_right = theta_0 + phis[
rear_right];
93 Eigen::Vector3d initial_positions[] = {initial_position_front_left, initial_position_front_right, initial_position_rear_left, initial_position_rear_right};
95 Eigen::Vector3d goal_positions[] = {goal_position_front_left, goal_position_front_right, goal_position_rear_left, goal_position_rear_right};
97 Eigen::Matrix<drake::symbolic::Expression, 3, 1> init_pos_i;
99 Eigen::Matrix<drake::symbolic::Expression, 3, 1> goal_pos_i;
101 for (
int i = 0; i < n_legs; ++i)
103 init_pos_i = sequence_offset(0)*initial_positions[
step_sequence[i]]
104 + sequence_offset(1)*initial_positions[
step_sequence[(i + 1) % n_legs]]
105 + sequence_offset(2)*initial_positions[
step_sequence[(i + 2) % n_legs]]
106 + sequence_offset(3)*initial_positions[(i + 3) % n_legs];
108 auto constr_init = prog.AddLinearConstraint(
position.row(i).transpose() == init_pos_i);
110 if (enforce_goal_hard)
112 goal_pos_i = sequence_offset(0)*goal_positions[
step_sequence[(n_steps + i) % n_legs]]
113 + sequence_offset(1)*goal_positions[
step_sequence[(n_steps + i + 1) % n_legs]]
114 + sequence_offset(2)*goal_positions[
step_sequence[(n_steps + i + 2) % n_legs]]
115 + sequence_offset(3)*goal_positions[(n_steps + i + 3) % n_legs];
117 auto constr_goal = prog.AddLinearConstraint(
position.row(n_steps - n_legs + i).transpose() == goal_pos_i);
123 prog.AddLinearConstraint(theta(0) == theta_0);
125 prog.AddLinearConstraint(theta(theta.rows()-1) == theta_0);
132 void theta_limits(drake::solvers::MathematicalProgram &prog,
int n_steps,
int n_legs,
DecVars &decision_variables)
134 MatrixXDecisionVariable &theta = decision_variables.
theta;
136 MatrixXDecisionVariable &lin_sin = decision_variables.
lin_sin;
138 MatrixXDecisionVariable &lin_cos = decision_variables.
lin_cos;
140 MatrixXDecisionVariable &bin_sin = decision_variables.
bin_sin;
142 MatrixXDecisionVariable &bin_cos = decision_variables.
bin_cos;
144 double big_M = 2*M_PI;
146 double sin_dividers[] = {0, 1, M_PI - 1, M_PI + 1, 2*M_PI - 1, 2*M_PI};
148 double cos_dividers[] = {0, M_PI/2 - 1, M_PI/2 + 1, 3*M_PI/2 - 1, 3*M_PI/2 + 1, 2*M_PI};
155 for (
int i = 0; i < n_steps/n_legs + 1; ++i)
158 prog.AddLinearConstraint(theta(i) >= 0);
160 prog.AddLinearConstraint(theta(i) <= 2*M_PI);
163 for (
int l = 0; l < 5; ++l)
165 prog.AddLinearConstraint(theta(i) >= sin_dividers[l] - (1 - bin_sin(i, l))*big_M);
167 prog.AddLinearConstraint(theta(i) <= sin_dividers[l + 1] + (1 - bin_sin(i, l))*big_M);
169 prog.AddLinearConstraint(theta(i) >= cos_dividers[l] - (1 - bin_cos(i, l))*big_M);
171 prog.AddLinearConstraint(theta(i) <= cos_dividers[l + 1] + (1 - bin_cos(i, l))*big_M);
174 auto sin_const = prog.AddLinearConstraint((bin_sin.row(i)*Eigen::VectorXd::Ones(5))(0) == 1);
176 auto cos_const = prog.AddLinearConstraint((bin_cos.row(i)*Eigen::VectorXd::Ones(5))(0) == 1);
180 auto sin_upper = prog.AddLinearConstraint(lin_sin(i)*Eigen::VectorXd::Ones(5) - (sin_coeffs.col(0) + sin_coeffs.col(1)*theta(i)) <= (Eigen::VectorXd::Ones(5) - bin_sin.row(i).transpose())*big_M);
182 auto sin_lower = prog.AddLinearConstraint(lin_sin(i)*Eigen::VectorXd::Ones(5) - (sin_coeffs.col(0) + sin_coeffs.col(1)*theta(i)) >= -(Eigen::VectorXd::Ones(5) - bin_sin.row(i).transpose())*big_M);
184 auto cos_upper = prog.AddLinearConstraint(lin_cos(i)*Eigen::VectorXd::Ones(5) - (cos_coeffs.col(0) + cos_coeffs.col(1)*theta(i)) <= (Eigen::VectorXd::Ones(5) - bin_cos.row(i).transpose())*big_M);
186 auto cos_lower = prog.AddLinearConstraint(lin_cos(i)*Eigen::VectorXd::Ones(5) - (cos_coeffs.col(0) + cos_coeffs.col(1)*theta(i)) >= -(Eigen::VectorXd::Ones(5) - bin_cos.row(i).transpose())*big_M);
194 MatrixXDecisionVariable &lin_sin = decision_variables.
lin_sin;
196 MatrixXDecisionVariable &lin_cos = decision_variables.
lin_cos;
200 Eigen::Vector4d sequence_offset(1, 0, 0, 0);
202 double angle_divided = 2*M_PI/n_legs;
204 double phis[] = {0.5*angle_divided, -0.5*angle_divided, 1.5*angle_divided, -1.5*angle_divided};
208 Eigen::Matrix<drake::symbolic::Expression, 2, 1> p_i;
210 Eigen::Matrix<drake::symbolic::Expression, 2, 1> leg_offset;
216 for (
int i = n_legs; i < n_steps; ++i)
218 p_i = (Eigen::VectorXd::Ones(n_legs).transpose()*
position.block(i - n_legs, 0, n_legs, 2)/n_legs).transpose();
220 leg_offset << length_legs*(lin_cos(i/n_legs)*cos(phis_ordered[i % n_legs]) - lin_sin(i/n_legs)*sin(phis_ordered[i % n_legs])),
222 length_legs*(lin_sin(i/n_legs)*cos(phis_ordered[i % n_legs]) + lin_cos(i/n_legs)*sin(phis_ordered[i % n_legs]));
224 prog.AddLinearConstraint(
position.block(i, 0, 1, 2).transpose() - (p_i + leg_offset) <= Eigen::Vector2d::Constant(bbox_len/2));
226 prog.AddLinearConstraint(
position.block(i, 0, 1, 2).transpose() - (p_i + leg_offset) >= Eigen::Vector2d::Constant(-bbox_len/2));
234 for (
int i = n_legs; i < n_steps; ++i)
244 prog.AddLinearConstraint(
position(i, 2) -
position(i - n_legs, 2) <= step_height);
246 prog.AddLinearConstraint(
position(i, 2) -
position(i - n_legs, 2) >= -step_height);
252 MatrixXDecisionVariable &stone = decision_variables.
stone;
254 auto stone_const = prog.AddLinearConstraint(stone*Eigen::VectorXd::Ones(stone.cols()) == Eigen::VectorXd::Ones(stone.rows()));
278 MatrixXDecisionVariable &stone = decision_variables.
stone;
282 Eigen::Matrix<double, 1, 1> M_height = Eigen::Matrix<double, 1, 1>::Constant(10);
286 Eigen::MatrixXd A_ineq, b_ineq, A_eq, b_eq;
287 for (
int i = 0; i < n_steps; ++i)
289 for (
int l = 0; l < n_stones ; ++l)
299 prog.AddLinearConstraint(A_ineq*
position.row(i).transpose() <= b_ineq + (1 - stone(i, l))*M);
301 prog.AddLinearConstraint(A_eq*
position.row(i).transpose() <= b_eq + (1 - stone(i, l))*M_height);
303 prog.AddLinearConstraint(A_eq*
position.row(i).transpose() >= b_eq - (1 - stone(i, l))*M_height);
312 Eigen::Matrix<drake::symbolic::Expression, 2, 1> dist;
314 for (
int i = n_legs; i < n_steps; ++i)
318 prog.AddQuadraticCost((dist.transpose()*dist)(0));
326 Eigen::Matrix<drake::symbolic::Expression, 3, 1> center;
328 Eigen::Matrix<drake::symbolic::Expression, 3, 1> dist;
330 center =
position.block(n_steps - n_legs, 0, n_legs, 3).transpose()*Eigen::Vector4d::Ones()/n_legs;
334 prog.AddQuadraticCost(10*(dist.transpose()*dist)(0));
341 for (
int l = 0; l < n_legs; ++l)
343 if (
bool(std::round(sequence_offset(l))))
351 Eigen::Array<Eigen::MatrixXd, Eigen::Dynamic, 1> res;
353 res.conservativeResize(n_legs);
357 for (
int l = 0; l < n_legs; ++l)
361 res(ind) = Eigen::MatrixXd();
363 res(ind).conservativeResize(n_steps - n_legs + 1, arr.cols());
365 res(ind).row(0) << arr.row(l);
367 for (
int i = 1; i < res(ind).rows(); ++i)
369 if (((i + l - 1) % n_legs) == 0)
371 res(ind).row(i) << arr.row(n_legs + i - 1);
375 res(ind).row(i) << res(ind).row(i - 1);
406 res.
cost = decision_variables_raw.
cost;
417 std::ofstream file(filename);
425 ROS_INFO(
"writeMatToFile: Successfully wrote to file");
428 ROS_ERROR(
"could not open file");
430 throw "could not open file " + filename;
438 std::string fend =
".csv";
const Eigen::Vector3d & getCenter() const
const Eigen::Vector3d & getTopRight() const
const SteppingStone & getStoneByName(std::string name) const
const Eigen::Array< SteppingStone, Eigen::Dynamic, 1 > & getSteppingStones() const
void step_sequence(drake::solvers::MathematicalProgram &prog, int n_steps, double step_span, DecVars &decision_variables)
void theta_limits(drake::solvers::MathematicalProgram &prog, int n_steps, int n_legs, DecVars &decision_variables)
DecVars_res get_decvars_res(DecVars_res_raw &decision_variables_raw, int n_steps, int n_legs, Leg step_sequence[])
Eigen::Vector4d get_big_M(Terrain terrain)
void one_stone_per_foot(drake::solvers::MathematicalProgram &prog, int n_steps, DecVars &decision_variables)
void minimize_step_length(drake::solvers::MathematicalProgram &prog, int n_steps, int n_legs, DecVars &decision_variables)
void relative_position_limits(drake::solvers::MathematicalProgram &prog, int n_steps, int n_legs, double step_span, double step_height, DecVars &decision_variables)
void foot_in_stepping_stone(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps, DecVars &decision_variables)
DecVars add_decision_variables(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps, int n_legs)
Eigen::Array< Eigen::MatrixXd, Eigen::Dynamic, 1 > get_uncompressed_arrays(Eigen::MatrixXd &arr, Eigen::MatrixXd &sequence_offset, int n_steps, int n_legs, Leg step_sequence[])
void set_initial_and_goal_position(drake::solvers::MathematicalProgram &prog, int n_steps, double length_legs, Leg step_sequence[], Terrain &terrain, DecVars &decision_variables, bool enforce_goal_hard=true)
void writeMatToFile(Eigen::MatrixXd &mat, std::string filename)
void geometry_limits(drake::solvers::MathematicalProgram &prog, int n_steps, int n_legs, double length_legs, Leg step_sequence[], Terrain &terrain, double bbox_len, DecVars &decision_variables)
void writeDecVarsToFile(DecVars_res &decision_variables, std::string base_name="footstep_planner")
void minimize_remaining_length(drake::solvers::MathematicalProgram &prog, Terrain &terrain, int n_steps, int n_legs, DecVars &decision_variables)
Eigen::MatrixXd sequence_offset
Eigen::MatrixXd stone_rear_right
Eigen::MatrixXd position_ts
Eigen::MatrixXd position_rear_left
Eigen::MatrixXd position_rear_right
Eigen::MatrixXd position_front_right
Eigen::MatrixXd stone_front_right
Eigen::MatrixXd stone_rear_left
Eigen::MatrixXd stone_front_left
Eigen::MatrixXd position_front_left
MatrixXDecisionVariable position
MatrixXDecisionVariable bin_cos
MatrixXDecisionVariable stone
MatrixXDecisionVariable bin_sin
MatrixXDecisionVariable lin_sin
MatrixXDecisionVariable theta
MatrixXDecisionVariable lin_cos
Eigen::MatrixXd get_cos_coeffs()
Eigen::MatrixXd get_sin_coeffs()