safe_trajectory_planner.cpp
Go to the documentation of this file.
2 
3 using namespace std;
4 using namespace costmap_2d;
5 using namespace base_local_planner;
6 
7 namespace safe_teleop {
8 SafeTrajectoryPlanner::SafeTrajectoryPlanner(WorldModel& world_model,
9  const Costmap2D& costmap,
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)
31 {
32 }
33 
35 
36 //create and score a trajectory given the current pose of the robot and selected velocities
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,
44  Trajectory& traj){
45  double x_i = x;
46  double y_i = y;
47  double theta_i = theta;
48 
49  double vx_i, vy_i, vtheta_i;
50 
51  vx_i = vx;
52  vy_i = vy;
53  vtheta_i = vtheta;
54 
55  //compute the magnitude of the velocities
56  // double vmag = sqrt(vx_samp * vx_samp + vy_samp * vy_samp);
57 
58  //compute the number of steps we must take along this trajectory to be "safe"
59  int num_steps = int(sim_time_ / sim_granularity_ + 0.5);
60 
61  double dt = sim_time_ / num_steps;
62  double time = 0.0;
63 
64  //create a potential trajectory
65  traj.resetPoints();
66  traj.xv_ = vx_samp;
67  traj.yv_ = vy_samp;
68  traj.thetav_ = vtheta_samp;
69  traj.cost_ = -1.0;
70 
71  if(num_steps == 0)
72  return;
73 
74  //initialize the costs for the trajectory
75  double user_dist = 0.0;
76  double occ_cost = 0.0;
77 
78  for(int i = 0; i < num_steps; ++i){
79  //get map coordinates of a point
80  unsigned int cell_x, cell_y;
81 
82  //we don't want a path that goes off the know map
83  if(!costmap_.worldToMap(x_i, y_i, cell_x, cell_y)){
84  traj.cost_ = -1.0;
85  return;
86  }
87 
88  //check the point on the trajectory for legality
89  double footprint_cost = footprintCost(x_i, y_i, theta_i);
90 
91  //if the footprint hits an obstacle this trajectory is invalid
92  if(footprint_cost < 0){
93  traj.cost_ = -1.0;
94  return;
95  }
96 
97  occ_cost = std::max(std::max(occ_cost, footprint_cost), double(costmap_.getCost(cell_x, cell_y)));
98 
99  time += dt;
100 
101  //the point is legal... add it to the trajectory
102  traj.addPoint(x_i, y_i, theta_i);
103 
104  //calculate velocities
105  vx_i = computeNewVelocity(vx_samp, vx_i, acc_x, dt);
106  vy_i = computeNewVelocity(vy_samp, vy_i, acc_y, dt);
107  vtheta_i = computeNewVelocity(vtheta_samp, vtheta_i, acc_theta, dt);
108 
109  //calculate positions
110  x_i = computeNewXPosition(x_i, vx_i, vy_i, theta_i, dt);
111  y_i = computeNewYPosition(y_i, vx_i, vy_i, theta_i, dt);
112  theta_i = computeNewThetaPosition(theta_i, vtheta_i, dt);
113 
114  }
115 
116  user_dist = sqrt((vx_samp - dx) * (vx_samp - dx) +
117  (vy_samp - dy) * (vy_samp - dy) +
118  (vtheta_samp - dtheta) * (vtheta_samp - dtheta));
119 
120  traj.cost_ = user_dist * userdist_scale_ + occdist_scale_ * occ_cost;
121 }
122 
123 //calculate the cost of a ray-traced line
124 double SafeTrajectoryPlanner::lineCost(int x0, int x1,
125  int y0, int y1){
126  //Bresenham Ray-Tracing
127  int deltax = abs(x1 - x0); // The difference between the x's
128  int deltay = abs(y1 - y0); // The difference between the y's
129  int x = x0; // Start x off at the first pixel
130  int y = y0; // Start y off at the first pixel
131 
132  int xinc1, xinc2, yinc1, yinc2;
133  int den, num, numadd, numpixels;
134 
135  double line_cost = 0.0;
136  double point_cost = -1.0;
137 
138  if (x1 >= x0) // The x-values are increasing
139  {
140  xinc1 = 1;
141  xinc2 = 1;
142  }
143  else // The x-values are decreasing
144  {
145  xinc1 = -1;
146  xinc2 = -1;
147  }
148 
149  if (y1 >= y0) // The y-values are increasing
150  {
151  yinc1 = 1;
152  yinc2 = 1;
153  }
154  else // The y-values are decreasing
155  {
156  yinc1 = -1;
157  yinc2 = -1;
158  }
159 
160  if (deltax >= deltay) // There is at least one x-value for every y-value
161  {
162  xinc1 = 0; // Don't change the x when numerator >= denominator
163  yinc2 = 0; // Don't change the y for every iteration
164  den = deltax;
165  num = deltax / 2;
166  numadd = deltay;
167  numpixels = deltax; // There are more x-values than y-values
168  }
169  else // There is at least one y-value for every x-value
170  {
171  xinc2 = 0; // Don't change the x for every iteration
172  yinc1 = 0; // Don't change the y when numerator >= denominator
173  den = deltay;
174  num = deltay / 2;
175  numadd = deltax;
176  numpixels = deltay; // There are more y-values than x-values
177  }
178 
179  for (int curpixel = 0; curpixel <= numpixels; curpixel++)
180  {
181  point_cost = pointCost(x, y); //Score the current point
182 
183  if(point_cost < 0)
184  return -1;
185 
186  if(line_cost < point_cost)
187  line_cost = point_cost;
188 
189  num += numadd; // Increase the numerator by the top of the fraction
190  if (num >= den) // Check if numerator >= denominator
191  {
192  num -= den; // Calculate the new numerator value
193  x += xinc1; // Change the x as appropriate
194  y += yinc1; // Change the y as appropriate
195  }
196  x += xinc2; // Change the x as appropriate
197  y += yinc2; // Change the y as appropriate
198  }
199 
200  return line_cost;
201 }
202 
203 double SafeTrajectoryPlanner::pointCost(int x, int y){
204  unsigned char cost = costmap_.getCost(x, y);
205  //if the cell is in an obstacle the path is invalid
206  if(cost == LETHAL_OBSTACLE || cost == INSCRIBED_INFLATED_OBSTACLE || cost == NO_INFORMATION){
207  return -1;
208  }
209 
210  return cost;
211 }
212 
213 //create the trajectories we wish to score
214 Trajectory SafeTrajectoryPlanner::createTrajectories(double x, double y, double theta,
215  double vx, double vy, double vtheta,
216  double acc_x, double acc_y, double acc_theta,
217  double dx, double dy, double dtheta){
218  //compute feasible velocity limits in robot space
219  double max_vel_x, max_vel_y, max_vel_theta;
220  double min_vel_x, min_vel_y, min_vel_theta;
221 
222  //should we use the dynamic window approach?
223  if(dwa_){
224  max_vel_x = min(max_vel_x_, vx + acc_x * .1);
225  min_vel_x = max(min_vel_x_, vx - acc_x * .1);
226 
227  max_vel_y = min(max_vel_y_, vy + acc_y * .1);
228  min_vel_y = max(min_vel_y_, vy - acc_y * .1);
229 
230  max_vel_theta = min(max_vel_th_, vtheta + acc_theta * .1);
231  min_vel_theta = max(min_vel_th_, vtheta - acc_theta * .1);
232  } else {
233  max_vel_x = min(max_vel_x_, vx + acc_x * sim_time_);
234  min_vel_x = max(min_vel_x_, vx - acc_x * sim_time_);
235 
236  max_vel_y = min(max_vel_y_, vy + acc_y * sim_time_);
237  min_vel_y = max(min_vel_y_, vy - acc_y * sim_time_);
238 
239  max_vel_theta = min(max_vel_th_, vtheta + acc_theta * sim_time_);
240  min_vel_theta = max(min_vel_th_, vtheta - acc_theta * sim_time_);
241  }
242 
243  //keep track of the best trajectory seen so far
244  Trajectory* best_traj = &traj_one;
245  best_traj->cost_ = -1.0;
246 
247  Trajectory* comp_traj = &traj_two;
248  comp_traj->cost_ = -1.0;
249 
250  Trajectory* swap = NULL;
251 
252  //any cell with a cost greater than the size of the map is impossible
253  double impossible_cost = map_.obstacleCosts();
254 
255  // first sample the user suggested trajectory
256  generateTrajectory(x, y, theta, vx, vy, vtheta, dx, dy, dtheta, acc_x, acc_y, acc_theta, impossible_cost, dx, dy, dtheta, *comp_traj);
257 
258  //if the new trajectory is better... let's take it
259  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
260  swap = best_traj;
261  best_traj = comp_traj;
262  comp_traj = swap;
263  }
264 
265  //we want to sample the velocity space regularly
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);
269 
270  double vx_samp = 0.0;
271  double vy_samp = 0.0;
272  double vtheta_samp = 0.0;
273 
274  if (holonomic_robot_) {
275  //loop through all x velocities
276  vx_samp = min_vel_x;
277  for(int i = 0; i < vx_samples_; ++i){
278  vy_samp = 0;
279  vtheta_samp = 0;
280  //first sample the straight trajectory
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);
282 
283  //if the new trajectory is better... let's take it
284  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
285  swap = best_traj;
286  best_traj = comp_traj;
287  comp_traj = swap;
288  }
289 
290  vy_samp = min_vel_y;
291  for (int k = 0; k < vy_samples_; k++) {
292  vtheta_samp = 0;
293  //first sample the trajectory with no rotation
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);
295 
296  //if the new trajectory is better... let's take it
297  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
298  swap = best_traj;
299  best_traj = comp_traj;
300  comp_traj = swap;
301  }
302 
303 
304  vtheta_samp = min_vel_theta;
305  //next sample all theta trajectories
306  for(int j = 0; j < vtheta_samples_ - 1; ++j){
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);
308 
309  //if the new trajectory is better... let's take it
310  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
311  swap = best_traj;
312  best_traj = comp_traj;
313  comp_traj = swap;
314  }
315  vtheta_samp += dvtheta;
316  }
317  vy_samp += dvy;
318  }
319  vx_samp += dvx;
320  }
321  } else {
322  vy_samp = 0.0;
323  //loop through all x velocities
324  vx_samp = min_vel_x;
325  for(int i = 0; i < vx_samples_; ++i){
326  vtheta_samp = 0;
327  //first sample the straight trajectory
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);
329 
330  //if the new trajectory is better... let's take it
331  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
332  swap = best_traj;
333  best_traj = comp_traj;
334  comp_traj = swap;
335  }
336 
337  vtheta_samp = min_vel_theta;
338  //next sample all theta trajectories
339  for(int j = 0; j < vtheta_samples_ - 1; ++j){
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);
341 
342  //if the new trajectory is better... let's take it
343  if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
344  swap = best_traj;
345  best_traj = comp_traj;
346  comp_traj = swap;
347  }
348  vtheta_samp += dvtheta;
349 
350  }
351  vx_samp += dvx;
352  }
353  }
354 
355 
356 
357  return *best_traj;
358 }
359 
360 //given the current state of the robot, find a good trajectory
362  tf::Stamped<tf::Pose> user_vel, tf::Stamped<tf::Pose>& drive_velocities){
363 
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());
367 
368  double x = global_pose.getOrigin().getX();
369  double y = global_pose.getOrigin().getY();
370  double theta = yaw;
371 
372  double vx = global_vel.getOrigin().getX();
373  double vy = global_vel.getOrigin().getY();
374  double vtheta = vel_yaw;
375 
376  double dx = user_vel.getOrigin().getX();
377  double dy = user_vel.getOrigin().getY();
378  double dtheta = dyaw;
379 
380  //reset the map for new operations
382 
383  //temporarily remove obstacles that are within the footprint of the robot
384  vector<base_local_planner::Position2DInt> footprint_list = getFootprintCells(x, y, theta, true);
385 
386  //mark cells within the initial footprint of the robot
387  for(unsigned int i = 0; i < footprint_list.size(); ++i){
388  map_(footprint_list[i].x, footprint_list[i].y).within_robot = true;
389  }
390 
391  //rollout trajectories and find the minimum cost one
392  Trajectory best = createTrajectories(x, y, theta, vx, vy, vtheta, acc_lim_x_, acc_lim_y_, acc_lim_theta_, dx, dy, dtheta);
393  ROS_DEBUG("Trajectories created");
394 
395  if(best.cost_ < 0) {
396  drive_velocities.setIdentity();
397  ROS_INFO("No safe trajectory found");
398  }
399  else {
400  tf::Vector3 start(best.xv_, best.yv_, 0);
401  drive_velocities.setOrigin(start);
402  tf::Matrix3x3 matrix;
404  drive_velocities.setBasis(matrix);
405  }
406 
407  return best;
408 }
409 
411  tf::Stamped<tf::Pose> user_vel){
412 
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());
416 
417  double x = global_pose.getOrigin().getX();
418  double y = global_pose.getOrigin().getY();
419  double theta = yaw;
420 
421  double vx = global_vel.getOrigin().getX();
422  double vy = global_vel.getOrigin().getY();
423  double vtheta = vel_yaw;
424 
425  double dx = user_vel.getOrigin().getX();
426  double dy = user_vel.getOrigin().getY();
427  double dtheta = dyaw;
428 
429  //reset the map for new operations
431 
432  //temporarily remove obstacles that are within the footprint of the robot
433  vector<base_local_planner::Position2DInt> footprint_list = getFootprintCells(x, y, theta, true);
434 
435  //mark cells within the initial footprint of the robot
436  for(unsigned int i = 0; i < footprint_list.size(); ++i){
437  map_(footprint_list[i].x, footprint_list[i].y).within_robot = true;
438  }
439 
440  Trajectory traj;
441  double impossible_cost = map_.obstacleCosts();
442  generateTrajectory(x, y, theta, vx, vy, vtheta, dx, dy, dtheta,
443  acc_lim_x_, acc_lim_y_, acc_lim_theta_, impossible_cost, dx, dy, dtheta, traj);
444 
445  return traj;
446 }
447 
448 //we need to take the footprint of the robot into account when we calculate cost to obstacles
449 double SafeTrajectoryPlanner::footprintCost(double x_i, double y_i, double theta_i){
450  //build the oriented footprint
451  double cos_th = cos(theta_i);
452  double sin_th = sin(theta_i);
453  vector<geometry_msgs::Point> oriented_footprint;
454  for(unsigned int i = 0; i < footprint_spec_.size(); ++i){
455  geometry_msgs::Point new_pt;
456  new_pt.x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
457  new_pt.y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
458  oriented_footprint.push_back(new_pt);
459  }
460 
461  geometry_msgs::Point robot_position;
462  robot_position.x = x_i;
463  robot_position.y = y_i;
464 
465  //check if the footprint is legal
466  double footprint_cost = world_model_.footprintCost(robot_position, oriented_footprint, inscribed_radius_, circumscribed_radius_);
467 
468  return footprint_cost;
469 }
470 
471 void SafeTrajectoryPlanner::getLineCells(int x0, int x1, int y0, int y1, vector<base_local_planner::Position2DInt>& pts){
472  //Bresenham Ray-Tracing
473  int deltax = abs(x1 - x0); // The difference between the x's
474  int deltay = abs(y1 - y0); // The difference between the y's
475  int x = x0; // Start x off at the first pixel
476  int y = y0; // Start y off at the first pixel
477 
478  int xinc1, xinc2, yinc1, yinc2;
479  int den, num, numadd, numpixels;
480 
481  base_local_planner::Position2DInt pt;
482 
483  if (x1 >= x0) // The x-values are increasing
484  {
485  xinc1 = 1;
486  xinc2 = 1;
487  }
488  else // The x-values are decreasing
489  {
490  xinc1 = -1;
491  xinc2 = -1;
492  }
493 
494  if (y1 >= y0) // The y-values are increasing
495  {
496  yinc1 = 1;
497  yinc2 = 1;
498  }
499  else // The y-values are decreasing
500  {
501  yinc1 = -1;
502  yinc2 = -1;
503  }
504 
505  if (deltax >= deltay) // There is at least one x-value for every y-value
506  {
507  xinc1 = 0; // Don't change the x when numerator >= denominator
508  yinc2 = 0; // Don't change the y for every iteration
509  den = deltax;
510  num = deltax / 2;
511  numadd = deltay;
512  numpixels = deltax; // There are more x-values than y-values
513  }
514  else // There is at least one y-value for every x-value
515  {
516  xinc2 = 0; // Don't change the x for every iteration
517  yinc1 = 0; // Don't change the y when numerator >= denominator
518  den = deltay;
519  num = deltay / 2;
520  numadd = deltax;
521  numpixels = deltay; // There are more y-values than x-values
522  }
523 
524  for (int curpixel = 0; curpixel <= numpixels; curpixel++)
525  {
526  pt.x = x; //Draw the current pixel
527  pt.y = y;
528  pts.push_back(pt);
529 
530  num += numadd; // Increase the numerator by the top of the fraction
531  if (num >= den) // Check if numerator >= denominator
532  {
533  num -= den; // Calculate the new numerator value
534  x += xinc1; // Change the x as appropriate
535  y += yinc1; // Change the y as appropriate
536  }
537  x += xinc2; // Change the x as appropriate
538  y += yinc2; // Change the y as appropriate
539  }
540 }
541 
542 //get the cellsof a footprint at a given position
543 vector<base_local_planner::Position2DInt> SafeTrajectoryPlanner::getFootprintCells(double x_i, double y_i, double theta_i, bool fill){
544  vector<base_local_planner::Position2DInt> footprint_cells;
545 
546  //if we have no footprint... do nothing
547  if(footprint_spec_.size() <= 1){
548  unsigned int mx, my;
549  if(costmap_.worldToMap(x_i, y_i, mx, my)){
550  Position2DInt center;
551  center.x = mx;
552  center.y = my;
553  footprint_cells.push_back(center);
554  }
555  return footprint_cells;
556  }
557 
558  //pre-compute cos and sin values
559  double cos_th = cos(theta_i);
560  double sin_th = sin(theta_i);
561  double new_x, new_y;
562  unsigned int x0, y0, x1, y1;
563  unsigned int last_index = footprint_spec_.size() - 1;
564 
565  for(unsigned int i = 0; i < last_index; ++i){
566  //find the cell coordinates of the first segment point
567  new_x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
568  new_y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
569  if(!costmap_.worldToMap(new_x, new_y, x0, y0))
570  return footprint_cells;
571 
572  //find the cell coordinates of the second segment point
573  new_x = x_i + (footprint_spec_[i + 1].x * cos_th - footprint_spec_[i + 1].y * sin_th);
574  new_y = y_i + (footprint_spec_[i + 1].x * sin_th + footprint_spec_[i + 1].y * cos_th);
575  if(!costmap_.worldToMap(new_x, new_y, x1, y1))
576  return footprint_cells;
577 
578  getLineCells(x0, x1, y0, y1, footprint_cells);
579  }
580 
581  //we need to close the loop, so we also have to raytrace from the last pt to first pt
582  new_x = x_i + (footprint_spec_[last_index].x * cos_th - footprint_spec_[last_index].y * sin_th);
583  new_y = y_i + (footprint_spec_[last_index].x * sin_th + footprint_spec_[last_index].y * cos_th);
584  if(!costmap_.worldToMap(new_x, new_y, x0, y0))
585  return footprint_cells;
586 
587  new_x = x_i + (footprint_spec_[0].x * cos_th - footprint_spec_[0].y * sin_th);
588  new_y = y_i + (footprint_spec_[0].x * sin_th + footprint_spec_[0].y * cos_th);
589  if(!costmap_.worldToMap(new_x, new_y, x1, y1))
590  return footprint_cells;
591 
592  getLineCells(x0, x1, y0, y1, footprint_cells);
593 
594  if(fill)
595  getFillCells(footprint_cells);
596 
597  return footprint_cells;
598 }
599 
600 void SafeTrajectoryPlanner::getFillCells(vector<base_local_planner::Position2DInt>& footprint){
601  //quick bubble sort to sort pts by x
602  base_local_planner::Position2DInt swap, pt;
603  unsigned int i = 0;
604  while(i < footprint.size() - 1){
605  if(footprint[i].x > footprint[i + 1].x){
606  swap = footprint[i];
607  footprint[i] = footprint[i + 1];
608  footprint[i + 1] = swap;
609  if(i > 0)
610  --i;
611  }
612  else
613  ++i;
614  }
615 
616  i = 0;
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;
621  //walk through each column and mark cells inside the footprint
622  for(unsigned int x = min_x; x <= max_x; ++x){
623  if(i >= footprint.size() - 1)
624  break;
625 
626  if(footprint[i].y < footprint[i + 1].y){
627  min_pt = footprint[i];
628  max_pt = footprint[i + 1];
629  }
630  else{
631  min_pt = footprint[i + 1];
632  max_pt = footprint[i];
633  }
634 
635  i += 2;
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];
641  ++i;
642  }
643 
644  //loop though cells in the column
645  for(unsigned int y = min_pt.y; y < max_pt.y; ++y){
646  pt.x = x;
647  pt.y = y;
648  footprint.push_back(pt);
649  }
650  }
651 }
652 
653 };
654 
655 
void getLineCells(int x0, int x1, int y0, int y1, std::vector< base_local_planner::Position2DInt > &pts)
Use Bresenham&#39;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&#39;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...
#define ROS_INFO(...)
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 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.
int min(int a, int b)
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.
#define ROS_DEBUG(...)


safe_teleop_base
Author(s):
autogenerated on Fri Dec 20 2019 04:00:23