moveit2
The MoveIt Motion Planning Framework for ROS 2.
time_optimal_trajectory_generation.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2012, Georgia Tech Research Corporation
3  * All rights reserved.
4  *
5  * Author: Tobias Kunz <tobias@gatech.edu>
6  * Date: 05/2012
7  *
8  * Humanoid Robotics Lab Georgia Institute of Technology
9  * Director: Mike Stilman http://www.golems.org
10  *
11  * Algorithm details and publications:
12  * http://www.golems.org/node/1570
13  *
14  * This file is provided under the following "BSD-style" License:
15  * Redistribution and use in source and binary forms, with or
16  * without modification, are permitted provided that the following
17  * conditions are met:
18  * * Redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer.
20  * * Redistributions in binary form must reproduce the above
21  * copyright notice, this list of conditions and the following
22  * disclaimer in the documentation and/or other materials provided
23  * with the distribution.
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #pragma once
40 
41 #include <Eigen/Core>
42 #include <list>
45 
46 namespace trajectory_processing
47 {
48 
49 // The intermediate waypoints of the input path need to be blended so that the entire path is diffentiable.
50 // This constant defines the maximum deviation allowed at those intermediate waypoints, in radians for revolute joints,
51 // or meters for prismatic joints.
52 constexpr double DEFAULT_PATH_TOLERANCE = 0.1;
53 
55 {
58 };
59 
60 const std::unordered_map<LimitType, std::string> LIMIT_TYPES = { { VELOCITY, "velocity" },
61  { ACCELERATION, "acceleration" } };
63 {
64 public:
65  PathSegment(double length = 0.0) : length_(length)
66  {
67  }
68  virtual ~PathSegment() // is required for destructing derived classes
69  {
70  }
71  double getLength() const
72  {
73  return length_;
74  }
75  virtual Eigen::VectorXd getConfig(double s) const = 0;
76  virtual Eigen::VectorXd getTangent(double s) const = 0;
77  virtual Eigen::VectorXd getCurvature(double s) const = 0;
78  virtual std::list<double> getSwitchingPoints() const = 0;
79  virtual PathSegment* clone() const = 0;
80 
81  double position_;
82 
83 protected:
84  double length_;
85 };
86 
87 class Path
88 {
89 public:
90  // Create a Path from a vector of waypoints and a maximum deviation to tolerate at the intermediate waypoints.
91  // The algorithm needs max_deviation to be greater than zero so that the path is differentiable.
92  static std::optional<Path> create(const std::vector<Eigen::VectorXd>& waypoint,
93  double max_deviation = DEFAULT_PATH_TOLERANCE);
94 
95  // Copy constructor.
96  Path(const Path& path);
97 
98  double getLength() const;
99  Eigen::VectorXd getConfig(double s) const;
100  Eigen::VectorXd getTangent(double s) const;
101  Eigen::VectorXd getCurvature(double s) const;
102 
108  double getNextSwitchingPoint(double s, bool& discontinuity) const;
109 
111  std::list<std::pair<double, bool>> getSwitchingPoints() const;
112 
113 private:
114  // Default constructor private to prevent misuse. Use `create` instead to create a Path object.
115  Path() = default;
116 
117  PathSegment* getPathSegment(double& s) const;
118 
119  double length_ = 0.0;
120  std::list<std::pair<double, bool>> switching_points_;
121  std::list<std::unique_ptr<PathSegment>> path_segments_;
122 };
123 
125 {
126 public:
129  static std::optional<Trajectory> create(const Path& path, const Eigen::VectorXd& max_velocity,
130  const Eigen::VectorXd& max_acceleration, double time_step = 0.001);
131 
133  double getDuration() const;
134 
137  Eigen::VectorXd getPosition(double time) const;
139  Eigen::VectorXd getVelocity(double time) const;
141  Eigen::VectorXd getAcceleration(double time) const;
142 
143 private:
144  Trajectory(const Path& path, const Eigen::VectorXd& max_velocity, const Eigen::VectorXd& max_acceleration,
145  double time_step);
146 
147  struct TrajectoryStep
148  {
149  TrajectoryStep()
150  {
151  }
152  TrajectoryStep(double path_pos, double path_vel) : path_pos_(path_pos), path_vel_(path_vel)
153  {
154  }
155  double path_pos_;
156  double path_vel_;
157  double time_;
158  };
159 
160  bool getNextSwitchingPoint(double path_pos, TrajectoryStep& next_switching_point, double& before_acceleration,
161  double& after_acceleration);
162  bool getNextAccelerationSwitchingPoint(double path_pos, TrajectoryStep& next_switching_point,
163  double& before_acceleration, double& after_acceleration);
164  bool getNextVelocitySwitchingPoint(double path_pos, TrajectoryStep& next_switching_point, double& before_acceleration,
165  double& after_acceleration);
166  bool integrateForward(std::list<TrajectoryStep>& trajectory, double acceleration);
167  void integrateBackward(std::list<TrajectoryStep>& start_trajectory, double path_pos, double path_vel,
168  double acceleration);
169  double getMinMaxPathAcceleration(double path_position, double path_velocity, bool max);
170  double getMinMaxPhaseSlope(double path_position, double path_velocity, bool max);
171  double getAccelerationMaxPathVelocity(double path_pos) const;
172  double getVelocityMaxPathVelocity(double path_pos) const;
173  double getAccelerationMaxPathVelocityDeriv(double path_pos);
174  double getVelocityMaxPathVelocityDeriv(double path_pos);
175 
176  std::list<TrajectoryStep>::const_iterator getTrajectorySegment(double time) const;
177 
178  Path path_;
179  Eigen::VectorXd max_velocity_;
180  Eigen::VectorXd max_acceleration_;
181  unsigned int joint_num_ = 0.0;
182  bool valid_ = true;
183  std::list<TrajectoryStep> trajectory_;
184  std::list<TrajectoryStep> end_trajectory_; // non-empty only if the trajectory generation failed.
185 
186  double time_step_ = 0.0;
187 
188  mutable double cached_time_ = std::numeric_limits<double>::max();
189  mutable std::list<TrajectoryStep>::const_iterator cached_trajectory_segment_;
190 };
191 
194 {
195 public:
196  TimeOptimalTrajectoryGeneration(const double path_tolerance = DEFAULT_PATH_TOLERANCE, const double resample_dt = 0.1,
197  const double min_angle_change = 0.001);
198 
199  // clang-format off
212  // clang-format on
213  bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor = 1.0,
214  const double max_acceleration_scaling_factor = 1.0) const override;
215 
216  // clang-format off
231  // clang-format on
233  const std::unordered_map<std::string, double>& velocity_limits,
234  const std::unordered_map<std::string, double>& acceleration_limits,
235  const double max_velocity_scaling_factor = 1.0,
236  const double max_acceleration_scaling_factor = 1.0) const override;
237 
238  // clang-format off
252  // clang-format on
254  const std::vector<moveit_msgs::msg::JointLimits>& joint_limits,
255  const double max_velocity_scaling_factor = 1.0,
256  const double max_acceleration_scaling_factor = 1.0) const override;
257 
258 private:
259  bool doTimeParameterizationCalculations(robot_trajectory::RobotTrajectory& trajectory,
260  const Eigen::VectorXd& max_velocity,
261  const Eigen::VectorXd& max_acceleration) const;
262 
268  bool hasMixedJointTypes(const moveit::core::JointModelGroup* group) const;
269 
276  double verifyScalingFactor(const double requested_scaling_factor, const LimitType limit_type) const;
277 
278  const double path_tolerance_;
279  const double resample_dt_;
280  const double min_angle_change_;
281 };
282 
283 // clang-format off
298 // clang-format on
299 bool totgComputeTimeStamps(const size_t num_waypoints, robot_trajectory::RobotTrajectory& trajectory,
300  const double max_velocity_scaling_factor = 1.0,
301  const double max_acceleration_scaling_factor = 1.0);
302 } // namespace trajectory_processing
Maintain a sequence of waypoints and the time durations between these waypoints.
virtual Eigen::VectorXd getConfig(double s) const =0
virtual std::list< double > getSwitchingPoints() const =0
virtual PathSegment * clone() const =0
virtual Eigen::VectorXd getCurvature(double s) const =0
virtual Eigen::VectorXd getTangent(double s) const =0
Eigen::VectorXd getTangent(double s) const
std::list< std::pair< double, bool > > getSwitchingPoints() const
Return a list of all switching points as a pair (arc length to switching point, discontinuity)
static std::optional< Path > create(const std::vector< Eigen::VectorXd > &waypoint, double max_deviation=DEFAULT_PATH_TOLERANCE)
Eigen::VectorXd getCurvature(double s) const
double getNextSwitchingPoint(double s, bool &discontinuity) const
Get the next switching point.
bool computeTimeStamps(robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0) const override
Compute a trajectory with waypoints spaced equally in time (according to resample_dt_)....
TimeOptimalTrajectoryGeneration(const double path_tolerance=DEFAULT_PATH_TOLERANCE, const double resample_dt=0.1, const double min_angle_change=0.001)
Eigen::VectorXd getAcceleration(double time) const
Return the acceleration vector for a given point in time.
Eigen::VectorXd getPosition(double time) const
Return the position/configuration vector for a given point in time.
double getDuration() const
Returns the optimal duration of the trajectory.
Eigen::VectorXd getVelocity(double time) const
Return the velocity vector for a given point in time.
static std::optional< Trajectory > create(const Path &path, const Eigen::VectorXd &max_velocity, const Eigen::VectorXd &max_acceleration, double time_step=0.001)
Generates a time-optimal trajectory.
const std::unordered_map< LimitType, std::string > LIMIT_TYPES
MOVEIT_CLASS_FORWARD(TimeOptimalTrajectoryGeneration)
bool totgComputeTimeStamps(const size_t num_waypoints, robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0)
Compute a trajectory with the desired number of waypoints. Resampling the trajectory doesn't change t...