00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <footstep_planner/FootstepPlanner.h>
00025 #include <humanoid_nav_msgs/ClipFootstep.h>
00026
00027
00028 using gridmap_2d::GridMap2D;
00029 using gridmap_2d::GridMap2DPtr;
00030
00031
00032 namespace footstep_planner
00033 {
00034 FootstepPlanner::FootstepPlanner()
00035 : ivStartPoseSetUp(false),
00036 ivGoalPoseSetUp(false),
00037 ivLastMarkerMsgSize(0),
00038 ivPathCost(0),
00039 ivMarkerNamespace("")
00040 {
00041
00042 ros::NodeHandle nh_private("~");
00043 ros::NodeHandle nh_public;
00044
00045
00046 ivExpandedStatesVisPub = nh_private.advertise<
00047 sensor_msgs::PointCloud>("expanded_states", 1);
00048 ivRandomStatesVisPub = nh_private.advertise<
00049 sensor_msgs::PointCloud>("random_states", 1);
00050 ivFootstepPathVisPub = nh_private.advertise<
00051 visualization_msgs::MarkerArray>("footsteps_array", 1);
00052 ivHeuristicPathVisPub = nh_private.advertise<
00053 nav_msgs::Path>("heuristic_path", 1);
00054 ivPathVisPub = nh_private.advertise<nav_msgs::Path>("path", 1);
00055 ivStartPoseVisPub = nh_private.advertise<
00056 geometry_msgs::PoseStamped>("start", 1);
00057
00058 std::string heuristic_type;
00059 double diff_angle_cost;
00060
00061
00062
00063 nh_private.param("heuristic_type", heuristic_type,
00064 std::string("EuclideanHeuristic"));
00065 nh_private.param("heuristic_scale", ivEnvironmentParams.heuristic_scale, 1.0);
00066 nh_private.param("max_hash_size", ivEnvironmentParams.hash_table_size, 65536);
00067 nh_private.param("accuracy/collision_check",
00068 ivEnvironmentParams.collision_check_accuracy,
00069 2);
00070 nh_private.param("accuracy/cell_size", ivEnvironmentParams.cell_size, 0.01);
00071 nh_private.param("accuracy/num_angle_bins",
00072 ivEnvironmentParams.num_angle_bins,
00073 64);
00074 nh_private.param("step_cost", ivEnvironmentParams.step_cost, 0.05);
00075 nh_private.param("diff_angle_cost", diff_angle_cost, 0.0);
00076
00077 nh_private.param("planner_type", ivPlannerType, std::string("ARAPlanner"));
00078 nh_private.param("search_until_first_solution", ivSearchUntilFirstSolution,
00079 false);
00080 nh_private.param("allocated_time", ivMaxSearchTime, 7.0);
00081 nh_private.param("forward_search", ivEnvironmentParams.forward_search, false);
00082 nh_private.param("initial_epsilon", ivInitialEpsilon, 3.0);
00083 nh_private.param("changed_cells_limit", ivChangedCellsLimit, 20000);
00084 nh_private.param("num_random_nodes", ivEnvironmentParams.num_random_nodes,
00085 20);
00086 nh_private.param("random_node_dist", ivEnvironmentParams.random_node_distance,
00087 1.0);
00088
00089
00090 nh_private.param("foot/size/x", ivEnvironmentParams.footsize_x, 0.16);
00091 nh_private.param("foot/size/y", ivEnvironmentParams.footsize_y, 0.06);
00092 nh_private.param("foot/size/z", ivEnvironmentParams.footsize_z, 0.015);
00093 nh_private.param("foot/separation", ivFootSeparation, 0.1);
00094 nh_private.param("foot/origin_shift/x",
00095 ivEnvironmentParams.foot_origin_shift_x,
00096 0.02);
00097 nh_private.param("foot/origin_shift/y",
00098 ivEnvironmentParams.foot_origin_shift_y,
00099 0.0);
00100 nh_private.param("foot/max/step/x", ivEnvironmentParams.max_footstep_x, 0.08);
00101 nh_private.param("foot/max/step/y", ivEnvironmentParams.max_footstep_y, 0.16);
00102 nh_private.param("foot/max/step/theta",
00103 ivEnvironmentParams.max_footstep_theta,
00104 0.3);
00105 nh_private.param("foot/max/inverse/step/x",
00106 ivEnvironmentParams.max_inverse_footstep_x,
00107 -0.04);
00108 nh_private.param("foot/max/inverse/step/y",
00109 ivEnvironmentParams.max_inverse_footstep_y,
00110 0.09);
00111 nh_private.param("foot/max/inverse/step/theta",
00112 ivEnvironmentParams.max_inverse_footstep_theta,
00113 -0.3);
00114
00115
00116 XmlRpc::XmlRpcValue footsteps_x;
00117 XmlRpc::XmlRpcValue footsteps_y;
00118 XmlRpc::XmlRpcValue footsteps_theta;
00119 nh_private.getParam("footsteps/x", footsteps_x);
00120 nh_private.getParam("footsteps/y", footsteps_y);
00121 nh_private.getParam("footsteps/theta", footsteps_theta);
00122 if (footsteps_x.getType() != XmlRpc::XmlRpcValue::TypeArray)
00123 ROS_ERROR("Error reading footsteps/x from config file.");
00124 if (footsteps_y.getType() != XmlRpc::XmlRpcValue::TypeArray)
00125 ROS_ERROR("Error reading footsteps/y from config file.");
00126 if (footsteps_theta.getType() != XmlRpc::XmlRpcValue::TypeArray)
00127 ROS_ERROR("Error reading footsteps/theta from config file.");
00128 int size_x = footsteps_x.size();
00129 int size_y = footsteps_y.size();
00130 int size_t = footsteps_theta.size();
00131 if (size_x != size_y || size_x != size_t)
00132 {
00133 ROS_ERROR("Footstep parameterization has different sizes for x/y/theta. "
00134 "Exit!");
00135 exit(2);
00136 }
00137
00138 ivEnvironmentParams.footstep_set.clear();
00139 double max_step_width = 0;
00140 for(int i=0; i < footsteps_x.size(); ++i)
00141 {
00142 double x = (double)footsteps_x[i];
00143 double y = (double)footsteps_y[i];
00144 double theta = (double)footsteps_theta[i];
00145
00146 Footstep f(x, y, theta,
00147 ivEnvironmentParams.cell_size,
00148 ivEnvironmentParams.num_angle_bins,
00149 ivEnvironmentParams.hash_table_size);
00150 ivEnvironmentParams.footstep_set.push_back(f);
00151
00152 double cur_step_width = sqrt(x*x + y*y);
00153
00154 if (cur_step_width > max_step_width)
00155 max_step_width = cur_step_width;
00156 }
00157
00158
00159 XmlRpc::XmlRpcValue step_range_x;
00160 XmlRpc::XmlRpcValue step_range_y;
00161 nh_private.getParam("step_range/x", step_range_x);
00162 nh_private.getParam("step_range/y", step_range_y);
00163 if (step_range_x.getType() != XmlRpc::XmlRpcValue::TypeArray)
00164 ROS_ERROR("Error reading footsteps/x from config file.");
00165 if (step_range_y.getType() != XmlRpc::XmlRpcValue::TypeArray)
00166 ROS_ERROR("Error reading footsteps/y from config file.");
00167 if (step_range_x.size() != step_range_y.size())
00168 {
00169 ROS_ERROR("Step range points have different size. Exit!");
00170 exit(2);
00171 }
00172
00173 ivEnvironmentParams.step_range.clear();
00174 ivEnvironmentParams.step_range.reserve(step_range_x.size());
00175 double x, y;
00176 double max_x = 0.0;
00177 double max_y = 0.0;
00178 double cell_size = ivEnvironmentParams.cell_size;
00179 for (int i=0; i < step_range_x.size(); ++i)
00180 {
00181 x = (double)step_range_x[i];
00182 y = (double)step_range_y[i];
00183 if (fabs(x) > max_x)
00184 max_x = fabs(x);
00185 if (fabs(y) > max_y)
00186 max_y = fabs(y);
00187 ivEnvironmentParams.step_range.push_back(
00188 std::pair<int, int>(disc_val(x, cell_size), disc_val(y, cell_size)));
00189 }
00190
00191 ivEnvironmentParams.step_range.push_back(ivEnvironmentParams.step_range[0]);
00192 ivEnvironmentParams.max_step_width = sqrt(max_x*max_x + max_y*max_y) * 1.5;
00193
00194
00195 boost::shared_ptr<Heuristic> h;
00196 if (heuristic_type == "EuclideanHeuristic")
00197 {
00198 h.reset(
00199 new EuclideanHeuristic(ivEnvironmentParams.cell_size,
00200 ivEnvironmentParams.num_angle_bins));
00201 ROS_INFO("FootstepPlanner heuristic: euclidean distance");
00202 }
00203 else if(heuristic_type == "EuclStepCostHeuristic")
00204 {
00205 h.reset(
00206 new EuclStepCostHeuristic(ivEnvironmentParams.cell_size,
00207 ivEnvironmentParams.num_angle_bins,
00208 ivEnvironmentParams.step_cost,
00209 diff_angle_cost,
00210 max_step_width));
00211 ROS_INFO("FootstepPlanner heuristic: euclidean distance with step costs");
00212 }
00213 else if (heuristic_type == "PathCostHeuristic")
00214 {
00215
00216 double foot_incircle =
00217 std::min((ivEnvironmentParams.footsize_x / 2.0 -
00218 std::abs(ivEnvironmentParams.foot_origin_shift_x)),
00219 (ivEnvironmentParams.footsize_y / 2.0 -
00220 std::abs(ivEnvironmentParams.foot_origin_shift_y)));
00221 assert(foot_incircle > 0.0);
00222
00223 h.reset(
00224 new PathCostHeuristic(ivEnvironmentParams.cell_size,
00225 ivEnvironmentParams.num_angle_bins,
00226 ivEnvironmentParams.step_cost,
00227 diff_angle_cost,
00228 max_step_width,
00229 foot_incircle));
00230 ROS_INFO("FootstepPlanner heuristic: 2D path euclidean distance with step "
00231 "costs");
00232
00233
00234 ivPathCostHeuristicPtr = boost::dynamic_pointer_cast<PathCostHeuristic>(h);
00235 }
00236 else
00237 {
00238 ROS_ERROR_STREAM("Heuristic " << heuristic_type << " not available, "
00239 "exiting.");
00240 exit(1);
00241 }
00242 ivEnvironmentParams.heuristic = h;
00243
00244
00245 ivPlannerEnvironmentPtr.reset(
00246 new FootstepPlannerEnvironment(ivEnvironmentParams));
00247
00248
00249 if (ivPlannerType == "ARAPlanner" ||
00250 ivPlannerType == "ADPlanner" ||
00251 ivPlannerType == "RSTARPlanner" )
00252 {
00253 ROS_INFO_STREAM("Planning with " << ivPlannerType);
00254 }
00255 else
00256 {
00257 ROS_ERROR_STREAM("Planner "<< ivPlannerType <<" not available / "
00258 "untested.");
00259 exit(1);
00260 }
00261 if (ivEnvironmentParams.forward_search)
00262 {
00263 ROS_INFO_STREAM("Search direction: forward planning");
00264 }
00265 else
00266 {
00267 ROS_INFO_STREAM("Search direction: backward planning");
00268 }
00269 setPlanner();
00270 }
00271
00272
00273 FootstepPlanner::~FootstepPlanner()
00274 {}
00275
00276
00277 void
00278 FootstepPlanner::setPlanner()
00279 {
00280 if (ivPlannerType == "ARAPlanner")
00281 {
00282 ivPlannerPtr.reset(
00283 new ARAPlanner(ivPlannerEnvironmentPtr.get(),
00284 ivEnvironmentParams.forward_search));
00285 }
00286 else if (ivPlannerType == "ADPlanner")
00287 {
00288 ivPlannerPtr.reset(
00289 new ADPlanner(ivPlannerEnvironmentPtr.get(),
00290 ivEnvironmentParams.forward_search));
00291 }
00292 else if (ivPlannerType == "RSTARPlanner")
00293 {
00294 RSTARPlanner* p =
00295 new RSTARPlanner(ivPlannerEnvironmentPtr.get(),
00296 ivEnvironmentParams.forward_search);
00297
00298
00299
00300 ivPlannerPtr.reset(p);
00301 }
00302
00303
00304
00305 }
00306
00307
00308 bool
00309 FootstepPlanner::run()
00310 {
00311 bool path_existed = (bool)ivPath.size();
00312 int ret = 0;
00313 MDPConfig mdp_config;
00314 std::vector<int> solution_state_ids;
00315
00316
00317 ivPlannerEnvironmentPtr->updateStart(ivStartFootLeft, ivStartFootRight);
00318 ivPlannerEnvironmentPtr->updateGoal(ivGoalFootLeft, ivGoalFootRight);
00319 ivPlannerEnvironmentPtr->updateHeuristicValues();
00320 ivPlannerEnvironmentPtr->InitializeEnv(NULL);
00321 ivPlannerEnvironmentPtr->InitializeMDPCfg(&mdp_config);
00322
00323
00324 if (path_existed &&
00325 !ivEnvironmentParams.forward_search &&
00326 ivPlannerType == "ADPlanner")
00327 {
00328 std::vector<int> changed_edges;
00329 changed_edges.push_back(mdp_config.startstateid);
00330
00331 boost::shared_ptr<ADPlanner> ad_planner =
00332 boost::dynamic_pointer_cast<ADPlanner>(ivPlannerPtr);
00333 ad_planner->update_preds_of_changededges(&changed_edges);
00334 }
00335
00336
00337 if (ivPlannerPtr->set_start(mdp_config.startstateid) == 0)
00338 {
00339 ROS_ERROR("Failed to set start state.");
00340 return false;
00341 }
00342 if (ivPlannerPtr->set_goal(mdp_config.goalstateid) == 0)
00343 {
00344 ROS_ERROR("Failed to set goal state\n");
00345 return false;
00346 }
00347
00348 ivPlannerPtr->set_initialsolution_eps(ivInitialEpsilon);
00349 ivPlannerPtr->set_search_mode(ivSearchUntilFirstSolution);
00350
00351 ROS_INFO("Start planning (max time: %f, initial eps: %f (%f))\n",
00352 ivMaxSearchTime, ivInitialEpsilon,
00353 ivPlannerPtr->get_initial_eps());
00354 int path_cost;
00355 ros::WallTime startTime = ros::WallTime::now();
00356 try
00357 {
00358 ret = ivPlannerPtr->replan(ivMaxSearchTime, &solution_state_ids,
00359 &path_cost);
00360 }
00361 catch (const SBPL_Exception& e)
00362 {
00363
00364 return false;
00365 }
00366 ivPathCost = double(path_cost) / FootstepPlannerEnvironment::cvMmScale;
00367
00368 bool path_is_new = pathIsNew(solution_state_ids);
00369 if (ret && solution_state_ids.size() > 0 && path_is_new)
00370 {
00371 ROS_INFO("Solution of size %zu found after %f s",
00372 solution_state_ids.size(),
00373 (ros::WallTime::now()-startTime).toSec());
00374
00375 if (extractPath(solution_state_ids))
00376 {
00377 ROS_INFO("Expanded states: %i total / %i new",
00378 ivPlannerEnvironmentPtr->getNumExpandedStates(),
00379 ivPlannerPtr->get_n_expands());
00380 ROS_INFO("Final eps: %f", ivPlannerPtr->get_final_epsilon());
00381 ROS_INFO("Path cost: %f (%i)\n", ivPathCost, path_cost);
00382
00383 ivPlanningStatesIds = solution_state_ids;
00384
00385 broadcastExpandedNodesVis();
00386 broadcastRandomNodesVis();
00387 broadcastFootstepPathVis();
00388 broadcastPathVis();
00389
00390 return true;
00391 }
00392 else
00393 {
00394 ROS_ERROR("extracting path failed\n\n");
00395 return false;
00396 }
00397 }
00398 else if (!path_is_new)
00399 {
00400 ROS_ERROR("Solution found by SBPL is the same as the old solution. "
00401 "Replanning failed.");
00402 return false;
00403 }
00404 else
00405 {
00406 broadcastExpandedNodesVis();
00407 broadcastRandomNodesVis();
00408
00409 ROS_ERROR("No solution found");
00410 return false;
00411 }
00412 }
00413
00414
00415 bool
00416 FootstepPlanner::extractPath(const std::vector<int>& state_ids)
00417 {
00418 ivPath.clear();
00419
00420 State s;
00421 State start_left;
00422 std::vector<int>::const_iterator state_ids_iter = state_ids.begin();
00423
00424
00425 if (!ivPlannerEnvironmentPtr->getState(*state_ids_iter, &start_left))
00426 {
00427 ivPath.clear();
00428 return false;
00429 }
00430 ++state_ids_iter;
00431 if (!ivPlannerEnvironmentPtr->getState(*state_ids_iter, &s))
00432 {
00433 ivPath.clear();
00434 return false;
00435 }
00436 ++state_ids_iter;
00437
00438
00439
00440 if (s.getLeg() == LEFT)
00441 ivPath.push_back(ivStartFootRight);
00442 else
00443 ivPath.push_back(start_left);
00444 ivPath.push_back(s);
00445
00446 for(; state_ids_iter < state_ids.end(); ++state_ids_iter)
00447 {
00448 if (!ivPlannerEnvironmentPtr->getState(*state_ids_iter, &s))
00449 {
00450 ivPath.clear();
00451 return false;
00452 }
00453 ivPath.push_back(s);
00454 }
00455
00456
00457 if (ivPath.back().getLeg() == RIGHT)
00458 ivPath.push_back(ivGoalFootLeft);
00459 else
00460 ivPath.push_back(ivGoalFootRight);
00461
00462 return true;
00463 }
00464
00465
00466 void
00467 FootstepPlanner::reset()
00468 {
00469
00470 ivPath.clear();
00471 ivPlanningStatesIds.clear();
00472
00473
00474
00475
00476
00477 ivPlannerEnvironmentPtr->reset();
00478 setPlanner();
00479 }
00480
00481
00482 void
00483 FootstepPlanner::resetTotally()
00484 {
00485
00486 ivPath.clear();
00487 ivPlanningStatesIds.clear();
00488
00489 ivPlannerEnvironmentPtr.reset(
00490 new FootstepPlannerEnvironment(ivEnvironmentParams));
00491 setPlanner();
00492 }
00493
00494
00495 bool
00496 FootstepPlanner::plan()
00497 {
00498 if (!ivMapPtr)
00499 {
00500 ROS_ERROR("FootstepPlanner has no map for planning yet.");
00501 return false;
00502 }
00503 if (!ivGoalPoseSetUp || !ivStartPoseSetUp)
00504 {
00505 ROS_ERROR("FootstepPlanner has not set the start and/or goal pose "
00506 "yet.");
00507 return false;
00508 }
00509
00510 reset();
00511
00512 return run();
00513 }
00514
00515
00516 bool
00517 FootstepPlanner::replan()
00518 {
00519 if (!ivMapPtr)
00520 {
00521 ROS_ERROR("FootstepPlanner has no map for re-planning yet.");
00522 return false;
00523 }
00524 if (!ivGoalPoseSetUp || !ivStartPoseSetUp)
00525 {
00526 ROS_ERROR("FootstepPlanner has not set start and/or goal pose yet.");
00527 return false;
00528 }
00529
00530 if (ivPlannerType == "RSTARPlanner" || ivPlannerType == "ARAPlanner")
00531 {
00532 ROS_INFO("Reset planning information because planner cannot handle "
00533 "replanning.");
00534 reset();
00535 }
00536
00537 return run();
00538 }
00539
00540
00541 bool
00542 FootstepPlanner::plan(const geometry_msgs::PoseStampedConstPtr start,
00543 const geometry_msgs::PoseStampedConstPtr goal)
00544 {
00545 return plan(start->pose.position.x, start->pose.position.y,
00546 tf::getYaw(start->pose.orientation),
00547 goal->pose.position.x, goal->pose.position.y,
00548 tf::getYaw(goal->pose.orientation));
00549 }
00550
00551
00552 bool
00553 FootstepPlanner::plan(float start_x, float start_y, float start_theta,
00554 float goal_x, float goal_y, float goal_theta)
00555 {
00556 if (!(setStart(start_x, start_y, start_theta) &&
00557 setGoal(goal_x, goal_y, goal_theta)))
00558 {
00559 return false;
00560 }
00561
00562 return plan();
00563 }
00564
00565
00566 bool
00567 FootstepPlanner::planService(humanoid_nav_msgs::PlanFootsteps::Request &req,
00568 humanoid_nav_msgs::PlanFootsteps::Response &resp)
00569 {
00570 bool result = plan(req.start.x, req.start.y, req.start.theta,
00571 req.goal.x, req.goal.y, req.goal.theta);
00572
00573 resp.costs = getPathCosts();
00574 resp.footsteps.reserve(getPathSize());
00575 resp.final_eps = ivPlannerPtr->get_final_epsilon();
00576 resp.expanded_states = ivPlannerEnvironmentPtr->getNumExpandedStates();
00577
00578 humanoid_nav_msgs::StepTarget foot;
00579 state_iter_t path_iter;
00580 for (path_iter = getPathBegin(); path_iter != getPathEnd(); ++path_iter)
00581 {
00582 foot.pose.x = path_iter->getX();
00583 foot.pose.y = path_iter->getY();
00584 foot.pose.theta = path_iter->getTheta();
00585 if (path_iter->getLeg() == LEFT)
00586 foot.leg = humanoid_nav_msgs::StepTarget::left;
00587 else if (path_iter->getLeg() == RIGHT)
00588 foot.leg = humanoid_nav_msgs::StepTarget::right;
00589 else
00590 {
00591 ROS_ERROR("Footstep pose at (%f, %f, %f) is set to NOLEG!",
00592 path_iter->getX(), path_iter->getY(),
00593 path_iter->getTheta());
00594 continue;
00595 }
00596
00597 resp.footsteps.push_back(foot);
00598 }
00599 resp.result = result;
00600
00601
00602
00603 return true;
00604 }
00605
00606
00607 void
00608 FootstepPlanner::goalPoseCallback(
00609 const geometry_msgs::PoseStampedConstPtr& goal_pose)
00610 {
00611
00612 if (setGoal(goal_pose))
00613 {
00614 if (ivStartPoseSetUp)
00615 {
00616
00617
00618 if (ivEnvironmentParams.forward_search)
00619 replan();
00620 else
00621 plan();
00622 }
00623 }
00624 }
00625
00626
00627 void
00628 FootstepPlanner::startPoseCallback(
00629 const geometry_msgs::PoseWithCovarianceStampedConstPtr& start_pose)
00630 {
00631 if (setStart(start_pose->pose.pose.position.x,
00632 start_pose->pose.pose.position.y,
00633 tf::getYaw(start_pose->pose.pose.orientation)))
00634 {
00635 if (ivGoalPoseSetUp)
00636 {
00637
00638
00639 if (ivEnvironmentParams.forward_search)
00640 plan();
00641 else
00642 replan();
00643 }
00644 }
00645 }
00646
00647
00648 void
00649 FootstepPlanner::mapCallback(
00650 const nav_msgs::OccupancyGridConstPtr& occupancy_map)
00651 {
00652 GridMap2DPtr map(new GridMap2D(occupancy_map));
00653
00654
00655 if (updateMap(map))
00656 {
00657
00658
00659 replan();
00660 }
00661 }
00662
00663
00664 bool
00665 FootstepPlanner::setGoal(const geometry_msgs::PoseStampedConstPtr goal_pose)
00666 {
00667 return setGoal(goal_pose->pose.position.x,
00668 goal_pose->pose.position.y,
00669 tf::getYaw(goal_pose->pose.orientation));
00670 }
00671
00672
00673 bool
00674 FootstepPlanner::setGoal(float x, float y, float theta)
00675 {
00676 if (!ivMapPtr)
00677 {
00678 ROS_ERROR("Distance map hasn't been initialized yet.");
00679 return false;
00680 }
00681
00682 State goal(x, y, theta, NOLEG);
00683 State foot_left = getFootPose(goal, LEFT);
00684 State foot_right = getFootPose(goal, RIGHT);
00685
00686 if (ivPlannerEnvironmentPtr->occupied(foot_left) ||
00687 ivPlannerEnvironmentPtr->occupied(foot_right))
00688 {
00689 ROS_ERROR("Goal pose at (%f %f %f) not accessible.", x, y, theta);
00690 ivGoalPoseSetUp = false;
00691 return false;
00692 }
00693 ivGoalFootLeft = foot_left;
00694 ivGoalFootRight = foot_right;
00695
00696 ivGoalPoseSetUp = true;
00697 ROS_INFO("Goal pose set to (%f %f %f)", x, y, theta);
00698
00699 return true;
00700 }
00701
00702
00703 bool
00704 FootstepPlanner::setStart(const geometry_msgs::PoseStampedConstPtr start_pose)
00705 {
00706 return setStart(start_pose->pose.position.x,
00707 start_pose->pose.position.y,
00708 tf::getYaw(start_pose->pose.orientation));
00709 }
00710
00711
00712 bool
00713 FootstepPlanner::setStart(const State& left_foot, const State& right_foot)
00714 {
00715 if (ivPlannerEnvironmentPtr->occupied(left_foot) ||
00716 ivPlannerEnvironmentPtr->occupied(right_foot))
00717 {
00718 ivStartPoseSetUp = false;
00719 return false;
00720 }
00721 ivStartFootLeft = left_foot;
00722 ivStartFootRight = right_foot;
00723
00724 ivStartPoseSetUp = true;
00725
00726 return true;
00727 }
00728
00729
00730 bool
00731 FootstepPlanner::setStart(float x, float y, float theta)
00732 {
00733 if (!ivMapPtr)
00734 {
00735 ROS_ERROR("Distance map hasn't been initialized yet.");
00736 return false;
00737 }
00738
00739 State start(x, y, theta, NOLEG);
00740 State foot_left = getFootPose(start, LEFT);
00741 State foot_right = getFootPose(start, RIGHT);
00742
00743 bool success = setStart(foot_left, foot_right);
00744 if (success)
00745 ROS_INFO("Start pose set to (%f %f %f)", x, y, theta);
00746 else
00747 ROS_ERROR("Start pose (%f %f %f) not accessible.", x, y, theta);
00748
00749
00750 geometry_msgs::PoseStamped start_pose;
00751 start_pose.pose.position.x = x;
00752 start_pose.pose.position.y = y;
00753 start_pose.pose.position.z = 0.025;
00754 start_pose.pose.orientation = tf::createQuaternionMsgFromYaw(theta);
00755 start_pose.header.frame_id = ivMapPtr->getFrameID();
00756 start_pose.header.stamp = ros::Time::now();
00757 ivStartPoseVisPub.publish(start_pose);
00758
00759 return success;
00760 }
00761
00762
00763 bool
00764 FootstepPlanner::updateMap(const GridMap2DPtr map)
00765 {
00766
00767 GridMap2DPtr old_map = ivMapPtr;
00768
00769 ivMapPtr.reset();
00770 ivMapPtr = map;
00771
00772
00773 if (old_map && (bool)ivPath.size())
00774 {
00775 updateEnvironment(old_map);
00776 return true;
00777 }
00778
00779
00780 ivPlannerEnvironmentPtr->updateMap(map);
00781 return false;
00782 }
00783
00784
00785 void
00786 FootstepPlanner::updateEnvironment(const GridMap2DPtr old_map)
00787 {
00788 ROS_INFO("Reseting the planning environment.");
00789
00790 resetTotally();
00791
00792 ivPlannerEnvironmentPtr->updateMap(ivMapPtr);
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 }
00899
00900
00901 State
00902 FootstepPlanner::getFootPose(const State& robot, Leg leg)
00903 {
00904 double shift_x = -sin(robot.getTheta()) * ivFootSeparation / 2.0;
00905 double shift_y = cos(robot.getTheta()) * ivFootSeparation / 2.0;
00906
00907 double sign = -1.0;
00908 if (leg == LEFT)
00909 sign = 1.0;
00910
00911 return State(robot.getX() + sign * shift_x,
00912 robot.getY() + sign * shift_y,
00913 robot.getTheta(),
00914 leg);
00915 }
00916
00917
00918 bool
00919 FootstepPlanner::pathIsNew(const std::vector<int>& new_path)
00920 {
00921 if (new_path.size() != ivPlanningStatesIds.size())
00922 return true;
00923
00924 bool unequal = true;
00925 for (unsigned i = 0; i < new_path.size(); ++i)
00926 unequal = new_path[i] != ivPlanningStatesIds[i] && unequal;
00927
00928 return unequal;
00929 }
00930
00931
00932 void
00933 FootstepPlanner::clearFootstepPathVis(unsigned num_footsteps)
00934 {
00935 visualization_msgs::Marker marker;
00936 visualization_msgs::MarkerArray marker_msg;
00937
00938 marker.header.stamp = ros::Time::now();
00939 marker.header.frame_id = ivMapPtr->getFrameID();
00940
00941
00942 if (num_footsteps < 1)
00943 num_footsteps = ivLastMarkerMsgSize;
00944
00945 for (unsigned i = 0; i < num_footsteps; ++i)
00946 {
00947 marker.ns = ivMarkerNamespace;
00948 marker.id = i;
00949 marker.action = visualization_msgs::Marker::DELETE;
00950
00951 marker_msg.markers.push_back(marker);
00952 }
00953
00954 ivFootstepPathVisPub.publish(marker_msg);
00955 }
00956
00957
00958 void
00959 FootstepPlanner::broadcastExpandedNodesVis()
00960 {
00961 if (ivExpandedStatesVisPub.getNumSubscribers() > 0)
00962 {
00963 sensor_msgs::PointCloud cloud_msg;
00964 geometry_msgs::Point32 point;
00965 std::vector<geometry_msgs::Point32> points;
00966
00967 State s;
00968 FootstepPlannerEnvironment::exp_states_2d_iter_t state_id_it;
00969 for(state_id_it = ivPlannerEnvironmentPtr->getExpandedStatesStart();
00970 state_id_it != ivPlannerEnvironmentPtr->getExpandedStatesEnd();
00971 ++state_id_it)
00972 {
00973 point.x = cell_2_state(state_id_it->first,
00974 ivEnvironmentParams.cell_size);
00975 point.y = cell_2_state(state_id_it->second,
00976 ivEnvironmentParams.cell_size);
00977 point.z = 0.01;
00978 points.push_back(point);
00979 }
00980 cloud_msg.header.stamp = ros::Time::now();
00981 cloud_msg.header.frame_id = ivMapPtr->getFrameID();
00982
00983 cloud_msg.points = points;
00984
00985 ivExpandedStatesVisPub.publish(cloud_msg);
00986 }
00987 }
00988
00989
00990 void
00991 FootstepPlanner::broadcastFootstepPathVis()
00992 {
00993 if (getPathSize() == 0)
00994 {
00995 ROS_INFO("no path has been extracted yet");
00996 return;
00997 }
00998
00999 clearFootstepPathVis(0);
01000
01001 visualization_msgs::Marker marker;
01002 visualization_msgs::MarkerArray broadcast_msg;
01003 std::vector<visualization_msgs::Marker> markers;
01004
01005 int markers_counter = 0;
01006
01007 marker.header.stamp = ros::Time::now();
01008 marker.header.frame_id = ivMapPtr->getFrameID();
01009
01010
01011 if (ivPath.front().getLeg() == LEFT)
01012 footPoseToMarker(ivStartFootRight, &marker);
01013 else
01014 footPoseToMarker(ivStartFootLeft, &marker);
01015 marker.id = markers_counter++;
01016 markers.push_back(marker);
01017
01018
01019 for(state_iter_t path_iter = getPathBegin(); path_iter != getPathEnd();
01020 ++path_iter)
01021 {
01022 footPoseToMarker(*path_iter, &marker);
01023 marker.id = markers_counter++;
01024 markers.push_back(marker);
01025 }
01026
01027 broadcast_msg.markers = markers;
01028 ivLastMarkerMsgSize = markers.size();
01029
01030 ivFootstepPathVisPub.publish(broadcast_msg);
01031 }
01032
01033
01034 void
01035 FootstepPlanner::broadcastRandomNodesVis()
01036 {
01037 if (ivRandomStatesVisPub.getNumSubscribers() > 0){
01038 sensor_msgs::PointCloud cloud_msg;
01039 geometry_msgs::Point32 point;
01040 std::vector<geometry_msgs::Point32> points;
01041 visualization_msgs::Marker marker;
01042 visualization_msgs::MarkerArray broadcast_msg;
01043 std::vector<visualization_msgs::Marker> markers;
01044
01045 marker.header.stamp = ros::Time::now();
01046 marker.header.frame_id = ivMapPtr->getFrameID();
01047
01048 State s;
01049 FootstepPlannerEnvironment::exp_states_iter_t state_id_iter;
01050 for(state_id_iter = ivPlannerEnvironmentPtr->getRandomStatesStart();
01051 state_id_iter != ivPlannerEnvironmentPtr->getRandomStatesEnd();
01052 ++state_id_iter)
01053 {
01054 if (!ivPlannerEnvironmentPtr->getState(*state_id_iter, &s))
01055 {
01056 ROS_WARN("Could not get random state %d", *state_id_iter);
01057 }
01058 else
01059 {
01060 point.x = s.getX();
01061 point.y = s.getY();
01062 point.z = 0.01;
01063 points.push_back(point);
01064 }
01065 }
01066 cloud_msg.header.stamp = ros::Time::now();
01067 cloud_msg.header.frame_id = ivMapPtr->getFrameID();
01068
01069 cloud_msg.points = points;
01070
01071 ivRandomStatesVisPub.publish(cloud_msg);
01072 }
01073 }
01074
01075
01076 void
01077 FootstepPlanner::broadcastPathVis()
01078 {
01079 if (getPathSize() == 0)
01080 {
01081 ROS_INFO("no path has been extracted yet");
01082 return;
01083 }
01084
01085 nav_msgs::Path path_msg;
01086 geometry_msgs::PoseStamped state;
01087
01088 state.header.stamp = ros::Time::now();
01089 state.header.frame_id = ivMapPtr->getFrameID();
01090
01091 state_iter_t path_iter;
01092 for(path_iter = getPathBegin(); path_iter != getPathEnd(); ++path_iter)
01093 {
01094 state.pose.position.x = path_iter->getX();
01095 state.pose.position.y = path_iter->getY();
01096 path_msg.poses.push_back(state);
01097 }
01098
01099 path_msg.header = state.header;
01100 ivPathVisPub.publish(path_msg);
01101 }
01102
01103
01104 void
01105 FootstepPlanner::footPoseToMarker(const State& foot_pose,
01106 visualization_msgs::Marker* marker)
01107 {
01108 marker->header.stamp = ros::Time::now();
01109 marker->header.frame_id = ivMapPtr->getFrameID();
01110 marker->ns = ivMarkerNamespace;
01111 marker->type = visualization_msgs::Marker::CUBE;
01112 marker->action = visualization_msgs::Marker::ADD;
01113
01114 float cos_theta = cos(foot_pose.getTheta());
01115 float sin_theta = sin(foot_pose.getTheta());
01116 float x_shift = cos_theta * ivEnvironmentParams.foot_origin_shift_x -
01117 sin_theta * ivEnvironmentParams.foot_origin_shift_y;
01118 float y_shift;
01119 if (foot_pose.getLeg() == LEFT)
01120 y_shift = sin_theta * ivEnvironmentParams.foot_origin_shift_x +
01121 cos_theta * ivEnvironmentParams.foot_origin_shift_y;
01122 else
01123 y_shift = sin_theta * ivEnvironmentParams.foot_origin_shift_x -
01124 cos_theta * ivEnvironmentParams.foot_origin_shift_y;
01125 marker->pose.position.x = foot_pose.getX() + x_shift;
01126 marker->pose.position.y = foot_pose.getY() + y_shift;
01127 marker->pose.position.z = ivEnvironmentParams.footsize_z / 2.0;
01128 tf::quaternionTFToMsg(tf::createQuaternionFromYaw(foot_pose.getTheta()),
01129 marker->pose.orientation);
01130
01131 marker->scale.x = ivEnvironmentParams.footsize_x;
01132 marker->scale.y = ivEnvironmentParams.footsize_y;
01133 marker->scale.z = ivEnvironmentParams.footsize_z;
01134
01135
01136 if (foot_pose.getLeg() == RIGHT)
01137 {
01138 marker->color.r = 0.0f;
01139 marker->color.g = 1.0f;
01140 }
01141 else
01142 {
01143 marker->color.r = 1.0f;
01144 marker->color.g = 0.0f;
01145 }
01146 marker->color.b = 0.0;
01147 marker->color.a = 0.6;
01148
01149 marker->lifetime = ros::Duration();
01150 }
01151 }