trajectory.h
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2014-2015, Fetch Robotics Inc.
00005  *  Copyright (c) 2013, Unbounded Robotics Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of Unbounded Robotics nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 // Author: Michael Ferguson
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   // Find mapping of joint names into message joint names
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   // Make sure trajectory is empty
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   // Fill in Trajectory
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   // Parsed this
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   // Need at least one point in t1 for the following code to work
00138   if (t1.size() == 0)
00139   {
00140     return false;
00141   }
00142 
00143   // Need at least one point in t2 for the following code to work
00144   if (t2.size() == 0)
00145   {
00146     *t = t1;
00147     return true;
00148   }
00149 
00150   // Check sizes
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   // Just to be sure
00158   t->points.clear();
00159 
00160   // When does t2 start?
00161   double start_t2 = t2.points[0].time;
00162 
00163   // Find points in t1 after time, but before start_t2
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         /* This is first point in trajectory, and is after our
00171            start time, see if we can add one point in front of it */
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   // Add points from t2
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         /* This is first point in trajectory, and is after our
00187            start time, see if we can add one point in front of it */
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     // Remove any accelerations in output trajectory
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     // Remove any velocities in output trajectory
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       // Size does not match
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           // Unwind by taking shortest path from previous point
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           // Start between -PI and PI
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   // You no copy...
00325   TrajectorySampler(const TrajectorySampler&);
00326   TrajectorySampler& operator=(const TrajectorySampler&);
00327 };
00328 
00329 }  // namespace robot_controllers
00330 
00331 #endif // ROBOT_CONTROLLERS_TRAJECTORY_H_


robot_controllers
Author(s): Michael Ferguson
autogenerated on Wed Jun 14 2017 04:09:10