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 #include <ros/ros.h>
00041 #include <moveit/controller_manager/controller_manager.h>
00042 #include <control_msgs/FollowJointTrajectoryAction.h>
00043 #include <control_msgs/GripperCommandAction.h>
00044 #include <actionlib/client/simple_action_client.h>
00045 #include <pluginlib/class_list_macros.h>
00046 #include <algorithm>
00047 #include <map>
00048
00049 namespace simple_moveit_controller_manager
00050 {
00051
00052
00053
00054
00055 template<typename T>
00056 class ActionBasedControllerHandle : public moveit_controller_manager::MoveItControllerHandle
00057 {
00058 public:
00059 ActionBasedControllerHandle(const std::string &name, const std::string &ns) :
00060 moveit_controller_manager::MoveItControllerHandle(name),
00061 namespace_(ns),
00062 done_(true)
00063 {
00064 controller_action_client_.reset(new actionlib::SimpleActionClient<T>(name_ +"/" + namespace_, true));
00065 unsigned int attempts = 0;
00066 while (ros::ok() && !controller_action_client_->waitForServer(ros::Duration(5.0)) && ++attempts < 3)
00067 ROS_INFO_STREAM("Waiting for " << name_ + "/" + namespace_ << " to come up");
00068
00069 if (!controller_action_client_->isServerConnected())
00070 {
00071 ROS_ERROR_STREAM("Action client not connected: " << name_ + "/" + namespace_);
00072 controller_action_client_.reset();
00073 }
00074
00075 last_exec_ = moveit_controller_manager::ExecutionStatus::SUCCEEDED;
00076 }
00077
00078 bool isConnected() const
00079 {
00080 return controller_action_client_;
00081 }
00082
00083 virtual bool cancelExecution()
00084 {
00085 if (!controller_action_client_)
00086 return false;
00087 if (!done_)
00088 {
00089 ROS_INFO_STREAM("Cancelling execution for " << name_);
00090 controller_action_client_->cancelGoal();
00091 last_exec_ = moveit_controller_manager::ExecutionStatus::PREEMPTED;
00092 done_ = true;
00093 }
00094 return true;
00095 }
00096
00097 virtual bool waitForExecution(const ros::Duration &timeout = ros::Duration(0))
00098 {
00099 if (controller_action_client_ && !done_)
00100 return controller_action_client_->waitForResult(timeout);
00101 return true;
00102 }
00103
00104 virtual moveit_controller_manager::ExecutionStatus getLastExecutionStatus()
00105 {
00106 return last_exec_;
00107 }
00108
00109 protected:
00110
00111 void finishControllerExecution(const actionlib::SimpleClientGoalState& state)
00112 {
00113 ROS_DEBUG_STREAM("Controller " << name_ << " is done with state " << state.toString() << ": " << state.getText());
00114 if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
00115 last_exec_ = moveit_controller_manager::ExecutionStatus::SUCCEEDED;
00116 else
00117 if (state == actionlib::SimpleClientGoalState::ABORTED)
00118 last_exec_ = moveit_controller_manager::ExecutionStatus::ABORTED;
00119 else
00120 if (state == actionlib::SimpleClientGoalState::PREEMPTED)
00121 last_exec_ = moveit_controller_manager::ExecutionStatus::PREEMPTED;
00122 else
00123 last_exec_ = moveit_controller_manager::ExecutionStatus::FAILED;
00124 done_ = true;
00125 }
00126
00127 moveit_controller_manager::ExecutionStatus last_exec_;
00128 std::string namespace_;
00129 bool done_;
00130 boost::shared_ptr<actionlib::SimpleActionClient<T> > controller_action_client_;
00131 };
00132
00133
00134
00135
00136 class GripperControllerHandle : public ActionBasedControllerHandle<control_msgs::GripperCommandAction>
00137 {
00138 public:
00139
00140 GripperControllerHandle(const std::string &name, const std::string &ns = "gripper_action") :
00141 ActionBasedControllerHandle<control_msgs::GripperCommandAction>(name, ns),
00142 closing_(false)
00143 {
00144 }
00145
00146 virtual bool sendTrajectory(const moveit_msgs::RobotTrajectory &trajectory)
00147 {
00148 ROS_INFO_STREAM("new trajectory to " << name_);
00149 if (!controller_action_client_)
00150 return false;
00151 if (!trajectory.multi_dof_joint_trajectory.points.empty())
00152 {
00153 ROS_ERROR("The simple gripper controller cannot execute multi-dof trajectories.");
00154 return false;
00155 }
00156
00157 if (trajectory.joint_trajectory.points.size() != 1)
00158 {
00159 ROS_ERROR("The simple gripper controller expects a joint trajectory with one point only, but %u provided)", (unsigned int)trajectory.joint_trajectory.points.size());
00160 return false;
00161 }
00162
00163 if (trajectory.joint_trajectory.points[0].positions.empty())
00164 {
00165 ROS_ERROR("The simple gripper controller expects a joint trajectory with one point that specifies at least one position, but 0 positions provided)");
00166 return false;
00167 }
00168
00169
00170 control_msgs::GripperCommandGoal goal;
00171 if (!trajectory.joint_trajectory.points[0].velocities.empty())
00172 goal.command.max_effort = trajectory.joint_trajectory.points[0].velocities[0];
00173 goal.command.position = trajectory.joint_trajectory.points[0].positions[0];
00174 controller_action_client_->sendGoal(goal,
00175 boost::bind(&GripperControllerHandle::controllerDoneCallback, this, _1, _2),
00176 boost::bind(&GripperControllerHandle::controllerActiveCallback, this),
00177 boost::bind(&GripperControllerHandle::controllerFeedbackCallback, this, _1));
00178 done_ = false;
00179 last_exec_ = moveit_controller_manager::ExecutionStatus::RUNNING;
00180 return true;
00181 }
00182
00183 private:
00184
00185 void controllerDoneCallback(const actionlib::SimpleClientGoalState& state,
00186 const control_msgs::GripperCommandResultConstPtr& result)
00187 {
00188
00189
00190 finishControllerExecution(actionlib::SimpleClientGoalState::SUCCEEDED);
00191
00192
00193 }
00194
00195 void controllerActiveCallback()
00196 {
00197 ROS_DEBUG_STREAM("Controller " << name_ << " started execution");
00198 }
00199
00200 void controllerFeedbackCallback(const control_msgs::GripperCommandFeedbackConstPtr& feedback)
00201 {
00202 }
00203
00204 bool closing_;
00205 };
00206
00207
00208
00209
00210 class SimpleFollowJointTrajectoryControllerHandle : public ActionBasedControllerHandle<control_msgs::FollowJointTrajectoryAction>
00211 {
00212 public:
00213
00214 SimpleFollowJointTrajectoryControllerHandle(const std::string &name, const std::string &ns = "follow_joint_trajectory") :
00215 ActionBasedControllerHandle<control_msgs::FollowJointTrajectoryAction>(name, ns)
00216 {
00217 }
00218
00219 virtual bool sendTrajectory(const moveit_msgs::RobotTrajectory &trajectory)
00220 {
00221 ROS_INFO_STREAM("new trajectory to " << name_);
00222 if (!controller_action_client_)
00223 return false;
00224 if (!trajectory.multi_dof_joint_trajectory.points.empty())
00225 {
00226 ROS_ERROR("The FollowJointTrajectory controller cannot execute multi-dof trajectories.");
00227 return false;
00228 }
00229 if (done_)
00230 ROS_DEBUG_STREAM("Sending trajectory to FollowJointTrajectory action for controller " << name_);
00231 else
00232 ROS_DEBUG_STREAM("Sending continuation for the currently executed trajectory to FollowJointTrajectory action for controller " << name_);
00233 control_msgs::FollowJointTrajectoryGoal goal;
00234 goal.trajectory = trajectory.joint_trajectory;
00235 controller_action_client_->sendGoal(goal,
00236 boost::bind(&SimpleFollowJointTrajectoryControllerHandle::controllerDoneCallback, this, _1, _2),
00237 boost::bind(&SimpleFollowJointTrajectoryControllerHandle::controllerActiveCallback, this),
00238 boost::bind(&SimpleFollowJointTrajectoryControllerHandle::controllerFeedbackCallback, this, _1));
00239 done_ = false;
00240 last_exec_ = moveit_controller_manager::ExecutionStatus::RUNNING;
00241 return true;
00242 }
00243
00244 protected:
00245
00246 void controllerDoneCallback(const actionlib::SimpleClientGoalState& state,
00247 const control_msgs::FollowJointTrajectoryResultConstPtr& result)
00248 {
00249 finishControllerExecution(state);
00250 }
00251
00252 void controllerActiveCallback()
00253 {
00254 ROS_DEBUG_STREAM("Controller " << name_ << " started execution");
00255 }
00256
00257 void controllerFeedbackCallback(const control_msgs::FollowJointTrajectoryFeedbackConstPtr& feedback)
00258 {
00259 }
00260 };
00261
00262 class SimpleMoveItControllerManager : public moveit_controller_manager::MoveItControllerManager
00263 {
00264 public:
00265
00266 SimpleMoveItControllerManager() : node_handle_("~")
00267 {
00268
00269 XmlRpc::XmlRpcValue controller_list;
00270 if (node_handle_.hasParam("controller_list"))
00271 {
00272 node_handle_.getParam("controller_list", controller_list);
00273 if (controller_list.getType() != XmlRpc::XmlRpcValue::TypeArray)
00274 ROS_ERROR("Controller list should be specified as an array");
00275 else
00276 for (int i = 0 ; i < controller_list.size() ; ++i)
00277 if (!controller_list[i].hasMember("name") || !controller_list[i].hasMember("joints"))
00278 ROS_ERROR("Name and joints must be specifed for each controller");
00279 else
00280 {
00281 try
00282 {
00283 std::string name = std::string(controller_list[i]["name"]);
00284 std::string ns;
00285 if (controller_list[i].hasMember("ns"))
00286 ns = std::string(controller_list[i]["ns"]);
00287 if (controller_list[i]["joints"].getType() == XmlRpc::XmlRpcValue::TypeArray)
00288 {
00289 int nj = controller_list[i]["joints"].size();
00290 for (int j = 0 ; j < nj ; ++j)
00291 controller_joints_[name].push_back(std::string(controller_list[i]["joints"][j]));
00292
00293 if (controller_list[i].hasMember("type"))
00294 {
00295 std::string type = std::string(controller_list[i]["type"]);
00296
00297 moveit_controller_manager::MoveItControllerHandlePtr new_handle;
00298 if ( type == "GripperCommand" )
00299 {
00300 new_handle.reset(ns.empty() ? new GripperControllerHandle(name) : new GripperControllerHandle(name, ns));
00301 if (static_cast<GripperControllerHandle*>(new_handle.get())->isConnected())
00302 {
00303 ROS_INFO_STREAM("Added GripperCommand controller for " << name );
00304 controller_handles_[name] = new_handle;
00305 }
00306 }
00307 else if ( type == "FollowJointTrajectory" )
00308 {
00309 new_handle.reset(ns.empty() ? new SimpleFollowJointTrajectoryControllerHandle(name) : new SimpleFollowJointTrajectoryControllerHandle(name, ns));
00310 if (static_cast<SimpleFollowJointTrajectoryControllerHandle*>(new_handle.get())->isConnected())
00311 {
00312 ROS_INFO_STREAM("Added FollowJointTrajectory controller for " << name );
00313 controller_handles_[name] = new_handle;
00314 }
00315 }
00316 }
00317 else
00318 ROS_ERROR_STREAM("No type specified for controller " << name);
00319 }
00320 else
00321 ROS_ERROR_STREAM("The list of joints for controller " << name << " is not specified as an array");
00322 }
00323 catch (...)
00324 {
00325 ROS_ERROR("Unable to parse controller information");
00326 }
00327 }
00328 }
00329 else
00330 {
00331 ROS_ERROR_STREAM("No controllers specified.");
00332 }
00333 }
00334
00335 virtual ~SimpleMoveItControllerManager()
00336 {
00337 }
00338
00339 virtual moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string &name)
00340 {
00341 std::map<std::string, moveit_controller_manager::MoveItControllerHandlePtr>::const_iterator it = controller_handles_.find(name);
00342 if (it != controller_handles_.end())
00343 return it->second;
00344 else
00345 ROS_FATAL_STREAM("No such controller: " << name);
00346 }
00347
00348 virtual void getControllersList(std::vector<std::string> &names)
00349 {
00350 for (std::map<std::string, moveit_controller_manager::MoveItControllerHandlePtr>::const_iterator it = controller_handles_.begin() ; it != controller_handles_.end() ; ++it)
00351 names.push_back(it->first);
00352 ROS_INFO_STREAM("Returned " << names.size() << " controllers in list");
00353 }
00354
00355 virtual void getActiveControllers(std::vector<std::string> &names)
00356 {
00357 getControllersList(names);
00358 }
00359
00360 virtual void getLoadedControllers(std::vector<std::string> &names)
00361 {
00362 getControllersList(names);
00363 }
00364
00365 virtual void getControllerJoints(const std::string &name, std::vector<std::string> &joints)
00366 {
00367 std::map<std::string, std::vector<std::string> >::const_iterator it = controller_joints_.find(name);
00368 if (it != controller_joints_.end())
00369 {
00370 joints = it->second;
00371 ROS_INFO_STREAM("Returned " << joints.size() << " joints for " << name);
00372 }
00373 else
00374 {
00375 ROS_WARN("The joints for controller '%s' are not known. Perhaps the controller configuration is not loaded on the param server?", name.c_str());
00376 joints.clear();
00377 }
00378 }
00379
00380 virtual moveit_controller_manager::MoveItControllerManager::ControllerState getControllerState(const std::string &name)
00381 {
00382
00383 moveit_controller_manager::MoveItControllerManager::ControllerState state;
00384 state.loaded_ = true;
00385 state.active_ = true;
00386 state.default_ = true;
00387 return state;
00388 }
00389
00390 virtual bool loadController(const std::string &name)
00391 {
00392
00393 return true;
00394 }
00395
00396 virtual bool unloadController(const std::string &name)
00397 {
00398
00399 return false;
00400 }
00401
00402 virtual bool switchControllers(const std::vector<std::string> &activate, const std::vector<std::string> &deactivate)
00403 {
00404
00405 return false;
00406 }
00407
00408 protected:
00409
00410 ros::NodeHandle node_handle_;
00411 ros::NodeHandle root_node_handle_;
00412 std::map<std::string, std::vector<std::string> > controller_joints_;
00413 std::map<std::string, moveit_controller_manager::MoveItControllerHandlePtr> controller_handles_;
00414 };
00415
00416 }
00417
00418 PLUGINLIB_EXPORT_CLASS(simple_moveit_controller_manager::SimpleMoveItControllerManager,
00419 moveit_controller_manager::MoveItControllerManager);