trajectory.h
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2014-2015, Fetch Robotics Inc.
5  * Copyright (c) 2013, Unbounded Robotics 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 Unbounded Robotics 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 
36 // Author: Michael Ferguson
37 
38 #ifndef ROBOT_CONTROLLERS_TRAJECTORY_H_
39 #define ROBOT_CONTROLLERS_TRAJECTORY_H_
40 
41 #include <ros/ros.h>
42 #include <angles/angles.h>
43 #include <trajectory_msgs/JointTrajectory.h>
44 
45 namespace robot_controllers
46 {
47 
52 {
53  std::vector<double> q;
54  std::vector<double> qd;
55  std::vector<double> qdd;
56  double time;
57 };
58 
59 struct Trajectory
60 {
61  std::vector<TrajectoryPoint> points;
62 
63  size_t size() const
64  {
65  return points.size();
66  }
67 };
68 
76 inline bool trajectoryFromMsg(const trajectory_msgs::JointTrajectory& message,
77  const std::vector<std::string> joints,
78  Trajectory* trajectory)
79 {
80  // Find mapping of joint names into message joint names
81  std::vector<int> mapping(joints.size(), -1);
82  for (size_t j = 0; j < joints.size(); ++j)
83  {
84  for (size_t i = 0; i < message.joint_names.size(); ++i)
85  {
86  if (joints[j] == message.joint_names[i])
87  {
88  mapping[j] = i;
89  break;
90  }
91  }
92  if (mapping[j] == -1)
93  {
94  return false;
95  }
96  }
97 
98  // Make sure trajectory is empty
99  trajectory->points.clear();
100 
101  double start_time = message.header.stamp.toSec();
102  if (start_time == 0.0)
103  start_time = ros::Time::now().toSec();
104 
105  // Fill in Trajectory
106  for (size_t p = 0; p < message.points.size(); ++p)
107  {
108  TrajectoryPoint point;
109  for (size_t j = 0; j < joints.size(); ++j)
110  {
111  point.q.push_back(message.points[p].positions[mapping[j]]);
112  if (message.points[p].velocities.size() == message.points[p].positions.size())
113  point.qd.push_back(message.points[p].velocities[mapping[j]]);
114  if (message.points[p].accelerations.size() == message.points[p].positions.size())
115  point.qdd.push_back(message.points[p].accelerations[mapping[j]]);
116  }
117  point.time = start_time + message.points[p].time_from_start.toSec();
118  trajectory->points.push_back(point);
119  }
120 
121  // Parsed this
122  return true;
123 }
124 
132 inline bool spliceTrajectories(const Trajectory& t1,
133  const Trajectory& t2,
134  const double time,
135  Trajectory * t)
136 {
137  // Need at least one point in t1 for the following code to work
138  if (t1.size() == 0)
139  {
140  return false;
141  }
142 
143  // Need at least one point in t2 for the following code to work
144  if (t2.size() == 0)
145  {
146  *t = t1;
147  return true;
148  }
149 
150  // Check sizes
151  size_t num_joints = t1.points[0].q.size();
152  bool has_velocities = (t1.points[0].qd.size() == num_joints) &&
153  (t2.points[0].qd.size() == num_joints);
154  bool has_accelerations = (t1.points[0].qdd.size() == num_joints) &&
155  (t2.points[0].qdd.size() == num_joints);
156 
157  // Just to be sure
158  t->points.clear();
159 
160  // When does t2 start?
161  double start_t2 = t2.points[0].time;
162 
163  // Find points in t1 after time, but before start_t2
164  for (size_t p = 0; p < t1.size(); ++p)
165  {
166  if (t1.points[p].time >= time && t1.points[p].time < start_t2)
167  {
168  if (t1.points[p].time > time && t->size() == 0)
169  {
170  /* This is first point in trajectory, and is after our
171  start time, see if we can add one point in front of it */
172  if (p > 0)
173  t->points.push_back(t1.points[p-1]);
174  }
175  t->points.push_back(t1.points[p]);
176  }
177  }
178 
179  // Add points from t2
180  for (size_t p = 0; p < t2.size(); ++p)
181  {
182  if (t2.points[p].time >= time)
183  {
184  if (t2.points[p].time > time && t->size() == 0)
185  {
186  /* This is first point in trajectory, and is after our
187  start time, see if we can add one point in front of it */
188  if (p > 0)
189  t->points.push_back(t2.points[p-1]);
190  else if (t1.size() > 0)
191  t->points.push_back(t1.points[t1.size()-1]);
192  }
193  t->points.push_back(t2.points[p]);
194  }
195  }
196 
197  if (!has_accelerations)
198  {
199  // Remove any accelerations in output trajectory
200  for (size_t i = 0; i < t->points.size(); i++)
201  {
202  t->points[i].qdd.clear();
203  }
204  }
205 
206  if (!has_velocities)
207  {
208  // Remove any velocities in output trajectory
209  for (size_t i = 0; i < t->points.size(); i++)
210  {
211  t->points[i].qd.clear();
212  }
213  }
214 
215  return true;
216 }
217 
222 {
223  ROS_INFO_STREAM("Trajectory with " << t.size() << " points:");
224  for (size_t p = 0; p < t.size(); ++p)
225  {
226  ROS_INFO_STREAM(" Point " << p << " at " << std::setprecision (15) << t.points[p].time);
227  for (size_t j = 0; j < t.points[p].q.size(); ++j)
228  {
229  if (t.points[p].qdd.size() == t.points[p].q.size())
230  {
231  ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j] <<
232  ", " << std::setprecision (5) << t.points[p].qd[j] <<
233  ", " << std::setprecision (5) << t.points[p].qdd[j]);
234  }
235  else if(t.points[p].q.size() == t.points[p].q.size())
236  {
237  ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j] <<
238  ", " << std::setprecision (5) << t.points[p].qd[j]);
239  }
240  else
241  {
242  ROS_INFO_STREAM(" " << std::setprecision (5) << t.points[p].q[j]);
243  }
244  }
245  }
246 }
247 
253 inline bool windupTrajectory(std::vector<bool> continuous,
254  Trajectory& trajectory)
255 {
256  for (size_t p = 0; p < trajectory.size(); p++)
257  {
258  if (continuous.size() != trajectory.points[p].q.size())
259  {
260  // Size does not match
261  return false;
262  }
263 
264  for (size_t j = 0; j < continuous.size(); j++)
265  {
266  if (continuous[j])
267  {
268  if (p > 0)
269  {
270  // Unwind by taking shortest path from previous point
271  double shortest = angles::shortest_angular_distance(trajectory.points[p-1].q[j], trajectory.points[p].q[j]);
272  trajectory.points[p].q[j] = trajectory.points[p-1].q[j] + shortest;
273  }
274  else
275  {
276  // Start between -PI and PI
277  trajectory.points[p].q[j] = angles::normalize_angle(trajectory.points[p].q[j]);
278  }
279  }
280  }
281  }
282  return true;
283 }
284 
285 inline bool unwindTrajectoryPoint(std::vector<bool> continuous,
286  TrajectoryPoint& p)
287 {
288  if (continuous.size() != p.q.size())
289  {
290  return false;
291  }
292 
293  for (size_t j = 0; j < continuous.size(); j++)
294  {
295  if (continuous[j])
296  {
297  p.q[j] = angles::normalize_angle(p.q[j]);
298  }
299  }
300 
301  return true;
302 }
303 
308 {
309 public:
312  virtual ~TrajectorySampler() {}
313 
315  virtual TrajectoryPoint sample(double time) = 0;
316 
318  virtual double end_time() = 0;
319 
321  virtual Trajectory getTrajectory() = 0;
322 
323 private:
324  // You no copy...
326  TrajectorySampler& operator=(const TrajectorySampler&);
327 };
328 
329 } // namespace robot_controllers
330 
331 #endif // ROBOT_CONTROLLERS_TRAJECTORY_H_
Basis for a Trajectory Point.
Definition: trajectory.h:51
bool trajectoryFromMsg(const trajectory_msgs::JointTrajectory &message, const std::vector< std::string > joints, Trajectory *trajectory)
Convert message into Trajectory.
Definition: trajectory.h:76
std::vector< double > qdd
Definition: trajectory.h:55
std::vector< TrajectoryPoint > points
Definition: trajectory.h:61
bool windupTrajectory(std::vector< bool > continuous, Trajectory &trajectory)
Windup the trajectory so that continuous joints do not wrap.
Definition: trajectory.h:253
std::vector< double > qd
Definition: trajectory.h:54
def normalize_angle(angle)
void rosPrintTrajectory(Trajectory &t)
Print trajectory to ROS INFO.
Definition: trajectory.h:221
std::vector< double > q
Definition: trajectory.h:53
#define ROS_INFO_STREAM(args)
TrajectorySampler()
Construct a trajectory sampler.
Definition: trajectory.h:311
static Time now()
bool unwindTrajectoryPoint(std::vector< bool > continuous, TrajectoryPoint &p)
Definition: trajectory.h:285
bool spliceTrajectories(const Trajectory &t1, const Trajectory &t2, const double time, Trajectory *t)
Splice two trajectories.
Definition: trajectory.h:132
def shortest_angular_distance(from_angle, to_angle)
Base class for samplers of trajectories.
Definition: trajectory.h:307


robot_controllers
Author(s): Michael Ferguson
autogenerated on Sun Sep 27 2020 03:22:39