Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef ROBOT_CONTROLLERS_TRAJECTORY_H_
00039 #define ROBOT_CONTROLLERS_TRAJECTORY_H_
00040
00041 #include <ros/ros.h>
00042 #include <angles/angles.h>
00043 #include <trajectory_msgs/JointTrajectory.h>
00044
00045 namespace robot_controllers
00046 {
00047
00051 struct TrajectoryPoint
00052 {
00053 std::vector<double> q;
00054 std::vector<double> qd;
00055 std::vector<double> qdd;
00056 double time;
00057 };
00058
00059 struct Trajectory
00060 {
00061 std::vector<TrajectoryPoint> points;
00062
00063 size_t size() const
00064 {
00065 return points.size();
00066 }
00067 };
00068
00076 inline bool trajectoryFromMsg(const trajectory_msgs::JointTrajectory& message,
00077 const std::vector<std::string> joints,
00078 Trajectory* trajectory)
00079 {
00080
00081 std::vector<int> mapping(joints.size(), -1);
00082 for (size_t j = 0; j < joints.size(); ++j)
00083 {
00084 for (size_t i = 0; i < message.joint_names.size(); ++i)
00085 {
00086 if (joints[j] == message.joint_names[i])
00087 {
00088 mapping[j] = i;
00089 break;
00090 }
00091 }
00092 if (mapping[j] == -1)
00093 {
00094 return false;
00095 }
00096 }
00097
00098
00099 trajectory->points.clear();
00100
00101 double start_time = message.header.stamp.toSec();
00102 if (start_time == 0.0)
00103 start_time = ros::Time::now().toSec();
00104
00105
00106 for (size_t p = 0; p < message.points.size(); ++p)
00107 {
00108 TrajectoryPoint point;
00109 for (size_t j = 0; j < joints.size(); ++j)
00110 {
00111 point.q.push_back(message.points[p].positions[mapping[j]]);
00112 if (message.points[p].velocities.size() == message.points[p].positions.size())
00113 point.qd.push_back(message.points[p].velocities[mapping[j]]);
00114 if (message.points[p].accelerations.size() == message.points[p].positions.size())
00115 point.qdd.push_back(message.points[p].accelerations[mapping[j]]);
00116 }
00117 point.time = start_time + message.points[p].time_from_start.toSec();
00118 trajectory->points.push_back(point);
00119 }
00120
00121
00122 return true;
00123 }
00124
00132 inline bool spliceTrajectories(const Trajectory& t1,
00133 const Trajectory& t2,
00134 const double time,
00135 Trajectory * t)
00136 {
00137
00138 if (t1.size() == 0)
00139 {
00140 return false;
00141 }
00142
00143
00144 if (t2.size() == 0)
00145 {
00146 *t = t1;
00147 return true;
00148 }
00149
00150
00151 size_t num_joints = t1.points[0].q.size();
00152 bool has_velocities = (t1.points[0].qd.size() == num_joints) &&
00153 (t2.points[0].qd.size() == num_joints);
00154 bool has_accelerations = (t1.points[0].qdd.size() == num_joints) &&
00155 (t2.points[0].qdd.size() == num_joints);
00156
00157
00158 t->points.clear();
00159
00160
00161 double start_t2 = t2.points[0].time;
00162
00163
00164 for (size_t p = 0; p < t1.size(); ++p)
00165 {
00166 if (t1.points[p].time >= time && t1.points[p].time < start_t2)
00167 {
00168 if (t1.points[p].time > time && t->size() == 0)
00169 {
00170
00171
00172 if (p > 0)
00173 t->points.push_back(t1.points[p-1]);
00174 }
00175 t->points.push_back(t1.points[p]);
00176 }
00177 }
00178
00179
00180 for (size_t p = 0; p < t2.size(); ++p)
00181 {
00182 if (t2.points[p].time >= time)
00183 {
00184 if (t2.points[p].time > time && t->size() == 0)
00185 {
00186
00187
00188 if (p > 0)
00189 t->points.push_back(t2.points[p-1]);
00190 else if (t1.size() > 0)
00191 t->points.push_back(t1.points[t1.size()-1]);
00192 }
00193 t->points.push_back(t2.points[p]);
00194 }
00195 }
00196
00197 if (!has_accelerations)
00198 {
00199
00200 for (size_t i = 0; i < t->points.size(); i++)
00201 {
00202 t->points[i].qdd.clear();
00203 }
00204 }
00205
00206 if (!has_velocities)
00207 {
00208
00209 for (size_t i = 0; i < t->points.size(); i++)
00210 {
00211 t->points[i].qd.clear();
00212 }
00213 }
00214
00215 return true;
00216 }
00217
00221 inline void rosPrintTrajectory(Trajectory& t)
00222 {
00223 ROS_INFO_STREAM("Trajectory with " << t.size() << " points:");
00224 for (size_t p = 0; p < t.size(); ++p)
00225 {
00226 ROS_INFO_STREAM(" Point " << p << " at " << std::setprecision (15) << t.points[p].time);
00227 for (size_t j = 0; j < t.points[p].q.size(); ++j)
00228 {
00229 if (t.points[p].qdd.size() == t.points[p].q.size())
00230 {
00231 ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j] <<
00232 ", " << std::setprecision (5) << t.points[p].qd[j] <<
00233 ", " << std::setprecision (5) << t.points[p].qdd[j]);
00234 }
00235 else if(t.points[p].q.size() == t.points[p].q.size())
00236 {
00237 ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j] <<
00238 ", " << std::setprecision (5) << t.points[p].qd[j]);
00239 }
00240 else
00241 {
00242 ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j]);
00243 }
00244 }
00245 }
00246 }
00247
00253 inline bool windupTrajectory(std::vector<bool> continuous,
00254 Trajectory& trajectory)
00255 {
00256 for (size_t p = 0; p < trajectory.size(); p++)
00257 {
00258 if (continuous.size() != trajectory.points[p].q.size())
00259 {
00260
00261 return false;
00262 }
00263
00264 for (size_t j = 0; j < continuous.size(); j++)
00265 {
00266 if (continuous[j])
00267 {
00268 if (p > 0)
00269 {
00270
00271 double shortest = angles::shortest_angular_distance(trajectory.points[p-1].q[j], trajectory.points[p].q[j]);
00272 trajectory.points[p].q[j] = trajectory.points[p-1].q[j] + shortest;
00273 }
00274 else
00275 {
00276
00277 trajectory.points[p].q[j] = angles::normalize_angle(trajectory.points[p].q[j]);
00278 }
00279 }
00280 }
00281 }
00282 return true;
00283 }
00284
00285 inline bool unwindTrajectoryPoint(std::vector<bool> continuous,
00286 TrajectoryPoint& p)
00287 {
00288 if (continuous.size() != p.q.size())
00289 {
00290 return false;
00291 }
00292
00293 for (size_t j = 0; j < continuous.size(); j++)
00294 {
00295 if (continuous[j])
00296 {
00297 p.q[j] = angles::normalize_angle(p.q[j]);
00298 }
00299 }
00300
00301 return true;
00302 }
00303
00307 class TrajectorySampler
00308 {
00309 public:
00311 TrajectorySampler() {}
00312 virtual ~TrajectorySampler() {}
00313
00315 virtual TrajectoryPoint sample(double time) = 0;
00316
00318 virtual double end_time() = 0;
00319
00321 virtual Trajectory getTrajectory() = 0;
00322
00323 private:
00324
00325 TrajectorySampler(const TrajectorySampler&);
00326 TrajectorySampler& operator=(const TrajectorySampler&);
00327 };
00328
00329 }
00330
00331 #endif // ROBOT_CONTROLLERS_TRAJECTORY_H_