simple_trajectory_generator.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2008, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Willow Garage, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author: TKruse
36  *********************************************************************/
37 
39 
40 #include <cmath>
41 
43 
44 namespace base_local_planner {
45 
47  const Eigen::Vector3f& pos,
48  const Eigen::Vector3f& vel,
49  const Eigen::Vector3f& goal,
51  const Eigen::Vector3f& vsamples,
52  std::vector<Eigen::Vector3f> additional_samples,
53  bool discretize_by_time) {
54  initialise(pos, vel, goal, limits, vsamples, discretize_by_time);
55  // add static samples if any
56  sample_params_.insert(sample_params_.end(), additional_samples.begin(), additional_samples.end());
57 }
58 
59 
61  const Eigen::Vector3f& pos,
62  const Eigen::Vector3f& vel,
63  const Eigen::Vector3f& goal,
65  const Eigen::Vector3f& vsamples,
66  bool discretize_by_time) {
67  /*
68  * We actually generate all velocity sample vectors here, from which to generate trajectories later on
69  */
70  double max_vel_th = limits->max_vel_theta;
71  double min_vel_th = -1.0 * max_vel_th;
72  discretize_by_time_ = discretize_by_time;
73  Eigen::Vector3f acc_lim = limits->getAccLimits();
74  pos_ = pos;
75  vel_ = vel;
76  limits_ = limits;
78  sample_params_.clear();
79 
80  double min_vel_x = limits->min_vel_x;
81  double max_vel_x = limits->max_vel_x;
82  double min_vel_y = limits->min_vel_y;
83  double max_vel_y = limits->max_vel_y;
84 
85  // if sampling number is zero in any dimension, we don't generate samples generically
86  if (vsamples[0] * vsamples[1] * vsamples[2] > 0) {
87  //compute the feasible velocity space based on the rate at which we run
88  Eigen::Vector3f max_vel = Eigen::Vector3f::Zero();
89  Eigen::Vector3f min_vel = Eigen::Vector3f::Zero();
90 
91  if ( ! use_dwa_) {
92  // there is no point in overshooting the goal, and it also may break the
93  // robot behavior, so we limit the velocities to those that do not overshoot in sim_time
94  double dist = hypot(goal[0] - pos[0], goal[1] - pos[1]);
95  max_vel_x = std::max(std::min(max_vel_x, dist / sim_time_), min_vel_x);
96  max_vel_y = std::max(std::min(max_vel_y, dist / sim_time_), min_vel_y);
97 
98  // if we use continous acceleration, we can sample the max velocity we can reach in sim_time_
99  max_vel[0] = std::min(max_vel_x, vel[0] + acc_lim[0] * sim_time_);
100  max_vel[1] = std::min(max_vel_y, vel[1] + acc_lim[1] * sim_time_);
101  max_vel[2] = std::min(max_vel_th, vel[2] + acc_lim[2] * sim_time_);
102 
103  min_vel[0] = std::max(min_vel_x, vel[0] - acc_lim[0] * sim_time_);
104  min_vel[1] = std::max(min_vel_y, vel[1] - acc_lim[1] * sim_time_);
105  min_vel[2] = std::max(min_vel_th, vel[2] - acc_lim[2] * sim_time_);
106  } else {
107  // with dwa do not accelerate beyond the first step, we only sample within velocities we reach in sim_period
108  max_vel[0] = std::min(max_vel_x, vel[0] + acc_lim[0] * sim_period_);
109  max_vel[1] = std::min(max_vel_y, vel[1] + acc_lim[1] * sim_period_);
110  max_vel[2] = std::min(max_vel_th, vel[2] + acc_lim[2] * sim_period_);
111 
112  min_vel[0] = std::max(min_vel_x, vel[0] - acc_lim[0] * sim_period_);
113  min_vel[1] = std::max(min_vel_y, vel[1] - acc_lim[1] * sim_period_);
114  min_vel[2] = std::max(min_vel_th, vel[2] - acc_lim[2] * sim_period_);
115  }
116 
117  Eigen::Vector3f vel_samp = Eigen::Vector3f::Zero();
118  VelocityIterator x_it(min_vel[0], max_vel[0], vsamples[0]);
119  VelocityIterator y_it(min_vel[1], max_vel[1], vsamples[1]);
120  VelocityIterator th_it(min_vel[2], max_vel[2], vsamples[2]);
121  for(; !x_it.isFinished(); x_it++) {
122  vel_samp[0] = x_it.getVelocity();
123  for(; !y_it.isFinished(); y_it++) {
124  vel_samp[1] = y_it.getVelocity();
125  for(; !th_it.isFinished(); th_it++) {
126  vel_samp[2] = th_it.getVelocity();
127  //ROS_DEBUG("Sample %f, %f, %f", vel_samp[0], vel_samp[1], vel_samp[2]);
128  sample_params_.push_back(vel_samp);
129  }
130  th_it.reset();
131  }
132  y_it.reset();
133  }
134  }
135 }
136 
138  double sim_time,
139  double sim_granularity,
140  double angular_sim_granularity,
141  bool use_dwa,
142  double sim_period) {
143  sim_time_ = sim_time;
144  sim_granularity_ = sim_granularity;
145  angular_sim_granularity_ = angular_sim_granularity;
146  use_dwa_ = use_dwa;
148  sim_period_ = sim_period;
149 }
150 
155  return next_sample_index_ < sample_params_.size();
156 }
157 
161 bool SimpleTrajectoryGenerator::nextTrajectory(Trajectory &comp_traj) {
162  bool result = false;
163  if (hasMoreTrajectories()) {
164  if (generateTrajectory(
165  pos_,
166  vel_,
168  comp_traj)) {
169  result = true;
170  }
171  }
173  return result;
174 }
175 
181  Eigen::Vector3f pos,
182  Eigen::Vector3f vel,
183  Eigen::Vector3f sample_target_vel,
185  double vmag = hypot(sample_target_vel[0], sample_target_vel[1]);
186  double eps = 1e-4;
187  traj.cost_ = -1.0; // placed here in case we return early
188  //trajectory might be reused so we'll make sure to reset it
189  traj.resetPoints();
190 
191  // make sure that the robot would at least be moving with one of
192  // the required minimum velocities for translation and rotation (if set)
193  if ((limits_->min_vel_trans >= 0 && vmag + eps < limits_->min_vel_trans) &&
194  (limits_->min_vel_theta >= 0 && fabs(sample_target_vel[2]) + eps < limits_->min_vel_theta)) {
195  return false;
196  }
197  // make sure we do not exceed max diagonal (x+y) translational velocity (if set)
198  if (limits_->max_vel_trans >=0 && vmag - eps > limits_->max_vel_trans) {
199  return false;
200  }
201 
202  int num_steps;
203  if (discretize_by_time_) {
204  num_steps = ceil(sim_time_ / sim_granularity_);
205  } else {
206  //compute the number of steps we must take along this trajectory to be "safe"
207  double sim_time_distance = vmag * sim_time_; // the distance the robot would travel in sim_time if it did not change velocity
208  double sim_time_angle = fabs(sample_target_vel[2]) * sim_time_; // the angle the robot would rotate in sim_time
209  num_steps =
210  ceil(std::max(sim_time_distance / sim_granularity_,
211  sim_time_angle / angular_sim_granularity_));
212  }
213 
214  if (num_steps == 0) {
215  return false;
216  }
217 
218  //compute a timestep
219  double dt = sim_time_ / num_steps;
220  traj.time_delta_ = dt;
221 
222  Eigen::Vector3f loop_vel;
224  // assuming the velocity of the first cycle is the one we want to store in the trajectory object
225  loop_vel = computeNewVelocities(sample_target_vel, vel, limits_->getAccLimits(), dt);
226  traj.xv_ = loop_vel[0];
227  traj.yv_ = loop_vel[1];
228  traj.thetav_ = loop_vel[2];
229  } else {
230  // assuming sample_vel is our target velocity within acc limits for one timestep
231  loop_vel = sample_target_vel;
232  traj.xv_ = sample_target_vel[0];
233  traj.yv_ = sample_target_vel[1];
234  traj.thetav_ = sample_target_vel[2];
235  }
236 
237  //simulate the trajectory and check for collisions, updating costs along the way
238  for (int i = 0; i < num_steps; ++i) {
239 
240  //add the point to the trajectory so we can draw it later if we want
241  traj.addPoint(pos[0], pos[1], pos[2]);
242 
244  //calculate velocities
245  loop_vel = computeNewVelocities(sample_target_vel, loop_vel, limits_->getAccLimits(), dt);
246  //ROS_WARN_NAMED("Generator", "Flag: %d, Loop_Vel %f, %f, %f", continued_acceleration_, loop_vel[0], loop_vel[1], loop_vel[2]);
247  }
248 
249  //update the position of the robot using the velocities passed in
250  pos = computeNewPositions(pos, loop_vel, dt);
251 
252  } // end for simulation steps
253 
254  return true; // trajectory has at least one point
255 }
256 
257 Eigen::Vector3f SimpleTrajectoryGenerator::computeNewPositions(const Eigen::Vector3f& pos,
258  const Eigen::Vector3f& vel, double dt) {
259  Eigen::Vector3f new_pos = Eigen::Vector3f::Zero();
260  new_pos[0] = pos[0] + (vel[0] * cos(pos[2]) + vel[1] * cos(M_PI_2 + pos[2])) * dt;
261  new_pos[1] = pos[1] + (vel[0] * sin(pos[2]) + vel[1] * sin(M_PI_2 + pos[2])) * dt;
262  new_pos[2] = pos[2] + vel[2] * dt;
263  return new_pos;
264 }
265 
269 Eigen::Vector3f SimpleTrajectoryGenerator::computeNewVelocities(const Eigen::Vector3f& sample_target_vel,
270  const Eigen::Vector3f& vel, Eigen::Vector3f acclimits, double dt) {
271  Eigen::Vector3f new_vel = Eigen::Vector3f::Zero();
272  for (int i = 0; i < 3; ++i) {
273  if (vel[i] < sample_target_vel[i]) {
274  new_vel[i] = std::min(double(sample_target_vel[i]), vel[i] + acclimits[i] * dt);
275  } else {
276  new_vel[i] = std::max(double(sample_target_vel[i]), vel[i] - acclimits[i] * dt);
277  }
278  }
279  return new_vel;
280 }
281 
282 } /* namespace base_local_planner */
base_local_planner::SimpleTrajectoryGenerator::computeNewVelocities
static Eigen::Vector3f computeNewVelocities(const Eigen::Vector3f &sample_target_vel, const Eigen::Vector3f &vel, Eigen::Vector3f acclimits, double dt)
Definition: simple_trajectory_generator.cpp:304
base_local_planner::SimpleTrajectoryGenerator::pos_
Eigen::Vector3f pos_
Definition: simple_trajectory_generator.h:217
base_local_planner::Trajectory::resetPoints
void resetPoints()
Clear the trajectory's points.
Definition: trajectory.cpp:97
base_local_planner::Trajectory::xv_
double xv_
Definition: trajectory.h:92
base_local_planner::SimpleTrajectoryGenerator::next_sample_index_
unsigned int next_sample_index_
Definition: simple_trajectory_generator.h:213
simple_trajectory_generator.h
base_local_planner::SimpleTrajectoryGenerator::setParameters
void setParameters(double sim_time, double sim_granularity, double angular_sim_granularity, bool use_dwa=false, double sim_period=0.0)
Definition: simple_trajectory_generator.cpp:172
base_local_planner::LocalPlannerLimits::min_vel_x
double min_vel_x
Definition: local_planner_limits.h:114
base_local_planner::SimpleTrajectoryGenerator::generateTrajectory
bool generateTrajectory(Eigen::Vector3f pos, Eigen::Vector3f vel, Eigen::Vector3f sample_target_vel, base_local_planner::Trajectory &traj)
Definition: simple_trajectory_generator.cpp:215
velocity_iterator.h
base_local_planner::LocalPlannerLimits
Definition: local_planner_limits.h:75
base_local_planner::LocalPlannerLimits::min_vel_y
double min_vel_y
Definition: local_planner_limits.h:116
base_local_planner::LocalPlannerLimits::max_vel_theta
double max_vel_theta
Definition: local_planner_limits.h:117
base_local_planner::Trajectory::time_delta_
double time_delta_
The time gap between points.
Definition: trajectory.h:96
base_local_planner::Trajectory::addPoint
void addPoint(double x, double y, double th)
Add a point to the end of a trajectory.
Definition: trajectory.cpp:91
base_local_planner::LocalPlannerLimits::max_vel_x
double max_vel_x
Definition: local_planner_limits.h:113
base_local_planner::Trajectory::cost_
double cost_
The cost/score of the trajectory.
Definition: trajectory.h:94
base_local_planner::SimpleTrajectoryGenerator::sim_period_
double sim_period_
Definition: simple_trajectory_generator.h:226
base_local_planner::LocalPlannerLimits::max_vel_trans
double max_vel_trans
Definition: local_planner_limits.h:111
base_local_planner::Trajectory::yv_
double yv_
Definition: trajectory.h:92
base_local_planner::SimpleTrajectoryGenerator::computeNewPositions
static Eigen::Vector3f computeNewPositions(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, double dt)
Definition: simple_trajectory_generator.cpp:292
base_local_planner::SimpleTrajectoryGenerator::use_dwa_
bool use_dwa_
Definition: simple_trajectory_generator.h:225
base_local_planner::LocalPlannerLimits::getAccLimits
Eigen::Vector3f getAccLimits()
Get the acceleration limits of the robot.
Definition: local_planner_limits.h:174
base_local_planner::LocalPlannerLimits::min_vel_theta
double min_vel_theta
Definition: local_planner_limits.h:118
base_local_planner::SimpleTrajectoryGenerator::hasMoreTrajectories
bool hasMoreTrajectories()
Definition: simple_trajectory_generator.cpp:189
base_local_planner::SimpleTrajectoryGenerator::nextTrajectory
bool nextTrajectory(Trajectory &traj)
Definition: simple_trajectory_generator.cpp:196
base_local_planner::SimpleTrajectoryGenerator::initialise
void initialise(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, const Eigen::Vector3f &goal, base_local_planner::LocalPlannerLimits *limits, const Eigen::Vector3f &vsamples, std::vector< Eigen::Vector3f > additional_samples, bool discretize_by_time=false)
Definition: simple_trajectory_generator.cpp:81
base_local_planner::SimpleTrajectoryGenerator::vel_
Eigen::Vector3f vel_
Definition: simple_trajectory_generator.h:218
base_local_planner::SimpleTrajectoryGenerator::continued_acceleration_
bool continued_acceleration_
Definition: simple_trajectory_generator.h:221
base_local_planner::SimpleTrajectoryGenerator::discretize_by_time_
bool discretize_by_time_
Definition: simple_trajectory_generator.h:222
base_local_planner::SimpleTrajectoryGenerator::angular_sim_granularity_
double angular_sim_granularity_
Definition: simple_trajectory_generator.h:224
base_local_planner::SimpleTrajectoryGenerator::sample_params_
std::vector< Eigen::Vector3f > sample_params_
Definition: simple_trajectory_generator.h:215
base_local_planner::SimpleTrajectoryGenerator::sim_time_
double sim_time_
Definition: simple_trajectory_generator.h:224
base_local_planner::Trajectory
Holds a trajectory generated by considering an x, y, and theta velocity.
Definition: trajectory.h:76
base_local_planner::SimpleTrajectoryGenerator::sim_granularity_
double sim_granularity_
Definition: simple_trajectory_generator.h:224
base_local_planner::LocalPlannerLimits::min_vel_trans
double min_vel_trans
Definition: local_planner_limits.h:112
base_local_planner::SimpleTrajectoryGenerator::limits_
base_local_planner::LocalPlannerLimits * limits_
Definition: simple_trajectory_generator.h:216
base_local_planner
Definition: costmap_model.h:44
base_local_planner::LocalPlannerLimits::max_vel_y
double max_vel_y
Definition: local_planner_limits.h:115
base_local_planner::Trajectory::thetav_
double thetav_
The x, y, and theta velocities of the trajectory.
Definition: trajectory.h:92


base_local_planner
Author(s): Eitan Marder-Eppstein, Eric Perko, contradict@gmail.com
autogenerated on Mon Mar 6 2023 03:50:24