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 #include <ros/ros.h>
00040 #include <tf/tf.h>
00041 #include <tf/transform_listener.h>
00042 #include <actionlib/server/simple_action_server.h>
00043 #include <actionlib/client/simple_action_client.h>
00044 #include <arm_navigation_msgs/MoveArmAction.h>
00045 #include <arm_navigation_msgs/utils.h>
00046 #include <simple_arm_server/MoveArmAction.h>
00047 #include <std_msgs/Float64.h>
00048 #include <math.h>
00049
00050 class SimpleArmNavigationServer
00051 {
00052 private:
00053 ros::NodeHandle nh;
00054 tf::TransformListener listener;
00055
00056
00057 actionlib::SimpleActionServer<simple_arm_server::MoveArmAction> server;
00058 actionlib::SimpleActionClient<arm_navigation_msgs::MoveArmAction> client;
00059 ros::Publisher gripper;
00060
00061 simple_arm_server::MoveArmFeedback feedback_;
00062 simple_arm_server::MoveArmResult result_;
00063 simple_arm_server::MoveArmGoalConstPtr goal_;
00064
00065
00066 int arm_dof_;
00067 std::string root_name_;
00068 std::string tip_name_;
00069 std::string pan_link_;
00070 double timeout_;
00071 double x_offset_;
00072 int max_tries_;
00073 std::vector<double> step_list_;
00074
00075 public:
00076
00077 SimpleArmNavigationServer() : nh("~"), listener(nh), server(ros::NodeHandle(), "simple_move_arm", false), client("move_arm", true)
00078 {
00079 ROS_INFO("Starting simple_move_arm_server.");
00080
00081 nh.param<int>("arm_dof", arm_dof_, 5);
00082 nh.param<std::string>("root_name", root_name_, "arm_link");
00083 nh.param<std::string>("tip_name", tip_name_, "gripper_link");
00084 nh.param<double>("timeout", timeout_, 5.0);
00085 nh.param<int>("iterations", max_tries_, 30);
00086 if(nh.hasParam("step_list")){
00087 XmlRpc::XmlRpcValue step_params;
00088 nh.getParam("step_list", step_params);
00089 for(int i=0; i<step_params.size(); ++i)
00090 {
00091 step_list_.push_back( static_cast<double>(step_params[i]) );
00092 }
00093 }else{
00094 step_list_.push_back(-0.05);
00095 step_list_.push_back( 0.05);
00096 }
00097
00098
00099 nh.param<std::string>("pan_link", pan_link_, "arm_link");
00100 if( !listener.waitForTransform(root_name_, pan_link_, ros::Time(0), ros::Duration(10.0)) ){
00101 ROS_ERROR("Cannot lookup transfrom from %s to %s", pan_link_.c_str(), root_name_.c_str());
00102 }
00103 tf::StampedTransform transform;
00104 try{
00105 listener.lookupTransform(root_name_, pan_link_, ros::Time(0), transform);
00106 }catch(tf::TransformException ex){
00107 ROS_ERROR("%s",ex.what());
00108 }
00109 x_offset_ = transform.getOrigin().x();
00110 ROS_INFO("X offset %f", x_offset_);
00111
00112
00113 client.waitForServer();
00114 gripper = nh.advertise<std_msgs::Float64>("/gripper_controller/command", 1, false);
00115 ROS_INFO("Connected to move_arm server");
00116
00117
00118 server.registerGoalCallback(boost::bind(&SimpleArmNavigationServer::goalCB, this));
00119 server.registerPreemptCallback(boost::bind(&SimpleArmNavigationServer::preemptCB, this));
00120 server.start();
00121
00122 ROS_INFO("simple_move_arm_server node started");
00123 }
00124
00125 void goalCB()
00126 {
00127
00128 goal_ = server.acceptNewGoal();
00129
00130 for(size_t i = 0; i < goal_->motions.size(); i++){
00131 simple_arm_server::ArmAction action = goal_->motions[i];
00132
00133 if( action.type == simple_arm_server::ArmAction::MOVE_ARM )
00134 {
00135
00136 geometry_msgs::PoseStamped in, pose;
00137 in.header = goal_->header;
00138 in.pose = action.goal;
00139 try{
00140 listener.transformPose(root_name_, in, pose);
00141 }catch(tf::TransformException ex){
00142 ROS_ERROR("%s",ex.what());
00143 }
00144
00145 double roll, pitch, yaw;
00146 btQuaternion q(pose.pose.orientation.x, pose.pose.orientation.y, pose.pose.orientation.z, pose.pose.orientation.w);
00147 btMatrix3x3(q).getRPY(roll, pitch, yaw);
00148 if( arm_dof_ < 6 ){
00149
00150 yaw = atan2(pose.pose.position.y, pose.pose.position.x-x_offset_);
00151 if( arm_dof_ < 5 ){
00152
00153 roll = 0.0;
00154 }
00155 }
00156
00157
00158 int tries;
00159 bool goal_reached = false;
00160 for( tries = 0; tries <= max_tries_; tries++ ){
00161 for(size_t i=0; i<step_list_.size(); i++){
00162
00163 arm_navigation_msgs::MoveArmGoal goal;
00164
00165 goal.motion_plan_request.group_name = "arm";
00166 goal.motion_plan_request.num_planning_attempts = 1;
00167 goal.motion_plan_request.planner_id = std::string("");
00168 goal.planner_service_name = std::string("ompl_planning/plan_kinematic_path");
00169 goal.motion_plan_request.allowed_planning_time = ros::Duration(timeout_);
00170
00171 arm_navigation_msgs::SimplePoseConstraint desired_pose;
00172 desired_pose.absolute_position_tolerance.x = 0.005;
00173 desired_pose.absolute_position_tolerance.y = 0.005;
00174 desired_pose.absolute_position_tolerance.z = 0.005;
00175 desired_pose.absolute_roll_tolerance = 0.25;
00176 desired_pose.absolute_pitch_tolerance = 0.05;
00177 desired_pose.absolute_yaw_tolerance = 0.5;
00178
00179 desired_pose.header.frame_id = pose.header.frame_id;
00180 desired_pose.link_name = tip_name_;
00181
00182 desired_pose.pose.position.x = pose.pose.position.x;
00183 desired_pose.pose.position.y = pose.pose.position.y;
00184 desired_pose.pose.position.z = pose.pose.position.z;
00185
00186 double attempt = pitch + (tries * step_list_[i]);
00187 q.setRPY(roll, attempt, yaw);
00188
00189 desired_pose.pose.orientation.x = (double) q.getX();
00190 desired_pose.pose.orientation.y = (double) q.getY();
00191 desired_pose.pose.orientation.z = (double) q.getZ();
00192 desired_pose.pose.orientation.w = (double) q.getW();
00193 ROS_INFO("%d: (%f, %f, %f)", tries, roll, attempt, yaw);
00194
00195 arm_navigation_msgs::addGoalConstraintToMoveArmGoal(desired_pose, goal);
00196
00197
00198 client.sendGoal(goal);
00199 bool finished_within_time = client.waitForResult(ros::Duration(300.0));
00200 if( !finished_within_time )
00201 {
00202 client.cancelGoal();
00203 ROS_INFO("Continue: goal timed out");
00204 }
00205 else
00206 {
00207 actionlib::SimpleClientGoalState state = client.getState();
00208 arm_navigation_msgs::MoveArmResultConstPtr result = client.getResult();
00209
00210 if(result->error_code.val == arm_navigation_msgs::ArmNavigationErrorCodes::SUCCESS ){
00211 ROS_INFO("Continue: goal succeeded.");
00212 goal_reached = true;
00213 }else if( result->error_code.val == int(arm_navigation_msgs::ArmNavigationErrorCodes::START_STATE_IN_COLLISION) ){
00214 ROS_INFO("Abort: start state in collision.");
00215 result_.success = false;
00216 server.setAborted(result_);
00217 return;
00218 }else if( (result->error_code.val == arm_navigation_msgs::ArmNavigationErrorCodes::GOAL_CONSTRAINTS_VIOLATED) ||
00219 (result->error_code.val == arm_navigation_msgs::ArmNavigationErrorCodes::PATH_CONSTRAINTS_VIOLATED) ) {
00220 ROS_INFO("Continue: goal constraints violated.");
00221 goal_reached = true;
00222 }else{
00223 ROS_INFO("Continue: path failed, trying again");
00224 }
00225 }
00226 if(tries==0) break;
00227 if(goal_reached) break;
00228 }
00229 if(goal_reached) break;
00230 }
00231 if( tries > max_tries_ ){
00232 result_.success = false;
00233 server.setAborted(result_);
00234 return;
00235 }
00236 }
00237 else if( action.type == simple_arm_server::ArmAction::MOVE_GRIPPER )
00238 {
00239 ROS_INFO("Move gripper to %f.", action.command);
00240 std_msgs::Float64 msg;
00241 msg.data = action.command;
00242 gripper.publish( msg );
00243 ros::Duration(action.move_time).sleep();
00244 }
00245 }
00246
00247 result_.success = true;
00248 server.setSucceeded(result_);
00249 }
00250
00251 void preemptCB()
00252 {
00253 ROS_INFO("simple_move_arm preempted");
00254 server.setPreempted();
00255 }
00256
00257 };
00258
00259 int main(int argc, char **argv)
00260 {
00261 ros::init (argc, argv, "simple_move_arm_server");
00262
00263 SimpleArmNavigationServer server;
00264 ros::spin();
00265
00266 return 0;
00267 }
00268