MoveArmActionClient.cpp
Go to the documentation of this file.
00001 
00002 /*
00003  * Copyright 2013 Southwest Research Institute
00004 
00005    Licensed under the Apache License, Version 2.0 (the "License");
00006    you may not use this file except in compliance with the License.
00007    You may obtain a copy of the License at
00008 
00009      http://www.apache.org/licenses/LICENSE-2.0
00010 
00011    Unless required by applicable law or agreed to in writing, software
00012    distributed under the License is distributed on an "AS IS" BASIS,
00013    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014    See the License for the specific language governing permissions and
00015    limitations under the License.
00016  */
00017 
00018 #include <mtconnect_cnc_robot_example/move_arm_action_clients/MoveArmActionClient.h>
00019 #include <arm_navigation_msgs/utils.h>
00020 
00021 using namespace mtconnect_cnc_robot_example;
00022 
00023 MoveArmActionClient::MoveArmActionClient()
00024 :
00025         move_arm_client_ptr_()
00026 {
00027 
00028 }
00029 
00030 MoveArmActionClient::~MoveArmActionClient()
00031 {
00032 
00033 }
00034 
00035 void MoveArmActionClient::run()
00036 {
00037         using namespace arm_navigation_msgs;
00038 
00039         if(!setup())
00040         {
00041                 return;
00042         }
00043 
00044         ros::AsyncSpinner spinner(2);
00045         spinner.start();
00046 
00047         // producing cartesian goals in term of arm base and tip link
00048         geometry_msgs::PoseArray cartesian_poses;
00049         if(!getTrajectoryInArmSpace(cartesian_traj_,cartesian_poses))
00050         {
00051                 ROS_ERROR_STREAM(ros::this_node::getName()<<": Cartesian Trajectory could not be transformed to arm space");
00052                 return;
00053         }
00054 
00055         while(ros::ok())
00056         {
00057                 if(!moveArm(cartesian_poses))
00058                 {
00059                         ros::Duration(DURATION_LOOP_PAUSE).sleep();
00060                 }
00061         }
00062 }
00063 
00064 /*
00065  * Takes and array of poses where each pose is the desired tip link pose described in terms of the arm base
00066  */
00067 bool MoveArmActionClient::moveArm(const geometry_msgs::PoseArray &cartesian_poses, bool wait_for_completion)
00068 {
00069         using namespace arm_navigation_msgs;
00070 
00071         ROS_INFO_STREAM(ros::this_node::getName()<<": Sending Cartesian Goal with "<<cartesian_poses.poses.size()<<" via points");
00072         bool success = !cartesian_poses.poses.empty();
00073         std::vector<geometry_msgs::Pose>::const_iterator i;
00074         for(i = cartesian_poses.poses.begin(); i != cartesian_poses.poses.end();i++)
00075         {
00076                 // clearing goal
00077                 move_arm_goal_.motion_plan_request.goal_constraints.position_constraints.clear();
00078                 move_arm_goal_.motion_plan_request.goal_constraints.orientation_constraints.clear();
00079                 move_arm_goal_.motion_plan_request.goal_constraints.joint_constraints.clear();
00080                 move_arm_goal_.motion_plan_request.goal_constraints.visibility_constraints.clear();
00081 
00082                 //tf::poseTFToMsg(*i,move_pose_constraint_.pose);
00083                 move_pose_constraint_.pose = *i;
00084                 arm_navigation_msgs::addGoalConstraintToMoveArmGoal(move_pose_constraint_,move_arm_goal_);
00085 
00086                 // sending goal
00087                 move_arm_client_ptr_->sendGoal(move_arm_goal_);
00088 
00089                 if(!wait_for_completion)
00090                 {
00091                         return success;
00092                 }
00093 
00094                 success = move_arm_client_ptr_->waitForResult(ros::Duration(DURATION_WAIT_RESULT));
00095                 if(success)
00096                 {
00097                         success = actionlib::SimpleClientGoalState::SUCCEEDED == move_arm_client_ptr_->getState().state_;
00098                         if(success)
00099                         {
00100                                 ROS_INFO_STREAM(ros::this_node::getName()<<": Goal Achieved");
00101                         }
00102                         else
00103                         {
00104                                 ROS_ERROR_STREAM(ros::this_node::getName()<<": Goal Rejected with error flag: "
00105                                                 <<(unsigned int)move_arm_client_ptr_->getState().state_);
00106                                 break;
00107                         }
00108                 }
00109                 else
00110                 {
00111                         move_arm_client_ptr_->cancelGoal();
00112                         ROS_ERROR_STREAM(ros::this_node::getName()<<": Goal Failed with error flag: "
00113                                         <<(unsigned int)move_arm_client_ptr_->getState().state_);
00114                         break;
00115                 }
00116         }
00117 
00118         return success;
00119 }
00120 
00121 bool MoveArmActionClient::fetchParameters(std::string nameSpace)
00122 {
00123         ros::NodeHandle nh("~");
00124 
00125         bool success =  nh.getParam(PARAM_ARM_GROUP,arm_group_) && cartesian_traj_.fetchParameters();
00126         return success;
00127 }
00128 
00129 void MoveArmActionClient::timerCallback(const ros::TimerEvent &evnt)
00130 {
00131         // updating msg
00132         cartesian_traj_.getMarker(path_msg_);
00133         if(!path_msg_.poses.empty())
00134         {
00135                 path_pub_.publish(path_msg_);
00136         }
00137 }
00138 
00139 bool MoveArmActionClient::getArmStartState(std::string group_name, arm_navigation_msgs::RobotState &robot_state)
00140 {
00141         using namespace arm_navigation_msgs;
00142 
00143         // calling set planning scene service
00144         SetPlanningSceneDiff::Request planning_scene_req;
00145         SetPlanningSceneDiff::Response planning_scene_res;
00146         if(planning_scene_client_.call(planning_scene_req,planning_scene_res))
00147         {
00148                 ROS_INFO_STREAM(ros::this_node::getName()<<": call to set planning scene succeeded");
00149         }
00150         else
00151         {
00152                 ROS_ERROR_STREAM(ros::this_node::getName()<<": call to set planning scene failed");
00153                 return false;
00154         }
00155 
00156         // updating robot kinematic state from planning scene
00157         planning_models::KinematicState *st = collision_models_ptr_->setPlanningScene(planning_scene_res.planning_scene);
00158         if(st == NULL)
00159         {
00160                 ROS_ERROR_STREAM(ros::this_node::getName()<<": Kinematic State for arm could not be retrieved from planning scene");
00161                 return false;
00162         }
00163 
00164         planning_environment::convertKinematicStateToRobotState(*st,
00165                                                                                                                   ros::Time::now(),
00166                                                                                                                   collision_models_ptr_->getWorldFrameId(),
00167                                                                                                                   robot_state);
00168 
00169         collision_models_ptr_->revertPlanningScene(st);
00170         return true;
00171 }
00172 
00173 bool MoveArmActionClient::setup()
00174 {
00175         ros::NodeHandle nh;
00176         bool success = true;
00177 
00178         if(!fetchParameters())
00179         {
00180                 return false;
00181         }
00182 
00183         // setting up action client
00184         move_arm_client_ptr_ = MoveArmClientPtr(new MoveArmClient(DEFAULT_MOVE_ARM_ACTION,true));
00185         unsigned int attempts = 0;
00186         while(attempts++ < MAX_WAIT_ATTEMPTS)
00187         {
00188                 ROS_WARN_STREAM(ros::this_node::getName()<<": waiting for "<<DEFAULT_MOVE_ARM_ACTION<<" server");
00189                 success = move_arm_client_ptr_->waitForServer(ros::Duration(DURATION_WAIT_SERVER));
00190                 if(success)
00191                 {
00192                         ROS_INFO_STREAM(ros::this_node::getName()<<": Found "<<DEFAULT_MOVE_ARM_ACTION<<" server");
00193                         break;
00194                 }
00195         }
00196 
00197         // setting up service clients
00198         planning_scene_client_ = nh.serviceClient<arm_navigation_msgs::SetPlanningSceneDiff>(DEFAULT_PLANNING_SCENE_DIFF_SERVICE);
00199 
00200         // setting up ros publishers
00201         path_pub_ = nh.advertise<nav_msgs::Path>(DEFAULT_PATH_MSG_TOPIC,1);
00202 
00203         // setting up ros timers
00204         publish_timer_ = nh.createTimer(ros::Duration(DURATION_TIMER_CYCLE),&MoveArmActionClient::timerCallback,this);
00205 
00206         // obtaining arm info
00207         collision_models_ptr_ = CollisionModelsPtr(new planning_environment::CollisionModels("robot_description"));
00208         getArmInfo(collision_models_ptr_.get(),arm_group_,base_link_frame_id_,tip_link_frame_id_);
00209 
00210         // initializing move arm request members
00211         move_arm_goal_.motion_plan_request.group_name = arm_group_;
00212         move_arm_goal_.motion_plan_request.num_planning_attempts = DEFAULT_PATH_PLANNING_ATTEMPTS;
00213         move_arm_goal_.planner_service_name = DEFAULT_PATH_PLANNER;
00214         move_arm_goal_.motion_plan_request.planner_id = "";
00215         move_arm_goal_.motion_plan_request.allowed_planning_time = ros::Duration(DEFAULT_PATH_PLANNING_TIME);
00216 
00217         move_pose_constraint_.header.frame_id = base_link_frame_id_;
00218         move_pose_constraint_.link_name = tip_link_frame_id_;
00219         move_pose_constraint_.absolute_position_tolerance.x = DEFAULT_POSITION_TOLERANCE;
00220         move_pose_constraint_.absolute_position_tolerance.y = DEFAULT_POSITION_TOLERANCE;
00221         move_pose_constraint_.absolute_position_tolerance.z = DEFAULT_POSITION_TOLERANCE;
00222         move_pose_constraint_.absolute_roll_tolerance = DEFAULT_ORIENTATION_TOLERANCE;
00223         move_pose_constraint_.absolute_pitch_tolerance = DEFAULT_ORIENTATION_TOLERANCE;
00224         move_pose_constraint_.absolute_yaw_tolerance = DEFAULT_ORIENTATION_TOLERANCE;
00225 
00226         return success;
00227 }
00228 
00229 bool MoveArmActionClient::getArmInfo(const planning_environment::CollisionModels *models,
00230                 const std::string &arm_group,std::string &base_link, std::string &tip_link)
00231 {
00232         ros::NodeHandle nh;
00233         XmlRpc::XmlRpcValue group_param;
00234         std::stringstream ss;
00235         bool success = false;
00236 
00237         // finding arm base and tip links from group member in ros parameters
00238         if(nh.getParam(DEFAULT_PLANNING_GROUPS_PARAMETER,group_param))
00239         {
00240                 for(int i = 0; i < group_param.size(); i++)
00241                 {
00242                         XmlRpc::XmlRpcValue &element = group_param[i];
00243                         if((element.getType() == XmlRpc::XmlRpcValue::TypeStruct) &&
00244                                         element.hasMember(PARAM_GROUP_KEY) &&
00245                                         (arm_group.compare(static_cast<std::string>(element[PARAM_GROUP_KEY])) == 0) &&
00246                                         element.hasMember(PARAM_BASE_KEY) &&
00247                                         element.hasMember(PARAM_TIP_KEY))
00248                         {
00249                                 base_link = static_cast<std::string>(element[PARAM_BASE_KEY]);
00250                                 tip_link = static_cast<std::string>(element[PARAM_TIP_KEY]);
00251                                 success = true;
00252                                 break;
00253                         }
00254                 }
00255         }
00256         else
00257         {
00258                 ROS_ERROR_STREAM("Did not find parameter '"<<DEFAULT_PLANNING_GROUPS_PARAMETER<<"', could not get arm information");
00259                 return false;
00260         }
00261 
00262         // obtaining arm joint info
00263         const planning_models::KinematicModel::JointModelGroup *joint_model_group =
00264                                         models->getKinematicModel()->getModelGroup(arm_group);
00265 
00266         // printing arm details
00267         const std::vector<std::string> &joint_names = joint_model_group->getJointModelNames();
00268         const std::vector<std::string> &link_names = joint_model_group->getGroupLinkNames();
00269         std::vector<std::string>::const_iterator i;
00270         ss<<"\nArm Base Link Frame: "<<base_link;
00271         ss<<"\nArm Tip Link Frame: "<<tip_link;
00272         ss<<"\nJoint Names in group '"<<arm_group<<"'";
00273         for(i = joint_names.begin(); i != joint_names.end() ; i++)
00274         {
00275                 ss<<"\n\t"<<*i;
00276         }
00277 
00278         ss<<"\nLink Names in group '"<<arm_group<<"'";
00279         for(i = link_names.begin(); i != link_names.end() ; i++)
00280         {
00281                 ss<<"\n\t"<<*i;
00282         }
00283         ROS_INFO_STREAM(ros::this_node::getName()<<ss.str());
00284 
00285         return success;
00286 }
00287 
00288 bool MoveArmActionClient::getPoseInArmSpace(
00289                 const CartesianGoal &cartesian_goal,geometry_msgs::Pose &base_to_tip_pose)
00290 {
00291         // declaring transforms
00292         static tf::StampedTransform base_to_parent_tf;
00293         static tf::StampedTransform tcp_to_tip_link_tf;
00294         tf::Transform base_to_tip_tf; // desired pose of tip link in base coordinates
00295 
00296         const std::string &parent_frame = boost::tuples::get<0>(cartesian_goal);
00297         const std::string &tcp_frame = boost::tuples::get<1>(cartesian_goal);
00298         const tf::Transform &parent_to_tcp_tf = boost::tuples::get<2>(cartesian_goal);
00299 
00300         // finding transforms
00301         try
00302         {
00303                 tf_listener_.lookupTransform(base_link_frame_id_,parent_frame,ros::Time(0),base_to_parent_tf);
00304                 tf_listener_.lookupTransform(tcp_frame,tip_link_frame_id_,ros::Time(0),tcp_to_tip_link_tf);
00305         }
00306         catch(tf::LookupException &e)
00307         {
00308                 ROS_ERROR_STREAM(ros::this_node::getName()<<": Unable to lookup transforms");
00309                 return false;
00310         }
00311 
00312         base_to_tip_tf = ((tf::Transform)base_to_parent_tf) * parent_to_tcp_tf * ((tf::Transform)tcp_to_tip_link_tf);
00313         tf::poseTFToMsg(base_to_tip_tf,base_to_tip_pose);
00314 
00315         return true;
00316 }
00317 
00318 bool MoveArmActionClient::getTrajectoryInArmSpace(
00319                 const CartesianTrajectory &cartesian_traj,geometry_msgs::PoseArray &base_to_tip_poses)
00320 {
00321         // declaring transforms
00322         static tf::StampedTransform base_to_parent_tf;
00323         static tf::StampedTransform tcp_to_tip_link_tf;
00324         tf::Transform base_to_tip_tf; // desired pose of tip link in base coordinates
00325         geometry_msgs::Pose base_to_tip_pose;
00326 
00327         // finding transforms
00328         try
00329         {
00330                 tf_listener_.lookupTransform(base_link_frame_id_,cartesian_traj.frame_id_,ros::Time(0),base_to_parent_tf);
00331                 tf_listener_.lookupTransform(cartesian_traj.link_name_,tip_link_frame_id_,ros::Time(0),tcp_to_tip_link_tf);
00332         }
00333         catch(tf::LookupException &e)
00334         {
00335                 ROS_ERROR_STREAM(ros::this_node::getName()<<": Unable to lookup transforms");
00336                 return false;
00337         }
00338 
00339         std::vector<tf::Transform>::const_iterator i;
00340         const std::vector<tf::Transform> &goal_array = cartesian_traj.cartesian_points_;
00341         for(i = goal_array.begin(); i != goal_array.end(); i++)
00342         {
00343                 base_to_tip_tf = (static_cast<tf::Transform>(base_to_parent_tf)) * (*i) * (static_cast<tf::Transform>(tcp_to_tip_link_tf));
00344                 tf::poseTFToMsg(base_to_tip_tf,base_to_tip_pose);
00345                 base_to_tip_poses.poses.push_back(base_to_tip_pose);
00346         }
00347 
00348         return true;
00349 }
00350 
00351 
00352 


mtconnect_cnc_robot_example
Author(s): Jnicho
autogenerated on Mon Jan 6 2014 11:31:45