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
00039
00040
00041 #ifndef PR2_BASE_TRAJECTORY_ACTION_CONTROLLER_H__
00042 #define PR2_BASE_TRAJECTORY_ACTION_CONTROLLER_H__
00043
00044 #include <algorithm>
00045 #include <string>
00046 #include <stdexcept>
00047
00048 #include <boost/shared_ptr.hpp>
00049 #include <boost/thread.hpp>
00050
00051 #include <ros/ros.h>
00052 #include <actionlib/server/action_server.h>
00053 #include <control_msgs/FollowJointTrajectoryAction.h>
00054 #include <trajectory_msgs/JointTrajectory.h>
00055 #include <nav_msgs/Odometry.h>
00056
00057 #include <pr2_base_trajectory_action/math_spline.h>
00058
00059 namespace pr2_base_trajectory_action {
00060 typedef actionlib::ActionServer<control_msgs::FollowJointTrajectoryAction> Server;
00061 typedef Server::GoalHandle GoalHandle;
00062
00063 struct JointState {
00064 std::string name;
00065 double position, velocity;
00066 double max_velocity;
00067 double commanded_velocity;
00068 double commanded_effort;
00069 };
00070
00071 struct BaseJointState {
00072 ros::Time real_latest_time;
00073 JointState x, y, yaw;
00074 const JointState &operator[] (size_t i) const {
00075 if (i == 0) return x;
00076 else if (i == 1) return y;
00077 else if (i == 2) return yaw;
00078 else throw std::out_of_range("range must be 0-2");
00079 }
00080 JointState &operator[] (size_t i) {
00081 if (i == 0) return x;
00082 else if (i == 1) return y;
00083 else if (i == 2) return yaw;
00084 else throw std::out_of_range("range must be 0-2");
00085 }
00086 };
00087
00088 struct Trajectory {
00089 struct Segment
00090 {
00091 double start_time;
00092 double duration;
00093 Spline splines[3];
00094 boost::shared_ptr<GoalHandle> gh;
00095 Segment(){}
00096 Segment(const double &start_time,
00097 const double &duration,
00098 const boost::shared_ptr<GoalHandle> &gh,
00099 const Spline &spline_x,
00100 const Spline &spline_y,
00101 const Spline &spline_yaw) :
00102 start_time(start_time),
00103 duration(duration),
00104 gh(gh) {
00105 splines[0] = spline_x;
00106 splines[1] = spline_y;
00107 splines[2] = spline_yaw;
00108 }
00109 void sample(const double &time, BaseMotion &base) {
00110 for (int i = 0; i < 3; ++i)
00111 splines[i].sampleWithTimeBounds(duration, time, base[i]);
00112 }
00113 typedef boost::shared_ptr< ::pr2_base_trajectory_action::Trajectory::Segment > Ptr;
00114 };
00115 std::vector<Segment> segments;
00116
00117 Trajectory() {}
00118 Trajectory(int size) : segments(size) {}
00119
00120 bool nextSegment(const double &time, Segment &seg) {
00121 if (size() == 0) {
00122 ROS_ERROR("no segments in trajectory");
00123 return false;
00124 }
00125 int seg_idx = -1;
00126 while (seg_idx + 1 < size() &&
00127 segments[seg_idx+1].start_time < time)
00128 ++seg_idx;
00129 if (seg_idx == -1) {
00130 ROS_ERROR("No earlier segments. Segment starts at %.3lf (now: %.3lf)",
00131 segments[0].start_time, time);
00132 return false;
00133 }
00134 seg = segments[seg_idx];
00135 return true;
00136 }
00137 bool motionAtTime(const double &time, BaseMotion &base) {
00138 Segment s;
00139 if (!nextSegment(time, s)) return false;
00140 double diff_time = time - s.start_time;
00141 s.sample(diff_time, base);
00142 return true;
00143 }
00144 bool goalAtTime(const double &time, boost::shared_ptr<GoalHandle> &gh) {
00145 Segment s;
00146 if (!nextSegment(time, s)) return false;
00147 gh = s.gh;
00148 return true;
00149 }
00150 double endTime() {
00151 Segment s = segments[size() - 1];
00152 return s.start_time + s.duration;
00153 }
00154 inline int size() const {
00155 return segments.size();
00156 }
00157 typedef boost::shared_ptr< ::pr2_base_trajectory_action::Trajectory > Ptr;
00158 typedef boost::shared_ptr< ::pr2_base_trajectory_action::Trajectory const > ConstPtr;
00159 };
00160
00161 class Controller
00162 {
00163
00164 boost::mutex mutex_;
00165 ros::NodeHandle nh_, pnh_;
00166 ros::Subscriber odom_sub_;
00167 ros::Publisher cmd_vel_pub_;
00168 ros::Timer update_timer_;
00169 boost::shared_ptr<Server> as_;
00170 boost::shared_ptr<GoalHandle> active_goal_;
00171 Trajectory::Ptr active_traj_;
00172 ros::Time real_latest_time_;
00173 BaseJointState joints_;
00174 double frequency_;
00175 double stopped_velocity_tolerance_;
00176 double goal_threshold_;
00177 double goal_time_constraint_;
00178 bool use_pid;
00179 control_msgs::FollowJointTrajectoryFeedback::Ptr feedback_msg_;
00180 geometry_msgs::Twist::Ptr cmd_vel_msg_;
00181
00182 void setFeedback(const ros::Time &time, const BaseMotion &desired, const BaseMotion &error);
00183 void clearTrajectory();
00184 void setTrajectory(const trajectory_msgs::JointTrajectory::ConstPtr &msg,
00185 boost::shared_ptr<GoalHandle> &gh);
00186 public:
00187
00188 Controller();
00189 virtual ~Controller();
00190 void goalCallback(GoalHandle gh);
00191 void cancelCallback(GoalHandle gh);
00192 void odomCallback(const nav_msgs::Odometry::ConstPtr & msg);
00193 void update(const ros::TimerEvent& event);
00194 };
00195
00196 template<typename T>
00197 inline int findIndex(std::vector<T> vec, T val)
00198 {
00199 typename
00200 std::vector<T>::iterator it = std::find(vec.begin(), vec.end(), val);
00201 int d = it - vec.begin();
00202 return d == vec.size() ? -1 : d;
00203 }
00204
00205 template <typename E, typename M>
00206 inline boost::shared_ptr<M> share_member(boost::shared_ptr<E> e, M &m)
00207 {
00208 actionlib::EnclosureDeleter<E> d(e);
00209 boost::shared_ptr<M> p(&m, d);
00210 return p;
00211 }
00212 }
00213
00214
00215 #endif // PR2_BASE_TRAJECTORY_ACTION_CONTROLLER_H__