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
00031 #include <sbpl_arm_planner_node/sbpl_arm_planner_node.h>
00032 #include <algorithm>
00033 #include <math.h>
00034
00035 clock_t starttime;
00036
00037 using namespace std;
00038 using namespace sbpl_arm_planner;
00039
00041 SBPLArmPlannerNode::SBPLArmPlannerNode() : node_handle_("~"),collision_map_subscriber_(root_handle_,"collision_map_occ",1), collision_map_filter_(NULL),jnt_to_pose_solver_(NULL),grid_(NULL),aviz_(NULL)
00042 {
00043 planner_initialized_ = false;
00044 attached_object_ = false;
00045 forward_search_ = true;
00046 planning_joint_ = "r_wrist_roll_link";
00047 attached_object_frame_ = "r_gripper_r_finger_tip_link";
00048 allocated_time_ = 10.0;
00049 env_resolution_ = 0.02;
00050 }
00051
00052 SBPLArmPlannerNode::~SBPLArmPlannerNode()
00053 {
00054 if(aviz_ != NULL)
00055 delete aviz_;
00056 if(collision_map_filter_ != NULL)
00057 delete collision_map_filter_;
00058 if(jnt_to_pose_solver_ != NULL)
00059 delete jnt_to_pose_solver_;
00060 if(planner_ != NULL)
00061 delete planner_;
00062 }
00063
00064 bool SBPLArmPlannerNode::init()
00065 {
00066
00067 node_handle_.param ("planner/search_mode", search_mode_, true);
00068 node_handle_.param ("planner/use_research_heuristic", use_research_heuristic_, false);
00069 node_handle_.param<std::string>("planner/arm_description_file", arm_description_filename_, "");
00070 node_handle_.param<std::string>("planner/motion_primitive_file", mprims_filename_, "");
00071 node_handle_.param ("debug/print_out_path", print_path_, true);
00072 node_handle_.param ("seconds_per_waypoint", waypoint_time_, 0.35);
00073 node_handle_.param<std::string>("reference_frame", reference_frame_, std::string("base_link"));
00074 node_handle_.param<std::string>("fk_service_name", fk_service_name_, "pr2_right_arm_kinematics/get_fk");
00075 node_handle_.param<std::string>("ik_service_name", ik_service_name_, "pr2_right_arm_kinematics/get_ik");
00076
00077
00078 node_handle_.param<std::string>("robot/arm_name", arm_name_, "right_arm");
00079 std::string robot_urdf_param;
00080 if(!node_handle_.searchParam("robot_description",robot_urdf_param))
00081 {
00082 ROS_ERROR("Unable to find robot description on param server (/robot_description is not set). Exiting");
00083 return false;
00084 }
00085 node_handle_.param<std::string>(robot_urdf_param, robot_description_, "robot_description");
00086 node_handle_.param ("robot/num_joints", num_joints_, 7);
00087
00088 joint_names_.resize(num_joints_);
00089 if(arm_name_ == "left_arm")
00090 {
00091 side_ = "l";
00092 planning_joint_ = "l_wrist_roll_link";
00093 attached_object_frame_ = "l_gripper_r_finger_tip_link";
00094 }
00095 else
00096 {
00097 side_ = "r";
00098 planning_joint_ = "r_wrist_roll_link";
00099 attached_object_frame_ = "r_gripper_r_finger_tip_link";
00100 }
00101
00102
00103 joint_names_[0] = side_ + "_shoulder_pan_joint";
00104 joint_names_[1] = side_ + "_shoulder_lift_joint";
00105 joint_names_[2] = side_ + "_upper_arm_roll_joint";
00106 joint_names_[3] = side_ + "_elbow_flex_joint";
00107 joint_names_[4] = side_ + "_forearm_roll_joint";
00108 joint_names_[5] = side_ + "_wrist_flex_joint";
00109 joint_names_[6] = side_ + "_wrist_roll_joint";
00110
00111
00112 node_handle_.param<std::string>("collision_space/collision_map_topic", collision_map_topic_, "collision_map_occ");
00113
00114
00115 node_handle_.param ("visualizations/goal", visualize_goal_, true);
00116 node_handle_.param ("visualizations/expanded_states",visualize_expanded_states_,true);
00117 node_handle_.param ("visualizations/heuristic", visualize_heuristic_, true);
00118 node_handle_.param ("visualizations/voxel_size", env_resolution_, 0.02);
00119 node_handle_.param ("visualizations/trajectory", visualize_trajectory_, false);
00120 node_handle_.param ("visualizations/collision_model_trajectory", visualize_collision_model_trajectory_, false);
00121 node_handle_.param ("visualizations/trajectory_throttle", throttle_, 4);
00122
00123 map_frame_ = "base_link";
00124
00125
00126 if(!initializePlannerAndEnvironment())
00127 return false;
00128
00129 collision_map_filter_ = new tf::MessageFilter<mapping_msgs::CollisionMap>(collision_map_subscriber_,tf_,reference_frame_,1);
00130 collision_map_filter_->registerCallback(boost::bind(&SBPLArmPlannerNode::collisionMapCallback, this, _1));
00131
00132 collision_object_subscriber_ = root_handle_.subscribe("collision_object", 3, &SBPLArmPlannerNode::collisionObjectCallback, this);
00133 object_subscriber_ = root_handle_.subscribe("attached_collision_object", 3, &SBPLArmPlannerNode::attachedObjectCallback,this);
00134
00135
00136 planning_service_ = root_handle_.advertiseService("/sbpl_planning/plan_path", &SBPLArmPlannerNode::planKinematicPath,this);
00137
00138 planner_initialized_ = true;
00139
00140 ROS_INFO("The SBPL arm planner node initialized succesfully.");
00141 return true;
00142 }
00143
00144 int SBPLArmPlannerNode::run()
00145 {
00146 ros::spin();
00147 return 0;
00148 }
00149
00150 bool SBPLArmPlannerNode::initializePlannerAndEnvironment()
00151 {
00152 planner_ = new ARAPlanner(&sbpl_arm_env_, forward_search_);
00153
00154 if(robot_description_.empty())
00155 {
00156 ROS_ERROR("Robot description file is empty. Exiting.");
00157 return false;
00158 }
00159
00160
00161 if(!sbpl_arm_env_.initEnvironment(arm_description_filename_,mprims_filename_))
00162 {
00163 ROS_ERROR("ERROR: initEnvironment failed");
00164 return false;
00165 }
00166
00167
00168 if(!sbpl_arm_env_.InitializeMDPCfg(&mdp_cfg_))
00169 {
00170 ROS_ERROR("ERROR: InitializeMDPCfg failed");
00171 return false;
00172 }
00173
00174 cspace_ = sbpl_arm_env_.getCollisionSpace();
00175
00176
00177 cspace_->addArmCuboidsToGrid();
00178
00179 grid_ = sbpl_arm_env_.getOccupancyGrid();
00180
00181
00182 planner_->set_initialsolution_eps(sbpl_arm_env_.getEpsilon());
00183
00184
00185 search_mode_ = false;
00186 planner_->set_search_mode(search_mode_);
00187
00188 if(!initChain(robot_description_))
00189 {
00190 ROS_ERROR("Unable to initialize KDL chain.");
00191 return false;
00192 }
00193
00194 aviz_ = new VisualizeArm(arm_name_);
00195 aviz_->setReferenceFrame(reference_frame_);
00196
00197 ROS_INFO("Initialized sbpl planning environment.");
00198 return true;
00199 }
00200
00202 void SBPLArmPlannerNode::collisionMapCallback(const mapping_msgs::CollisionMapConstPtr &collision_map)
00203 {
00204 updateMapFromCollisionMap(collision_map);
00205 }
00206
00207 void SBPLArmPlannerNode::updateMapFromCollisionMap(const mapping_msgs::CollisionMapConstPtr &collision_map)
00208 {
00209 ROS_DEBUG("[updateMapFromCollisionMap] trying to get colmap_mutex_");
00210 if(colmap_mutex_.try_lock())
00211 {
00212 ROS_DEBUG("[updateMapFromCollisionMap] locked colmap_mutex_");
00213
00214 if(collision_map->header.frame_id.compare(reference_frame_) != 0)
00215 {
00216 ROS_WARN("collision_map_occ is in %s not in %s", collision_map->header.frame_id.c_str(), reference_frame_.c_str());
00217 ROS_DEBUG("the collision map has %i cubic obstacles", int(collision_map->boxes.size()));
00218 }
00219
00220
00221 grid_->updateFromCollisionMap(*collision_map);
00222
00223
00224 cspace_->addArmCuboidsToGrid();
00225
00226 cspace_->putCollisionObjectsInGrid();
00227
00228 map_frame_ = collision_map->header.frame_id;
00229 setArmToMapTransform(map_frame_);
00230
00231 colmap_mutex_.unlock();
00232 ROS_DEBUG("[updateMapFromCollisionMap] released colmap_mutex_ mutex.");
00233
00234 visualizeCollisionObjects();
00235
00236 grid_->visualize();
00237 return;
00238 }
00239 else
00240 {
00241 ROS_DEBUG("[updateMapFromCollisionMap] failed trying to get colmap_mutex_ mutex");
00242 return;
00243 }
00244 }
00245
00246 void SBPLArmPlannerNode::attachedObjectCallback(const mapping_msgs::AttachedCollisionObjectConstPtr &attached_object)
00247 {
00248 if(object_mutex_.try_lock())
00249 {
00250
00251 if(attached_object->link_name.compare(mapping_msgs::AttachedCollisionObject::REMOVE_ALL_ATTACHED_OBJECTS) == 0 &&
00252 attached_object->object.operation.operation == mapping_msgs::CollisionObjectOperation::REMOVE)
00253 {
00254 ROS_DEBUG("[attachedObjectCallback] Removing all attached objects.");
00255 attached_object_ = false;
00256 cspace_->removeAttachedObject();
00257 }
00258
00259 else if(attached_object->object.operation.operation == mapping_msgs::CollisionObjectOperation::ADD)
00260 {
00261 ROS_DEBUG("[attachedObjectCallback] Received a message to ADD an object (%s) with %d shapes.", attached_object->object.id.c_str(), int(attached_object->object.shapes.size()));
00262 attachObject(attached_object->object);
00263 }
00264
00265 else if( attached_object->object.operation.operation == mapping_msgs::CollisionObjectOperation::ATTACH_AND_REMOVE_AS_OBJECT)
00266 {
00267 ROS_DEBUG("[attachedObjectCallback] Received a message to ATTACH_AND_REMOVE_AS_OBJECT of object: %s", attached_object->object.id.c_str());
00268
00269
00270 if(object_map_.find(attached_object->object.id) != object_map_.end())
00271 {
00272 ROS_DEBUG("[attachedObjectCallback] We have seen this object (%s) before.", attached_object->object.id.c_str());
00273 attachObject(object_map_.find(attached_object->object.id)->second);
00274 }
00275 else
00276 {
00277 ROS_DEBUG("[attachedObjectCallback] We have NOT seen this object (%s) before.", attached_object->object.id.c_str());
00278 object_map_[attached_object->object.id] = attached_object->object;
00279 attachObject(attached_object->object);
00280 }
00281 cspace_->removeCollisionObject(attached_object->object);
00282 }
00283
00284 else if(attached_object->object.operation.operation == mapping_msgs::CollisionObjectOperation::REMOVE)
00285 {
00286 attached_object_ = false;
00287 ROS_DEBUG("[attachedObjectCallback] Removing object (%s) from gripper.", attached_object->object.id.c_str());
00288 cspace_->removeAttachedObject();
00289 }
00290 else if(attached_object->object.operation.operation == mapping_msgs::CollisionObjectOperation::DETACH_AND_ADD_AS_OBJECT)
00291 {
00292 attached_object_ = false;
00293 ROS_DEBUG("[attachedObjectCallback] Removing object (%s) from gripper and adding to collision map.", attached_object->object.id.c_str());
00294 cspace_->removeAttachedObject();
00295 cspace_->addCollisionObject(attached_object->object);
00296 }
00297 else
00298 ROS_WARN("Received a collision object with an unknown operation");
00299
00300 object_mutex_.unlock();
00301 }
00302 visualizeCollisionObjects();
00303 }
00304
00305 void SBPLArmPlannerNode::collisionObjectCallback(const mapping_msgs::CollisionObjectConstPtr &collision_object)
00306 {
00307
00308 if(collision_object->id.compare("all") == 0)
00309 cspace_->removeAllCollisionObjects();
00310
00311 if(object_mutex_.try_lock())
00312 {
00313
00314 if(object_map_.find(collision_object->id) != object_map_.end())
00315 ROS_DEBUG("[collisionObjectCallback] We have seen this object ('%s') before.", collision_object->id.c_str());
00316 else
00317 ROS_DEBUG("[collisionObjectCallback] We have NOT seen this object ('%s') before.", collision_object->id.c_str());
00318 object_map_[collision_object->id] = (*collision_object);
00319 object_mutex_.unlock();
00320 }
00321
00322 ROS_DEBUG("[collisionObjectCallback] %s", collision_object->id.c_str());
00323 cspace_->processCollisionObjectMsg((*collision_object));
00324
00325 visualizeCollisionObjects();
00326 }
00327
00328 void SBPLArmPlannerNode::attachObject(const mapping_msgs::CollisionObject &obj)
00329 {
00330 geometry_msgs::PoseStamped pose_in, pose_out;
00331 mapping_msgs::CollisionObject object(obj);
00332
00333 attached_object_ = true;
00334
00335 ROS_INFO("Received a collision object message with %d shapes.", int(object.shapes.size()));
00336
00337 for(size_t i = 0; i < object.shapes.size(); i++)
00338 {
00339 pose_in.header = object.header;
00340 pose_in.header.stamp = ros::Time();
00341 pose_in.pose = object.poses[i];
00342 tf_.transformPose(attached_object_frame_, pose_in, pose_out);
00343 object.poses[i] = pose_out.pose;
00344 ROS_DEBUG("[attachObject] Converted shape from %s (%0.2f %0.2f %0.2f) to %s (%0.3f %0.3f %0.3f)", pose_in.header.frame_id.c_str(), pose_in.pose.position.x, pose_in.pose.position.y, pose_in.pose.position.z, attached_object_frame_.c_str(), pose_out.pose.position.x, pose_out.pose.position.y, pose_out.pose.position.z);
00345
00346 if(object.shapes[i].type == geometric_shapes_msgs::Shape::SPHERE)
00347 {
00348 ROS_INFO("Attaching a sphere with radius: %0.3fm", object.shapes[i].dimensions[0]);
00349 cspace_->attachSphereToGripper(object.header.frame_id, object.poses[i], object.shapes[i].dimensions[0]);
00350 }
00351 else if(object.shapes[i].type == geometric_shapes_msgs::Shape::CYLINDER)
00352 {
00353 ROS_INFO("Attaching a cylinder with radius: %0.3fm & length %0.3fm", object.shapes[i].dimensions[0], object.shapes[i].dimensions[1]);
00354
00355 cspace_->attachCylinderToGripper(object.header.frame_id, object.poses[i], object.shapes[i].dimensions[0], object.shapes[i].dimensions[1]);
00356 }
00357 else if(object.shapes[i].type == geometric_shapes_msgs::Shape::MESH)
00358 {
00359 ROS_INFO("Attaching a mesh with %d triangles & %d vertices.", int(object.shapes[i].triangles.size()/3), int(object.shapes[i].vertices.size()));
00360
00361 cspace_->attachMeshToGripper(object.header.frame_id, object.poses[i], object.shapes[i].triangles, object.shapes[i].vertices);
00362 }
00363 else if(object.shapes[i].type == geometric_shapes_msgs::Shape::BOX)
00364 {
00365 std::vector<double> dims(object.shapes[i].dimensions);
00366 sort(dims.begin(),dims.end());
00367 ROS_INFO("Attaching a box as a cylinder with length: %0.3fm radius: %0.3fm", dims[2], dims[1]);
00368 cspace_->attachCylinderToGripper(object.header.frame_id, object.poses[i], dims[1], dims[2]);
00369 }
00370 else
00371 ROS_WARN("Currently attaching objects of type '%d' aren't supported.", object.shapes[i].type);
00372 }
00373 }
00374
00376 bool SBPLArmPlannerNode::setStart(const sensor_msgs::JointState &start_state)
00377 {
00378 std::vector<double> sbpl_start(start_state.position.size(),0);
00379
00380 for(unsigned int i=0; i< start_state.position.size(); i++)
00381 sbpl_start[i] = (double)(start_state.position[i]);
00382
00383 std::vector<std::vector<double> > xyz;
00384
00385 ROS_INFO("start: %1.3f %1.3f %1.3f %1.3f %1.3f %1.3f %1.3f", sbpl_start[0],sbpl_start[1],sbpl_start[2],sbpl_start[3],sbpl_start[4],sbpl_start[5],sbpl_start[6]);
00386
00387 if(sbpl_arm_env_.setStartConfiguration(sbpl_start) == 0)
00388 {
00389 ROS_ERROR("Environment failed to set start state. Not Planning.\n");
00390 return false;
00391 }
00392
00393 if(planner_->set_start(mdp_cfg_.startstateid) == 0)
00394 {
00395 ROS_ERROR("Failed to set start state. Not Planning.");
00396 return false;
00397 }
00398
00399 if(attached_object_)
00400 visualizeAttachedObject(sbpl_start);
00401
00402 return true;
00403 }
00404
00405 bool SBPLArmPlannerNode::setGoalPosition(const motion_planning_msgs::Constraints &goals)
00406 {
00407 double roll,pitch,yaw;
00408 geometry_msgs::Pose pose_msg;
00409 tf::Pose tf_pose;
00410 std::vector <std::vector <double> > sbpl_goal(1, std::vector<double> (11,0));
00411 std::vector <std::vector <double> > sbpl_tolerance(1, std::vector<double> (12,0));
00412
00413 if(goals.position_constraints.size() != goals.orientation_constraints.size())
00414 ROS_WARN("There are %d position contraints and %d orientation constraints.", int(goals.position_constraints.size()),int(goals.orientation_constraints.size()));
00415
00416
00417 sbpl_goal[0][0] = goals.position_constraints[0].position.x;
00418 sbpl_goal[0][1] = goals.position_constraints[0].position.y;
00419 sbpl_goal[0][2] = goals.position_constraints[0].position.z;
00420
00421
00422 pose_msg.position = goals.position_constraints[0].position;
00423 pose_msg.orientation = goals.orientation_constraints[0].orientation;
00424
00425
00426
00427 pose_msg.orientation.w += 0.005;
00428
00429 tf::poseMsgToTF(pose_msg, tf_pose);
00430 tf_pose.getBasis().getRPY(roll,pitch,yaw);
00431 sbpl_goal[0][3] = roll;
00432 sbpl_goal[0][4] = pitch;
00433 sbpl_goal[0][5] = yaw;
00434
00435
00436 sbpl_goal[0][6] = true;
00437
00438
00439 sbpl_goal[0][7] = goals.orientation_constraints[0].orientation.x;
00440 sbpl_goal[0][8] = goals.orientation_constraints[0].orientation.y;
00441 sbpl_goal[0][9] = goals.orientation_constraints[0].orientation.z;
00442 sbpl_goal[0][10] = goals.orientation_constraints[0].orientation.w;
00443
00444
00445 sbpl_tolerance[0][0] = goals.position_constraints[0].constraint_region_shape.dimensions[0] / 2.0;
00446 sbpl_tolerance[0][1] = goals.position_constraints[0].constraint_region_shape.dimensions[0] / 2.0;
00447 sbpl_tolerance[0][2] = goals.position_constraints[0].constraint_region_shape.dimensions[0] / 2.0;
00448 sbpl_tolerance[0][3] = goals.orientation_constraints[0].absolute_roll_tolerance;
00449 sbpl_tolerance[0][4] = goals.orientation_constraints[0].absolute_pitch_tolerance;
00450 sbpl_tolerance[0][5] = goals.orientation_constraints[0].absolute_yaw_tolerance;
00451
00452 ROS_INFO("goal quat from move_arm: %0.3f %0.3f %0.3f %0.3f", goals.orientation_constraints[0].orientation.x, goals.orientation_constraints[0].orientation.y, goals.orientation_constraints[0].orientation.z, goals.orientation_constraints[0].orientation.w);
00453
00454 ROS_INFO("goal xyz(%s): %.3f %.3f %.3f (tol: %.3fm) rpy: %.3f %.3f %.3f (tol: %.3frad)", map_frame_.c_str(),sbpl_goal[0][0],sbpl_goal[0][1],sbpl_goal[0][2],sbpl_tolerance[0][0],sbpl_goal[0][3],sbpl_goal[0][4],sbpl_goal[0][5], sbpl_tolerance[0][1]);
00455
00456
00457 if(!sbpl_arm_env_.setGoalPosition(sbpl_goal, sbpl_tolerance))
00458 {
00459 ROS_ERROR("Failed to set goal state. Perhaps goal position is out of reach. Exiting.");
00460 return false;
00461 }
00462
00463
00464 if(planner_->set_goal(mdp_cfg_.goalstateid) == 0)
00465 {
00466 ROS_ERROR("Failed to set goal state. Exiting.");
00467 return false;
00468 }
00469
00470 tf::Quaternion q;
00471 q.setRPY(roll,pitch,yaw);
00472
00473 ROS_DEBUG("Quat from MoveArm: %0.3f %0.3f %0.3f %0.3f", goals.orientation_constraints[0].orientation.x, goals.orientation_constraints[0].orientation.y, goals.orientation_constraints[0].orientation.z, goals.orientation_constraints[0].orientation.w);
00474 ROS_DEBUG(" RPY with TF: %0.3f %0.3f %0.3f", roll,pitch,yaw);
00475 ROS_DEBUG(" Quat with TF: %0.3f %0.3f %0.3f %0.3f", q.x(), q.y(), q.z(), q.w());
00476
00477 return true;
00478 }
00479
00480 bool SBPLArmPlannerNode::planToPosition(motion_planning_msgs::GetMotionPlan::Request &req, motion_planning_msgs::GetMotionPlan::Response &res)
00481 {
00482 unsigned int i;
00483 int nind = 0;
00484 std::vector<trajectory_msgs::JointTrajectoryPoint> arm_path;
00485 sensor_msgs::JointState start;
00486
00487 starttime = clock();
00488
00489
00490 if(req.motion_plan_request.start_state.joint_state.position.size() <= 0)
00491 {
00492 ROS_ERROR("No start state given. Unable to plan.");
00493 return false;
00494 }
00495
00496
00497 if(req.motion_plan_request.goal_constraints.position_constraints.size() <= 0 ||
00498 req.motion_plan_request.goal_constraints.orientation_constraints.size() <= 0)
00499 {
00500 ROS_ERROR("Position constraint or orientation constraint is empty. Unable to plan.");
00501 return false;
00502 }
00503
00504
00505 if(req.motion_plan_request.goal_constraints.position_constraints.size() > 1 ||
00506 req.motion_plan_request.goal_constraints.orientation_constraints.size() > 1)
00507 ROS_WARN("The planning request message contains %d position and %d orientation constraints. Currently the planner only supports one position & orientation constraint pair at a time. Planning to the first goal may not satisfy move_arm.", int(req.motion_plan_request.goal_constraints.position_constraints.size()), int(req.motion_plan_request.goal_constraints.orientation_constraints.size()));
00508
00509
00510 cspace_->putCollisionObjectsInGrid();
00511
00512
00513 planning_joint_ = req.motion_plan_request.goal_constraints.position_constraints[0].link_name;
00514
00515 if(planning_joint_ != "r_wrist_roll_link" && arm_name_ == "right_arm")
00516 {
00517 ROS_ERROR("Planner is configured to plan for the right arm. It has only been tested with pose constraints for r_wrist_roll_link. Other links may be supported in the future.");
00518 return false;
00519 }
00520 else if(planning_joint_ != "l_wrist_roll_link" && arm_name_ == "left_arm")
00521 {
00522 ROS_ERROR("Planner is configured to plan for the left arm. It has only been tested with pose constraints for l_wrist_roll_link. Other links may be supported in the future.");
00523 return false;
00524 }
00525
00526
00527 geometry_msgs::PoseStamped pose_in, pose_out;
00528 pose_in.header = req.motion_plan_request.goal_constraints.position_constraints[0].header;
00529 pose_in.header.stamp = ros::Time();
00530 pose_in.pose.position = req.motion_plan_request.goal_constraints.position_constraints[0].position;
00531 pose_in.pose.orientation = req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation;
00532
00533
00534 tf_.transformPose(map_frame_,pose_in,pose_out);
00535
00536 req.motion_plan_request.goal_constraints.position_constraints[0].position = pose_out.pose.position;
00537 req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation = pose_out.pose.orientation;
00538
00539 ROS_DEBUG("[planToPosition] Transformed goal from (%s): %0.3f %0.3f %0.3f to (%s): %0.3f %0.3f %0.3f", req.motion_plan_request.goal_constraints.position_constraints[0].header.frame_id.c_str(),pose_in.pose.position.x, pose_in.pose.position.y, pose_in.pose.position.z, map_frame_.c_str(), pose_out.pose.position.x,pose_out.pose.position.y,pose_out.pose.position.z);
00540
00541
00542 start.position.resize(num_joints_);
00543 for(i = 0; i < req.motion_plan_request.start_state.joint_state.position.size(); i++)
00544 {
00545 if(joint_names_[nind].compare(req.motion_plan_request.start_state.joint_state.name[i]) == 0)
00546 {
00547 start.position[nind] = req.motion_plan_request.start_state.joint_state.position[i];
00548 nind++;
00549 }
00550 if(nind == num_joints_)
00551 break;
00552 }
00553 if(nind != num_joints_)
00554 ROS_WARN("Not all of the expected joints in the arm were assigned a starting position.");
00555
00556 allocated_time_ = req.motion_plan_request.allowed_planning_time.toSec();
00557
00558 colmap_mutex_.lock();
00559 object_mutex_.lock();
00560
00561 ROS_DEBUG("[planToPosition] About to set start configuration");
00562 if(setStart(start))
00563 {
00564 ROS_DEBUG("[planToPosition] Successfully set starting configuration");
00565
00566 if(visualize_goal_)
00567 visualizeGoalPosition(req.motion_plan_request.goal_constraints);
00568
00569 if(setGoalPosition(req.motion_plan_request.goal_constraints))
00570 {
00571 if(plan(arm_path))
00572 {
00573 colmap_mutex_.unlock();
00574 object_mutex_.unlock();
00575
00576 res.trajectory.joint_trajectory.points.resize(arm_path.size());
00577 res.trajectory.joint_trajectory.points = arm_path;
00578
00579
00580 res.trajectory.joint_trajectory.points[0].time_from_start.fromSec(waypoint_time_);
00581 for(i = 1; i < res.trajectory.joint_trajectory.points.size(); i++)
00582 res.trajectory.joint_trajectory.points[i].time_from_start.fromSec(res.trajectory.joint_trajectory.points[i-1].time_from_start.toSec() + waypoint_time_);
00583
00584 res.trajectory.joint_trajectory.header.seq = req.motion_plan_request.goal_constraints.position_constraints[0].header.seq;
00585 res.trajectory.joint_trajectory.header.stamp = ros::Time::now();
00586
00587 if(!req.motion_plan_request.start_state.joint_state.header.frame_id.empty())
00588 res.trajectory.joint_trajectory.header.frame_id = req.motion_plan_request.start_state.joint_state.header.frame_id;
00589 else
00590 res.trajectory.joint_trajectory.header.frame_id = reference_frame_;
00591
00592
00593 res.trajectory.joint_trajectory.joint_names.resize(num_joints_);
00594 for(i = 0; i < (unsigned int)num_joints_; i++)
00595 res.trajectory.joint_trajectory.joint_names[i] = joint_names_[i];
00596
00597 ROS_INFO("Planner completed in %lf seconds. Planned trajectory has %d waypoints.",(clock() - starttime) / (double)CLOCKS_PER_SEC, int(res.trajectory.joint_trajectory.points.size()));
00598
00599 if(print_path_)
00600 printPath(res.trajectory.joint_trajectory.points);
00601
00602
00603 if(!isGoalConstraintSatisfied(res.trajectory.joint_trajectory.points[res.trajectory.joint_trajectory.points.size()-1].positions, req.motion_plan_request.goal_constraints))
00604 ROS_WARN("Uh Oh. Goal constraint isn't satisfied.");
00605
00606
00607 if(visualize_expanded_states_)
00608 displayARAStarStates();
00609
00610 if(visualize_heuristic_)
00611 displayShortestPath();
00612
00613 if(visualize_trajectory_)
00614 aviz_->visualizeJointTrajectoryMsg(res.trajectory.joint_trajectory, throttle_);
00615
00616 if(visualize_collision_model_trajectory_)
00617 aviz_->visualizeCollisionModelFromJointTrajectoryMsg(res.trajectory.joint_trajectory, *cspace_, throttle_);
00618
00619 if(use_research_heuristic_)
00620 visualizeElbowPoses();
00621
00622 return true;
00623 }
00624 else
00625 {
00626 ROS_ERROR("Failed to plan within alotted time frame (%0.2f seconds).", allocated_time_);
00627 }
00628 }
00629 else
00630 {
00631 ROS_ERROR("Failed to set goal pose.");
00632 }
00633 }
00634 else
00635 {
00636 ROS_ERROR("Failed to set start configuration.");
00637 }
00638
00639 colmap_mutex_.unlock();
00640 object_mutex_.unlock();
00641
00642 if(visualize_expanded_states_)
00643 displayARAStarStates();
00644
00645 if(use_research_heuristic_)
00646 visualizeElbowPoses();
00647
00648 return false;
00649 }
00650
00651 bool SBPLArmPlannerNode::planKinematicPath(motion_planning_msgs::GetMotionPlan::Request &req, motion_planning_msgs::GetMotionPlan::Response &res)
00652 {
00653 if(!planner_initialized_)
00654 {
00655 ROS_ERROR("Hold up a second...the planner isn't initialized yet. Try again in a second or two.");
00656 return false;
00657 }
00658
00659 if(req.motion_plan_request.goal_constraints.position_constraints.empty())
00660 {
00661 ROS_ERROR("There are no goal pose constraints in the request message. We need those to plan :).");
00662 return false;
00663 }
00664
00665 if(!planToPosition(req, res))
00666 return false;
00667
00668 return true;
00669 }
00670
00671 bool SBPLArmPlannerNode::plan(std::vector<trajectory_msgs::JointTrajectoryPoint> &arm_path)
00672 {
00673 bool b_ret(false);
00674 int solution_cost;
00675 std::vector<double>angles(num_joints_,0);
00676 vector<int> solution_state_ids_v;
00677
00678
00679 planner_->force_planning_from_scratch();
00680
00681
00682 b_ret = planner_->replan(allocated_time_, &solution_state_ids_v, &solution_cost);
00683
00684
00685 if(b_ret && solution_state_ids_v.size() <= 0)
00686 b_ret = false;
00687
00688
00689 sbpl_arm_env_.debugAdaptiveMotionPrims();
00690
00691
00692 if(b_ret && (solution_state_ids_v.size() > 0))
00693 {
00694 ROS_DEBUG("[plan] A path was returned with %d waypoints.", int(solution_state_ids_v.size()));
00695 ROS_INFO("Initial Epsilon: %0.3f Final Epsilon: %0.3f", planner_->get_initial_eps(),planner_->get_final_epsilon());
00696 arm_path.resize(solution_state_ids_v.size()+1);
00697 for(size_t i=0; i < solution_state_ids_v.size(); i++)
00698 {
00699 arm_path[i].positions.resize(num_joints_);
00700 sbpl_arm_env_.StateID2Angles(solution_state_ids_v[i], angles);
00701
00702
00703 if(angles.size()==14)
00704 {
00705 arm_path[i+1].positions.resize(num_joints_);
00706 std::vector<double>test_angles(7,0);
00707 for (int p = 0; p < num_joints_; ++p)
00708 {
00709 arm_path[i].positions[p] = angles::normalize_angle(angles[p]);
00710 test_angles[p] = angles::normalize_angle(angles[p+7]);
00711 arm_path[i+1].positions[p] = angles::normalize_angle(angles[p+7]);
00712 }
00713 }
00714 else
00715 {
00716 for (int p = 0; p < num_joints_; ++p)
00717 arm_path[i].positions[p] = angles::normalize_angle(angles[p]);
00718 }
00719 ROS_DEBUG("%i: %.4f %.4f %.4f %.4f %.4f %.4f %.4f", int(i), arm_path[i].positions[0],arm_path[i].positions[1],arm_path[i].positions[2],arm_path[i].positions[3],arm_path[i].positions[4],arm_path[i].positions[5],arm_path[i].positions[6]);
00720 }
00721 }
00722 return b_ret;
00723 }
00724
00725 bool SBPLArmPlannerNode::isGoalConstraintSatisfied(const std::vector<double> &angles, const motion_planning_msgs::Constraints &goal)
00726 {
00727 bool satisfied = true;
00728 geometry_msgs::Pose pose, err;
00729
00730 if(!computeFK(angles,pose))
00731 {
00732 ROS_ERROR("Failed to check if goal constraint is satisfied because the FK service failed.");
00733 return false;
00734 }
00735
00736 if(goal.position_constraints.size() > 0)
00737 {
00738 err.position.x = fabs(pose.position.x - goal.position_constraints[0].position.x);
00739 err.position.y = fabs(pose.position.y - goal.position_constraints[0].position.y);
00740 err.position.z = fabs(pose.position.z - goal.position_constraints[0].position.z);
00741 }
00742
00743 if(goal.orientation_constraints.size() > 0)
00744 {
00745 err.orientation.x = fabs(pose.orientation.x - goal.orientation_constraints[0].orientation.x);
00746 err.orientation.y = fabs(pose.orientation.y - goal.orientation_constraints[0].orientation.y);
00747 err.orientation.z = fabs(pose.orientation.z - goal.orientation_constraints[0].orientation.z);
00748 err.orientation.w = fabs(pose.orientation.w - goal.orientation_constraints[0].orientation.w);
00749 }
00750
00751 ROS_INFO(" ");
00752 ROS_INFO("Pose: xyz: %0.4f %0.4f %0.4f quat: %0.4f %0.4f %0.4f %0.4f", pose.position.x, pose.position.y, pose.position.z, pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
00753 ROS_INFO("Goal: xyz: %0.4f %0.4f %0.4f quat: %0.4f %0.4f %0.4f %0.4f", goal.position_constraints[0].position.x, goal.position_constraints[0].position.y, goal.position_constraints[0].position.z, goal.orientation_constraints[0].orientation.x, goal.orientation_constraints[0].orientation.y, goal.orientation_constraints[0].orientation.z, goal.orientation_constraints[0].orientation.w);
00754 ROS_INFO("Error: xyz: %0.4f %0.4f %0.4f quat: %0.4f %0.4f %0.4f %0.4f", err.position.x, err.position.y, err.position.z, err.orientation.x, err.orientation.y, err.orientation.z, err.orientation.w);
00755 ROS_INFO(" ");
00756
00757 if(goal.position_constraints[0].constraint_region_shape.type == geometric_shapes_msgs::Shape::BOX)
00758 {
00759 if(goal.position_constraints[0].constraint_region_shape.dimensions.size() < 3)
00760 {
00761 ROS_WARN("Goal constraint region shape is a BOX but fewer than 3 dimensions are defined.");
00762 return false;
00763 }
00764 if(err.position.x >= goal.position_constraints[0].constraint_region_shape.dimensions[0])
00765 {
00766 ROS_WARN("X is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.x, goal.position_constraints[0].constraint_region_shape.dimensions[0]);
00767 satisfied = false;
00768 }
00769 if(err.position.y >= goal.position_constraints[0].constraint_region_shape.dimensions[1])
00770 {
00771 ROS_WARN("Y is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.y, goal.position_constraints[0].constraint_region_shape.dimensions[1]);
00772 satisfied = false;
00773 }
00774 if(err.position.z >= goal.position_constraints[0].constraint_region_shape.dimensions[2])
00775 {
00776 ROS_WARN("Z is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.z, goal.position_constraints[0].constraint_region_shape.dimensions[2]);
00777 satisfied = false;
00778 }
00779 }
00780 else if(goal.position_constraints[0].constraint_region_shape.type == geometric_shapes_msgs::Shape::SPHERE)
00781 {
00782 if(goal.position_constraints[0].constraint_region_shape.dimensions.size() < 1)
00783 {
00784 ROS_WARN("Goal constraint region shape is a SPHERE but it has no dimensions...");
00785 return false;
00786 }
00787 if(err.position.x >= goal.position_constraints[0].constraint_region_shape.dimensions[0])
00788 {
00789 ROS_WARN("X is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.x, goal.position_constraints[0].constraint_region_shape.dimensions[0]);
00790 satisfied = false;
00791 }
00792 if(err.position.y >= goal.position_constraints[0].constraint_region_shape.dimensions[0])
00793 {
00794 ROS_WARN("Y is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.y, goal.position_constraints[0].constraint_region_shape.dimensions[1]);
00795 satisfied = false;
00796 }
00797 if(err.position.z >= goal.position_constraints[0].constraint_region_shape.dimensions[0])
00798 {
00799 ROS_WARN("Z is not satisfied (error: %0.4f tolerance: %0.4f)", err.position.z, goal.position_constraints[0].constraint_region_shape.dimensions[2]);
00800 satisfied = false;
00801 }
00802 }
00803 else
00804 ROS_WARN("Goal constraint region shape is of type %d.", goal.position_constraints[0].constraint_region_shape.type);
00805
00806 return satisfied;
00807 }
00808
00809
00810
00811 bool SBPLArmPlannerNode::computeIK(const geometry_msgs::Pose &pose, std::vector<double> jnt_pos, std::vector<double> &solution)
00812 {
00813 kinematics_msgs::GetPositionIK::Request request;
00814 kinematics_msgs::GetPositionIK::Response response;
00815
00816 request.ik_request.ik_link_name = planning_joint_;
00817
00818 request.ik_request.pose_stamped.pose = pose;
00819 request.ik_request.pose_stamped.header.stamp = ros::Time();
00820 request.ik_request.pose_stamped.header.frame_id = reference_frame_;
00821
00822 request.ik_request.ik_seed_state.joint_state.header.stamp = ros::Time();
00823 request.ik_request.ik_seed_state.joint_state.header.frame_id = reference_frame_;
00824 request.ik_request.ik_seed_state.joint_state.name = joint_names_;
00825 request.ik_request.ik_seed_state.joint_state.position.clear();
00826
00827 for(int j = 0 ; j < num_joints_; ++j)
00828 request.ik_request.ik_seed_state.joint_state.position.push_back(jnt_pos[j]);
00829
00830 ros::service::waitForService(ik_service_name_);
00831 ros::ServiceClient client = root_handle_.serviceClient<kinematics_msgs::GetPositionIK>(ik_service_name_, true);
00832
00833 if(client.call(request, response))
00834 {
00835 ROS_DEBUG("Obtained IK solution");
00836 if(response.error_code.val == response.error_code.SUCCESS)
00837 for(unsigned int i=0; i < response.solution.joint_state.name.size(); i ++)
00838 {
00839 solution[i] = response.solution.joint_state.position[i];
00840 ROS_INFO("Joint: %s %f",response.solution.joint_state.name[i].c_str(),response.solution.joint_state.position[i]);
00841 }
00842 else
00843 {
00844 ROS_ERROR("Inverse kinematics failed");
00845 return false;
00846 }
00847
00848 ROS_DEBUG("IK Solution");
00849 for(unsigned int i = 0; i < solution.size() ; ++i)
00850 ROS_DEBUG("%i: %f", i, solution[i]);
00851 }
00852 else
00853 {
00854 ROS_ERROR("IK service failed");
00855 return false;
00856 }
00857 return true;
00858 }
00859
00860 bool SBPLArmPlannerNode::computeFK(const std::vector<double> &jnt_pos, geometry_msgs::Pose &pose)
00861 {
00862 kinematics_msgs::GetPositionFK::Request request;
00863 kinematics_msgs::GetPositionFK::Response response;
00864
00865 request.header.stamp = ros::Time();
00866 request.header.frame_id = reference_frame_;
00867
00868 request.robot_state.joint_state.name = joint_names_;
00869
00870 for(unsigned int j = 0 ; j < jnt_pos.size(); ++j)
00871 request.robot_state.joint_state.position.push_back(jnt_pos[j]);
00872
00873 request.fk_link_names.resize(1);
00874 request.fk_link_names[0] = planning_joint_;
00875
00876 ROS_DEBUG("waiting for %s service", fk_service_name_.c_str());
00877 ros::service::waitForService(fk_service_name_);
00878 ros::ServiceClient client = root_handle_.serviceClient<kinematics_msgs::GetPositionFK>(fk_service_name_);
00879
00880 if(client.call(request, response))
00881 {
00882 if(response.error_code.val == response.error_code.SUCCESS)
00883 {
00884 pose = response.pose_stamped[0].pose;
00885 return true;
00886 }
00887 else
00888 return false;
00889 }
00890 else
00891 {
00892 ROS_ERROR("FK service failed");
00893 return false;
00894 }
00895 }
00896
00897 void SBPLArmPlannerNode::computeFKwithKDL(const std::vector<double> &jnt_pos, geometry_msgs::Pose &pose, int joint_num)
00898 {
00899 KDL::JntArray jnt_array;
00900 KDL::Frame frame_out;
00901
00902 jnt_array.resize(arm_chain_.getNrOfJoints());
00903
00904 for(int i = 0; i < num_joints_; ++i)
00905 jnt_array(i+1)=jnt_pos[i];
00906
00907 if(jnt_to_pose_solver_->JntToCart(jnt_array, frame_out, joint_num) < 0)
00908 {
00909 ROS_ERROR("JntToCart returned < 0. Exiting.\n");
00910 return;
00911 }
00912
00913 pose.position.x = frame_out.p[0];
00914 pose.position.y = frame_out.p[1];
00915 pose.position.z = frame_out.p[2];
00916 }
00917
00918 bool SBPLArmPlannerNode::initChain(std::string robot_description)
00919 {
00920 KDL::Tree my_tree;
00921
00922 if (!kdl_parser::treeFromString(robot_description, my_tree))
00923 {
00924 ROS_ERROR("Failed to parse tree from manipulator description file.\n");
00925 return false;;
00926 }
00927
00928 if (!my_tree.getChain(reference_frame_, planning_joint_, arm_chain_))
00929 {
00930 ROS_ERROR("Could not fetch the KDL chain for the desired manipulator. Exiting.\n");
00931 return false;
00932 }
00933
00934 jnt_to_pose_solver_ = new KDL::ChainFkSolverPos_recursive(arm_chain_);
00935
00936 ROS_DEBUG("[initChain] arm_chain has %d segments and %d joints", arm_chain_.getNrOfSegments(), arm_chain_.getNrOfJoints());
00937
00938 return true;
00939 }
00940
00941 void SBPLArmPlannerNode::setArmToMapTransform(std::string &map_frame)
00942 {
00943 std::string fk_root_frame;
00944
00945
00946 sbpl_arm_env_.getArmChainRootLinkName(fk_root_frame);
00947
00948
00949 try
00950 {
00951 tf_.lookupTransform(map_frame, fk_root_frame, ros::Time(0), transform_);
00952
00953 ROS_DEBUG("Received transform from %s to %s (translation: %f %f %f)",fk_root_frame.c_str(),map_frame.c_str(), transform_.getOrigin().x(),transform_.getOrigin().y(),transform_.getOrigin().z());
00954 }
00955 catch (tf::TransformException ex)
00956 {
00957 ROS_ERROR("%s",ex.what());
00958 }
00959
00960
00961 tf::TransformTFToKDL(transform_,kdl_transform_);
00962 sbpl_arm_env_.setReferenceFrameTransform(kdl_transform_, map_frame);
00963 }
00964
00965
00966 void SBPLArmPlannerNode::displayARAStarStates()
00967 {
00968 std::vector<std::vector<double> > expanded_states;
00969 std::vector<double> expanded_color(4,1);
00970 expanded_color[0] = 0.5;
00971 expanded_color[2] = 0;
00972
00973 sbpl_arm_env_.getExpandedStates(&(expanded_states));
00974
00975 if(!expanded_states.empty())
00976 {
00977 std::vector<std::vector<double> > detailed_color(2);
00978 detailed_color[0].resize(4,0);
00979 detailed_color[0][0] = 1;
00980 detailed_color[0][1] = 0;
00981 detailed_color[0][2] = 0;
00982 detailed_color[0][3] = 1;
00983
00984 detailed_color[1].resize(4,0);
00985 detailed_color[1][0] = 0;
00986 detailed_color[1][1] = 1;
00987 detailed_color[1][2] = 0;
00988 detailed_color[1][3] = 1;
00989
00990 aviz_->visualizeDetailedStates(expanded_states, detailed_color,"expanded",0.01);
00991 }
00992
00993 ROS_INFO("[displayARAStarStates] displaying %d expanded states.\n",int(expanded_states.size()));
00994 }
00995
00996 void SBPLArmPlannerNode::visualizeGoalPosition(const motion_planning_msgs::Constraints &goal_pose)
00997 {
00998 geometry_msgs::Pose pose;
00999 pose.position = goal_pose.position_constraints[0].position;
01000 pose.orientation = goal_pose.orientation_constraints[0].orientation;
01001 aviz_->visualizePose(pose, "goal_pose");
01002 ROS_DEBUG("[visualizeGoalPosition] publishing goal marker visualizations.");
01003 }
01004
01005 void SBPLArmPlannerNode::visualizeElbowPoses()
01006 {
01007 std::vector<std::vector<double> > elbow_poses;
01008 sbpl_arm_env_.getElbowPoints(elbow_poses);
01009
01010 for(size_t i = 0; i < elbow_poses.size(); i++)
01011 {
01012 aviz_->visualizeSphere(elbow_poses[i], 100, "elbow_poses" + boost::lexical_cast<std::string>(i), 0.02);
01013 }
01014 ROS_INFO("[visualizeElbowPoses] Visualizing %d elbow poses.", int(elbow_poses.size()));
01015 }
01016
01017 void SBPLArmPlannerNode::visualizeCollisionObjects()
01018 {
01019 std::vector<geometry_msgs::Pose> poses;
01020 std::vector<std::vector<double> > points(1,std::vector<double>(3,0));
01021 std::vector<double> color(4,1);
01022 color[2] = 0;
01023
01024 cspace_->getCollisionObjectVoxelPoses(poses);
01025
01026 points.resize(poses.size());
01027 for(size_t i = 0; i < poses.size(); ++i)
01028 {
01029 points[i].resize(3);
01030 points[i][0] = poses[i].position.x;
01031 points[i][1] = poses[i].position.y;
01032 points[i][2] = poses[i].position.z;
01033 }
01034
01035 ROS_DEBUG("[visualizeCollisionObjects] Displaying %d known collision object voxels.", int(points.size()));
01036 aviz_->visualizeBasicStates(points, color, "known_objects", 0.01);
01037 }
01038
01039 void SBPLArmPlannerNode::visualizeAttachedObject(trajectory_msgs::JointTrajectory &traj_msg, int throttle)
01040 {
01041 std::vector<double> angles(7,0);
01042 std::vector<std::vector<double> > xyz;
01043
01044 if(traj_msg.points.empty())
01045 {
01046 ROS_WARN("Trajectory message is empty. Not visualizing anything.");
01047 return;
01048 }
01049
01050 for(size_t i = 0; i < traj_msg.points.size(); i++)
01051 {
01052 angles = traj_msg.points[i].positions;
01053
01054 if(!cspace_->getAttachedObject(angles, xyz))
01055 continue;
01056
01057 aviz_->visualizeSpheres(xyz, 10*(i+1), "sbpl_attached_object_" + boost::lexical_cast<std::string>(i), cspace_->getAttachedObjectRadius());
01058 }
01059 }
01060
01061 void SBPLArmPlannerNode::visualizeAttachedObject(const std::vector<double> &angles)
01062 {
01063 std::vector<std::vector<double> > xyz;
01064
01065 if(angles.size() < 7)
01066 {
01067 ROS_WARN("[visualizeAttachedObject] Joint configuration is not of the right length.");
01068 return;
01069 }
01070
01071 if(!cspace_->getAttachedObject(angles, xyz))
01072 return;
01073
01074 aviz_->visualizeSpheres(xyz, 50, "sbpl_attached_object", cspace_->getAttachedObjectRadius());
01075 }
01076
01077 void SBPLArmPlannerNode::displayShortestPath()
01078 {
01079 dpath_ = sbpl_arm_env_.getShortestPath();
01080
01081
01082 if(dpath_.empty())
01083 {
01084 ROS_INFO("The heuristic path has a length of 0");
01085 return;
01086 }
01087 else
01088 ROS_DEBUG("Visualizing heuristic path from start to goal with %d waypoints.",int(dpath_.size()));
01089
01090 aviz_->visualizeSpheres(dpath_, 45, "heuristic_path", 0.04);
01091 }
01092
01093 void SBPLArmPlannerNode::printPath(const std::vector<trajectory_msgs::JointTrajectoryPoint> &arm_path)
01094 {
01095 double roll,pitch,yaw;
01096 tf::Pose tf_pose;
01097 geometry_msgs::Pose pose;
01098 std::vector<double> jnt_pos(num_joints_,0);
01099
01100 ROS_INFO("Path:");
01101 for(unsigned int i = 0; i < arm_path.size(); i++)
01102 {
01103 for(int j = 0; j < num_joints_; ++j)
01104 jnt_pos[j] = arm_path[i].positions[j];
01105
01106 computeFK(jnt_pos, pose);
01107 tf::poseMsgToTF(pose, tf_pose);
01108 tf_pose.getBasis().getRPY(roll,pitch,yaw);
01109
01110 ROS_INFO("%3d: %1.4f %1.4f %1.4f %1.4f %1.4f %1.4f %1.4f\n xyz: %2.3f %2.3f %2.3f rpy: %0.3f %0.3f %0.3f quat: %0.2f %0.2f %0.2f %0.2f", i,arm_path[i].positions[0],arm_path[i].positions[1],arm_path[i].positions[2],arm_path[i].positions[3],arm_path[i].positions[4],arm_path[i].positions[5],arm_path[i].positions[6],pose.position.x, pose.position.y, pose.position.z, roll, pitch, yaw, pose.orientation.x,pose.orientation.y, pose.orientation.z, pose.orientation.w);
01111 }
01112 }
01113
01114 void SBPLArmPlannerNode::printPath(FILE* fOut, const std::vector<std::vector<double> > path)
01115 {
01116 time_t init_time;
01117 time(&init_time);
01118 std::string str_time(asctime (localtime(&init_time)));
01119
01120 fprintf(fOut, "%s", str_time.c_str());
01121 for(unsigned int i = 0; i < path.size(); i++)
01122 fprintf(fOut, "state %3d: %2.3f %2.3f %2.3f %2.3f %2.3f %2.3f %2.3f",i,path[i][0],path[i][1],path[i][2],path[i][3],path[i][4],path[i][5],path[i][6]);
01123 fprintf(fOut,"---------------------------------");
01124 }
01125
01126
01127
01128 int main(int argc, char **argv)
01129 {
01130 ros::init(argc, argv, "sbpl_arm_planner");
01131 SBPLArmPlannerNode arm_planner;
01132 if(!arm_planner.init())
01133 {
01134 ROS_ERROR("Failed to initialize arm planner node. Exiting.");
01135 return 0;
01136 }
01137
01138 return arm_planner.run();
01139 }
01140
01141