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 #include <sbpl_cart_planner/sbpl_cart_planner.h>
00039 #include <cart_pushing_msgs/RobotCartPath.h>
00040 #include <pluginlib/class_list_macros.h>
00041 #include <nav_msgs/Path.h>
00042 #include <sbpl_cart_planner/SBPLCartPlannerStats.h>
00043
00044 using namespace std;
00045 using namespace ros;
00046
00047
00048
00049 PLUGINLIB_REGISTER_CLASS(SBPLCartPlanner, SBPLCartPlanner, nav_core::BaseGlobalPlanner);
00050
00051 class LatticeSCQ : public StateChangeQuery{
00052 public:
00053 LatticeSCQ(EnvironmentNAVXYTHETACARTLAT* env, std::vector<nav2dcell_t> const & changedcellsV)
00054 : env_(env), changedcellsV_(changedcellsV) {
00055 }
00056
00057
00058 virtual std::vector<int> const * getPredecessors() const{
00059 if(predsOfChangedCells_.empty() && !changedcellsV_.empty())
00060 env_->GetPredsofChangedEdges(&changedcellsV_, &predsOfChangedCells_);
00061 return &predsOfChangedCells_;
00062 }
00063
00064
00065 virtual std::vector<int> const * getSuccessors() const{
00066 if(succsOfChangedCells_.empty() && !changedcellsV_.empty())
00067 env_->GetSuccsofChangedEdges(&changedcellsV_, &succsOfChangedCells_);
00068 return &succsOfChangedCells_;
00069 }
00070
00071 EnvironmentNAVXYTHETACARTLAT * env_;
00072 std::vector<nav2dcell_t> const & changedcellsV_;
00073 mutable std::vector<int> predsOfChangedCells_;
00074 mutable std::vector<int> succsOfChangedCells_;
00075 };
00076
00077 double SBPLCartPlanner::sign(double x)
00078 {
00079 return x < 0.0 ? -1.0 : 1.0;
00080 }
00081
00082 SBPLCartPlanner::SBPLCartPlanner()
00083 : initialized_(false), costmap_ros_(NULL){
00084 }
00085
00086 SBPLCartPlanner::SBPLCartPlanner(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00087 : initialized_(false), costmap_ros_(NULL){
00088 initialize(name, costmap_ros);
00089 if(!initialized_)
00090 ROS_ERROR("Could not initialize global planner");
00091 }
00092
00093
00094 void SBPLCartPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros){
00095 if(!initialized_){
00096 num_sbpl_markers_ = 0;
00097 ros::NodeHandle private_nh("~/"+name);
00098 ros::NodeHandle nh(name);
00099
00100 ROS_INFO("Name is %s", name.c_str());
00101
00102 private_nh.param("planner_type", planner_type_, string("ARAPlanner"));
00103 private_nh.param("allocated_time", allocated_time_, 10.0);
00104 private_nh.param("initial_epsilon",initial_epsilon_,3.0);
00105 private_nh.param("environment_type", environment_type_, string("XYThetaLattice"));
00106 private_nh.param("forward_search", forward_search_, bool(false));
00107 private_nh.param("primitive_filename",primitive_filename_,string(""));
00108 private_nh.param("force_scratch_limit",force_scratch_limit_,500);
00109
00110 double nominalvel_mpersecs, timetoturn45degsinplace_secs;
00111 private_nh.param("nominalvel_mpersecs", nominalvel_mpersecs, 0.4);
00112 private_nh.param("timetoturn45degsinplace_secs", timetoturn45degsinplace_secs, 0.6);
00113
00114 private_nh.param<int>("visualizer_skip_poses",visualizer_skip_poses_,5);
00115
00116 int lethal_obstacle;
00117 private_nh.param("lethal_obstacle",lethal_obstacle,20);
00118 lethal_obstacle_ = (unsigned char) lethal_obstacle;
00119 inscribed_inflated_obstacle_ = lethal_obstacle_-1;
00120 sbpl_cost_multiplier_ = (unsigned char) (costmap_2d::INSCRIBED_INFLATED_OBSTACLE/inscribed_inflated_obstacle_ + 1);
00121
00122 ROS_DEBUG("SBPL: lethal: %uz, inscribed inflated: %uz, multiplier: %uz",lethal_obstacle,inscribed_inflated_obstacle_,sbpl_cost_multiplier_);
00123 costmap_ros_ = costmap_ros;
00124 costmap_ros_->clearRobotFootprint();
00125
00126
00127 costmap_ros_->getCostmapCopy(cost_map_);
00128
00129 std::vector<geometry_msgs::Point> footprint = costmap_ros_->getRobotFootprint();
00130 robot_footprint_ = footprint;
00131 if ("XYThetaLattice" == environment_type_){
00132 ROS_INFO("Using a 3D costmap for theta lattice\n");
00133 env_ = new EnvironmentNAVXYTHETACARTLAT();
00134 }
00135 else
00136 {
00137 ROS_FATAL("XYThetaLattice is currently the only supported environment!\n");
00138 return;
00139 }
00140
00141 if(!env_->SetEnvParameter("cost_inscribed_thresh",inscribed_inflated_obstacle_))
00142 {
00143 ROS_FATAL("Failed to set cost_inscribed_thresh parameter");
00144 return;
00145 }
00146
00147 int obst_cost_thresh = costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE);
00148 vector<sbpl_2Dpt_t> perimeterptsV, cart_perimeterptsV;
00149 private_nh.param("cart_pivot_offset/x", cart_offset_.x, 0.35);
00150 private_nh.param("cart_pivot_offset/y", cart_offset_.y, 0.0);
00151 ROS_INFO("Cart pivot point offset (in base_footprint): %f %f",cart_offset_.x,cart_offset_.y);
00152
00153 ros::NodeHandle cart_pushing_nh("cart_pushing");
00154 double cart_length, cart_width;
00155 double fp_x_offset, fp_y_offset;
00156 cart_pushing_nh.param("length", cart_length, 0.0);
00157 cart_pushing_nh.param("width", cart_width, 0.0);
00158 cart_pushing_nh.param("footprint_x_offset", fp_x_offset, 0.0);
00159 cart_pushing_nh.param("footprint_y_offset", fp_y_offset, 0.0);
00160
00161 ROS_DEBUG("Length: %f %f, Footprint offset: %f %f",cart_length,cart_width,fp_x_offset,fp_y_offset);
00162 XmlRpc::XmlRpcValue init_position;
00163 geometry_msgs::Pose cart_init_pose;
00164 cart_pushing_nh.getParam("cart_init_pose/position", init_position);
00165 if(!(init_position.getType() == XmlRpc::XmlRpcValue::TypeArray && init_position.size() == 3)){
00166 ROS_FATAL("The init pose must be specified as a 3-Vector");
00167 return;
00168 }
00169 for(int i = 0; i < init_position.size(); ++i)
00170 if(!init_position[i].getType() == XmlRpc::XmlRpcValue::TypeDouble)
00171 ROS_FATAL("Values in the footprint specification must be numbers");
00172 cart_init_pose.position.x = (double) init_position[0];
00173 cart_init_pose.position.y = (double) init_position[1];
00174 cart_init_pose.position.z = (double) init_position[2];
00175
00176 ROS_DEBUG("Init pose: %f %f %f",cart_init_pose.position.x,cart_init_pose.position.y,cart_init_pose.position.z);
00177
00178 cart_cp_offset_.x = cart_init_pose.position.x - cart_offset_.x;
00179 cart_cp_offset_.y = cart_init_pose.position.y - cart_offset_.y;
00180 ROS_INFO("Cart control point offset (from pivot point): %f %f",cart_cp_offset_.x,cart_cp_offset_.y);
00181
00182
00183 double padding;
00184 std::string padding_param;
00185 if(!private_nh.searchParam("footprint_padding", padding_param))
00186 padding = 0.01;
00187 else
00188 private_nh.param(padding_param, padding, 0.01);
00189
00190
00191 std::vector<geometry_msgs::Point> cart_footprint;
00192 cart_footprint.resize(4);
00193 cart_footprint[0].x = -cart_length/2.0-padding;
00194 cart_footprint[0].y = -cart_width/2.0-padding;
00195 cart_footprint[0].z = 0.0;
00196
00197 cart_footprint[1].x = -cart_length/2.0-padding;
00198 cart_footprint[1].y = cart_width/2.0+padding;
00199 cart_footprint[1].z = 0.0;
00200
00201 cart_footprint[2].x = cart_length/2.0+padding;
00202 cart_footprint[2].y = cart_width/2.0+padding;
00203 cart_footprint[2].z = 0.0;
00204
00205 cart_footprint[3].x = cart_length/2.0+padding;
00206 cart_footprint[3].y = -cart_width/2.0-padding;
00207 cart_footprint[3].z = 0.0;
00208
00209 for(unsigned int i=0; i < cart_footprint.size(); i++)
00210 cart_footprint[i].x += (cart_init_pose.position.x + cart_length/2.0 - fp_x_offset -cart_offset_.x);
00211
00212
00213
00214 cart_footprint_ = cart_footprint;
00215 cart_perimeterptsV.reserve(cart_footprint.size());
00216 ROS_INFO("Cart footprint");
00217 for (size_t ii(0); ii < cart_footprint.size(); ++ii) {
00218 sbpl_2Dpt_t pt;
00219 pt.x = cart_footprint[ii].x;
00220 pt.y = cart_footprint[ii].y;
00221 cart_perimeterptsV.push_back(pt);
00222 ROS_INFO("%d: %f %f",(int)ii,pt.x,pt.y);
00223 }
00224 perimeterptsV.reserve(footprint.size());
00225 for (size_t ii(0); ii < footprint.size(); ++ii) {
00226 sbpl_2Dpt_t pt;
00227 pt.x = footprint[ii].x;
00228 pt.y = footprint[ii].y;
00229 perimeterptsV.push_back(pt);
00230 }
00231
00232 bool ret;
00233 try{
00234 ret = env_->InitializeEnv(costmap_ros_->getSizeInCellsX(),
00235 costmap_ros_->getSizeInCellsY(),
00236 0,
00237 0, 0, 0, 0,
00238 0, 0, 0, 0,
00239 0, 0, 0, 0,
00240 perimeterptsV,
00241 cart_offset_,
00242 cart_perimeterptsV,
00243 costmap_ros_->getResolution(), nominalvel_mpersecs,
00244 timetoturn45degsinplace_secs, obst_cost_thresh,
00245 primitive_filename_.c_str());
00246 }
00247 catch(SBPL_Exception e){
00248 ROS_ERROR("SBPL encountered a fatal exception");
00249 ret = false;
00250 }
00251 if(!ret){
00252 ROS_FATAL("SBPL initialization failed!");
00253 }
00254
00255 for (ssize_t ix(0); ix < costmap_ros_->getSizeInCellsX(); ++ix)
00256 for (ssize_t iy(0); iy < costmap_ros_->getSizeInCellsY(); ++iy)
00257 env_->UpdateCost(ix, iy, costMapCostToSBPLCost(cost_map_.getCost(ix,iy)));
00258
00259 if ("ARAPlanner" == planner_type_){
00260 planner_ = new ARAPlanner(env_, forward_search_);
00261 }
00262 else if ("ADPlanner" == planner_type_){
00263 planner_ = new ADPlanner(env_, forward_search_);
00264 }
00265 else{
00266 initialized_ = false;
00267 ROS_FATAL("ARAPlanner and ADPlanner are currently the only supported planners!\n");
00268 return;
00269 }
00270
00271 ROS_INFO("[sbpl_cart_planner] Initialized successfully");
00272 plan_pub_ = private_nh.advertise<nav_msgs::Path>("plan", 1);
00273 sbpl_plan_pub_ = private_nh.advertise<visualization_msgs::MarkerArray>("sbpl_plan_array", 1);
00274 sbpl_plan_footprint_pub_ = private_nh.advertise<visualization_msgs::MarkerArray>("sbpl_plan_footprint_array", 1);
00275 sbpl_robot_cart_plan_pub_ = private_nh.advertise<cart_pushing_msgs::RobotCartPath>("sbpl_robot_cart_plan", 1);
00276 stats_publisher_ = private_nh.advertise<sbpl_cart_planner::SBPLCartPlannerStats>("sbpl_cart_planner_stats", 1);
00277
00278 if(!env_->initialized_)
00279 initialized_ = false;
00280 else
00281 initialized_ = true;
00282 }
00283
00284 }
00285
00286 unsigned char SBPLCartPlanner::costMapCostToSBPLCost(unsigned char newcost)
00287 {
00288 if(newcost == costmap_2d::LETHAL_OBSTACLE)
00289 return lethal_obstacle_;
00290 else if(newcost == costmap_2d::INSCRIBED_INFLATED_OBSTACLE)
00291 return inscribed_inflated_obstacle_;
00292 else if(newcost == 0 || newcost == costmap_2d::NO_INFORMATION)
00293 return 0;
00294 else
00295 return (unsigned char) (newcost/sbpl_cost_multiplier_ + 0.5);
00296
00297 }
00298
00299 std::vector<geometry_msgs::Point> SBPLCartPlanner::loadRobotFootprint(ros::NodeHandle node)
00300 {
00301 std::vector<geometry_msgs::Point> footprint;
00302 geometry_msgs::Point pt;
00303 double padding;
00304
00305 std::string padding_param, footprint_param;
00306 if(!node.searchParam("footprint_padding", padding_param))
00307 padding = 0.01;
00308 else
00309 node.param(padding_param, padding, 0.01);
00310
00311
00312 XmlRpc::XmlRpcValue footprint_list;
00313 if(node.searchParam("cart_footprint", footprint_param)){
00314 ROS_INFO("Footprint param: %s", footprint_param.c_str());
00315 node.getParam(footprint_param, footprint_list);
00316
00317 if(!(footprint_list.getType() == XmlRpc::XmlRpcValue::TypeArray && footprint_list.size() > 2)){
00318 ROS_FATAL("The footprint must be specified as list of lists on the parameter server with at least 3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
00319 throw std::runtime_error("The footprint must be specified as list of lists on the parameter server with at least 3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
00320 }
00321 for(int i = 0; i < footprint_list.size(); ++i){
00322
00323 XmlRpc::XmlRpcValue point = footprint_list[i];
00324 if(!(point.getType() == XmlRpc::XmlRpcValue::TypeArray && point.size() == 2)){
00325 ROS_FATAL("The footprint must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
00326 throw std::runtime_error("The footprint must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
00327 }
00328
00329
00330 if(!(point[0].getType() == XmlRpc::XmlRpcValue::TypeInt || point[0].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
00331 ROS_FATAL("Values in the footprint specification must be numbers");
00332 throw std::runtime_error("Values in the footprint specification must be numbers");
00333 }
00334 pt.x = point[0].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(point[0]) : (double)(point[0]);
00335 pt.x += sign(pt.x) * padding;
00336
00337
00338 if(!(point[1].getType() == XmlRpc::XmlRpcValue::TypeInt || point[1].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
00339 ROS_FATAL("Values in the footprint specification must be numbers");
00340 throw std::runtime_error("Values in the footprint specification must be numbers");
00341 }
00342 pt.y = point[1].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(point[1]) : (double)(point[1]);
00343 pt.y += sign(pt.y) * padding;
00344
00345 footprint.push_back(pt);
00346
00347 }
00348 }
00349 return footprint;
00350 }
00351
00352
00353 bool SBPLCartPlanner::makePlan(const geometry_msgs::PoseStamped& start,
00354 const geometry_msgs::PoseStamped& goal,
00355 std::vector<geometry_msgs::PoseStamped>& plan){
00356 if(!initialized_)
00357 {
00358 ROS_ERROR("Global planner is not initialized");
00359 return false;
00360 }
00361
00362 plan.clear();
00363
00364 ROS_INFO("[sbpl_lattice_planner] getting fresh copy of costmap");
00365 costmap_ros_->clearRobotFootprint();
00366 ROS_INFO("[sbpl_lattice_planner] robot footprint cleared");
00367 geometry_msgs::Pose cart_pose = getGlobalCartPose(start.pose,0.0);
00368 costmap_ros_->getCostmapCopy(cost_map_);
00369 clearFootprint(cart_pose,cart_footprint_);
00370
00371 ROS_INFO("[sbpl_lattice_planner] getting start point (%g,%g) goal point (%g,%g)",
00372 start.pose.position.x, start.pose.position.y,goal.pose.position.x, goal.pose.position.y);
00373 double theta_start = 2 * atan2(start.pose.orientation.z, start.pose.orientation.w);
00374 double theta_goal = 2 * atan2(goal.pose.orientation.z, goal.pose.orientation.w);
00375 double cart_start = 0.0;
00376 double cart_goal = 0.0;
00377
00378 try
00379 {
00380 int ret = env_->SetStart(start.pose.position.x - cost_map_.getOriginX(), start.pose.position.y - cost_map_.getOriginY(), theta_start, cart_start);
00381 if(ret < 0 || planner_->set_start(ret) == 0){
00382 ROS_ERROR("Failed to set start state");
00383 return false;
00384 }
00385 }
00386 catch(SBPL_Exception e){
00387 ROS_ERROR("SBPL encountered a fatal exception while setting the start state");
00388 return false;
00389 }
00390
00391 try{
00392 int ret = env_->SetGoal(goal.pose.position.x - cost_map_.getOriginX(), goal.pose.position.y - cost_map_.getOriginY(), theta_goal, cart_goal);
00393 if(ret < 0 || planner_->set_goal(ret) == 0){
00394 ROS_ERROR("Failed to set goal state");
00395 return false;
00396 }
00397 }
00398 catch(SBPL_Exception e){
00399 ROS_ERROR("SBPL encountered a fatal exception while setting the goal state");
00400 return false;
00401 }
00402
00403
00404 int offOnCount = 0;
00405 int onOffCount = 0;
00406 int allCount = 0;
00407 vector<nav2dcell_t> changedcellsV;
00408
00409 for(unsigned int ix = 0; ix < cost_map_.getSizeInCellsX(); ix++) {
00410 for(unsigned int iy = 0; iy < cost_map_.getSizeInCellsY(); iy++) {
00411
00412 unsigned char oldCost = env_->GetMapCost(ix,iy);
00413 unsigned char newCost = cost_map_.getCost(ix,iy);
00414
00415 if(oldCost == newCost) continue;
00416
00417 allCount++;
00418
00419
00420
00421 if((oldCost != costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) && oldCost != costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE)) &&
00422 (newCost == costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) || newCost == costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE))) {
00423 offOnCount++;
00424 }
00425
00426 if((oldCost == costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) || oldCost == costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE)) &&
00427 (newCost != costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) && newCost != costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE))) {
00428 onOffCount++;
00429 }
00430 env_->UpdateCost(ix, iy, costMapCostToSBPLCost(cost_map_.getCost(ix,iy)));
00431
00432 nav2dcell_t nav2dcell;
00433 nav2dcell.x = ix;
00434 nav2dcell.y = iy;
00435 changedcellsV.push_back(nav2dcell);
00436 }
00437 }
00438
00439 try{
00440 if(!changedcellsV.empty()){
00441 StateChangeQuery* scq = new LatticeSCQ(env_, changedcellsV);
00442 planner_->costs_changed(*scq);
00443 delete scq;
00444 }
00445 if(allCount > force_scratch_limit_)
00446 planner_->force_planning_from_scratch();
00447 }
00448 catch(SBPL_Exception e){
00449 ROS_ERROR("SBPL failed to update the costmap");
00450 return false;
00451 }
00452
00453
00454 ROS_INFO("allocated:%f, init eps:%f\n",allocated_time_,initial_epsilon_);
00455 planner_->set_initialsolution_eps(initial_epsilon_);
00456 planner_->set_search_mode(false);
00457
00458 ROS_INFO("[sbpl_lattice_planner] run planner");
00459 vector<int> solution_stateIDs;
00460 int solution_cost;
00461 try{
00462 int ret = planner_->replan(allocated_time_, &solution_stateIDs, &solution_cost);
00463 if(ret)
00464 ROS_DEBUG("Solution is found\n");
00465 else
00466 {
00467 ROS_INFO("Solution does not exist\n");
00468 ARAPlanner *ara_planner = dynamic_cast<ARAPlanner*>(planner_);
00469
00470 sbpl_cart_planner::SBPLCartPlannerStats stats;
00471 stats.initial_epsilon = initial_epsilon_;
00472 stats.plan_to_first_solution = false;
00473 stats.allocated_time = allocated_time_;
00474 if(ara_planner)
00475 {
00476 stats.actual_time = ara_planner->get_final_eps_planning_time();
00477 stats.actual_time = ara_planner->get_initial_eps_planning_time();
00478 stats.number_of_expands_initial_solution = ara_planner->get_n_expands_init_solution();
00479 stats.final_epsilon = ara_planner->get_final_epsilon();
00480 }
00481 stats.solution_cost = solution_cost;
00482 stats.path_size = 0;
00483 stats.start = start;
00484 stats.goal = goal;
00485 stats.start_cart_angle = cart_start;
00486 stats.goal_cart_angle = cart_goal;
00487 stats_publisher_.publish(stats);
00488 stats.final_number_of_expands = planner_->get_n_expands();
00489 return false;
00490 }
00491 }
00492 catch(SBPL_Exception e){
00493 ROS_ERROR("SBPL encountered a fatal exception while planning");
00494 return false;
00495 }
00496
00497 ROS_DEBUG("size of solution=%d", (int)solution_stateIDs.size());
00498
00499 vector<EnvNAVXYTHETACARTLAT3Dpt_t> sbpl_path;
00500 try
00501 {
00502 env_->ConvertStateIDPathintoXYThetaPath(&solution_stateIDs, &sbpl_path);
00503 }
00504 catch(SBPL_Exception e)
00505 {
00506 ROS_ERROR("SBPL encountered a fatal exception while reconstructing the path");
00507 return false;
00508 }
00509
00510 ROS_INFO("Plan has %d points.\n", (int)sbpl_path.size());
00511 ros::Time plan_time = ros::Time::now();
00512
00513
00514 visualization_msgs::MarkerArray sbpl_plan_marker_array;
00515 convertPathToMarkerArray(sbpl_path,costmap_ros_->getGlobalFrameID(),sbpl_plan_marker_array);
00516 sbpl_plan_pub_.publish(sbpl_plan_marker_array);
00517
00518 visualization_msgs::MarkerArray sbpl_plan_footprint;
00519 getFootprintList(sbpl_path,costmap_ros_->getGlobalFrameID(),sbpl_plan_footprint);
00520 sbpl_plan_footprint_pub_.publish(sbpl_plan_footprint);
00521
00522
00523 nav_msgs::Path gui_path;
00524 gui_path.poses.resize(sbpl_path.size());
00525 gui_path.header.frame_id = costmap_ros_->getGlobalFrameID();
00526 gui_path.header.stamp = plan_time;
00527
00528 cart_pushing_msgs::RobotCartPath sbpl_robot_cart_plan;
00529 sbpl_robot_cart_plan.header.frame_id = costmap_ros_->getGlobalFrameID();
00530 sbpl_robot_cart_plan.header.stamp = plan_time;
00531
00532
00533 for(unsigned int i=0; i<sbpl_path.size(); i++){
00534 geometry_msgs::PoseStamped pose;
00535 pose.header.stamp = plan_time;
00536 pose.header.frame_id = costmap_ros_->getGlobalFrameID();
00537
00538 pose.pose.position.x = sbpl_path[i].x + cost_map_.getOriginX();
00539 pose.pose.position.y = sbpl_path[i].y + cost_map_.getOriginY();
00540 pose.pose.position.z = start.pose.position.z;
00541
00542 btQuaternion temp;
00543 temp.setEulerZYX(sbpl_path[i].theta,0,0);
00544 pose.pose.orientation.x = temp.getX();
00545 pose.pose.orientation.y = temp.getY();
00546 pose.pose.orientation.z = temp.getZ();
00547 pose.pose.orientation.w = temp.getW();
00548
00549 plan.push_back(pose);
00550
00551 cart_pushing_msgs::RobotCartConfiguration robot_cart_configuration;
00552 robot_cart_configuration.robot_pose = pose.pose;
00553 robot_cart_configuration.cart_pose = getLocalCartControlFramePose(sbpl_path[i]);
00554 ROS_DEBUG("Cartangle: %d %f",i,sbpl_path[i].cartangle);
00555 sbpl_robot_cart_plan.path.push_back(robot_cart_configuration);
00556
00557 gui_path.poses[i].pose.position.x = plan[i].pose.position.x;
00558 gui_path.poses[i].pose.position.y = plan[i].pose.position.y;
00559 gui_path.poses[i].pose.position.z = plan[i].pose.position.z;
00560 }
00561 plan_pub_.publish(gui_path);
00562 sbpl_robot_cart_plan_pub_.publish(sbpl_robot_cart_plan);
00563
00564 ARAPlanner *ara_planner = dynamic_cast<ARAPlanner*>(planner_);
00565
00566
00567 sbpl_cart_planner::SBPLCartPlannerStats stats;
00568 stats.initial_epsilon = initial_epsilon_;
00569 stats.plan_to_first_solution = false;
00570 stats.final_number_of_expands = planner_->get_n_expands();
00571 stats.allocated_time = allocated_time_;
00572 if(ara_planner)
00573 {
00574 stats.time_to_first_solution = ara_planner->get_initial_eps_planning_time();
00575 stats.actual_time = ara_planner->get_final_eps_planning_time();
00576 stats.number_of_expands_initial_solution = ara_planner->get_n_expands_init_solution();
00577 stats.final_epsilon = ara_planner->get_final_epsilon();
00578 }
00579 stats.solution_cost = solution_cost;
00580 stats.path_size = sbpl_path.size();
00581 stats.start = start;
00582 stats.goal = goal;
00583 stats.start_cart_angle = cart_start;
00584 stats.goal_cart_angle = cart_goal;
00585 stats.solution = sbpl_robot_cart_plan;
00586 stats_publisher_.publish(stats);
00587
00588 return true;
00589 }
00590
00591 void SBPLCartPlanner::convertPathToMarkerArray(const std::vector<EnvNAVXYTHETACARTLAT3Dpt_t> &sbpl_path,
00592 const std::string &path_frame_id,
00593 visualization_msgs::MarkerArray &ma)
00594 {
00595 unsigned int num_markers = sbpl_path.size();
00596 ma.markers.resize(2*num_markers);
00597
00598 for(unsigned int i=0; i< num_markers; i++)
00599 {
00600 ma.markers[2*i].header.frame_id = path_frame_id;
00601 ma.markers[2*i].header.stamp = ros::Time();
00602 ma.markers[2*i].ns = "sbpl_cart_plan";
00603 ma.markers[2*i].id = 2*i;
00604 ma.markers[2*i].type = visualization_msgs::Marker::ARROW;
00605 ma.markers[2*i].action = visualization_msgs::Marker::ADD;
00606 ma.markers[2*i].pose.position.x = sbpl_path[i].x;
00607 ma.markers[2*i].pose.position.y = sbpl_path[i].y;
00608 ma.markers[2*i].pose.position.z = 0.0;
00609 btQuaternion quat;
00610 quat.setRPY(0.0,0.0,sbpl_path[i].theta);
00611 tf::quaternionTFToMsg(quat,ma.markers[2*i].pose.orientation);
00612 ma.markers[2*i].scale.x = 0.1;
00613 ma.markers[2*i].scale.y = 0.05;
00614 ma.markers[2*i].scale.z = 0.05;
00615 ma.markers[2*i].color.a = 1.0;
00616 ma.markers[2*i].color.r = 0.0;
00617 ma.markers[2*i].color.g = 1.0;
00618 ma.markers[2*i].color.b = 0.0;
00619
00620 geometry_msgs::Pose cart_pose;
00621 cart_pose.position.x = sbpl_path[i].x + cos(sbpl_path[i].theta)*cart_offset_.x - sin(sbpl_path[i].theta)*cart_offset_.y;
00622 cart_pose.position.y = sbpl_path[i].y + sin(sbpl_path[i].theta)*cart_offset_.x + cos(sbpl_path[i].theta)*cart_offset_.y;
00623 cart_pose.position.z = 0.0;
00624 double yaw = sbpl_path[i].theta + sbpl_path[i].cartangle;
00625 quat.setRPY(0.0,0.0,yaw);
00626 tf::quaternionTFToMsg(quat,cart_pose.orientation);
00627
00628 ma.markers[2*i+1].header.frame_id = path_frame_id;
00629 ma.markers[2*i+1].header.stamp = ros::Time();
00630 ma.markers[2*i+1].ns = "sbpl_cart_plan";
00631 ma.markers[2*i+1].id = 2*i+1;
00632 ma.markers[2*i+1].type = visualization_msgs::Marker::ARROW;
00633 ma.markers[2*i+1].action = visualization_msgs::Marker::ADD;
00634 ma.markers[2*i+1].pose = cart_pose;
00635 ma.markers[2*i+1].scale.x = 0.1;
00636 ma.markers[2*i+1].scale.y = 0.05;
00637 ma.markers[2*i+1].scale.z = 0.05;
00638 ma.markers[2*i+1].color.a = 1.0;
00639 ma.markers[2*i+1].color.r = 1.0;
00640 ma.markers[2*i+1].color.g = 0.0;
00641 ma.markers[2*i+1].color.b = 0.0;
00642 }
00643 if(num_markers < num_sbpl_markers_)
00644 {
00645 for(unsigned int i = 0; i < (num_sbpl_markers_ - num_markers); i++)
00646 {
00647 visualization_msgs::Marker new_marker;
00648 new_marker.header.frame_id = path_frame_id;
00649 new_marker.header.stamp = ros::Time();
00650 new_marker.ns = "sbpl_cart_plan";
00651 new_marker.id = 2*(num_markers+i);
00652 new_marker.type = visualization_msgs::Marker::ARROW;
00653 new_marker.action = visualization_msgs::Marker::DELETE;
00654
00655 ma.markers.push_back(new_marker);
00656
00657 new_marker.id = 2*(num_markers+i)+1;
00658
00659 ma.markers.push_back(new_marker);
00660
00661 }
00662 }
00663 num_sbpl_markers_ = num_markers;
00664 }
00665
00666
00667
00668 geometry_msgs::Pose SBPLCartPlanner::getGlobalCartPose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00669 {
00670 geometry_msgs::Pose cart_pose;
00671 btQuaternion quat;
00672 cart_pose.position.x = sbpl_pose.x + cos(sbpl_pose.theta)*cart_offset_.x - sin(sbpl_pose.theta)*cart_offset_.y;
00673 cart_pose.position.y = sbpl_pose.y + sin(sbpl_pose.theta)*cart_offset_.x + cos(sbpl_pose.theta)*cart_offset_.y;
00674 cart_pose.position.z = 0.0;
00675 double yaw = sbpl_pose.theta + sbpl_pose.cartangle;
00676 quat.setRPY(0.0,0.0,yaw);
00677 tf::quaternionTFToMsg(quat,cart_pose.orientation);
00678 return cart_pose;
00679 }
00680
00681
00682 geometry_msgs::Pose SBPLCartPlanner::getLocalCartControlFramePose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00683 {
00684 geometry_msgs::Pose cart_pose;
00685 btQuaternion quat;
00686 cart_pose.position.x = cart_offset_.x + cos(sbpl_pose.cartangle)*cart_cp_offset_.x - sin(sbpl_pose.cartangle)*cart_cp_offset_.y;
00687 cart_pose.position.y = cart_offset_.y + sin(sbpl_pose.cartangle)*cart_cp_offset_.x + cos(sbpl_pose.cartangle)*cart_cp_offset_.y;
00688 cart_pose.position.z = 0.0;
00689 double yaw = sbpl_pose.cartangle;
00690 quat.setRPY(0.0,0.0,yaw);
00691 tf::quaternionTFToMsg(quat,cart_pose.orientation);
00692 return cart_pose;
00693 }
00694
00695 geometry_msgs::Pose SBPLCartPlanner::getLocalCartPose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00696 {
00697 geometry_msgs::Pose cart_pose;
00698 btQuaternion quat;
00699 cart_pose.position.x = cart_offset_.x;
00700 cart_pose.position.y = cart_offset_.y;
00701 cart_pose.position.z = 0.0;
00702 double yaw = sbpl_pose.cartangle;
00703 quat.setRPY(0.0,0.0,yaw);
00704 tf::quaternionTFToMsg(quat,cart_pose.orientation);
00705 return cart_pose;
00706 }
00707
00708 void SBPLCartPlanner::getFootprintList(const std::vector<EnvNAVXYTHETACARTLAT3Dpt_t> &sbpl_path,
00709 const std::string &path_frame_id,
00710 visualization_msgs::MarkerArray & ma)
00711 {
00712 ma.markers.resize(2);
00713 ma.markers[0].header.frame_id = path_frame_id;
00714 ma.markers[0].header.stamp = ros::Time();
00715 ma.markers[0].ns = "sbpl_cart_footprint";
00716 ma.markers[0].id = 0;
00717 ma.markers[0].type = visualization_msgs::Marker::LINE_LIST;
00718 ma.markers[0].action = visualization_msgs::Marker::ADD;
00719
00720 ma.markers[0].scale.x = 0.05;
00721 ma.markers[0].color.a = 1.0;
00722 ma.markers[0].color.r = 0.0;
00723 ma.markers[0].color.g = 0.0;
00724 ma.markers[0].color.b = 1.0;
00725
00726 ma.markers[1].header.frame_id = path_frame_id;
00727 ma.markers[1].header.stamp = ros::Time();
00728 ma.markers[1].ns = "sbpl_cart_footprint";
00729 ma.markers[1].id = 1;
00730 ma.markers[1].type = visualization_msgs::Marker::LINE_LIST;
00731 ma.markers[1].action = visualization_msgs::Marker::ADD;
00732
00733 ma.markers[1].scale.x = 0.05;
00734 ma.markers[1].color.a = 1.0;
00735 ma.markers[1].color.r = 0.0;
00736 ma.markers[1].color.g = 1.0;
00737 ma.markers[1].color.b = 0.0;
00738
00739
00740 for(unsigned int i=0; i < sbpl_path.size(); i= i+visualizer_skip_poses_)
00741 {
00742 std::vector<geometry_msgs::Point> transformed_cfp, transformed_rfp;
00743 geometry_msgs::Pose robot_pose;
00744 robot_pose.position.x = sbpl_path[i].x;
00745 robot_pose.position.y = sbpl_path[i].y;
00746 robot_pose.position.z = 0.0;
00747 btQuaternion quat;
00748 quat.setRPY(0.0,0.0,sbpl_path[i].theta);
00749 tf::quaternionTFToMsg(quat,robot_pose.orientation);
00750
00751 geometry_msgs::Pose cart_pose;
00752 cart_pose.position.x = sbpl_path[i].x + cos(sbpl_path[i].theta)*cart_offset_.x - sin(sbpl_path[i].theta)*cart_offset_.y;
00753 cart_pose.position.y = sbpl_path[i].y + sin(sbpl_path[i].theta)*cart_offset_.x + cos(sbpl_path[i].theta)*cart_offset_.y;
00754 cart_pose.position.z = 0.0;
00755 double yaw = sbpl_path[i].theta + sbpl_path[i].cartangle;
00756 quat.setRPY(0.0,0.0,yaw);
00757 tf::quaternionTFToMsg(quat,cart_pose.orientation);
00758
00759 transformFootprintToEdges(robot_pose,robot_footprint_,transformed_rfp);
00760 transformFootprintToEdges(cart_pose,cart_footprint_,transformed_cfp);
00761
00762 for(unsigned int i=0; i < transformed_rfp.size(); i++)
00763 ma.markers[0].points.push_back(transformed_rfp[i]);
00764
00765 for(unsigned int i=0; i < transformed_cfp.size(); i++)
00766 ma.markers[1].points.push_back(transformed_cfp[i]);
00767 }
00768
00769 return;
00770 }
00771
00772 void SBPLCartPlanner::transformFootprintToEdges(const geometry_msgs::Pose &robot_pose,
00773 const std::vector<geometry_msgs::Point> &footprint,
00774 std::vector<geometry_msgs::Point> &out_footprint)
00775 {
00776 out_footprint.resize(2*footprint.size());
00777 double yaw = tf::getYaw(robot_pose.orientation);
00778 for(unsigned int i=0; i < footprint.size(); i++)
00779 {
00780 out_footprint[2*i].x = robot_pose.position.x + cos(yaw)*footprint[i].x - sin(yaw)*footprint[i].y;
00781 out_footprint[2*i].y = robot_pose.position.y + sin(yaw)*footprint[i].x + cos(yaw)*footprint[i].y;
00782 if(i == 0)
00783 {
00784 out_footprint.back().x = out_footprint[i].x;
00785 out_footprint.back().y = out_footprint[i].y;
00786 }
00787 else
00788 {
00789 out_footprint[2*i-1].x = out_footprint[2*i].x;
00790 out_footprint[2*i-1].y = out_footprint[2*i].y;
00791 }
00792 }
00793 return;
00794 }
00795
00796 bool SBPLCartPlanner::clearFootprint(const geometry_msgs::Pose &robot_pose,
00797 const std::vector<geometry_msgs::Point> &footprint)
00798 {
00799 vector<geometry_msgs::Point> oriented_footprint;
00800 getOrientedFootprint(robot_pose, footprint, oriented_footprint);
00801
00802
00803 if(!cost_map_.setConvexPolygonCost(oriented_footprint, costmap_2d::FREE_SPACE))
00804 {
00805 ROS_ERROR("Could not clear robot footprint: ");
00806 for (uint i = 0; i < oriented_footprint.size(); ++i)
00807 ROS_ERROR("oriented_footprint: %.2lf %.2lf %.2lf", oriented_footprint[i].x, oriented_footprint[i].y, oriented_footprint[i].z);
00808 return false;
00809 }
00810 return true;
00811 }
00812
00813 void SBPLCartPlanner::getOrientedFootprint(const geometry_msgs::Pose &robot_pose,
00814 const std::vector<geometry_msgs::Point> &footprint,
00815 std::vector<geometry_msgs::Point> &oriented_footprint)
00816 {
00817 oriented_footprint.resize(footprint.size());
00818 double yaw = tf::getYaw(robot_pose.orientation);
00819 for(unsigned int i=0; i < footprint.size(); i++)
00820 {
00821 oriented_footprint[i].x = robot_pose.position.x + cos(yaw)*footprint[i].x - sin(yaw)*footprint[i].y;
00822 oriented_footprint[i].y = robot_pose.position.y + sin(yaw)*footprint[i].x + cos(yaw)*footprint[i].y;
00823 }
00824 return;
00825 }
00826
00827 geometry_msgs::Pose SBPLCartPlanner::getGlobalCartPose(const geometry_msgs::Pose &robot_pose, const double &cart_angle)
00828 {
00829 EnvNAVXYTHETACARTLAT3Dpt_t sbpl_pose;
00830 sbpl_pose.x = robot_pose.position.x;
00831 sbpl_pose.y = robot_pose.position.y;
00832 sbpl_pose.theta = tf::getYaw(robot_pose.orientation);
00833 sbpl_pose.cartangle = cart_angle;
00834 return getGlobalCartPose(sbpl_pose);
00835 }