00001 #include <vigir_footstep_planner/footstep_planner.h>
00002
00003 namespace vigir_footstep_planning
00004 {
00005 FootstepPlanner::FootstepPlanner(ros::NodeHandle &nh)
00006 : foot_pose_transformer(FootPoseTransformer(nh))
00007 , start_foot_selection(msgs::StepPlanRequest::AUTO)
00008 , start_pose_set_up(false)
00009 , goal_pose_set_up(false)
00010 , max_number_steps(0.0)
00011 , max_path_length_ratio(0.0)
00012 , ivPathCost(0)
00013 , ivCheckedFootContactSupport(new pcl::PointCloud<pcl::PointXYZI>())
00014 , step_plan_uid(0)
00015 {
00016 nh.getParam("world_frame_id", frame_id);
00017
00018
00019 ivCheckedFootContactSupportPub = nh.advertise<sensor_msgs::PointCloud2>("foot_contact_support", 1);
00020
00021
00022 if (!ParameterManager::empty())
00023 setParams(ParameterManager::getActive());
00024 else
00025 ROS_ERROR("[FootstepPlanner] Can't initialize environment due to missing parameters!");
00026 }
00027
00028 FootstepPlanner::~FootstepPlanner()
00029 {
00030 boost::recursive_mutex::scoped_lock lock(planner_mutex);
00031
00032 planning_thread.interrupt();
00033 planning_thread.join();
00034 }
00035
00036 void FootstepPlanner::setPlanner()
00037 {
00038 if (env_params->ivPlannerType == "ARAPlanner" ||
00039 env_params->ivPlannerType == "ADPlanner" ||
00040 env_params->ivPlannerType == "RSTARPlanner" )
00041 {
00042 ROS_INFO_STREAM("Planning with " << env_params->ivPlannerType);
00043 }
00044 else
00045 {
00046 ROS_ERROR_STREAM("Planner " << env_params->ivPlannerType << " not available / untested.");
00047 exit(1);
00048 }
00049 if (env_params->forward_search)
00050 {
00051 ROS_INFO_STREAM("Search direction: forward planning");
00052 }
00053 else
00054 {
00055 ROS_INFO_STREAM("Search direction: backward planning");
00056 }
00057
00058 if (env_params->ivPlannerType == "ARAPlanner")
00059 {
00060 ivPlannerPtr.reset(
00061 new ARAPlanner(ivPlannerEnvironmentPtr.get(),
00062 env_params->forward_search));
00063 }
00064 else if (env_params->ivPlannerType == "ADPlanner")
00065 {
00066 ivPlannerPtr.reset(
00067 new ADPlanner(ivPlannerEnvironmentPtr.get(),
00068 env_params->forward_search));
00069 }
00070 else if (env_params->ivPlannerType == "RSTARPlanner")
00071 {
00072 RSTARPlanner* p =
00073 new RSTARPlanner(ivPlannerEnvironmentPtr.get(),
00074 env_params->forward_search);
00075
00076
00077
00078 ivPlannerPtr.reset(p);
00079 }
00080
00081
00082
00083 }
00084
00085 bool FootstepPlanner::isPlanning() const
00086 {
00087 return planning_thread.joinable();
00088 }
00089
00090 bool FootstepPlanner::plan(ReplanParams& params)
00091 {
00092 bool path_existed = (bool)ivPath.size();
00093 int ret = 0;
00094 MDPConfig mdp_config;
00095 std::vector<int> solution_state_ids;
00096
00097
00099 ivPlannerEnvironmentPtr->getStateSpace()->updateStart(ivStartFootLeft, ivStartFootRight);
00100 ivPlannerEnvironmentPtr->getStateSpace()->updateGoal(ivGoalFootLeft, ivGoalFootRight);
00101 ivPlannerEnvironmentPtr->getStateSpace()->setPlannerStartAndGoal(start_foot_selection);
00102 ivPlannerEnvironmentPtr->updateHeuristicValues();
00103 ivPlannerEnvironmentPtr->InitializeEnv(NULL);
00104 ivPlannerEnvironmentPtr->InitializeMDPCfg(&mdp_config);
00105
00106
00107 if (path_existed &&
00108 !env_params->forward_search &&
00109 env_params->ivPlannerType == "ADPlanner")
00110 {
00111 std::vector<int> changed_edges;
00112 changed_edges.push_back(mdp_config.startstateid);
00113
00114 boost::shared_ptr<ADPlanner> ad_planner =
00115 boost::dynamic_pointer_cast<ADPlanner>(ivPlannerPtr);
00116 ad_planner->update_preds_of_changededges(&changed_edges);
00117 }
00118
00119
00120 if (ivPlannerPtr->set_start(mdp_config.startstateid) == 0)
00121 {
00122 ROS_ERROR("Failed to set start state.");
00123 return false;
00124 }
00125 if (ivPlannerPtr->set_goal(mdp_config.goalstateid) == 0)
00126 {
00127 ROS_ERROR("Failed to set goal state");
00128 return false;
00129 }
00130
00131 int path_cost;
00132 ros::WallTime startTime = ros::WallTime::now();
00133 try
00134 {
00135 ROS_INFO("Start planning (max time: %f, eps_0: %.2f, d_eps: %.2f, h(start, goal): %.3f (l) - %.3f (r))",
00136 params.max_time, params.initial_eps, params.dec_eps,
00137 (double)ivPlannerEnvironmentPtr->GetGoalHeuristic(ivPlannerEnvironmentPtr->getStateSpace()->ivIdStartFootLeft)/(double)cvMmScale,
00138 (double)ivPlannerEnvironmentPtr->GetGoalHeuristic(ivPlannerEnvironmentPtr->getStateSpace()->ivIdStartFootRight)/(double)cvMmScale);
00139 ret = ivPlannerPtr->replan(&solution_state_ids, params, &path_cost);
00140 }
00141 catch (const SBPL_Exception* e)
00142 {
00143 ROS_ERROR("SBPL planning failed (%s)", e->what());
00144 return false;
00145 }
00146 ivPathCost = double(path_cost) / cvMmScale;
00147
00148 bool path_is_new = pathIsNew(solution_state_ids);
00149 if (ret && solution_state_ids.size() > 0 && path_is_new)
00150 {
00151 ROS_INFO("Solution of size %zu found after %f s",
00152 solution_state_ids.size(),
00153 (ros::WallTime::now()-startTime).toSec());
00154
00155 if (extractPath(solution_state_ids))
00156 {
00157 ROS_INFO("Expanded states: %i total / %i new",
00158 ivPlannerEnvironmentPtr->getNumExpandedStates(),
00159 ivPlannerPtr->get_n_expands());
00160 ROS_INFO("Final eps: %f", ivPlannerPtr->get_final_epsilon());
00161 ROS_INFO("Path cost: %f (%i)\n", ivPathCost, path_cost);
00162
00163 ivPlanningStatesIds = solution_state_ids;
00164 return true;
00165 }
00166 else
00167 {
00168 ROS_ERROR("extracting path failed\n\n");
00169 return false;
00170 }
00171 }
00172 else if (!path_is_new)
00173 {
00174 ROS_ERROR("Solution found by SBPL is the same as the old solution. Replanning failed.");
00175 return false;
00176 }
00177 else
00178 {
00179 ROS_ERROR("No solution found");
00180 return false;
00181 }
00182 }
00183
00184 bool FootstepPlanner::extractPath(const std::vector<int>& state_ids)
00185 {
00186 ivPath.clear();
00187
00188 for(std::vector<int>::const_iterator state_ids_iter = state_ids.begin(); state_ids_iter != state_ids.end(); ++state_ids_iter)
00189 {
00190 State s;
00191 if (!ivPlannerEnvironmentPtr->getStateSpace()->getState(*state_ids_iter, s))
00192 {
00193 ivPath.clear();
00194 return false;
00195 }
00196 ivPath.push_back(s);
00197 }
00198
00199
00200 if (ivPath.back().getLeg() == RIGHT)
00201 ivPath.push_back(ivGoalFootLeft);
00202 else
00203 ivPath.push_back(ivGoalFootRight);
00204
00205 return true;
00206 }
00207
00208 bool FootstepPlanner::setParams(const vigir_generic_params::ParameterSet& params)
00209 {
00210 boost::recursive_mutex::scoped_lock lock(planner_mutex);
00211
00212
00213 env_params.reset(new EnvironmentParameters(params));
00214
00215 std::string plugin_set;
00216 if (params.getParam("plugin_set", plugin_set))
00217 vigir_pluginlib::PluginManager::loadPluginSet(plugin_set);
00218 else
00219 ROS_WARN("[FootstepPlanner] setParams: No plugin set was given by parameter set '%s'", params.getName().c_str());
00220
00221
00222 StepPlanMsgPlugin::Ptr plugin;
00223 if (vigir_pluginlib::PluginManager::getPlugin(plugin))
00224 plugin->loadParams(params);
00225
00226
00227 StateGenerator::mutableInstance().loadPlugins();
00228 StateGenerator::mutableInstance().loadParams(params);
00229
00230
00231 RobotModel::mutableInstance().loadPlugins();
00232 RobotModel::mutableInstance().loadParams(params);
00233
00234
00235 PostProcessor::mutableInstance().loadPlugins();
00236 PostProcessor::mutableInstance().loadParams(params);
00237
00238
00239 WorldModel::mutableInstance().loadPlugins();
00240 WorldModel::mutableInstance().loadParams(params);
00241
00242
00243 StepCostEstimator::mutableInstance().loadPlugins();
00244 StepCostEstimator::mutableInstance().loadParams(params);
00245
00246
00247 Heuristic::mutableInstance().loadPlugins();
00248 Heuristic::mutableInstance().loadParams(params);
00249
00250 resetTotally();
00251
00252 return true;
00253 }
00254
00255 msgs::ErrorStatus FootstepPlanner::updateFoot(msgs::Foot& foot, uint8_t mode, bool transform) const
00256 {
00257 msgs::ErrorStatus status;
00258
00259
00260 if (transform)
00261 foot_pose_transformer.transformToPlannerFrame(foot);
00262
00263 if (mode & msgs::UpdateMode::UPDATE_MODE_MOVE_TO_VALID)
00264 {
00265 State s(foot);
00266 if (findNearestValidState(s))
00267 s.getFoot(foot);
00268 else
00269 status += ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "updateFoot: Couldn't determine valid position!");
00270 }
00271 else if (mode & msgs::UpdateMode::UPDATE_MODE_3D)
00272 {
00273 if (!WorldModel::instance().isTerrainModelAvailable() || !WorldModel::instance().getTerrainModel()->update3DData(foot.pose))
00274 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "updateFoot: Couldn't update 3D data.", false);
00275 }
00276 else if (mode & msgs::UpdateMode::UPDATE_MODE_Z)
00277 {
00278 if (!WorldModel::instance().isTerrainModelAvailable() || !WorldModel::instance().getTerrainModel()->getHeight(foot.pose.position.x, foot.pose.position.y, foot.pose.position.z))
00279 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "updateFoot: Couldn't update z.", false);
00280 }
00281
00282
00283 if (transform)
00284 foot_pose_transformer.transformToRobotFrame(foot);
00285
00286 foot.header.stamp = ros::Time::now();
00287
00288 return status;
00289 }
00290
00291 msgs::ErrorStatus FootstepPlanner::updateFeet(msgs::Feet& feet, uint8_t mode, bool transform) const
00292 {
00293 msgs::ErrorStatus status;
00294
00295 if (mode & msgs::UpdateMode::UPDATE_MODE_MOVE_TO_VALID)
00296 {
00297 State left(feet.left);
00298 State right(feet.right);
00299 if (findNearestValidState(left) && findNearestValidState(right) && RobotModel::instance().isReachable(left, right))
00300 {
00301 left.getFoot(feet.left);
00302 right.getFoot(feet.right);
00303 }
00304 else
00305 status += ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "updateFeet: Couldn't determine valid position!");
00306
00307 mode -= msgs::UpdateMode::UPDATE_MODE_MOVE_TO_VALID;
00308 }
00309
00310 status += updateFoot(feet.left, mode, transform);
00311 status += updateFoot(feet.right, mode, transform);
00312
00313 return status;
00314 }
00315
00316 msgs::ErrorStatus FootstepPlanner::updateStepPlan(msgs::StepPlan& step_plan, uint8_t mode, const std::string& , bool transform) const
00317 {
00318 if (step_plan.steps.empty())
00319 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "[FootstepPlanner]", "updateStepPlan: Can't process empty step plan!");
00320 if (step_plan.start.header.frame_id.empty())
00321 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "[FootstepPlanner]", "updateStepPlan: Can't process step plan due to missing start feet poses!");
00322
00323
00324 boost::recursive_mutex::scoped_lock lock(planner_mutex);
00325
00326
00327 if (transform)
00328 foot_pose_transformer.transformToPlannerFrame(step_plan);
00329
00330 msgs::ErrorStatus status;
00331
00332 if (mode & msgs::UpdateMode::UPDATE_MODE_REPLAN)
00333 {
00334 ROS_WARN("UPDATE_MODE_REPLAN isn't implemented yet!");
00335 }
00336 else
00337 {
00338 std::vector<msgs::Step>::iterator itr = step_plan.steps.begin();
00339
00340 State left_state(step_plan.start.left);
00341 State right_state(step_plan.start.right);
00342 State prev_state(*itr);
00343
00344 itr++;
00345 for (; itr != step_plan.steps.end(); itr++)
00346 {
00347 msgs::Step& cur_step = *itr;
00348 State cur_state = State(cur_step);
00349
00350
00351 status += updateFoot(cur_step.foot, mode, false);
00352
00353
00354 if (mode & msgs::UpdateMode::UPDATE_MODE_CHECK_VALIDITY)
00355 {
00356 cur_step.valid = RobotModel::instance().isReachable(left_state, right_state, cur_state);
00357 }
00358
00359
00360 if (mode & msgs::UpdateMode::UPDATE_MODE_CHECK_COLLISION)
00361 {
00362 cur_step.colliding = !WorldModel::instance().isAccessible(cur_state, prev_state);
00363 }
00364
00365
00366 if (mode & msgs::UpdateMode::UPDATE_MODE_COST)
00367 {
00368 double c, r;
00369 if (StepCostEstimator::instance().getCost(left_state, right_state, cur_state, c, r))
00370 {
00371 cur_step.cost = c;
00372 cur_step.risk = r;
00373 }
00374 else
00375 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "updateStepPlan: Couldn't determine cost for step " + boost::lexical_cast<std::string>(cur_step.step_index) + "!");
00376 }
00377
00378
00379 if (cur_state.getLeg() == LEFT)
00380 left_state = cur_state;
00381 else
00382 right_state = cur_state;
00383
00384 prev_state = cur_state;
00385 }
00386 }
00387
00388
00389 if (transform)
00390 foot_pose_transformer.transformToRobotFrame(step_plan);
00391
00392 return msgs::ErrorStatus();
00393 }
00394
00395 void FootstepPlanner::reset()
00396 {
00397 boost::recursive_mutex::scoped_lock lock(planner_mutex);
00398
00399 Heuristic::mutableInstance().resetPlugins();
00400
00401
00402 ivPath.clear();
00403 ivPlanningStatesIds.clear();
00404 ivCheckedFootContactSupport->clear();
00405
00406
00407
00408
00409
00410 ivPlannerEnvironmentPtr->reset();
00411 setPlanner();
00412 }
00413
00414
00415 void FootstepPlanner::resetTotally()
00416 {
00417 boost::recursive_mutex::scoped_lock lock(planner_mutex);
00418
00419
00420 StepPlanMsgPlugin::Ptr plugin;
00421 if (vigir_pluginlib::PluginManager::getPlugin(plugin))
00422 plugin->reset();
00423
00424 StateGenerator::mutableInstance().resetPlugins();
00425 RobotModel::mutableInstance().resetPlugins();
00426 PostProcessor::mutableInstance().resetPlugins();
00427 StepCostEstimator::mutableInstance().resetPlugins();
00428 Heuristic::mutableInstance().resetPlugins();
00429
00430
00431 ivPath.clear();
00432 ivPlanningStatesIds.clear();
00433 ivCheckedFootContactSupport->clear();
00434
00435 ivPlannerEnvironmentPtr.reset(new FootstepPlannerEnvironment(*env_params, foot_pose_transformer, feedback_cb));
00436 setPlanner();
00437 }
00438
00439 msgs::ErrorStatus FootstepPlanner::planSteps(msgs::StepPlanRequestService::Request& req)
00440 {
00441
00442 if (!setStart(req.plan_request, true))
00443 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_START, "FootstepPlanner", "planSteps: Couldn't set start pose! Please check if poses are set!");
00444
00445
00446 if (!setGoal(req.plan_request))
00447 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_GOAL, "FootstepPlanner", "planSteps: Couldn't set goal pose! Please check if poses are set!");
00448
00449 reset();
00450
00451 ReplanParams params(req.plan_request.max_planning_time > 0 ? req.plan_request.max_planning_time : env_params->max_planning_time);
00452 params.initial_eps = env_params->initial_eps;
00453 params.final_eps = 1.0;
00454 params.dec_eps = env_params->decrease_eps;
00455 params.return_first_solution = env_params->ivSearchUntilFirstSolution;
00456 params.repair_time = -1;
00457
00458
00459 if (!plan(params))
00460 return ErrorStatusError(msgs::ErrorStatus::ERR_NO_SOLUTION, "FootstepPlanner", "planSteps: No solution found!");
00461
00462 return msgs::ErrorStatus();
00463 }
00464
00465 msgs::ErrorStatus FootstepPlanner::planPattern(msgs::StepPlanRequestService::Request& req)
00466 {
00467 double cell_size = 0.0001;
00468 int num_angle_bins = 2048;
00469 double angle_bin_size = (2.0*M_PI / num_angle_bins);
00470
00471
00472 if (!setStart(req.plan_request, true))
00473 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_START, "FootstepPlanner", "planPattern: Couldn't set start pose! Please check if poses are set!");
00474
00475 boost::shared_ptr<Footstep> footstep;
00476 boost::shared_ptr<Footstep> footstep_left;
00477 boost::shared_ptr<Footstep> footstep_right;
00478
00479 unsigned int num_steps = req.plan_request.pattern_parameters.steps;
00480 bool close_step = req.plan_request.pattern_parameters.close_step && num_steps > 0;
00481 bool single_step_mode = false;
00482
00483 bool change_z = true;
00484 double step_up_height = std::abs(req.plan_request.pattern_parameters.dz);
00485 double extra_seperation_factor = req.plan_request.pattern_parameters.extra_seperation ? 1.25 : 1.0;
00486
00487 ROS_INFO("Start planning stepping (mode: %u, steps: %u)\n", req.plan_request.pattern_parameters.mode, num_steps);
00488
00489 State previous_state;
00490 State current_state;
00491
00492 msgs::ErrorStatus status;
00493
00494 switch (req.plan_request.pattern_parameters.mode)
00495 {
00496 case msgs::PatternParameters::STEP_UP:
00497 case msgs::PatternParameters::STEP_DOWN:
00498 case msgs::PatternParameters::STEP_OVER:
00499 change_z = false;
00500 case msgs::PatternParameters::FORWARD:
00501 {
00502 footstep = boost::shared_ptr<Footstep>(
00503 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation, 0.0,
00504 0.0,
00505 cell_size,
00506 num_angle_bins,
00507 env_params->hash_table_size));
00508 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00509 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00510 break;
00511 }
00512 case msgs::PatternParameters::BACKWARD:
00513 {
00514 footstep = boost::shared_ptr<Footstep>(
00515 new Footstep(-req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation, 0.0,
00516 0.0,
00517 cell_size,
00518 num_angle_bins,
00519 env_params->hash_table_size));
00520 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00521 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00522 break;
00523 }
00524 case msgs::PatternParameters::STRAFE_LEFT:
00525 {
00526 footstep = boost::shared_ptr<Footstep>(
00527 new Footstep(0.0, env_params->foot_seperation+req.plan_request.pattern_parameters.step_distance_sideward, 0.0,
00528 0.0,
00529 cell_size,
00530 num_angle_bins,
00531 env_params->hash_table_size));
00532 previous_state = ivStartFootLeft;
00533 current_state = ivStartFootRight;
00534 single_step_mode = true;
00535 break;
00536 }
00537 case msgs::PatternParameters::STRAFE_RIGHT:
00538 {
00539 footstep = boost::shared_ptr<Footstep>(
00540 new Footstep(0.0, env_params->foot_seperation+req.plan_request.pattern_parameters.step_distance_sideward, 0.0,
00541 0.0,
00542 cell_size,
00543 num_angle_bins,
00544 env_params->hash_table_size));
00545 previous_state = ivStartFootRight;
00546 current_state = ivStartFootLeft;
00547 single_step_mode = true;
00548 break;
00549 }
00550 case msgs::PatternParameters::ROTATE_LEFT:
00551 {
00552 footstep = boost::shared_ptr<Footstep>(
00553 new Footstep(-sin(req.plan_request.pattern_parameters.turn_angle)*(env_params->foot_seperation*extra_seperation_factor)/2,
00554 cos(req.plan_request.pattern_parameters.turn_angle)*(env_params->foot_seperation*extra_seperation_factor)/2+(env_params->foot_seperation*extra_seperation_factor)/2,
00555 req.plan_request.pattern_parameters.turn_angle,
00556 0.0,
00557 cell_size,
00558 num_angle_bins,
00559 env_params->hash_table_size));
00560 previous_state = ivStartFootLeft;
00561 current_state = ivStartFootRight;
00562 single_step_mode = true;
00563 break;
00564 }
00565 case msgs::PatternParameters::ROTATE_RIGHT:
00566 {
00567 footstep = boost::shared_ptr<Footstep>(
00568 new Footstep(-sin(req.plan_request.pattern_parameters.turn_angle)*(env_params->foot_seperation*extra_seperation_factor)/2,
00569 cos(req.plan_request.pattern_parameters.turn_angle)*(env_params->foot_seperation*extra_seperation_factor)/2+(env_params->foot_seperation*extra_seperation_factor)/2,
00570 req.plan_request.pattern_parameters.turn_angle,
00571 0.0,
00572 cell_size,
00573 num_angle_bins,
00574 env_params->hash_table_size));
00575 previous_state = ivStartFootRight;
00576 current_state = ivStartFootLeft;
00577 single_step_mode = true;
00578 break;
00579 }
00580 case msgs::PatternParameters::SAMPLING:
00581 {
00582
00583 unsigned int start_foot;
00584
00585 if (req.plan_request.start_foot_selection != msgs::StepPlanRequest::AUTO)
00586 start_foot = req.plan_request.start_foot_selection;
00587 else
00588 {
00589 if (req.plan_request.pattern_parameters.step_distance_sideward < 0.0 || (req.plan_request.pattern_parameters.step_distance_sideward == 0.0 && req.plan_request.pattern_parameters.turn_angle < 0.0))
00590 start_foot = msgs::StepPlanRequest::RIGHT;
00591 else
00592 start_foot = msgs::StepPlanRequest::LEFT;
00593 }
00594
00595
00596 if (req.plan_request.pattern_parameters.step_distance_sideward == 0.0 && req.plan_request.pattern_parameters.turn_angle == 0.0)
00597 {
00598 footstep_left = boost::shared_ptr<Footstep>(
00599 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation+req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle,
00600 0.0,
00601 cell_size,
00602 num_angle_bins,
00603 env_params->hash_table_size));
00604 footstep_right = boost::shared_ptr<Footstep>(
00605 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation-req.plan_request.pattern_parameters.step_distance_sideward, -req.plan_request.pattern_parameters.turn_angle,
00606 0.0,
00607 cell_size,
00608 num_angle_bins,
00609 env_params->hash_table_size));
00610 }
00611 else if (start_foot == msgs::StepPlanRequest::LEFT)
00612 {
00613 footstep_left = boost::shared_ptr<Footstep>(
00614 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation+req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle,
00615 0.0,
00616 cell_size,
00617 num_angle_bins,
00618 env_params->hash_table_size));
00619 footstep_right = boost::shared_ptr<Footstep>(
00620 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation, 0.0,
00621 0.0,
00622 cell_size,
00623 num_angle_bins,
00624 env_params->hash_table_size));
00625 }
00626 else
00627 {
00628 footstep_left = boost::shared_ptr<Footstep>(
00629 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation, 0.0,
00630 0.0,
00631 cell_size,
00632 num_angle_bins,
00633 env_params->hash_table_size));
00634 footstep_right = boost::shared_ptr<Footstep>(
00635 new Footstep(req.plan_request.pattern_parameters.step_distance_forward, env_params->foot_seperation-req.plan_request.pattern_parameters.step_distance_sideward, -req.plan_request.pattern_parameters.turn_angle,
00636 0.0,
00637 cell_size,
00638 num_angle_bins,
00639 env_params->hash_table_size));
00640 }
00641
00642
00643 previous_state = start_foot == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00644 current_state = start_foot == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00645 break;
00646 }
00647 case msgs::PatternParameters::FEET_REALIGN_ON_CENTER:
00648 {
00649 State feet_center(0.5*(ivStartFootLeft.getX()+ivStartFootRight.getX()),
00650 0.5*(ivStartFootLeft.getY()+ivStartFootRight.getY()),
00651 0.5*(ivStartFootLeft.getZ()+ivStartFootRight.getZ()),
00652 0.5*(ivStartFootLeft.getRoll()+ivStartFootRight.getRoll()),
00653 0.5*(ivStartFootLeft.getPitch()+ivStartFootRight.getPitch()),
00654 0.5*(ivStartFootLeft.getYaw()+ivStartFootRight.getYaw()),
00655 NOLEG);
00656
00657
00658 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00659 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00660 status += finalizeAndAddStepToPlan(current_state, req.plan_request.pattern_parameters, false);
00661 if (hasError(status))
00662 return status;
00663
00664
00665 if (req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT)
00666 {
00667 State temp = getFootPose(feet_center, RIGHT);
00668 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00669
00670 temp = getFootPose(feet_center, LEFT);
00671 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00672 }
00673 else
00674 {
00675 State temp = getFootPose(feet_center, LEFT);
00676 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00677
00678 temp = getFootPose(feet_center, RIGHT);
00679 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00680 }
00681
00682 return status;
00683 }
00684 case msgs::PatternParameters::FEET_REALIGN_ON_LEFT:
00685 {
00686 previous_state = ivStartFootRight;
00687 current_state = ivStartFootLeft;
00688 num_steps = 0;
00689 close_step = true;
00690 break;
00691 }
00692 case msgs::PatternParameters::FEET_REALIGN_ON_RIGHT:
00693 {
00694 previous_state = ivStartFootLeft;
00695 current_state = ivStartFootRight;
00696 num_steps = 0;
00697 close_step = true;
00698 break;
00699 }
00700 case msgs::PatternParameters::WIDE_STANCE:
00701 {
00702 State feet_center(0.5*(ivStartFootLeft.getX()+ivStartFootRight.getX()),
00703 0.5*(ivStartFootLeft.getY()+ivStartFootRight.getY()),
00704 0.5*(ivStartFootLeft.getZ()+ivStartFootRight.getZ()),
00705 0.5*(ivStartFootLeft.getRoll()+ivStartFootRight.getRoll()),
00706 0.5*(ivStartFootLeft.getPitch()+ivStartFootRight.getPitch()),
00707 0.5*(ivStartFootLeft.getYaw()+ivStartFootRight.getYaw()),
00708 NOLEG);
00709
00710
00711 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00712 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00713 status += finalizeAndAddStepToPlan(current_state, req.plan_request.pattern_parameters, false);
00714 if (hasError(status))
00715 return status;
00716
00717
00718 if (req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT)
00719 {
00720 State temp = getFootPose(feet_center, RIGHT, req.plan_request.pattern_parameters.step_distance_forward, req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle);
00721 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00722
00723 temp = getFootPose(feet_center, LEFT, req.plan_request.pattern_parameters.step_distance_forward, req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle);
00724 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00725 }
00726 else
00727 {
00728 State temp = getFootPose(feet_center, LEFT, req.plan_request.pattern_parameters.step_distance_forward, req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle);
00729 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00730
00731 temp = getFootPose(feet_center, RIGHT, req.plan_request.pattern_parameters.step_distance_forward, req.plan_request.pattern_parameters.step_distance_sideward, req.plan_request.pattern_parameters.turn_angle);
00732 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00733 }
00734
00735 return status;
00736 }
00737 default:
00738 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "planPattern: Unknown walk mode (" + boost::lexical_cast<std::string>(req.plan_request.pattern_parameters.mode) + ") set!");
00739 }
00740
00741
00742 Footstep parallel_step(0.0, env_params->foot_seperation, 0.0, 0.0, cell_size, num_angle_bins, env_params->hash_table_size);
00743 Footstep parallel_step_extra(0.0, env_params->foot_seperation*extra_seperation_factor, 0.0, 0.0, cell_size, num_angle_bins, env_params->hash_table_size);
00744 Footstep step_up(1.4*env_params->foot_size.x, env_params->foot_seperation, 0.0, 0.0, cell_size, num_angle_bins, env_params->hash_table_size);
00745 Footstep step_down(1.1*env_params->foot_size.x, env_params->foot_seperation, 0.0, 0.0, cell_size, num_angle_bins, env_params->hash_table_size);
00746
00747
00748 PlanningState previous_pstate(previous_state, cell_size, angle_bin_size, env_params->hash_table_size);
00749 PlanningState current_pstate(current_state, cell_size, angle_bin_size, env_params->hash_table_size, &previous_pstate);
00750
00751
00752 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00753 if (hasError(status))
00754 return status;
00755
00756
00757 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_UP || req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_OVER)
00758 {
00759
00760 PlanningState temp = step_up.performMeOnThisState(current_pstate);
00761 previous_pstate = current_pstate;
00762 current_pstate = temp;
00763
00764 current_pstate.getState().setZ(current_pstate.getState().getZ() + step_up_height);
00765
00766
00767 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00768 if (hasError(status))
00769 return status;
00770 }
00771
00772
00773 for (unsigned int i = 0; i < num_steps; i++)
00774 {
00775
00776 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::SAMPLING)
00777 {
00778 if (current_pstate.getState().getLeg() == LEFT)
00779 footstep = footstep_right;
00780 else if (current_pstate.getState().getLeg() == RIGHT)
00781 footstep = footstep_left;
00782 }
00783
00784
00785 PlanningState temp = footstep->performMeOnThisState(current_pstate);
00786 previous_pstate = current_pstate;
00787 current_pstate = temp;
00788
00789
00790 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, change_z);
00791 if (hasError(status))
00792 return status;
00793
00794
00795 if (single_step_mode && (!req.plan_request.pattern_parameters.close_step || i < (num_steps-1)))
00796 {
00797
00798 PlanningState temp = parallel_step_extra.performMeOnThisState(current_pstate);
00799 previous_pstate = current_pstate;
00800 current_pstate = temp;
00801
00802
00803 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, change_z);
00804 if (hasError(status))
00805 return status;
00806 i++;
00807 }
00808 }
00809
00810
00811 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_DOWN || req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_OVER)
00812 {
00813
00814 PlanningState temp = step_down.performMeOnThisState(current_pstate);
00815 previous_pstate = current_pstate;
00816 current_pstate = temp;
00817
00818 current_pstate.getState().setZ(current_pstate.getState().getZ() - step_up_height);
00819
00820
00821 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00822 if (hasError(status))
00823 return status;
00824 }
00825
00826
00827 if (close_step)
00828 {
00829
00830 PlanningState temp = parallel_step.performMeOnThisState(current_pstate);
00831 previous_pstate = current_pstate;
00832 current_pstate = temp;
00833
00834
00835 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00836 if (hasError(status))
00837 return status;
00838 }
00839
00840 return status;
00841 }
00842
00843 msgs::ErrorStatus FootstepPlanner::finalizeAndAddStepToPlan(State& s, const msgs::PatternParameters& params, bool change_z)
00844 {
00845 if (change_z)
00846 s.setZ(s.getZ() + params.dz);
00847
00848 if (params.override)
00849 {
00850 State temp = s;
00851 temp.setRoll(params.roll);
00852 temp.setPitch(params.pitch);
00853 ivPath.push_back(temp);
00854 return msgs::ErrorStatus();
00855 }
00856 else
00857 {
00858 ivPath.push_back(s);
00859 return msgs::ErrorStatus();
00860 }
00861
00862 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "addStepping: Something went wrong...");
00863 }
00864
00865 bool FootstepPlanner::finalizeStepPlan(msgs::StepPlanRequestService::Request& req, msgs::StepPlanRequestService::Response& resp, bool post_process)
00866 {
00867 resp.step_plan.header.frame_id = frame_id;
00868 resp.step_plan.header.stamp = req.plan_request.header.stamp;
00869 resp.step_plan.header.seq = step_plan_uid++;
00870
00871
00872 msgs::Step step;
00873
00874
00875 StepPlanMsgPlugin::Ptr plugin;
00876 if (vigir_pluginlib::PluginManager::getPlugin(plugin))
00877 {
00878 plugin->initMsg(resp.step_plan);
00879 plugin->initMsg(step);
00880 }
00881
00882 step.header = resp.step_plan.header;
00883 step.foot.header = resp.step_plan.header;
00884 step.valid = true;
00885 step.colliding = false;
00886
00887 State left_foot = ivStartFootLeft;
00888 State right_foot = ivStartFootRight;
00889
00890 int step_index = req.plan_request.start_step_index;
00891 resp.step_plan.steps.reserve(getPathSize());
00892 for (state_iter_t path_iter = getPathBegin(); path_iter != getPathEnd(); ++path_iter)
00893 {
00894 State swing_foot = *path_iter;
00895 const State& stand_foot = swing_foot.getLeg() == LEFT ? right_foot : left_foot;
00896
00897
00898 if (swing_foot == ivGoalFootLeft || swing_foot == ivGoalFootRight ||
00899 (path_iter != getPathBegin() && req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN))
00900 {
00901 if (env_params->forward_search)
00902 PostProcessor::instance().postProcessForward(left_foot, right_foot, swing_foot);
00903 else
00904 PostProcessor::instance().postProcessBackward(left_foot, right_foot, swing_foot);
00905 }
00906
00907
00908 swing_foot.getStep(step);
00909 if (swing_foot.getLeg() == LEFT)
00910 step.foot.foot_index = msgs::Foot::LEFT;
00911 else if (swing_foot.getLeg() == RIGHT)
00912 step.foot.foot_index = msgs::Foot::RIGHT;
00913 else
00914 {
00915 ROS_ERROR("Footstep pose at (%.3f, %.3f, %.3f, %.3f) is set to NOLEG!", swing_foot.getX(), swing_foot.getY(), swing_foot.getZ(), swing_foot.getYaw());
00916 continue;
00917 }
00918 step.step_index = step_index++;
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 if (std::abs(stand_foot.getZ() - swing_foot.getZ()) > 0.18)
00929 resp.status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "finalizeStepPlan: Plan contains large lift heights");
00930
00931
00932 resp.step_plan.steps.push_back(step);
00933
00934
00935 if (swing_foot.getLeg() == LEFT)
00936 left_foot = swing_foot;
00937 else if (swing_foot.getLeg() == RIGHT)
00938 right_foot = swing_foot;
00939 }
00940
00941
00942 PostProcessor::instance().postProcess(resp.step_plan);
00943
00944
00945 resp.step_plan.start.header = resp.step_plan.header;
00946
00947 ivStartFootLeft.getFoot(resp.step_plan.start.left);
00948 resp.step_plan.start.left.foot_index = msgs::Foot::LEFT;
00949 resp.step_plan.start.left.header = resp.step_plan.header;
00950
00951 ivStartFootRight.getFoot(resp.step_plan.start.right);
00952 resp.step_plan.start.right.foot_index = msgs::Foot::RIGHT;
00953 resp.step_plan.start.right.header = resp.step_plan.header;
00954
00955 resp.step_plan.goal.header = resp.step_plan.header;
00956
00957 ivGoalFootLeft.getFoot(resp.step_plan.goal.left);
00958 resp.step_plan.goal.left.foot_index = msgs::Foot::LEFT;
00959 resp.step_plan.goal.left.header = resp.step_plan.header;
00960
00961 ivGoalFootRight.getFoot(resp.step_plan.goal.right);
00962 resp.step_plan.goal.right.foot_index = msgs::Foot::RIGHT;
00963 resp.step_plan.goal.right.header = resp.step_plan.header;
00964
00965
00966 if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN)
00967 updateStepPlan(resp.step_plan, msgs::UpdateMode::UPDATE_MODE_CHECK_VALIDITY | msgs::UpdateMode::UPDATE_MODE_CHECK_COLLISION | msgs::UpdateMode::UPDATE_MODE_COST, std::string(), false);
00968 else
00969 updateStepPlan(resp.step_plan, msgs::UpdateMode::UPDATE_MODE_COST, std::string(), false);
00970
00971 resp.final_eps = ivPlannerPtr->get_final_epsilon();
00972 resp.planning_time = ivPlannerPtr->get_final_eps_planning_time();
00973
00974 if (resp.status.error == msgs::ErrorStatus::NO_ERROR && resp.final_eps > 1.8)
00975 resp.status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "stepPlanRequestService: Suboptimal plan (eps: " + boost::lexical_cast<std::string>(resp.final_eps) + ")!");
00976
00977
00978 double total_cost = 0.0;
00979 double last_cost = 0.0;
00980 for (std::vector<msgs::Step>::const_iterator itr = resp.step_plan.steps.begin(); itr != resp.step_plan.steps.end(); itr++)
00981 {
00982 step = *itr;
00983
00984 geometry_msgs::Vector3 n;
00985 quaternionToNormal(step.foot.pose.orientation, n);
00986 ROS_INFO("[%i] x/y/z: %.3f/%.3f/%.3f - %.3f", step.step_index, step.foot.pose.position.x, step.foot.pose.position.y, step.foot.pose.position.z, tf::getYaw(step.foot.pose.orientation));
00987 ROS_INFO("[%i] n: %.3f/%.3f/%.3f", step.step_index, n.x, n.y, n.z);
00988 ROS_INFO("[%i] swing height: %.3f, sway duration: %.3f, step duration: %.3f", step.step_index, step.swing_height, step.sway_duration, step.step_duration);
00989 ROS_INFO("[%i] valid: %s, colliding: %s", step.step_index, step.valid ? "y" : "n", step.colliding ? "y" : "n");
00990 ROS_INFO("[%i] cost: %.3f risk: %.3f", step.step_index, step.cost, step.risk);
00991
00992 total_cost += step.cost;
00993 last_cost = step.cost;
00994
00995 if (WorldModel::instance().isTerrainModelAvailable())
00996 {
00997 double support = 0.0;
00998 WorldModel::instance().getTerrainModel()->getFootContactSupport(step.foot.pose, support, ivCheckedFootContactSupport);
00999 ROS_INFO("[%i] Ground contact support: %.3f", step.step_index, support);
01000 }
01001
01002 ROS_INFO("-------------------------------------");
01003 }
01004 ROS_INFO("Total path cost: %f (%f)", total_cost, total_cost-last_cost);
01005
01006 if (ivCheckedFootContactSupportPub.getNumSubscribers() > 0)
01007 {
01008 sensor_msgs::PointCloud2 msg;
01009 pcl::toROSMsg(*ivCheckedFootContactSupport, msg);
01010 msg.header.frame_id = frame_id;
01011 msg.header.stamp = ros::Time::now();
01012 ivCheckedFootContactSupportPub.publish(msg);
01013 }
01014
01015
01016 foot_pose_transformer.transformToRobotFrame(resp.step_plan);
01017
01018 return true;
01019 }
01020
01021 msgs::ErrorStatus FootstepPlanner::stepPlanRequest(msgs::StepPlanRequestService::Request& req, ResultCB result_cb, FeedbackCB feedback_cb, PreemptCB preempt_cb)
01022 {
01023
01024 preemptPlanning();
01025
01026 this->result_cb = result_cb;
01027 this->feedback_cb = feedback_cb;
01028 this->preempt_cb = preempt_cb;
01029
01030
01031
01032 std::string request_frame_id = strip_const(req.plan_request.header.frame_id, '/');
01033 std::string start_frame_id = strip_const(req.plan_request.start.header.frame_id, '/');
01034 std::string goal_frame_id = strip_const(req.plan_request.goal.header.frame_id, '/');
01035
01036 if (request_frame_id != start_frame_id)
01037 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "stepPlanRequest: Frame IDs of plan request ('" + request_frame_id + ") and start pose ('" + start_frame_id + "') do not match!");
01038
01039 if (req.plan_request.planning_mode != msgs::StepPlanRequest::PLANNING_MODE_PATTERN && request_frame_id != goal_frame_id)
01040 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "stepPlanRequest: Frame IDs of plan request ('" + request_frame_id + "') and goal pose ('" + goal_frame_id + "') do not match!");
01041
01042
01043 if (!req.plan_request.parameter_set_name.data.empty())
01044 {
01045 if (!ParameterManager::setActive(req.plan_request.parameter_set_name.data))
01046 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_PARAMETERS, "FootstepPlanner", "stepPlanRequest: Can't find parameter set named '" + req.plan_request.parameter_set_name.data + "'!");
01047
01048 setParams(ParameterManager::getActive());
01049 }
01050 else
01051 {
01052
01053 reset();
01054 }
01055
01056
01057 foot_pose_transformer.transformToPlannerFrame(req.plan_request.start);
01058 foot_pose_transformer.transformToPlannerFrame(req.plan_request.goal);
01059
01060
01061 start_foot_selection = req.plan_request.start_foot_selection;
01062 max_number_steps = req.plan_request.max_number_steps;
01063 max_path_length_ratio = req.plan_request.max_path_length_ratio;
01064 frame_id = req.plan_request.header.frame_id;
01065 ivPlannerEnvironmentPtr->setFrameId(frame_id);
01066
01067
01068 startPlanning(req);
01069
01070 return msgs::ErrorStatus();
01071 }
01072
01073 bool FootstepPlanner::stepPlanRequestService(msgs::StepPlanRequestService::Request& req, msgs::StepPlanRequestService::Response& resp)
01074 {
01075
01076 resp.status += stepPlanRequest(req);
01077
01078 if (hasError(resp.status))
01079 return true;
01080
01081
01082 planning_thread.join();
01083
01084
01085 finalizeStepPlan(req, resp, true);
01086
01087 return true;
01088 }
01089
01090 void FootstepPlanner::startPlanning(msgs::StepPlanRequestService::Request& req)
01091 {
01092
01093 planning_thread = boost::thread(&FootstepPlanner::doPlanning, this, req);
01094 }
01095
01096 void FootstepPlanner::doPlanning(msgs::StepPlanRequestService::Request& req)
01097 {
01098
01099 boost::recursive_mutex::scoped_lock lock(planner_mutex);
01100
01101 msgs::StepPlanRequestService::Response resp;
01102
01103
01104 if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_3D)
01105 WorldModel::mutableInstance().useTerrainModel(true);
01106 else if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN)
01107 WorldModel::mutableInstance().useTerrainModel(req.plan_request.pattern_parameters.use_terrain_model);
01108 else
01109 WorldModel::mutableInstance().useTerrainModel(false);
01110
01111
01112 switch (req.plan_request.planning_mode)
01113 {
01114 case msgs::StepPlanRequest::PLANNING_MODE_2D:
01115 case msgs::StepPlanRequest::PLANNING_MODE_3D:
01116 resp.status = planSteps(req);
01117 break;
01118 case msgs::StepPlanRequest::PLANNING_MODE_PATTERN:
01119 resp.status = planPattern(req);
01120 break;
01121 default:
01122 resp.status = ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "stepPlanRequest: A not supported planning mode '" + boost::lexical_cast<std::string>(req.plan_request.planning_mode) + "' was given!");
01123 break;
01124 }
01125
01126
01127 if (!result_cb.empty())
01128 {
01129
01130 if (!hasError(resp.status))
01131 finalizeStepPlan(req, resp, true);
01132 result_cb(resp);
01133 }
01134 }
01135
01136 void FootstepPlanner::preemptPlanning()
01137 {
01138 if (!isPlanning())
01139 return;
01140
01141
01142 planning_thread.interrupt();
01143 planning_thread.join();
01144
01145 if (!preempt_cb.empty())
01146 preempt_cb();
01147 }
01148
01149 bool FootstepPlanner::findNearestValidState(State& s) const
01150 {
01151 if (WorldModel::instance().isAccessible(s))
01152 return true;
01153
01154 State current_state = s;
01155 State best_state = s;
01156
01157 double pos_diff = FLT_MAX;
01158 double yaw_diff = FLT_MAX;
01159 bool solution_found = false;
01160
01161
01162 tf::Transform t;
01163 t.setOrigin(s.getPose().getOrigin());
01164 t.setBasis(s.getPose().getBasis());
01165
01166 tf::Vector3 orig_pos;
01167 tf::Vector3 trans_pos;
01168 orig_pos.setZ(0.0);
01169
01170 for (double yaw = -0.2; yaw <= 0.4; yaw+=env_params->angle_bin_size)
01171 {
01172 current_state.setYaw(s.getYaw() + (s.getLeg() == LEFT ? yaw : -yaw));
01173 for (double y = -0.05; y <= 0.2; y+=env_params->cell_size)
01174 {
01175 orig_pos.setY(s.getLeg() == LEFT ? y : -y);
01176 for (double x = -0.15; x <= 0.15; x+=env_params->cell_size)
01177 {
01178
01179 orig_pos.setX(x);
01180 trans_pos = t * orig_pos;
01181
01182 current_state.setX(trans_pos.getX());
01183 current_state.setY(trans_pos.getY());
01184
01185 if (!WorldModel::instance().update3DData(current_state))
01186 continue;
01187
01188 if (!WorldModel::instance().isAccessible(current_state))
01189 continue;
01190
01191 double dist = std::sqrt(x*x + y*y);
01192 if (pos_diff >= dist && yaw_diff >= std::abs(yaw))
01193 {
01194 best_state = current_state;
01195 pos_diff = dist;
01196 yaw_diff = std::abs(yaw);
01197 solution_found = true;
01198 }
01199 }
01200 }
01201 }
01202
01203 if (solution_found)
01204 s = best_state;
01205
01206 return solution_found;
01207 }
01208
01209 bool FootstepPlanner::checkRobotCollision(const State& left_foot, const State& right_foot, bool& left, bool& right) const
01210 {
01211 left = !WorldModel::instance().isAccessible(left_foot);
01212 right = !WorldModel::instance().isAccessible(right_foot);
01213
01214 if (!left && !right && !WorldModel::instance().isAccessible(left_foot, right_foot))
01215 {
01216 left = true;
01217 right = true;
01218 }
01219
01220 return left || right;
01221 }
01222
01223 bool FootstepPlanner::setStart(const State& left_foot, const State& right_foot, bool ignore_collision)
01224 {
01225
01226 if (std::isnan(left_foot.getRoll())) return false;
01227 if (std::isnan(left_foot.getPitch())) return false;
01228 if (std::isnan(left_foot.getYaw())) return false;
01229 if (std::isnan(right_foot.getRoll())) return false;
01230 if (std::isnan(right_foot.getPitch())) return false;
01231 if (std::isnan(right_foot.getYaw())) return false;
01232
01233 bool left_collision = false;
01234 bool right_collision = false;
01235
01236 if (!ignore_collision && checkRobotCollision(left_foot, right_foot, left_collision, right_collision))
01237 {
01238 start_pose_set_up = false;
01239 return false;
01240 }
01241 else
01242 start_pose_set_up = true;
01243
01244 ivStartFootLeft = left_foot;
01245 ivStartFootRight = right_foot;
01246
01247 ROS_INFO("Start foot poses set to (left: %f %f %f %f) and (right: %f %f %f %f)",
01248 ivStartFootLeft.getX(), ivStartFootLeft.getY(), ivStartFootLeft.getZ(), ivStartFootLeft.getYaw(),
01249 ivStartFootRight.getX(), ivStartFootRight.getY(), ivStartFootRight.getZ(), ivStartFootRight.getYaw());
01250
01251 return true;
01252 }
01253
01254 bool FootstepPlanner::setStart(const msgs::StepPlanRequest& req, bool ignore_collision)
01255 {
01256 State left_foot(req.start.left);
01257 State right_foot(req.start.right);
01258
01259 if (req.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_2D)
01260 {
01261 double z = 0.5*(req.start.left.pose.position.z + req.start.right.pose.position.z);
01262 left_foot.setZ(z);
01263 right_foot.setZ(z);
01264 }
01265
01266 return setStart(left_foot, right_foot, ignore_collision);
01267 }
01268
01269 bool FootstepPlanner::setGoal(const State& left_foot, const State& right_foot, bool ignore_collision)
01270 {
01271
01272 if (std::isnan(left_foot.getRoll())) return false;
01273 if (std::isnan(left_foot.getPitch())) return false;
01274 if (std::isnan(left_foot.getYaw())) return false;
01275 if (std::isnan(right_foot.getRoll())) return false;
01276 if (std::isnan(right_foot.getPitch())) return false;
01277 if (std::isnan(right_foot.getYaw())) return false;
01278
01279 bool left_collision = false;
01280 bool right_collision = false;
01281
01282 if (!ignore_collision && checkRobotCollision(left_foot, right_foot, left_collision, right_collision))
01283 {
01284 goal_pose_set_up = false;
01285 return false;
01286 }
01287 else
01288 goal_pose_set_up = true;
01289
01290 ivGoalFootLeft = left_foot;
01291 ivGoalFootRight = right_foot;
01292
01293 ROS_INFO("Goal foot poses set to (left: %f %f %f %f) and (right: %f %f %f %f)",
01294 ivGoalFootLeft.getX(), ivGoalFootLeft.getY(), ivGoalFootLeft.getZ(), ivGoalFootLeft.getYaw(),
01295 ivGoalFootRight.getX(), ivGoalFootRight.getY(), ivGoalFootRight.getZ(), ivGoalFootRight.getYaw());
01296
01297 return true;
01298 }
01299
01300 bool FootstepPlanner::setGoal(const msgs::StepPlanRequest& req, bool ignore_collision)
01301 {
01302 State left_foot(req.goal.left);
01303 State right_foot(req.goal.right);
01304
01305 if (req.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_2D)
01306 {
01307 double z = 0.5*(req.start.left.pose.position.z + req.start.right.pose.position.z);
01308 geometry_msgs::Vector3 n;
01309
01310 left_foot.setZ(z);
01311 quaternionToNormal(req.start.left.pose.orientation, n);
01312 left_foot.setNormal(n);
01313
01314 right_foot.setZ(z);
01315 quaternionToNormal(req.start.right.pose.orientation, n);
01316 right_foot.setNormal(n);
01317 }
01318
01319 return setGoal(left_foot, right_foot, ignore_collision);
01320 }
01321
01322 State FootstepPlanner::getFootPose(const State& robot, Leg leg, double dx, double dy, double dyaw)
01323 {
01324 double sign = -1.0;
01325 if (leg == LEFT)
01326 sign = 1.0;
01327
01328 double cos_theta = cos(robot.getYaw());
01329 double sin_theta = sin(robot.getYaw());
01330 double shift_x = cos_theta * sign * dx - sin_theta * (0.5 * env_params->foot_seperation + dy);
01331 double shift_y = sin_theta * sign * dx + cos_theta * (0.5 * env_params->foot_seperation + dy);
01332
01333 State foot(robot.getX() + sign * shift_x,
01334 robot.getY() + sign * shift_y,
01335 robot.getZ(),
01336 robot.getRoll(),
01337 robot.getPitch(),
01338 robot.getYaw() + sign * dyaw,
01339 leg);
01340
01341 WorldModel::instance().update3DData(foot);
01342
01343 return foot;
01344 }
01345
01346 State FootstepPlanner::getFootPose(const State& robot, Leg leg)
01347 {
01348 return getFootPose(robot, leg, 0.0, 0.0, 0.0);
01349 }
01350
01351 bool FootstepPlanner::pathIsNew(const std::vector<int>& new_path)
01352 {
01353 if (new_path.size() != ivPlanningStatesIds.size())
01354 return true;
01355
01356 bool unequal = true;
01357 for (unsigned i = 0; i < new_path.size(); ++i)
01358 unequal = new_path[i] != ivPlanningStatesIds[i] && unequal;
01359
01360 return unequal;
01361 }
01362 }