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
00037 #include <ros/ros.h>
00038 #include <arm_navigation_msgs/FilterJointTrajectoryWithConstraints.h>
00039 #include <pr2_controllers_msgs/JointTrajectoryAction.h>
00040 #include <planning_environment/monitors/monitor_utils.h>
00041 #include <planning_environment/models/model_utils.h>
00042 #include <planning_environment/monitors/kinematic_model_state_monitor.h>
00043 #include <planning_environment/models/collision_models_interface.h>
00044
00045 #include <actionlib/server/simple_action_server.h>
00046 #include <actionlib/client/simple_action_client.h>
00047 #include <actionlib/client/simple_client_goal_state.h>
00048
00049
00050 #include <boost/thread/condition.hpp>
00051 #include <boost/scoped_ptr.hpp>
00052 #include <algorithm>
00053 #include <string>
00054 #include <limits>
00055
00056 namespace collision_free_arm_trajectory_controller
00057 {
00058 static const std::string TRAJECTORY_FILTER = "/trajectory_filter_server/filter_trajectory_with_constraints";
00059 static const std::string TRAJECTORY_CONTROLLER = "/joint_trajectory_action";
00060 static const double MIN_DELTA = 0.01;
00061
00062 enum ControllerState{
00063 IDLE,
00064 START_CONTROL,
00065 MONITOR
00066 };
00067
00068
00069 class CollisionFreeArmTrajectoryController
00070 {
00071
00072 public:
00073 CollisionFreeArmTrajectoryController(): private_handle_("~")
00074 {
00075 std::string robot_description_name = node_handle_.resolveName("robot_description", true);
00076
00077 collision_models_interface_ = new planning_environment::CollisionModelsInterface(robot_description_name);
00078 kmsm_ = new planning_environment::KinematicModelStateMonitor(collision_models_interface_, &tf_);
00079
00080 kmsm_->addOnStateUpdateCallback(boost::bind(&CollisionFreeArmTrajectoryController::jointStateCallback, this, _1));
00081
00082 collision_models_interface_->addSetPlanningSceneCallback(boost::bind(&CollisionFreeArmTrajectoryController::setPlanningSceneCallback, this, _1));
00083
00084 ros::service::waitForService("filter_trajectory");
00085
00086 filter_trajectory_client_ = node_handle_.serviceClient<arm_navigation_msgs::FilterJointTrajectoryWithConstraints>("filter_trajectory",true);
00087
00088 private_handle_.param<std::string>("group_name", group_name_, "");
00089
00090 traj_action_client_ = new actionlib::SimpleActionClient<pr2_controllers_msgs::JointTrajectoryAction>(TRAJECTORY_CONTROLLER, true);
00091 while(ros::ok() && !traj_action_client_->waitForServer(ros::Duration(1.0))){
00092 ROS_INFO("Waiting for the arm trajectory controller to come up");
00093 }
00094
00095 action_server_.reset(new actionlib::SimpleActionServer<pr2_controllers_msgs::JointTrajectoryAction>(node_handle_, "collision_free_arm_trajectory_action_" + group_name_, false));
00096
00097 action_server_->registerGoalCallback(boost::bind(&CollisionFreeArmTrajectoryController::executeTrajectory, this));
00098 action_server_->start();
00099 state_ = IDLE;
00100 }
00101
00102 ~CollisionFreeArmTrajectoryController()
00103 {
00104 delete traj_action_client_;
00105 delete collision_models_interface_;
00106 delete kmsm_;
00107 }
00108
00109 void setPlanningSceneCallback(const arm_navigation_msgs::PlanningScene& scene) {
00110 collision_models_interface_->bodiesLock();
00111 collision_models_interface_->disableCollisionsForNonUpdatedLinks(group_name_);
00112 collision_models_interface_->bodiesUnlock();
00113 }
00114
00115 void jointStateCallback(const sensor_msgs::JointStateConstPtr& joint_state) {
00116
00117 collision_models_interface_->bodiesLock();
00118 if(!collision_models_interface_->getPlanningSceneState()) {
00119 if(state_ == MONITOR) {
00120 ROS_WARN("Should be monitoring, but no planning scene set");
00121 traj_action_client_->cancelAllGoals();
00122 action_server_->setAborted();
00123 state_ = IDLE;
00124 }
00125 collision_models_interface_->bodiesUnlock();
00126 return;
00127 }
00128 kmsm_->setStateValuesFromCurrentValues(*collision_models_interface_->getPlanningSceneState());
00129 if(state_ != MONITOR || current_joint_trajectory_.points.size() == 0) {
00130 collision_models_interface_->bodiesUnlock();
00131 return;
00132 }
00133 trajectory_msgs::JointTrajectory joint_trajectory_subset;
00134 planning_environment::removeCompletedTrajectory(collision_models_interface_->getParsedDescription(),
00135 current_joint_trajectory_,
00136 *joint_state,
00137 joint_trajectory_subset,
00138 false);
00139 current_joint_trajectory_ = joint_trajectory_subset;
00140 arm_navigation_msgs::Constraints emp;
00141 arm_navigation_msgs::ArmNavigationErrorCodes error_code;
00142 std::vector<arm_navigation_msgs::ArmNavigationErrorCodes> error_code_vec;
00143 if(current_joint_trajectory_.points.size() > 0) {
00144 if(!collision_models_interface_->isJointTrajectoryValid(*collision_models_interface_->getPlanningSceneState(),
00145 current_joint_trajectory_,
00146 emp, emp,
00147 error_code,
00148 error_code_vec,
00149 false)) {
00150 ROS_WARN_STREAM("Collision at point " << error_code_vec.size() << " of remaining trajectory points " << current_joint_trajectory_.points.size());
00151 traj_action_client_->cancelAllGoals();
00152 action_server_->setAborted();
00153 state_ = IDLE;
00154 }
00155 }
00156 collision_models_interface_->bodiesUnlock();
00157 }
00158
00159 void executeTrajectory()
00160 {
00161 if(state_ != IDLE) {
00162 ROS_INFO_STREAM("Preempted, so stopping");
00163 traj_action_client_->cancelAllGoals();
00164 }
00165 pr2_controllers_msgs::JointTrajectoryGoal goal(*(action_server_->acceptNewGoal()));
00166
00167 ROS_INFO("Got trajectory with %d points and %d joints",(int)goal.trajectory.points.size(),(int)goal.trajectory.joint_names.size());
00168
00169 collision_models_interface_->bodiesLock();
00170 if(!collision_models_interface_->isPlanningSceneSet()) {
00171 ROS_WARN_STREAM("Can't execute safe trajectory control without planning scene");
00172 action_server_->setAborted();
00173 collision_models_interface_->bodiesUnlock();
00174 return;
00175 }
00176
00177 arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Request req;
00178 arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Response res;
00179
00180 planning_environment::convertKinematicStateToRobotState(*collision_models_interface_->getPlanningSceneState(),
00181 ros::Time::now(),
00182 collision_models_interface_->getWorldFrameId(),
00183 req.start_state);
00184 std::map<std::string, double> current_values;
00185 collision_models_interface_->getPlanningSceneState()->getKinematicStateValues(current_values);
00186 req.trajectory = goal.trajectory;
00187
00188 trajectory_msgs::JointTrajectoryPoint jtp;
00189 for(unsigned int i = 0; i < req.trajectory.joint_names.size(); i++) {
00190 ROS_DEBUG_STREAM("Setting joint " << req.trajectory.joint_names[i] << " value " << current_values[req.trajectory.joint_names[i]]);
00191 jtp.positions.push_back(current_values[req.trajectory.joint_names[i]]);
00192 }
00193 req.trajectory.points.insert(req.trajectory.points.begin(), jtp);
00194 req.group_name = group_name_;
00195 if(filter_trajectory_client_.call(req,res))
00196 {
00197 if(res.error_code.val == res.error_code.SUCCESS)
00198 {
00199 current_joint_trajectory_ = res.trajectory;
00200 pr2_controllers_msgs::JointTrajectoryGoal goal;
00201 goal.trajectory = current_joint_trajectory_;
00202 goal.trajectory.header.stamp = ros::Time::now()+ros::Duration(0.2);
00203 traj_action_client_->sendGoal(goal,boost::bind(&CollisionFreeArmTrajectoryController::controllerDoneCallback, this, _1, _2));
00204 state_ = MONITOR;
00205 collision_models_interface_->bodiesUnlock();
00206 return;
00207 }
00208 else
00209 {
00210 ROS_INFO_STREAM("Filter rejects trajectory based on current state with status " << res.error_code.val);
00211 action_server_->setAborted();
00212 collision_models_interface_->bodiesUnlock();
00213 return;
00214 }
00215 } else {
00216 ROS_WARN_STREAM("Filter trajectory call failed entirely");
00217 action_server_->setAborted();
00218 collision_models_interface_->bodiesUnlock();
00219 return;
00220 }
00221 }
00222
00223
00224 void controllerDoneCallback(const actionlib::SimpleClientGoalState& state,
00225 const pr2_controllers_msgs::JointTrajectoryResultConstPtr& result)
00226 {
00227 ROS_INFO_STREAM("Trajectory reported done with state " << state.toString());
00228 state_ = IDLE;
00229 action_server_->setSucceeded();
00230 }
00231
00232 private:
00233 ros::NodeHandle node_handle_, private_handle_;
00234
00235 std::string group_name_;
00236
00237 planning_environment::CollisionModelsInterface* collision_models_interface_;
00238 planning_environment::KinematicModelStateMonitor* kmsm_;
00239
00240 ros::ServiceClient filter_trajectory_client_;
00241
00242 tf::TransformListener tf_;
00243
00244 boost::shared_ptr<actionlib::SimpleActionServer<pr2_controllers_msgs::JointTrajectoryAction> > action_server_;
00245 actionlib::SimpleActionClient<pr2_controllers_msgs::JointTrajectoryAction>* traj_action_client_;
00246
00247 ControllerState state_;
00248 trajectory_msgs::JointTrajectory current_joint_trajectory_;
00249 };
00250 }
00251
00252 int main(int argc, char** argv)
00253 {
00254 ros::init(argc, argv, "collision_free_arm_trajectory_controller");
00255 collision_free_arm_trajectory_controller::CollisionFreeArmTrajectoryController cf;
00256 ROS_INFO("Collision free arm trajectory controller started");
00257 ros::spin();
00258 return 0;
00259 }
00260