8 SafeTrajectoryPlanner::SafeTrajectoryPlanner(
WorldModel& world_model,
10 std::vector<geometry_msgs::Point> footprint_spec,
11 double inscribed_radius,
double circumscribed_radius,
12 double acc_lim_x,
double acc_lim_y,
double acc_lim_theta,
13 double sim_time,
double sim_granularity,
14 int vx_samples,
int vy_samples,
int vtheta_samples,
15 double userdist_scale,
double occdist_scale,
16 double max_vel_x,
double min_vel_x,
17 double max_vel_y,
double min_vel_y,
18 double max_vel_th,
double min_vel_th,
19 bool holonomic_robot,
bool dwa)
20 : map_(costmap.getSizeInCellsX(), costmap.getSizeInCellsY()), costmap_(costmap),
21 world_model_(world_model), footprint_spec_(footprint_spec),
22 inscribed_radius_(inscribed_radius), circumscribed_radius_(circumscribed_radius),
23 sim_time_(sim_time), sim_granularity_(sim_granularity),
24 vx_samples_(vx_samples), vy_samples_(vy_samples), vtheta_samples_(vtheta_samples),
25 userdist_scale_(userdist_scale), occdist_scale_(occdist_scale),
26 acc_lim_x_(acc_lim_x), acc_lim_y_(acc_lim_y), acc_lim_theta_(acc_lim_theta),
27 max_vel_x_(max_vel_x), min_vel_x_(min_vel_x),
28 max_vel_y_(max_vel_y), min_vel_y_(min_vel_y),
29 max_vel_th_(max_vel_th), min_vel_th_(min_vel_th),
30 holonomic_robot_(holonomic_robot), dwa_(dwa)
38 double x,
double y,
double theta,
39 double vx,
double vy,
double vtheta,
40 double vx_samp,
double vy_samp,
double vtheta_samp,
41 double acc_x,
double acc_y,
double acc_theta,
42 double impossible_cost,
43 double dx,
double dy,
double dtheta,
47 double theta_i = theta;
49 double vx_i, vy_i, vtheta_i;
75 double user_dist = 0.0;
76 double occ_cost = 0.0;
78 for(
int i = 0; i < num_steps; ++i){
80 unsigned int cell_x, cell_y;
92 if(footprint_cost < 0){
97 occ_cost = std::max(std::max(occ_cost, footprint_cost),
double(
costmap_.
getCost(cell_x, cell_y)));
116 user_dist = sqrt((vx_samp - dx) * (vx_samp - dx) +
117 (vy_samp - dy) * (vy_samp - dy) +
118 (vtheta_samp - dtheta) * (vtheta_samp - dtheta));
127 int deltax = abs(x1 - x0);
128 int deltay = abs(y1 - y0);
132 int xinc1, xinc2, yinc1, yinc2;
133 int den, num, numadd, numpixels;
135 double line_cost = 0.0;
136 double point_cost = -1.0;
160 if (deltax >= deltay)
179 for (
int curpixel = 0; curpixel <= numpixels; curpixel++)
186 if(line_cost < point_cost)
187 line_cost = point_cost;
206 if(cost == LETHAL_OBSTACLE || cost == INSCRIBED_INFLATED_OBSTACLE || cost == NO_INFORMATION){
215 double vx,
double vy,
double vtheta,
216 double acc_x,
double acc_y,
double acc_theta,
217 double dx,
double dy,
double dtheta){
219 double max_vel_x, max_vel_y, max_vel_theta;
220 double min_vel_x, min_vel_y, min_vel_theta;
231 min_vel_theta = max(
min_vel_th_, vtheta - acc_theta * .1);
234 min_vel_x = max(
min_vel_x_, vx - acc_x * sim_time_);
237 min_vel_y = max(
min_vel_y_, vy - acc_y * sim_time_);
240 min_vel_theta = max(
min_vel_th_, vtheta - acc_theta * sim_time_);
245 best_traj->
cost_ = -1.0;
248 comp_traj->
cost_ = -1.0;
256 generateTrajectory(x, y, theta, vx, vy, vtheta, dx, dy, dtheta, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
261 best_traj = comp_traj;
266 double dvx = (max_vel_x - min_vel_x) / (
vx_samples_ - 1);
267 double dvy = (max_vel_y - min_vel_y) / (
vy_samples_ - 1);
268 double dvtheta = (max_vel_theta - min_vel_theta) / (
vtheta_samples_ - 1);
270 double vx_samp = 0.0;
271 double vy_samp = 0.0;
272 double vtheta_samp = 0.0;
281 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
286 best_traj = comp_traj;
294 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
299 best_traj = comp_traj;
304 vtheta_samp = min_vel_theta;
307 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
312 best_traj = comp_traj;
315 vtheta_samp += dvtheta;
328 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
333 best_traj = comp_traj;
337 vtheta_samp = min_vel_theta;
340 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
345 best_traj = comp_traj;
348 vtheta_samp += dvtheta;
364 double yaw =
tf::getYaw(global_pose.getRotation());
365 double vel_yaw =
tf::getYaw(global_vel.getRotation());
366 double dyaw =
tf::getYaw(user_vel.getRotation());
368 double x = global_pose.getOrigin().getX();
369 double y = global_pose.getOrigin().getY();
372 double vx = global_vel.getOrigin().getX();
373 double vy = global_vel.getOrigin().getY();
374 double vtheta = vel_yaw;
376 double dx = user_vel.getOrigin().getX();
377 double dy = user_vel.getOrigin().getY();
378 double dtheta = dyaw;
384 vector<base_local_planner::Position2DInt> footprint_list =
getFootprintCells(x, y, theta,
true);
387 for(
unsigned int i = 0; i < footprint_list.size(); ++i){
388 map_(footprint_list[i].x, footprint_list[i].y).within_robot =
true;
392 Trajectory best =
createTrajectories(x, y, theta, vx, vy, vtheta,
acc_lim_x_,
acc_lim_y_,
acc_lim_theta_, dx, dy, dtheta);
396 drive_velocities.setIdentity();
397 ROS_INFO(
"No safe trajectory found");
401 drive_velocities.setOrigin(start);
404 drive_velocities.setBasis(matrix);
413 double yaw =
tf::getYaw(global_pose.getRotation());
414 double vel_yaw =
tf::getYaw(global_vel.getRotation());
415 double dyaw =
tf::getYaw(user_vel.getRotation());
417 double x = global_pose.getOrigin().getX();
418 double y = global_pose.getOrigin().getY();
421 double vx = global_vel.getOrigin().getX();
422 double vy = global_vel.getOrigin().getY();
423 double vtheta = vel_yaw;
425 double dx = user_vel.getOrigin().getX();
426 double dy = user_vel.getOrigin().getY();
427 double dtheta = dyaw;
433 vector<base_local_planner::Position2DInt> footprint_list =
getFootprintCells(x, y, theta,
true);
436 for(
unsigned int i = 0; i < footprint_list.size(); ++i){
437 map_(footprint_list[i].x, footprint_list[i].y).within_robot =
true;
451 double cos_th = cos(theta_i);
452 double sin_th = sin(theta_i);
453 vector<geometry_msgs::Point> oriented_footprint;
455 geometry_msgs::Point new_pt;
458 oriented_footprint.push_back(new_pt);
461 geometry_msgs::Point robot_position;
462 robot_position.x = x_i;
463 robot_position.y = y_i;
468 return footprint_cost;
473 int deltax = abs(x1 - x0);
474 int deltay = abs(y1 - y0);
478 int xinc1, xinc2, yinc1, yinc2;
479 int den, num, numadd, numpixels;
481 base_local_planner::Position2DInt pt;
505 if (deltax >= deltay)
524 for (
int curpixel = 0; curpixel <= numpixels; curpixel++)
544 vector<base_local_planner::Position2DInt> footprint_cells;
550 Position2DInt center;
553 footprint_cells.push_back(center);
555 return footprint_cells;
559 double cos_th = cos(theta_i);
560 double sin_th = sin(theta_i);
562 unsigned int x0, y0, x1, y1;
565 for(
unsigned int i = 0; i < last_index; ++i){
570 return footprint_cells;
576 return footprint_cells;
585 return footprint_cells;
590 return footprint_cells;
597 return footprint_cells;
602 base_local_planner::Position2DInt swap, pt;
604 while(i < footprint.size() - 1){
605 if(footprint[i].
x > footprint[i + 1].
x){
607 footprint[i] = footprint[i + 1];
608 footprint[i + 1] = swap;
617 base_local_planner::Position2DInt min_pt;
618 base_local_planner::Position2DInt max_pt;
619 unsigned int min_x = footprint[0].x;
620 unsigned int max_x = footprint[footprint.size() -1].x;
622 for(
unsigned int x = min_x;
x <= max_x; ++
x){
623 if(i >= footprint.size() - 1)
626 if(footprint[i].
y < footprint[i + 1].
y){
627 min_pt = footprint[i];
628 max_pt = footprint[i + 1];
631 min_pt = footprint[i + 1];
632 max_pt = footprint[i];
636 while(i < footprint.size() && footprint[i].x ==
x){
637 if(footprint[i].
y < min_pt.y)
638 min_pt = footprint[i];
639 else if(footprint[i].
y > max_pt.y)
640 max_pt = footprint[i];
645 for(
unsigned int y = min_pt.y;
y < max_pt.y; ++
y){
648 footprint.push_back(pt);
void getLineCells(int x0, int x1, int y0, int y1, std::vector< base_local_planner::Position2DInt > &pts)
Use Bresenham's algorithm to trace a line between two points in a grid.
~SafeTrajectoryPlanner()
Destructs a trajectory controller.
virtual double footprintCost(const geometry_msgs::Point &position, const std::vector< geometry_msgs::Point > &footprint, double inscribed_radius, double circumscribed_radius)=0
double sim_granularity_
The distance between simulation points.
base_local_planner::MapGrid map_
The local map grid where we propagate goal and path distance.
static double getYaw(const Quaternion &bt_q)
double computeNewYPosition(double yi, double vx, double vy, double theta, double dt)
Compute y position based on velocity.
double occdist_scale_
Scaling factors for the controller's cost function.
base_local_planner::Trajectory traj_two
Used for scoring trajectories.
TFSIMD_FORCE_INLINE const tfScalar & y() const
void getFillCells(std::vector< base_local_planner::Position2DInt > &footprint)
Fill the outline of a polygon, in this case the robot footprint, in a grid.
void setRotation(const Quaternion &q)
double acc_lim_theta_
The acceleration limits of the robot.
base_local_planner::Trajectory createTrajectories(double x, double y, double theta, double vx, double vy, double vtheta, double acc_x, double acc_y, double acc_theta, double dx, double dy, double dtheta)
Create the trajectories we wish to explore, score them, and return the best option.
unsigned char getCost(unsigned int mx, unsigned int my) const
double min_vel_th_
Velocity limits for the controller.
double sim_time_
The number of seconds each trajectory is "rolled-out".
static Quaternion createQuaternionFromYaw(double yaw)
base_local_planner::Trajectory findPath(tf::Stamped< tf::Pose > global_pose, tf::Stamped< tf::Pose > global_vel, tf::Stamped< tf::Pose > user_vel)
Given the current position, orientation, and velocity of the robot, return a trajectory to follow...
base_local_planner::Trajectory traj_one
double computeNewThetaPosition(double thetai, double vth, double dt)
Compute orientation based on velocity.
std::vector< geometry_msgs::Point > footprint_spec_
The footprint specification of the robot.
TFSIMD_FORCE_INLINE const tfScalar & x() const
double pointCost(int x, int y)
double computeNewVelocity(double vg, double vi, double a_max, double dt)
Compute velocity based on acceleration.
double circumscribed_radius_
The inscribed and circumscribed radii of the robot.
std::vector< base_local_planner::Position2DInt > getFootprintCells(double x_i, double y_i, double theta_i, bool fill)
Used to get the cells that make up the footprint of the robot.
void addPoint(double x, double y, double th)
double computeNewXPosition(double xi, double vx, double vy, double theta, double dt)
Compute x position based on velocity.
base_local_planner::WorldModel & world_model_
The world model that the controller uses for collision detection.
double lineCost(int x0, int x1, int y0, int y1)
double footprintCost(double x_i, double y_i, double theta_i)
Checks the legality of the robot footprint at a position and orientation using the world model...
base_local_planner::Trajectory findBestPath(tf::Stamped< tf::Pose > global_pose, tf::Stamped< tf::Pose > global_vel, tf::Stamped< tf::Pose > user_vel, tf::Stamped< tf::Pose > &drive_velocities)
Given the current position, orientation, and velocity of the robot, return a trajectory to follow...
const costmap_2d::Costmap2D & costmap_
Provides access to cost map information.
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
void generateTrajectory(double x, double y, double theta, double vx, double vy, double vtheta, double vx_samp, double vy_samp, double vtheta_samp, double acc_x, double acc_y, double acc_theta, double impossible_cost, double dx, double dy, double dtheta, base_local_planner::Trajectory &traj)
Generate and score a single trajectory.