simple_moveit_controller_manager.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2012, Willow Garage, Inc.
00005 *  Copyright (c) 2013, Michael E. Ferguson
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the Willow Garage nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *********************************************************************/
00035 
00036 /* Author: Ioan Sucan, E. Gil Jones, Michael Ferguson */
00037 /* This is a simplified controller manager which uses control_msgs
00038  * actions. It is based off the earlier pr2_controller_manager. */
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  * This is a simple base class, which handles all of the action creation/etc
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  * The gripper ...
00135  */
00136 class GripperControllerHandle : public ActionBasedControllerHandle<control_msgs::GripperCommandAction>
00137 {
00138 public:
00139   /* Topics will map to name/ns/goal, name/ns/result, etc */
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     /* TODO: currently sending velocity as effort, make this better. */
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     // the gripper action reports failure when closing the gripper and an object is inside
00189     //if (state == actionlib::SimpleClientGoalState::ABORTED && closing_)
00190       finishControllerExecution(actionlib::SimpleClientGoalState::SUCCEEDED);
00191     //else
00192       //finishControllerExecution(state);
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  * This is generally used for arms, but could also be used for multi-dof hands.
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     /* need to initialize controllers_ from the param server */
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     /* Controllers need to be loaded and active to be used. */
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     /* All of our controllers are already loaded. */
00393     return true;
00394   }
00395   
00396   virtual bool unloadController(const std::string &name)
00397   {
00398     /* Cannot unload our controllers */
00399     return false;
00400   }
00401   
00402   virtual bool switchControllers(const std::vector<std::string> &activate, const std::vector<std::string> &deactivate)
00403   {
00404     /* Cannot switch our controllers */
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);
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends


simple_moveit_plugins
Author(s): Michael Ferguson
autogenerated on Tue May 28 2013 17:42:22