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 #include <ros/ros.h>
00034 #include <actionlib/server/action_server.h>
00035
00036 #include <trajectory_msgs/JointTrajectory.h>
00037 #include <control_msgs/FollowJointTrajectoryAction.h>
00038 #include <control_msgs/FollowJointTrajectoryFeedback.h>
00039
00040 const double DEFAULT_GOAL_THRESHOLD = 0.01;
00041
00042 class JointTrajectoryExecuter
00043 {
00044 private:
00045 typedef actionlib::ActionServer<control_msgs::FollowJointTrajectoryAction> JTAS;
00046 typedef JTAS::GoalHandle GoalHandle;
00047 public:
00048 JointTrajectoryExecuter(ros::NodeHandle &n) :
00049 node_(n),
00050 action_server_(node_, "joint_trajectory_action",
00051 boost::bind(&JointTrajectoryExecuter::goalCB, this, _1),
00052 boost::bind(&JointTrajectoryExecuter::cancelCB, this, _1),
00053 false),
00054 has_active_goal_(false)
00055 {
00056 using namespace XmlRpc;
00057 ros::NodeHandle pn("~");
00058
00059 joint_names_.push_back("joint_s");
00060 joint_names_.push_back("joint_l");
00061 joint_names_.push_back("joint_e");
00062 joint_names_.push_back("joint_u");
00063 joint_names_.push_back("joint_r");
00064 joint_names_.push_back("joint_b");
00065 joint_names_.push_back("joint_t");
00066
00067 pn.param("constraints/goal_time", goal_time_constraint_, 0.0);
00068
00069
00070 for (size_t i = 0; i < joint_names_.size(); ++i)
00071 {
00072 std::string ns = std::string("constraints/") + joint_names_[i];
00073 double g, t;
00074 pn.param(ns + "/goal", g, DEFAULT_GOAL_THRESHOLD);
00075 pn.param(ns + "/trajectory", t, -1.0);
00076 goal_constraints_[joint_names_[i]] = g;
00077 trajectory_constraints_[joint_names_[i]] = t;
00078 }
00079 pn.param("constraints/stopped_velocity_tolerance", stopped_velocity_tolerance_, 0.01);
00080
00081
00082 pub_controller_command_ =
00083 node_.advertise<trajectory_msgs::JointTrajectory>("command", 1);
00084 sub_controller_state_ =
00085 node_.subscribe("feedback_states", 1, &JointTrajectoryExecuter::controllerStateCB, this);
00086
00087 action_server_.start();
00088 }
00089
00090 ~JointTrajectoryExecuter()
00091 {
00092 pub_controller_command_.shutdown();
00093 sub_controller_state_.shutdown();
00094 watchdog_timer_.stop();
00095 }
00096
00097 bool withinGoalConstraints(const control_msgs::FollowJointTrajectoryFeedbackConstPtr &msg,
00098 const std::map<std::string, double>& constraints,
00099 const trajectory_msgs::JointTrajectory& traj) {
00100 ROS_DEBUG("Checking goal contraints");
00101 int last = traj.points.size() - 1;
00102 for (size_t i = 0; i < msg->joint_names.size(); ++i)
00103 {
00104 double abs_error = fabs(msg->actual.positions[i]-traj.points[last].positions[i]);
00105 double goal_constraint = constraints.at(msg->joint_names[i]);
00106 if (goal_constraint >= 0 && abs_error > goal_constraint)
00107 {
00108 ROS_DEBUG("Bad constraint: %f, abs_errs: %f", goal_constraint, abs_error);
00109 return false;
00110 }
00111 ROS_DEBUG("Checking constraint: %f, abs_errs: %f", goal_constraint, abs_error);
00112 }
00113 return true;
00114 }
00115
00116 private:
00117
00118 static bool setsEqual(const std::vector<std::string> &a, const std::vector<std::string> &b)
00119 {
00120 if (a.size() != b.size())
00121 return false;
00122
00123 for (size_t i = 0; i < a.size(); ++i)
00124 {
00125 if (count(b.begin(), b.end(), a[i]) != 1)
00126 return false;
00127 }
00128 for (size_t i = 0; i < b.size(); ++i)
00129 {
00130 if (count(a.begin(), a.end(), b[i]) != 1)
00131 return false;
00132 }
00133
00134 return true;
00135 }
00136
00137 void watchdog(const ros::TimerEvent &e)
00138 {
00139 ros::Time now = ros::Time::now();
00140
00141
00142 if (has_active_goal_)
00143 {
00144 bool should_abort = false;
00145 if (!last_controller_state_)
00146 {
00147 should_abort = true;
00148 ROS_WARN("Aborting goal because we have never heard a controller state message.");
00149 }
00150 else if ((now - last_controller_state_->header.stamp) > ros::Duration(5.0))
00151 {
00152 should_abort = true;
00153 ROS_WARN("Aborting goal because we haven't heard from the controller in %.3lf seconds",
00154 (now - last_controller_state_->header.stamp).toSec());
00155 }
00156
00157 if (should_abort)
00158 {
00159
00160 trajectory_msgs::JointTrajectory empty;
00161 empty.joint_names = joint_names_;
00162 pub_controller_command_.publish(empty);
00163
00164
00165 active_goal_.setAborted();
00166 has_active_goal_ = false;
00167 }
00168 }
00169 }
00170
00171 void goalCB(GoalHandle gh)
00172 {
00173
00174 ROS_DEBUG("Received goal: goalCB");
00175 if (!setsEqual(joint_names_, gh.getGoal()->trajectory.joint_names))
00176 {
00177 ROS_ERROR("Joints on incoming goal don't match our joints");
00178 gh.setRejected();
00179 return;
00180 }
00181
00182
00183 if (has_active_goal_)
00184 {
00185 ROS_DEBUG("Received new goal, canceling current goal");
00186
00187 trajectory_msgs::JointTrajectory empty;
00188 empty.joint_names = joint_names_;
00189 pub_controller_command_.publish(empty);
00190
00191
00192 active_goal_.setCanceled();
00193 has_active_goal_ = false;
00194 }
00195
00196
00197 if(withinGoalConstraints(last_controller_state_,
00198 goal_constraints_,
00199 gh.getGoal()->trajectory)) {
00200 ROS_INFO_STREAM("Already within goal constraints");
00201 gh.setAccepted();
00202 gh.setSucceeded();
00203 } else {
00204 gh.setAccepted();
00205 active_goal_ = gh;
00206 has_active_goal_ = true;
00207
00208 ROS_INFO("Publishing trajectory");
00209
00210 current_traj_ = active_goal_.getGoal()->trajectory;
00211 pub_controller_command_.publish(current_traj_);
00212 }
00213 }
00214
00215 void cancelCB(GoalHandle gh)
00216 {
00217 ROS_DEBUG("Received action cancel request");
00218 if (active_goal_ == gh)
00219 {
00220
00221 trajectory_msgs::JointTrajectory empty;
00222 empty.joint_names = joint_names_;
00223 pub_controller_command_.publish(empty);
00224
00225
00226 active_goal_.setCanceled();
00227 has_active_goal_ = false;
00228 }
00229 }
00230
00231
00232 ros::NodeHandle node_;
00233 JTAS action_server_;
00234 ros::Publisher pub_controller_command_;
00235 ros::Subscriber sub_controller_state_;
00236 ros::Timer watchdog_timer_;
00237
00238 bool has_active_goal_;
00239 GoalHandle active_goal_;
00240 trajectory_msgs::JointTrajectory current_traj_;
00241
00242
00243 std::vector<std::string> joint_names_;
00244 std::map<std::string,double> goal_constraints_;
00245 std::map<std::string,double> trajectory_constraints_;
00246 double goal_time_constraint_;
00247 double stopped_velocity_tolerance_;
00248
00249 control_msgs::FollowJointTrajectoryFeedbackConstPtr last_controller_state_;
00250
00251 void controllerStateCB(const control_msgs::FollowJointTrajectoryFeedbackConstPtr &msg)
00252 {
00253
00254 last_controller_state_ = msg;
00255 ros::Time now = ros::Time::now();
00256
00257 if (!has_active_goal_)
00258 {
00259
00260 return;
00261 }
00262 if (current_traj_.points.empty())
00263 {
00264 ROS_DEBUG("Current trajecotry is empty, ignoring feedback");
00265 return;
00266 }
00267
00268
00269
00270
00271
00272 if (!setsEqual(joint_names_, msg->joint_names))
00273 {
00274 ROS_ERROR("Joint names from the controller don't match our joint names.");
00275 return;
00276 }
00277
00278
00279
00280
00281 ROS_DEBUG("Checking goal contraints");
00282 if(withinGoalConstraints(msg,
00283 goal_constraints_,
00284 current_traj_)) {
00285 ROS_INFO("Inside goal contraints, return success for action");
00286 active_goal_.setSucceeded();
00287 has_active_goal_ = false;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 }
00354 };
00355
00356
00357 int main(int argc, char** argv)
00358 {
00359 ros::init(argc, argv, "joint_trajectory_action_node");
00360 ros::NodeHandle node;
00361 JointTrajectoryExecuter jte(node);
00362
00363 ros::spin();
00364
00365 return 0;
00366 }
00367
00368
00369
00370