Quad-SDK
Loading...
Searching...
No Matches
local_footstep_planner.h
1#ifndef LOCAL_FOOTSTEP_PLANNER_H
2#define LOCAL_FOOTSTEP_PLANNER_H
3
4#include <eigen_conversions/eigen_msg.h>
5#include <local_planner/local_planner_modes.h>
6#include <nav_msgs/Path.h>
7#include <quad_msgs/FootPlanDiscrete.h>
8#include <quad_msgs/FootState.h>
9#include <quad_msgs/MultiFootPlanContinuous.h>
10#include <quad_msgs/MultiFootPlanDiscrete.h>
11#include <quad_msgs/MultiFootState.h>
12#include <quad_msgs/RobotPlan.h>
13#include <quad_msgs/RobotState.h>
14#include <quad_utils/fast_terrain_map.h>
15#include <quad_utils/function_timer.h>
16#include <quad_utils/math_utils.h>
17#include <quad_utils/quad_kd.h>
18#include <quad_utils/ros_utils.h>
19#include <ros/ros.h>
20
21#include <eigen3/Eigen/Eigen>
22#include <grid_map_core/grid_map_core.hpp>
23#include <grid_map_ros/GridMapRosConverter.hpp>
24#include <grid_map_ros/grid_map_ros.hpp>
25
27
33 public:
39
47 void setTemporalParams(double dt, int period, int horizon_length,
48 const std::vector<double> &duty_cycles,
49 const std::vector<double> &phase_offsets);
50
66 void setSpatialParams(double ground_clearance, double hip_clearance,
67 double grf_weight, double standing_error_threshold,
68 std::shared_ptr<quad_utils::QuadKD> kinematics,
69 double foothold_search_radius,
70 double foothold_obj_threshold,
71 std::string obj_fun_layer, double toe_radius);
72
80 void getFootPositionsBodyFrame(const Eigen::VectorXd &body_plan,
81 const Eigen::VectorXd &foot_positions_world,
82 Eigen::VectorXd &foot_positions_body);
83
90 void getFootPositionsBodyFrame(const Eigen::MatrixXd &body_plan,
91 const Eigen::MatrixXd &foot_positions_world,
92 Eigen::MatrixXd &foot_positions_body);
93
98 void updateMap(const FastTerrainMap &terrain);
99
104 void updateMap(const grid_map::GridMap &terrain);
105
114 void computeContactSchedule(int current_plan_index,
115 const Eigen::MatrixXd &body_plan,
116 const Eigen::VectorXi &ref_primitive_plan_,
117 int control_mode,
118 std::vector<std::vector<bool>> &contact_schedule);
119
137 void computeFootPlan(int current_plan_index,
138 const std::vector<std::vector<bool>> &contact_schedule,
139 const Eigen::MatrixXd &body_plan,
140 const Eigen::MatrixXd &grf_plan,
141 const Eigen::MatrixXd &ref_body_plan,
142 const Eigen::VectorXd &foot_positions_current,
143 const Eigen::VectorXd &foot_velocities_current,
144 double first_element_duration,
145 quad_msgs::MultiFootState &past_footholds_msg,
146 Eigen::MatrixXd &foot_positions,
147 Eigen::MatrixXd &foot_velocities,
148 Eigen::MatrixXd &foot_accelerations);
149
164 void loadFootPlanMsgs(
165 const std::vector<std::vector<bool>> &contact_schedule,
166 int current_plan_index, double first_element_duration,
167 const Eigen::MatrixXd &foot_positions,
168 const Eigen::MatrixXd &foot_velocities,
169 const Eigen::MatrixXd &foot_accelerations,
170 quad_msgs::MultiFootPlanDiscrete &future_footholds_msg,
171 quad_msgs::MultiFootPlanContinuous &foot_plan_continuous_msg);
172
173 inline void printContactSchedule(
174 const std::vector<std::vector<bool>> &contact_schedule) {
175 for (int i = 0; i < contact_schedule.size(); i++) {
176 for (int j = 0; j < contact_schedule.at(i).size(); j++) {
177 if (contact_schedule[i][j]) {
178 printf("1 ");
179 } else {
180 printf("0 ");
181 }
182 }
183 printf("\n");
184 }
185 }
186
187 inline double getTerrainHeight(double x, double y) {
188 grid_map::Position pos = {x, y};
189 double height = this->terrain_grid_.atPosition(
190 "z_smooth", terrain_grid_.getClosestPositionInMap(pos),
191 grid_map::InterpolationMethods::INTER_LINEAR);
192 return (height);
193 }
194
195 inline double getTerrainSlope(double x, double y, double dx, double dy) {
196 std::array<double, 3> surf_norm =
198
199 double denom = dx * dx + dy * dy;
200 if (denom <= 0 || surf_norm[2] <= 0) {
201 double default_pitch = 0;
202 return default_pitch;
203 } else {
204 double v_proj = (dx * surf_norm[0] + dy * surf_norm[1]) / sqrt(denom);
205 double pitch = atan2(v_proj, surf_norm[2]);
206
207 return pitch;
208 }
209 }
210
211 inline void getTerrainSlope(double x, double y, double yaw, double &roll,
212 double &pitch) {
213 std::array<double, 3> surf_norm =
215
216 Eigen::Vector3d norm_vec(surf_norm.data());
217 Eigen::Vector3d axis = Eigen::Vector3d::UnitZ().cross(norm_vec);
218 double ang = acos(
219 std::max(std::min(Eigen::Vector3d::UnitZ().dot(norm_vec), 1.), -1.));
220
221 if (ang < 1e-3) {
222 roll = 0;
223 pitch = 0;
224 return;
225 } else {
226 Eigen::Matrix3d rot(Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()));
227 axis = rot.transpose() * (axis / axis.norm());
228 tf2::Quaternion quat(tf2::Vector3(axis(0), axis(1), axis(2)), ang);
229 tf2::Matrix3x3 m(quat);
230 double tmp;
231 m.getRPY(roll, pitch, tmp);
232 }
233 }
234
235 inline void setTerrainMap(const grid_map::GridMap &grid_map) {
236 terrain_grid_ = grid_map;
237 }
238
239 // Compute future states by integrating linear states (hold orientation
240 // states)
241 inline Eigen::VectorXd computeFutureBodyPlan(
242 double step, const Eigen::VectorXd &body_plan) {
243 // Initialize vector
244 Eigen::VectorXd future_body_plan = body_plan;
245
246 // Integrate the linear state
247 future_body_plan.segment(0, 3) =
248 future_body_plan.segment(0, 3) + body_plan.segment(6, 3) * step * dt_;
249
250 return future_body_plan;
251 }
252
253 private:
258
271 void cubicHermiteSpline(double pos_prev, double vel_prev, double pos_next,
272 double vel_next, double phase, double duration,
273 double &pos, double &vel, double &acc);
274
281 Eigen::Vector3d getNearestValidFoothold(
282 const Eigen::Vector3d &foot_position,
283 const Eigen::Vector3d &foot_position_prev_solve) const;
284
291 Eigen::Vector3d welzlMinimumCircle(std::vector<Eigen::Vector2d> P,
292 std::vector<Eigen::Vector2d> R);
293
302 double computeSwingApex(int leg_idx, const Eigen::VectorXd &body_plan,
303 const Eigen::Vector3d &foot_position_prev,
304 const Eigen::Vector3d &foot_position_next);
305
309 inline Eigen::Vector3d getFootData(const Eigen::MatrixXd &foot_state_vars,
310 int horizon_index, int foot_index) {
311 return foot_state_vars.block<1, 3>(horizon_index, 3 * foot_index);
312 }
313
317 inline bool isContact(const std::vector<std::vector<bool>> &contact_schedule,
318 int horizon_index, int foot_index) {
319 return (contact_schedule.at(horizon_index).at(foot_index));
320 }
321
325 inline bool isNewContact(
326 const std::vector<std::vector<bool>> &contact_schedule, int horizon_index,
327 int foot_index) {
328 if (horizon_index == 0) return false;
329
330 return (!isContact(contact_schedule, horizon_index - 1, foot_index) &&
331 isContact(contact_schedule, horizon_index, foot_index));
332 }
333
337 inline bool isNewLiftoff(
338 const std::vector<std::vector<bool>> &contact_schedule, int horizon_index,
339 int foot_index) {
340 if (horizon_index == 0) return false;
341
342 return (isContact(contact_schedule, horizon_index - 1, foot_index) &&
343 !isContact(contact_schedule, horizon_index, foot_index));
344 }
345
351 const std::vector<std::vector<bool>> &contact_schedule, int horizon_index,
352 int foot_index) {
353 // Loop through the rest of this contact schedule, if a new contact is found
354 // return its index
355 for (int i_touchdown = horizon_index; i_touchdown < horizon_length_;
356 i_touchdown++) {
357 if (isNewContact(contact_schedule, i_touchdown, foot_index)) {
358 return i_touchdown;
359 }
360 }
361
362 // If no contact is found, return the last index in the horizon
363 return (horizon_length_ - 1);
364 }
365
371 const std::vector<std::vector<bool>> &contact_schedule, int horizon_index,
372 int foot_index) {
373 // Loop through the rest of this contact schedule, if a new liftoff is found
374 // return its index
375 for (int i_liftoff = horizon_index; i_liftoff < horizon_length_;
376 i_liftoff++) {
377 if (isNewLiftoff(contact_schedule, i_liftoff, foot_index)) {
378 return i_liftoff;
379 }
380 }
381
382 // If no contact is found, return the last index in the horizon
383 return (horizon_length_ - 1);
384 }
385
388
390 grid_map::GridMap terrain_grid_;
391
393 const int num_feet_ = 4;
394
396 double dt_;
397
400
403
405 std::vector<double> phase_offsets_ = {0, 0.5, 0.5, 0.0};
406
408 std::vector<double> duty_cycles_ = {0.5, 0.5, 0.5, 0.5};
409
411 std::vector<std::vector<bool>> nominal_contact_schedule_;
412
415
418
421
423 const int CONNECT_STANCE = 0;
424
426 const int LEAP_STANCE = 1;
427
429 const int FLIGHT = 2;
430
432 const int LAND_STANCE = 3;
433
435 std::shared_ptr<quad_utils::QuadKD> quadKD_;
436
439
442
445
447 std::string obj_fun_layer_;
448
451};
452
453#endif // LOCAL_FOOTSTEP_PLANNER_H
A terrain map class built for fast and efficient sampling.
Definition fast_terrain_map.h:16
std::array< double, 3 > getSurfaceNormalFiltered(const double x, const double y) const
Return the filtered surface normal at a requested location.
Definition fast_terrain_map.cpp:345
A local footstep planning class for quad.
Definition local_footstep_planner.h:32
std::vector< double > phase_offsets_
Phase offsets for the touchdown of each foot.
Definition local_footstep_planner.h:405
double foothold_obj_threshold_
Minimum objective function value for valid foothold.
Definition local_footstep_planner.h:444
Eigen::Vector3d welzlMinimumCircle(std::vector< Eigen::Vector2d > P, std::vector< Eigen::Vector2d > R)
Compute minimum covering circle problem using Welzl's algorithm.
Definition local_footstep_planner.cpp:625
void computeContactSchedule(int current_plan_index, const Eigen::MatrixXd &body_plan, const Eigen::VectorXi &ref_primitive_plan_, int control_mode, std::vector< std::vector< bool > > &contact_schedule)
Compute the contact schedule based on the current phase.
Definition local_footstep_planner.cpp:86
void getFootPositionsBodyFrame(const Eigen::VectorXd &body_plan, const Eigen::VectorXd &foot_positions_world, Eigen::VectorXd &foot_positions_body)
Transform a vector of foot positions from the world to the body frame.
Definition local_footstep_planner.cpp:63
const int LEAP_STANCE
Primitive ids - LEAP_STANCE.
Definition local_footstep_planner.h:426
void setTemporalParams(double dt, int period, int horizon_length, const std::vector< double > &duty_cycles, const std::vector< double > &phase_offsets)
Set the temporal parameters of this object.
Definition local_footstep_planner.cpp:9
LocalFootstepPlanner()
Constructor for LocalFootstepPlanner Class.
Definition local_footstep_planner.cpp:7
double dt_
Timestep for one finite element.
Definition local_footstep_planner.h:396
grid_map::GridMap terrain_grid_
GridMap for terrain map data.
Definition local_footstep_planner.h:390
bool isContact(const std::vector< std::vector< bool > > &contact_schedule, int horizon_index, int foot_index)
Check if a foot is in contact at a given index.
Definition local_footstep_planner.h:317
double grf_weight_
Weighting on the projection of the grf.
Definition local_footstep_planner.h:420
int horizon_length_
Horizon length in timesteps.
Definition local_footstep_planner.h:402
double computeSwingApex(int leg_idx, const Eigen::VectorXd &body_plan, const Eigen::Vector3d &foot_position_prev, const Eigen::Vector3d &foot_position_next)
Compute swing apex height.
Definition local_footstep_planner.cpp:714
double standing_error_threshold_
Threshold of body error from desired goal to start stepping.
Definition local_footstep_planner.h:438
const int FLIGHT
Primitive ids - FLIGHT.
Definition local_footstep_planner.h:429
FastTerrainMap terrain_
Struct for terrain map data.
Definition local_footstep_planner.h:387
int getNextLiftoffIndex(const std::vector< std::vector< bool > > &contact_schedule, int horizon_index, int foot_index)
Compute the index of the next liftoff for a foot. If none exist return the last.
Definition local_footstep_planner.h:370
void computeFootPlan(int current_plan_index, const std::vector< std::vector< bool > > &contact_schedule, const Eigen::MatrixXd &body_plan, const Eigen::MatrixXd &grf_plan, const Eigen::MatrixXd &ref_body_plan, const Eigen::VectorXd &foot_positions_current, const Eigen::VectorXd &foot_velocities_current, double first_element_duration, quad_msgs::MultiFootState &past_footholds_msg, Eigen::MatrixXd &foot_positions, Eigen::MatrixXd &foot_velocities, Eigen::MatrixXd &foot_accelerations)
Update the discrete footstep plan with the current plan.
Definition local_footstep_planner.cpp:168
double hip_clearance_
Hip clearance.
Definition local_footstep_planner.h:417
void loadFootPlanMsgs(const std::vector< std::vector< bool > > &contact_schedule, int current_plan_index, double first_element_duration, const Eigen::MatrixXd &foot_positions, const Eigen::MatrixXd &foot_velocities, const Eigen::MatrixXd &foot_accelerations, quad_msgs::MultiFootPlanDiscrete &future_footholds_msg, quad_msgs::MultiFootPlanContinuous &foot_plan_continuous_msg)
Convert the foot positions and contact schedule into ros messages for the foot plan.
Definition local_footstep_planner.cpp:518
std::vector< double > duty_cycles_
Duty cycles for the stance duration of each foot.
Definition local_footstep_planner.h:408
Eigen::Vector3d getFootData(const Eigen::MatrixXd &foot_state_vars, int horizon_index, int foot_index)
Extract foot data from the matrix.
Definition local_footstep_planner.h:309
double ground_clearance_
Ground clearance.
Definition local_footstep_planner.h:414
bool isNewLiftoff(const std::vector< std::vector< bool > > &contact_schedule, int horizon_index, int foot_index)
Check if a foot is newly in swing at a given index.
Definition local_footstep_planner.h:337
const int num_feet_
Number of feet.
Definition local_footstep_planner.h:393
int period_
Gait period in timesteps.
Definition local_footstep_planner.h:399
Eigen::Vector3d getNearestValidFoothold(const Eigen::Vector3d &foot_position, const Eigen::Vector3d &foot_position_prev_solve) const
Search locally around foothold for optimal location.
Definition local_footstep_planner.cpp:572
const int LAND_STANCE
Primitive ids - LAND_STANCE.
Definition local_footstep_planner.h:432
void setSpatialParams(double ground_clearance, double hip_clearance, double grf_weight, double standing_error_threshold, std::shared_ptr< quad_utils::QuadKD > kinematics, double foothold_search_radius, double foothold_obj_threshold, std::string obj_fun_layer, double toe_radius)
Set the spatial parameters of this object.
Definition local_footstep_planner.cpp:38
void updateContinuousPlan()
Update the continuous foot plan to match the discrete.
void updateMap(const FastTerrainMap &terrain)
Update the map of this object.
Definition local_footstep_planner.cpp:55
void cubicHermiteSpline(double pos_prev, double vel_prev, double pos_next, double vel_next, double phase, double duration, double &pos, double &vel, double &acc)
Compute the cubic hermite spline.
Definition local_footstep_planner.cpp:129
bool isNewContact(const std::vector< std::vector< bool > > &contact_schedule, int horizon_index, int foot_index)
Check if a foot is newly in contact at a given index.
Definition local_footstep_planner.h:325
std::vector< std::vector< bool > > nominal_contact_schedule_
Nominal contact schedule.
Definition local_footstep_planner.h:411
std::shared_ptr< quad_utils::QuadKD > quadKD_
QuadKD class.
Definition local_footstep_planner.h:435
double toe_radius_
Toe radius.
Definition local_footstep_planner.h:450
int getNextContactIndex(const std::vector< std::vector< bool > > &contact_schedule, int horizon_index, int foot_index)
Compute the index of the next contact for a foot. If none exist return the last.
Definition local_footstep_planner.h:350
const int CONNECT_STANCE
Primitive ids - CONNECT_STANCE TODO(yanhaoy, astutt) make these enums.
Definition local_footstep_planner.h:423
double foothold_search_radius_
Radius to locally search for valid footholds (m)
Definition local_footstep_planner.h:441
std::string obj_fun_layer_
Terrain layer for foothold search.
Definition local_footstep_planner.h:447