Quad-SDK
Loading...
Searching...
No Matches
planning_utils.h
1#ifndef PLANNING_UTILS_H
2#define PLANNING_UTILS_H
3
4#include <math.h>
5#include <quad_utils/fast_terrain_map.h>
6#include <quad_utils/math_utils.h>
7#include <quad_utils/ros_utils.h>
8#include <ros/ros.h>
9#include <unistd.h>
10#include <visualization_msgs/MarkerArray.h>
11
12#include <algorithm>
13#include <chrono>
14#include <eigen3/Eigen/Eigen>
15#include <grid_map_core/grid_map_core.hpp>
16#include <iostream>
17#include <limits>
18#include <random>
19#include <unordered_map>
20#include <unordered_set>
21#include <vector>
22
23// Uncomment to add visualization features
24// #define VISUALIZE_TREE
25// #define VISUALIZE_ALL_CANDIDATE_ACTIONS
26// #define PLOT_TRAJECTORIES
27// #define DEBUG_REFINE_STATE
28// #define DEBUG_INVALID_STATE
29// #define DEBUG_SOLVE_RESULT
30
31namespace planning_utils {
32
37 // Declare the terrain map object
38 FastTerrainMap terrain; // Terrain in FastTerrainMap format
39 grid_map::GridMap terrain_grid_map; // Terrain in grid_map format
40
41 // Define kinematic constraint parameters
42 double h_max; // Maximum height of leg base, m
43 double h_min; // Minimum ground clearance of body corners, m
44 double h_nom; // Nominal ground clearance of body, m
45 double v_max; // Maximum robot velocity, m/s
46 double v_nom; // Nominal velocity, m/s (used during connect function)
47
48 // Define dynamic constraint parameters
49 double mass; // Robot mass, kg
50 double g; // Gravity constant, m/s^2
51 double grf_min; // Minimum GRF in units of body weight
52 double grf_max; // Maximum GRF in units of body weight
53 double mu; // Friction coefficient
54 double t_s_min; // Minimum stance time, s
55 double t_s_max; // Maximum stance time, s
56 double dz0_min; // Minimum vertical velocity impulse, m/s
57 double dz0_max; // Maximum vertical velocity impulse, m/s
58
59 // Define planning parameters
60 double dt; // Resolution of kinematic feasibility checks, m
61 int trapped_buffer_factor; // Number of feasibility that must pass to not a
62 // state trapped
63 double backup_ratio; // Ratio of trajectory to back up after finding an
64 // invalid state, s
65 int num_leap_samples; // Number of actions computed for each extend function
66 double max_planning_time; // Maximum planning time allowed
67 Eigen::Vector3d g_vec; // Maximum planning time allowed
68
69 // Define robot params and declare points used for validity checking
70 double robot_l; // Length of robot body, m
71 double robot_w; // Width of robot body, m
72 double robot_h; // Vertical distance between leg base and bottom of robot, m
73
74 double traversability_threshold; // Min traversability for contact location
75 // unless in flight
76
77 bool enable_leaping = true; // Leaping mode switch
78 static const int num_reachability_points =
79 4; // Number of points on body used to check reachability
80 static const int num_collision_points =
81 5; // Number of points on body used to check for collisions
82
83 Eigen::Matrix<double, 3, num_reachability_points>
84 reachability_points_body; // Positions of reachability points in thebody
85 // frame
86 Eigen::Matrix<double, 3, num_collision_points>
87 collision_points_body; // Positions of collision points in the bodyframe
88
94 // Load the gravity vector
95 g_vec << 0, 0, -g;
96
97 // Load the reachability test points
98 reachability_points_body << 0.5 * robot_l, -0.5 * robot_l, 0.5 * robot_l,
99 -0.5 * robot_l, 0.5 * robot_w, 0.5 * robot_w, -0.5 * robot_w,
100 -0.5 * robot_w, 0, 0, 0, 0;
101 // Load the collision test points
102 collision_points_body << 0.5 * robot_l, -0.5 * robot_l, 0.5 * robot_l,
103 -0.5 * robot_l, 0, 0.5 * robot_w, 0.5 * robot_w, -0.5 * robot_w,
104 -0.5 * robot_w, 0, -0.5 * robot_h, -0.5 * robot_h, -0.5 * robot_h,
105 -0.5 * robot_h, -0.5 * robot_h;
106 }
107
111 void loadParamsFromServer(ros::NodeHandle nh) {
112 // Load robot parameters
113 quad_utils::loadROSParam(nh, "global_body_planner/h_max", h_max);
114 quad_utils::loadROSParam(nh, "global_body_planner/h_min", h_min);
115 quad_utils::loadROSParam(nh, "global_body_planner/h_nom", h_nom);
116 quad_utils::loadROSParam(nh, "global_body_planner/v_max", v_max);
117 quad_utils::loadROSParam(nh, "global_body_planner/v_nom", v_nom);
118 quad_utils::loadROSParam(nh, "global_body_planner/robot_l", robot_l);
119 quad_utils::loadROSParam(nh, "global_body_planner/robot_w", robot_w);
120 quad_utils::loadROSParam(nh, "global_body_planner/robot_h", robot_h);
121
122 quad_utils::loadROSParam(nh, "global_body_planner/mass", mass);
123 quad_utils::loadROSParam(nh, "global_body_planner/grf_min", grf_min);
124 quad_utils::loadROSParam(nh, "global_body_planner/grf_max", grf_max);
125 quad_utils::loadROSParam(nh,
126 "/global_body_planner/traversability_threshold",
127 traversability_threshold);
128
129 // Load global parameters
130 quad_utils::loadROSParam(nh, "/global_body_planner/g", g);
131 quad_utils::loadROSParam(nh, "/global_body_planner/mu", mu);
132 quad_utils::loadROSParam(nh, "/global_body_planner/t_s_min", t_s_min);
133 quad_utils::loadROSParam(nh, "/global_body_planner/t_s_max", t_s_max);
134 quad_utils::loadROSParam(nh, "/global_body_planner/dz0_min", dz0_min);
135 quad_utils::loadROSParam(nh, "/global_body_planner/dz0_max", dz0_max);
136 quad_utils::loadROSParam(nh, "/global_body_planner/dt", dt);
137 quad_utils::loadROSParam(nh, "/global_body_planner/backup_ratio",
138 backup_ratio);
139 quad_utils::loadROSParam(nh, "/global_body_planner/trapped_buffer_factor",
140 trapped_buffer_factor);
141 quad_utils::loadROSParam(nh, "/global_body_planner/num_leap_samples",
142 num_leap_samples);
143 quad_utils::loadROSParam(nh, "/global_body_planner/max_planning_time",
144 max_planning_time);
145
146 // Load the scalar parameters into Eigen vectors
148 }
149};
150
154enum Phase { CONNECT, LEAP_STANCE, FLIGHT, LAND_STANCE };
155
160enum TreeDirection { FORWARD, REVERSE };
161
165enum ExitFlag {
166 UNSOLVED,
167 VALID,
168 VALID_PARTIAL,
169 INVALID_START_STATE,
170 INVALID_GOAL_STATE,
171 INVALID_START_GOAL_EQUAL
172};
173
175const grid_map::InterpolationMethods INTER_TYPE =
176 grid_map::InterpolationMethods::INTER_NEAREST;
177
179typedef Eigen::Vector3d GRF;
180
184struct State {
185 Eigen::Vector3d pos;
186 Eigen::Vector3d vel;
187
188 bool operator==(const State rhs) const {
189 // Z velocity is overridden by action
190 return ((pos == rhs.pos) && (vel.head<2>() == rhs.vel.head<2>()));
191 }
192
193 bool operator!=(const State rhs) const {
194 // Z velocity is overridden by action
195 return ((pos != rhs.pos) || (vel.head<2>() != rhs.vel.head<2>()));
196 }
197
198 bool isApprox(const State rhs) const {
199 // Z velocity is overridden by action
200 return ((pos.isApprox(rhs.pos)) &&
201 (vel.head<2>().isApprox(rhs.vel.head<2>())));
202 }
203};
204
208struct FullState {
209 Eigen::Vector3d pos; // Position
210 Eigen::Vector3d vel; // Velocity
211 Eigen::Vector3d ang; // Linear Velocity
212 Eigen::Vector3d ang_vel; // Angular Velocity
213};
214
218struct Action {
219 GRF grf_0; // Ground reaction force at the beginning of leaping phase
220 GRF grf_f; // Ground reaction froce at the end of landing phase
221 double t_s_leap; // Time length of leaping phase
222 double t_f; // Time length of flight phase
223 double t_s_land; // Time length of landing phase
224 double dz_0; // Velocity at the beginning of leaping phase
225 double dz_f; // Velocity at the end of landing phase
226};
227
229 State s_new; // New State
230 Action a_new; // New Action
231 double t_new = 0; // !!!
232 double length = 0; // Distance between new State and previous State
233};
234
240State fullStateToState(const FullState &full_state);
241
253FullState stateToFullState(const State &state, double roll, double pitch,
254 double yaw, double roll_rate, double pitch_rate,
255 double yaw_rate);
256
262void eigenToFullState(const Eigen::VectorXd &s_eig, FullState &s);
263
269Eigen::VectorXd fullStateToEigen(const FullState &s);
270
276void vectorToFullState(const std::vector<double> &v, FullState &s);
277
282void flipDirection(State &s);
283
289void flipDirection(Action &a);
290
295void printState(const State &s);
296
301void printFullState(const FullState &s);
302
307void printStateNewline(const State &s);
308
313void printAction(const Action &a);
314
319void printActionNewline(const Action &a);
320
325void printStateSequence(const std::vector<State> &state_sequence);
326
333void printInterpStateSequence(const std::vector<State> &state_sequence,
334 const std::vector<double> &interp_t);
335
340void printActionSequence(const std::vector<Action> &action_sequence);
341
348double poseDistance(const State &q1, const State &q2);
349
356double poseDistance(const FullState &q1, const FullState &q2);
357
365double poseDistance(const std::vector<double> &v1,
366 const std::vector<double> &v2);
367
376double stateDistance(const State &q1, const State &q2);
377
384Eigen::Vector3d rotateGRF(const Eigen::Vector3d &surface_norm,
385 const Eigen::Vector3d &grf);
386
392inline double getSpeed(const State &s) { return s.vel.norm(); }
393
402void addFullStates(const FullState &start_state,
403 std::vector<State> interp_reduced_path, double dt,
404 std::vector<FullState> &interp_full_path,
405 const PlannerConfig &planner_config);
406
424State interpStateActionPair(const State &s, const Action &a, double t0,
425 double dt, std::vector<State> &interp_plan,
426 std::vector<GRF> &interp_GRF,
427 std::vector<double> &interp_t,
428 std::vector<int> &interp_primitive_id,
429 std::vector<double> &interp_length,
430 const PlannerConfig &planner_config);
431
448void getInterpPlan(const FullState &start_state,
449 const std::vector<State> &state_sequence,
450 const std::vector<Action> &action_sequence, double dt,
451 double t0, std::vector<FullState> &interp_full_plan,
452 std::vector<GRF> &interp_GRF, std::vector<double> &interp_t,
453 std::vector<int> &interp_primitive_id,
454 std::vector<double> &interp_length,
455 const PlannerConfig &planner_config);
456
463double getPitchFromState(const State &s, const PlannerConfig &planner_config);
464
471double getDzFromState(const State &s, const PlannerConfig &planner_config);
472
479void setDz(State &s, const PlannerConfig &planner_config);
480
487void setDz(State &s, const Eigen::Vector3d &surf_norm);
488
496inline bool isInMap(const Eigen::Vector3d &pos,
497 const PlannerConfig &planner_config) {
498 // Uncomment to use grid_map
499 return planner_config.terrain_grid_map.isInside(pos.head<2>());
500 // return planner_config.terrain.isInRange(pos[0], pos[1]);
501}
502
509inline bool isInMap(const State &s, const PlannerConfig &planner_config) {
510 return isInMap(s.pos, planner_config);
511}
512
519inline double getTerrainZ(const Eigen::Vector3d &pos,
520 const PlannerConfig &planner_config) {
521 // Uncomment to use grid_map
522 // return planner_config.terrain_grid_map.atPosition("z_inpainted",
523 // pos.head<2>(),
524 // INTER_TYPE);
525 return (planner_config.terrain.getGroundHeight(pos[0], pos[1]));
526}
527
534inline double getTerrainZFiltered(const Eigen::Vector3d &pos,
535 const PlannerConfig &planner_config) {
536 // Uncomment to use grid_map
537 // return planner_config.terrain_grid_map.atPosition("z_smooth",
538 // pos.head<2>(),
539 // INTER_TYPE);
540 return (planner_config.terrain.getGroundHeightFiltered(pos[0], pos[1]));
541}
542
549inline double getTraversability(const Eigen::Vector3d &pos,
550 const PlannerConfig &planner_config) {
551 return planner_config.terrain_grid_map.atPosition("traversability",
552 pos.head<2>(), INTER_TYPE);
553}
554
562inline bool isTraversable(const Eigen::Vector3d &pos,
563 const PlannerConfig &planner_config) {
564 return (getTraversability(pos, planner_config) >=
565 planner_config.traversability_threshold);
566}
567
574inline Eigen::Vector3d getSurfaceNormalFiltered(
575 const State &s, const PlannerConfig &planner_config) {
576 // Uncomment to use grid_map
577 // Eigen::Vector3d surf_norm;
578 // surf_norm.x() = planner_config.terrain_grid_map.atPosition(
579 // "normal_vectors_x", s.pos.head<2>(), INTER_TYPE);
580 // surf_norm.y() = planner_config.terrain_grid_map.atPosition(
581 // "normal_vectors_y", s.pos.head<2>(), INTER_TYPE);
582 // surf_norm.z() = planner_config.terrain_grid_map.atPosition(
583 // "normal_vectors_z", s.pos.head<2>(), INTER_TYPE);
584 // return surf_norm;
585 return planner_config.terrain.getSurfaceNormalFilteredEigen(s.pos[0],
586 s.pos[1]);
587}
588
595inline double getTerrainZFromState(const State &s,
596 const PlannerConfig &planner_config) {
597 return getTerrainZ(s.pos, planner_config);
598}
599
606inline double getTerrainZFilteredFromState(
607 const State &s, const PlannerConfig &planner_config) {
608 return getTerrainZFiltered(s.pos, planner_config);
609}
610
618inline double getZRelToTerrain(const Eigen::Vector3d &pos,
619 const PlannerConfig &planner_config) {
620 return (pos[2] - getTerrainZ(pos, planner_config));
621}
622
630inline double getZRelToTerrain(const State &s,
631 const PlannerConfig &planner_config) {
632 return getZRelToTerrain(s.pos, planner_config);
633}
634
643inline double getZRelToTerrainFiltered(const Eigen::Vector3d &pos,
644 const PlannerConfig &planner_config) {
645 return (pos[2] - getTerrainZFiltered(pos, planner_config));
646}
647
655inline double getZRelToTerrainFiltered(const State &s,
656 const PlannerConfig &planner_config) {
657 return getZRelToTerrainFiltered(s.pos, planner_config);
658}
659
668inline void getMapBounds(const PlannerConfig &planner_config, double &x_min,
669 double &x_max, double &y_min, double &y_max) {
670 double eps = 0.5;
671 x_min = planner_config.terrain.getXData().front() + eps;
672 x_max = planner_config.terrain.getXData().back() - eps;
673 y_min = planner_config.terrain.getYData().front() + eps;
674 y_max = planner_config.terrain.getYData().back() - eps;
675}
676
686State applyStance(const State &s, const Action &a, double t, int phase,
687 const PlannerConfig &planner_config);
688
699State applyStance(const State &s, const Action &a, int phase,
700 const PlannerConfig &planner_config);
701
709State applyFlight(const State &s, double t_f,
710 const PlannerConfig &planner_config);
711
719State applyAction(const State &s, const Action &a,
720 const PlannerConfig &planner_config);
721
730GRF getGRF(const Action &a, double t, int phase,
731 const PlannerConfig &planner_config);
732
740Eigen::Vector3d getAcceleration(const Action &a, double t, int phase,
741 const PlannerConfig &planner_config);
742
743// Action sampling
751bool getRandomLeapAction(const State &s, const Eigen::Vector3d &surf_norm,
752 Action &a, const PlannerConfig &planner_config);
753
754// Action refinement (for improved feasiblity)
762bool refineAction(const State &s, Action &a,
763 const PlannerConfig &planner_config);
773bool refineStance(const State &s, int phase, Action &a,
774 const PlannerConfig &planner_config);
782bool refineFlight(const State &s, double &t_f,
783 const PlannerConfig &planner_config);
784
785// Instantaneous validity checking
793bool isValidAction(const Action &a, const PlannerConfig &planner_config);
794
804bool isValidState(const State &s, const PlannerConfig &planner_config,
805 int phase);
806
816bool isValidState(const State &s, const PlannerConfig &planner_config,
817 int phase, double &max_height);
818
819// Trajectory validity checking
828bool isValidStateActionPair(const State &s, const Action &a,
829 StateActionResult &result,
830 const PlannerConfig &planner_config);
831
832// Define visualization functions
841void publishStateActionPair(const State &s, const Action &a,
842 const State &s_goal,
843 const PlannerConfig &planner_config,
844 visualization_msgs::MarkerArray &tree_viz_msg,
845 ros::Publisher &tree_pub);
846} // namespace planning_utils
847
848#endif
A terrain map class built for fast and efficient sampling.
Definition fast_terrain_map.h:16
Define action with Eigen data.
Definition planning_utils.h:218
Define full state with Eigen data.
Definition planning_utils.h:208
Planner Configuration.
Definition planning_utils.h:36
void loadEigenVectorsFromParams()
Definition planning_utils.h:93
void loadParamsFromServer(ros::NodeHandle nh)
Load the Global Body Planner parameters from ROS server.
Definition planning_utils.h:111
Definition planning_utils.h:228
Define state with Eigen data.
Definition planning_utils.h:184