joint_trajectory_segment.h
Go to the documentation of this file.
00001 
00002 // Copyright (C) 2013, PAL Robotics S.L.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are met:
00006 //   * Redistributions of source code must retain the above copyright notice,
00007 //     this list of conditions and the following disclaimer.
00008 //   * Redistributions in binary form must reproduce the above copyright
00009 //     notice, this list of conditions and the following disclaimer in the
00010 //     documentation and/or other materials provided with the distribution.
00011 //   * Neither the name of PAL Robotics S.L. nor the names of its
00012 //     contributors may be used to endorse or promote products derived from
00013 //     this software without specific prior written permission.
00014 //
00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00019 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025 // POSSIBILITY OF SUCH DAMAGE.
00027 
00029 
00030 #ifndef JOINT_TRAJECTORY_CONTROLLER_JOINT_TRAJECTORY_SEGMENT_H
00031 #define JOINT_TRAJECTORY_CONTROLLER_JOINT_TRAJECTORY_SEGMENT_H
00032 
00033 // C++ standard
00034 #include <cmath>
00035 #include <stdexcept>
00036 #include <string>
00037 #include <vector>
00038 
00039 // angles
00040 #include <angles/angles.h>
00041 
00042 // ROS messages
00043 #include <control_msgs/FollowJointTrajectoryAction.h>
00044 #include <trajectory_msgs/JointTrajectoryPoint.h>
00045 
00046 // ros_controls
00047 #include <realtime_tools/realtime_server_goal_handle.h>
00048 
00049 // Project
00050 #include <joint_trajectory_controller/joint_trajectory_msg_utils.h>
00051 #include <joint_trajectory_controller/tolerances.h>
00052 
00053 namespace joint_trajectory_controller
00054 {
00055 
00069 template <class Segment>
00070 class JointTrajectorySegment : public Segment
00071 {
00072 public:
00073   typedef typename Segment::Scalar Scalar;
00074   typedef typename Segment::Time   Time;
00075 
00076   typedef realtime_tools::RealtimeServerGoalHandle<control_msgs::FollowJointTrajectoryAction> RealtimeGoalHandle;
00077   typedef boost::shared_ptr<RealtimeGoalHandle>                                               RealtimeGoalHandlePtr;
00078 
00079   struct State : public Segment::State
00080   {
00081     typedef typename Segment::State::Scalar Scalar;
00082     State() : Segment::State() {}
00083     State(unsigned int size) : Segment::State(size) {}
00084 
00104     State(const trajectory_msgs::JointTrajectoryPoint& point,
00105           const std::vector<unsigned int>&             permutation     = std::vector<unsigned int>(),
00106           const std::vector<Scalar>&                   position_offset = std::vector<Scalar>())
00107     {
00108       init(point, permutation, position_offset);
00109     }
00110 
00111     void init(const trajectory_msgs::JointTrajectoryPoint& point,
00112               const std::vector<unsigned int>&             permutation     = std::vector<unsigned int>(),
00113               const std::vector<Scalar>&                   position_offset = std::vector<Scalar>())
00114     {
00115       using std::invalid_argument;
00116 
00117       const unsigned int joint_dim = point.positions.size();
00118 
00119       // Preconditions
00120       if (!isValid(point, joint_dim))
00121       {
00122         throw(invalid_argument("Size mismatch in trajectory point position, velocity or acceleration data."));
00123       }
00124       if (!permutation.empty() && joint_dim != permutation.size())
00125       {
00126         throw(invalid_argument("Size mismatch between trajectory point and permutation vector."));
00127       }
00128       for (unsigned int i = 0; i < permutation.size(); ++i)
00129       {
00130         if (permutation[i] >= joint_dim)
00131         {
00132           throw(invalid_argument("Permutation vector contains out-of-range indices."));
00133         }
00134       }
00135       if (!position_offset.empty() && joint_dim != position_offset.size())
00136       {
00137         throw(invalid_argument("Size mismatch between trajectory point "
00138                                "and vector specifying whether joints wrap around."));
00139       }
00140 
00141       // Initialize state
00142       if (!point.positions.empty())     {this->position.resize(joint_dim);}
00143       if (!point.velocities.empty())    {this->velocity.resize(joint_dim);}
00144       if (!point.accelerations.empty()) {this->acceleration.resize(joint_dim);}
00145 
00146       for (unsigned int i = 0; i < joint_dim; ++i)
00147       {
00148         // Apply permutation only if it was specified, otherwise preserve original message order
00149         const unsigned int id = permutation.empty() ? i : permutation[i];
00150 
00151         // Apply position offset only if it was specified
00152         const Scalar offset = position_offset.empty() ? 0.0 : position_offset[i];
00153 
00154         if (!point.positions.empty())     {this->position[i]     = point.positions[id] + offset;}
00155         if (!point.velocities.empty())    {this->velocity[i]     = point.velocities[id];}
00156         if (!point.accelerations.empty()) {this->acceleration[i] = point.accelerations[id];}
00157       }
00158     }
00159   };
00160 
00169   JointTrajectorySegment(const Time&  start_time,
00170                          const State& start_state,
00171                          const Time&  end_time,
00172                          const State& end_state)
00173     : rt_goal_handle_(),
00174       tolerances_(start_state.position.size())
00175   {
00176     Segment::init(start_time, start_state, end_time, end_state);
00177   }
00178 
00191   JointTrajectorySegment(const ros::Time&                             traj_start_time,
00192                          const trajectory_msgs::JointTrajectoryPoint& start_point,
00193                          const trajectory_msgs::JointTrajectoryPoint& end_point,
00194                          const std::vector<unsigned int>&             permutation     = std::vector<unsigned int>(),
00195                          const std::vector<Scalar>&                   position_offset = std::vector<Scalar>())
00196     : rt_goal_handle_(),
00197       tolerances_(start_point.positions.size())
00198   {
00199     if (start_point.positions.size() != end_point.positions.size())
00200     {
00201       throw(std::invalid_argument("Can't construct segment from ROS message: "
00202                                   "Start/end points data size mismatch."));
00203     }
00204 
00205     const Time start_time = (traj_start_time + start_point.time_from_start).toSec();
00206     const Time end_time   = (traj_start_time + end_point.time_from_start).toSec();
00207 
00208     try
00209     {
00210       const State start_state(start_point, permutation, position_offset);
00211       const State end_state(end_point,     permutation, position_offset);
00212 
00213       this->init(start_time, start_state,
00214                  end_time,   end_state);
00215     }
00216     catch(const std::invalid_argument& ex)
00217     {
00218       std::string msg = "Can't construct segment from ROS message: " + std::string(ex.what());
00219       throw(std::invalid_argument(msg));
00220     }
00221   }
00222 
00224   RealtimeGoalHandlePtr getGoalHandle() const {return rt_goal_handle_;}
00225 
00227   void setGoalHandle(RealtimeGoalHandlePtr rt_goal_handle) {rt_goal_handle_ = rt_goal_handle;}
00228 
00230   const SegmentTolerances<Scalar>& getTolerances() const {return tolerances_;}
00231 
00233   void setTolerances(const SegmentTolerances<Scalar>& tolerances) {tolerances_ = tolerances;}
00234 
00235 private:
00236   RealtimeGoalHandlePtr     rt_goal_handle_;
00237   SegmentTolerances<Scalar> tolerances_;
00238 };
00239 
00249 template <class Scalar>
00250 std::vector<Scalar> wraparoundOffset(const std::vector<Scalar>& prev_position,
00251                                      const std::vector<Scalar>& next_position,
00252                                      const std::vector<bool>&   angle_wraparound)
00253 {
00254   // Preconditions
00255   const unsigned int n_joints = angle_wraparound.size();
00256   if (n_joints != prev_position.size() || n_joints != next_position.size()) {return std::vector<Scalar>();}
00257 
00258   // Return value
00259   std::vector<Scalar> pos_offset(n_joints, 0.0);
00260 
00261   for (unsigned int i = 0; i < angle_wraparound.size(); ++i)
00262   {
00263     if (angle_wraparound[i])
00264     {
00265       Scalar dist = angles::shortest_angular_distance(prev_position[i], next_position[i]);
00266 
00267       // Deal with singularity at M_PI shortest distance
00268       if (std::abs(dist) - M_PI < 1e-9)
00269       {
00270         dist = next_position[i] > prev_position[i] ? std::abs(dist) : -std::abs(dist);
00271       }
00272       pos_offset[i] = (prev_position[i] + dist) - next_position[i];
00273     }
00274   }
00275   return pos_offset;
00276 }
00277 
00278 } // namespace
00279 
00280 #endif // header guard


joint_trajectory_controller
Author(s): Adolfo Rodriguez Tsouroukdissian
autogenerated on Sat Aug 13 2016 04:20:51