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
00027
00029
00030 #ifndef JOINT_TRAJECTORY_CONTROLLER_JOINT_TRAJECTORY_SEGMENT_H
00031 #define JOINT_TRAJECTORY_CONTROLLER_JOINT_TRAJECTORY_SEGMENT_H
00032
00033
00034 #include <cmath>
00035 #include <stdexcept>
00036 #include <string>
00037 #include <vector>
00038
00039
00040 #include <angles/angles.h>
00041
00042
00043 #include <control_msgs/FollowJointTrajectoryAction.h>
00044 #include <trajectory_msgs/JointTrajectoryPoint.h>
00045
00046
00047 #include <realtime_tools/realtime_server_goal_handle.h>
00048
00049
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
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
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
00149 const unsigned int id = permutation.empty() ? i : permutation[i];
00150
00151
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
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
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
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 }
00279
00280 #endif // header guard