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\n");
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 footstep_left = boost::shared_ptr<Footstep>(
00583 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,
00584 0.0,
00585 cell_size,
00586 num_angle_bins,
00587 env_params->hash_table_size));
00588 footstep_right = boost::shared_ptr<Footstep>(
00589 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,
00590 0.0,
00591 cell_size,
00592 num_angle_bins,
00593 env_params->hash_table_size));
00594 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00595 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00596 single_step_mode = std::abs(req.plan_request.pattern_parameters.step_distance_sideward) > 0.0;
00597 break;
00598 }
00599 case msgs::PatternParameters::FEET_REALIGN_ON_CENTER:
00600 {
00601 State feet_center(0.5*(ivStartFootLeft.getX()+ivStartFootRight.getX()),
00602 0.5*(ivStartFootLeft.getY()+ivStartFootRight.getY()),
00603 0.5*(ivStartFootLeft.getZ()+ivStartFootRight.getZ()),
00604 0.5*(ivStartFootLeft.getRoll()+ivStartFootRight.getRoll()),
00605 0.5*(ivStartFootLeft.getPitch()+ivStartFootRight.getPitch()),
00606 0.5*(ivStartFootLeft.getYaw()+ivStartFootRight.getYaw()),
00607 NOLEG);
00608
00609
00610 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00611 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00612 status += finalizeAndAddStepToPlan(current_state, req.plan_request.pattern_parameters, false);
00613 if (hasError(status))
00614 return status;
00615
00616
00617 if (req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT)
00618 {
00619 State temp = getFootPose(feet_center, RIGHT);
00620 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00621
00622 temp = getFootPose(feet_center, LEFT);
00623 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00624 }
00625 else
00626 {
00627 State temp = getFootPose(feet_center, LEFT);
00628 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00629
00630 temp = getFootPose(feet_center, RIGHT);
00631 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00632 }
00633
00634 return status;
00635 }
00636 case msgs::PatternParameters::FEET_REALIGN_ON_LEFT:
00637 {
00638 previous_state = ivStartFootRight;
00639 current_state = ivStartFootLeft;
00640 num_steps = 0;
00641 close_step = true;
00642 break;
00643 }
00644 case msgs::PatternParameters::FEET_REALIGN_ON_RIGHT:
00645 {
00646 previous_state = ivStartFootLeft;
00647 current_state = ivStartFootRight;
00648 num_steps = 0;
00649 close_step = true;
00650 break;
00651 }
00652 case msgs::PatternParameters::WIDE_STANCE:
00653 {
00654 State feet_center(0.5*(ivStartFootLeft.getX()+ivStartFootRight.getX()),
00655 0.5*(ivStartFootLeft.getY()+ivStartFootRight.getY()),
00656 0.5*(ivStartFootLeft.getZ()+ivStartFootRight.getZ()),
00657 0.5*(ivStartFootLeft.getRoll()+ivStartFootRight.getRoll()),
00658 0.5*(ivStartFootLeft.getPitch()+ivStartFootRight.getPitch()),
00659 0.5*(ivStartFootLeft.getYaw()+ivStartFootRight.getYaw()),
00660 NOLEG);
00661
00662
00663 previous_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootRight : ivStartFootLeft;
00664 current_state = req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT ? ivStartFootLeft : ivStartFootRight;
00665 status += finalizeAndAddStepToPlan(current_state, req.plan_request.pattern_parameters, false);
00666 if (hasError(status))
00667 return status;
00668
00669
00670 if (req.plan_request.start_foot_selection == msgs::StepPlanRequest::RIGHT)
00671 {
00672 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);
00673 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00674
00675 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);
00676 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00677 }
00678 else
00679 {
00680 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);
00681 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00682
00683 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);
00684 finalizeAndAddStepToPlan(temp, req.plan_request.pattern_parameters, false);
00685 }
00686
00687 return status;
00688 }
00689 default:
00690 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "planPattern: Unknown walk mode (" + boost::lexical_cast<std::string>(req.plan_request.pattern_parameters.mode) + ") set!");
00691 }
00692
00693
00694 Footstep parallel_step(0.0, env_params->foot_seperation, 0.0, 0.0, cell_size, num_angle_bins, env_params->hash_table_size);
00695 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);
00696 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);
00697 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);
00698
00699
00700 PlanningState previous_pstate(previous_state, cell_size, angle_bin_size, env_params->hash_table_size);
00701 PlanningState current_pstate(current_state, cell_size, angle_bin_size, env_params->hash_table_size, &previous_pstate);
00702
00703
00704 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00705 if (hasError(status))
00706 return status;
00707
00708
00709 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_UP || req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_OVER)
00710 {
00711
00712 PlanningState temp = step_up.performMeOnThisState(current_pstate);
00713 previous_pstate = current_pstate;
00714 current_pstate = temp;
00715
00716 current_pstate.getState().setZ(current_pstate.getState().getZ() + step_up_height);
00717
00718
00719 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00720 if (hasError(status))
00721 return status;
00722 }
00723
00724
00725 for (unsigned int i = 0; i < num_steps; i++)
00726 {
00727
00728 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::SAMPLING)
00729 {
00730 if (current_pstate.getState().getLeg() == LEFT)
00731 footstep = footstep_right;
00732 else if (current_pstate.getState().getLeg() == RIGHT)
00733 footstep = footstep_left;
00734 }
00735
00736
00737 PlanningState temp = footstep->performMeOnThisState(current_pstate);
00738 previous_pstate = current_pstate;
00739 current_pstate = temp;
00740
00741
00742 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, change_z);
00743 if (hasError(status))
00744 return status;
00745
00746
00747 if (single_step_mode && (!req.plan_request.pattern_parameters.close_step || i < (num_steps-1)))
00748 {
00749
00750 PlanningState temp = parallel_step_extra.performMeOnThisState(current_pstate);
00751 previous_pstate = current_pstate;
00752 current_pstate = temp;
00753
00754
00755 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, change_z);
00756 if (hasError(status))
00757 return status;
00758 i++;
00759 }
00760 }
00761
00762
00763 if (req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_DOWN || req.plan_request.pattern_parameters.mode == msgs::PatternParameters::STEP_OVER)
00764 {
00765
00766 PlanningState temp = step_down.performMeOnThisState(current_pstate);
00767 previous_pstate = current_pstate;
00768 current_pstate = temp;
00769
00770 current_pstate.getState().setZ(current_pstate.getState().getZ() - step_up_height);
00771
00772
00773 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00774 if (hasError(status))
00775 return status;
00776 }
00777
00778
00779 if (close_step)
00780 {
00781
00782 PlanningState temp = parallel_step.performMeOnThisState(current_pstate);
00783 previous_pstate = current_pstate;
00784 current_pstate = temp;
00785
00786
00787 status += finalizeAndAddStepToPlan(current_pstate.getState(), req.plan_request.pattern_parameters, false);
00788 if (hasError(status))
00789 return status;
00790 }
00791
00792 return status;
00793 }
00794
00795 msgs::ErrorStatus FootstepPlanner::finalizeAndAddStepToPlan(State& s, const msgs::PatternParameters& params, bool change_z)
00796 {
00797 if (change_z)
00798 s.setZ(s.getZ() + params.dz);
00799
00800 if (params.override)
00801 {
00802 State temp = s;
00803 temp.setRoll(params.roll);
00804 temp.setPitch(params.pitch);
00805 ivPath.push_back(temp);
00806 return msgs::ErrorStatus();
00807 }
00808 else
00809 {
00810 ivPath.push_back(s);
00811 return msgs::ErrorStatus();
00812 }
00813
00814 return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FootstepPlanner", "addStepping: Something went wrong...");
00815 }
00816
00817 bool FootstepPlanner::finalizeStepPlan(msgs::StepPlanRequestService::Request& req, msgs::StepPlanRequestService::Response& resp, bool post_process)
00818 {
00819 resp.step_plan.header.frame_id = frame_id;
00820 resp.step_plan.header.stamp = req.plan_request.header.stamp;
00821 resp.step_plan.header.seq = step_plan_uid++;
00822
00823
00824 msgs::Step step;
00825
00826
00827 StepPlanMsgPlugin::Ptr plugin;
00828 if (vigir_pluginlib::PluginManager::getPlugin(plugin))
00829 {
00830 plugin->initMsg(resp.step_plan);
00831 plugin->initMsg(step);
00832 }
00833
00834 step.header = resp.step_plan.header;
00835 step.foot.header = resp.step_plan.header;
00836 step.valid = true;
00837 step.colliding = false;
00838
00839 State left_foot = ivStartFootLeft;
00840 State right_foot = ivStartFootRight;
00841
00842 int step_index = req.plan_request.start_step_index;
00843 resp.step_plan.steps.reserve(getPathSize());
00844 for (state_iter_t path_iter = getPathBegin(); path_iter != getPathEnd(); ++path_iter)
00845 {
00846 State swing_foot = *path_iter;
00847 const State& stand_foot = swing_foot.getLeg() == LEFT ? right_foot : left_foot;
00848
00849
00850 if (swing_foot == ivGoalFootLeft || swing_foot == ivGoalFootRight ||
00851 (path_iter != getPathBegin() && req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN))
00852 {
00853 if (env_params->forward_search)
00854 PostProcessor::instance().postProcessForward(left_foot, right_foot, swing_foot);
00855 else
00856 PostProcessor::instance().postProcessBackward(left_foot, right_foot, swing_foot);
00857 }
00858
00859
00860 swing_foot.getStep(step);
00861 if (swing_foot.getLeg() == LEFT)
00862 step.foot.foot_index = msgs::Foot::LEFT;
00863 else if (swing_foot.getLeg() == RIGHT)
00864 step.foot.foot_index = msgs::Foot::RIGHT;
00865 else
00866 {
00867 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());
00868 continue;
00869 }
00870 step.step_index = step_index++;
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 if (std::abs(stand_foot.getZ() - swing_foot.getZ()) > 0.18)
00881 resp.status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "finalizeStepPlan: Plan contains large lift heights");
00882
00883
00884 resp.step_plan.steps.push_back(step);
00885
00886
00887 if (swing_foot.getLeg() == LEFT)
00888 left_foot = swing_foot;
00889 else if (swing_foot.getLeg() == RIGHT)
00890 right_foot = swing_foot;
00891 }
00892
00893
00894 PostProcessor::instance().postProcess(resp.step_plan);
00895
00896
00897 resp.step_plan.start.header = resp.step_plan.header;
00898
00899 ivStartFootLeft.getFoot(resp.step_plan.start.left);
00900 resp.step_plan.start.left.foot_index = msgs::Foot::LEFT;
00901 resp.step_plan.start.left.header = resp.step_plan.header;
00902
00903 ivStartFootRight.getFoot(resp.step_plan.start.right);
00904 resp.step_plan.start.right.foot_index = msgs::Foot::RIGHT;
00905 resp.step_plan.start.right.header = resp.step_plan.header;
00906
00907 resp.step_plan.goal.header = resp.step_plan.header;
00908
00909 ivGoalFootLeft.getFoot(resp.step_plan.goal.left);
00910 resp.step_plan.goal.left.foot_index = msgs::Foot::LEFT;
00911 resp.step_plan.goal.left.header = resp.step_plan.header;
00912
00913 ivGoalFootRight.getFoot(resp.step_plan.goal.right);
00914 resp.step_plan.goal.right.foot_index = msgs::Foot::RIGHT;
00915 resp.step_plan.goal.right.header = resp.step_plan.header;
00916
00917
00918 if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN)
00919 updateStepPlan(resp.step_plan, msgs::UpdateMode::UPDATE_MODE_CHECK_VALIDITY | msgs::UpdateMode::UPDATE_MODE_CHECK_COLLISION | msgs::UpdateMode::UPDATE_MODE_COST, std::string(), false);
00920 else
00921 updateStepPlan(resp.step_plan, msgs::UpdateMode::UPDATE_MODE_COST, std::string(), false);
00922
00923 resp.final_eps = ivPlannerPtr->get_final_epsilon();
00924 resp.planning_time = ivPlannerPtr->get_final_eps_planning_time();
00925
00926 if (resp.status.error == msgs::ErrorStatus::NO_ERROR && resp.final_eps > 1.8)
00927 resp.status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FootstepPlanner", "stepPlanRequestService: Suboptimal plan (eps: " + boost::lexical_cast<std::string>(resp.final_eps) + ")!");
00928
00929
00930 double total_cost = 0.0;
00931 double last_cost = 0.0;
00932 for (std::vector<msgs::Step>::const_iterator itr = resp.step_plan.steps.begin(); itr != resp.step_plan.steps.end(); itr++)
00933 {
00934 step = *itr;
00935
00936 geometry_msgs::Vector3 n;
00937 quaternionToNormal(step.foot.pose.orientation, n);
00938 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));
00939 ROS_INFO("[%i] n: %.3f/%.3f/%.3f", step.step_index, n.x, n.y, n.z);
00940 ROS_INFO("[%i] swing height: %.3f, sway duration: %.3f, step duration: %.3f", step.step_index, step.swing_height, step.sway_duration, step.step_duration);
00941 ROS_INFO("[%i] valid: %s, colliding: %s", step.step_index, step.valid ? "y" : "n", step.colliding ? "y" : "n");
00942 ROS_INFO("[%i] cost: %.3f risk: %.3f", step.step_index, step.cost, step.risk);
00943
00944 total_cost += step.cost;
00945 last_cost = step.cost;
00946
00947 if (WorldModel::instance().isTerrainModelAvailable())
00948 {
00949 double support = 0.0;
00950 WorldModel::instance().getTerrainModel()->getFootContactSupport(step.foot.pose, support, ivCheckedFootContactSupport);
00951 ROS_INFO("[%i] Ground contact support: %.3f", step.step_index, support);
00952 }
00953
00954 ROS_INFO("-------------------------------------");
00955 }
00956 ROS_INFO("Total path cost: %f (%f)", total_cost, total_cost-last_cost);
00957
00958 if (ivCheckedFootContactSupportPub.getNumSubscribers() > 0)
00959 {
00960 sensor_msgs::PointCloud2 msg;
00961 pcl::toROSMsg(*ivCheckedFootContactSupport, msg);
00962 msg.header.frame_id = frame_id;
00963 msg.header.stamp = ros::Time::now();
00964 ivCheckedFootContactSupportPub.publish(msg);
00965 }
00966
00967
00968 foot_pose_transformer.transformToRobotFrame(resp.step_plan);
00969
00970 return true;
00971 }
00972
00973 msgs::ErrorStatus FootstepPlanner::stepPlanRequest(msgs::StepPlanRequestService::Request& req, ResultCB result_cb, FeedbackCB feedback_cb, PreemptCB preempt_cb)
00974 {
00975
00976 preemptPlanning();
00977
00978 this->result_cb = result_cb;
00979 this->feedback_cb = feedback_cb;
00980 this->preempt_cb = preempt_cb;
00981
00982
00983
00984 std::string request_frame_id = strip_const(req.plan_request.header.frame_id, '/');
00985 std::string start_frame_id = strip_const(req.plan_request.start.header.frame_id, '/');
00986 std::string goal_frame_id = strip_const(req.plan_request.goal.header.frame_id, '/');
00987
00988 if (request_frame_id != start_frame_id)
00989 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!");
00990
00991 if (req.plan_request.planning_mode != msgs::StepPlanRequest::PLANNING_MODE_PATTERN && request_frame_id != goal_frame_id)
00992 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!");
00993
00994
00995 if (!req.plan_request.parameter_set_name.data.empty())
00996 {
00997 if (!ParameterManager::setActive(req.plan_request.parameter_set_name.data))
00998 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_PARAMETERS, "FootstepPlanner", "stepPlanRequest: Can't find parameter set named '" + req.plan_request.parameter_set_name.data + "'!");
00999
01000 setParams(ParameterManager::getActive());
01001 }
01002 else
01003 {
01004
01005 reset();
01006 }
01007
01008
01009 foot_pose_transformer.transformToPlannerFrame(req.plan_request.start);
01010 foot_pose_transformer.transformToPlannerFrame(req.plan_request.goal);
01011
01012
01013 start_foot_selection = req.plan_request.start_foot_selection;
01014 max_number_steps = req.plan_request.max_number_steps;
01015 max_path_length_ratio = req.plan_request.max_path_length_ratio;
01016 frame_id = req.plan_request.header.frame_id;
01017 ivPlannerEnvironmentPtr->setFrameId(frame_id);
01018
01019
01020 startPlanning(req);
01021
01022 return msgs::ErrorStatus();
01023 }
01024
01025 bool FootstepPlanner::stepPlanRequestService(msgs::StepPlanRequestService::Request& req, msgs::StepPlanRequestService::Response& resp)
01026 {
01027
01028 resp.status += stepPlanRequest(req);
01029
01030 if (hasError(resp.status))
01031 return true;
01032
01033
01034 planning_thread.join();
01035
01036
01037 finalizeStepPlan(req, resp, true);
01038
01039 return true;
01040 }
01041
01042 void FootstepPlanner::startPlanning(msgs::StepPlanRequestService::Request& req)
01043 {
01044
01045 planning_thread = boost::thread(&FootstepPlanner::doPlanning, this, req);
01046 }
01047
01048 void FootstepPlanner::doPlanning(msgs::StepPlanRequestService::Request& req)
01049 {
01050
01051 boost::recursive_mutex::scoped_lock lock(planner_mutex);
01052
01053 msgs::StepPlanRequestService::Response resp;
01054
01055
01056 if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_3D)
01057 WorldModel::mutableInstance().useTerrainModel(true);
01058 else if (req.plan_request.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_PATTERN)
01059 WorldModel::mutableInstance().useTerrainModel(req.plan_request.pattern_parameters.use_terrain_model);
01060 else
01061 WorldModel::mutableInstance().useTerrainModel(false);
01062
01063
01064 switch (req.plan_request.planning_mode)
01065 {
01066 case msgs::StepPlanRequest::PLANNING_MODE_2D:
01067 case msgs::StepPlanRequest::PLANNING_MODE_3D:
01068 resp.status = planSteps(req);
01069 break;
01070 case msgs::StepPlanRequest::PLANNING_MODE_PATTERN:
01071 resp.status = planPattern(req);
01072 break;
01073 default:
01074 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!");
01075 break;
01076 }
01077
01078
01079 if (!result_cb.empty())
01080 {
01081
01082 if (!hasError(resp.status))
01083 finalizeStepPlan(req, resp, true);
01084 result_cb(resp);
01085 }
01086 }
01087
01088 void FootstepPlanner::preemptPlanning()
01089 {
01090 if (!isPlanning())
01091 return;
01092
01093
01094 planning_thread.interrupt();
01095 planning_thread.join();
01096
01097 if (!preempt_cb.empty())
01098 preempt_cb();
01099 }
01100
01101 bool FootstepPlanner::findNearestValidState(State& s) const
01102 {
01103 if (WorldModel::instance().isAccessible(s))
01104 return true;
01105
01106 State current_state = s;
01107 State best_state = s;
01108
01109 double pos_diff = FLT_MAX;
01110 double yaw_diff = FLT_MAX;
01111 bool solution_found = false;
01112
01113
01114 tf::Transform t;
01115 t.setOrigin(s.getPose().getOrigin());
01116 t.setBasis(s.getPose().getBasis());
01117
01118 tf::Vector3 orig_pos;
01119 tf::Vector3 trans_pos;
01120 orig_pos.setZ(0.0);
01121
01122 for (double yaw = -0.2; yaw <= 0.4; yaw+=env_params->angle_bin_size)
01123 {
01124 current_state.setYaw(s.getYaw() + (s.getLeg() == LEFT ? yaw : -yaw));
01125 for (double y = -0.05; y <= 0.2; y+=env_params->cell_size)
01126 {
01127 orig_pos.setY(s.getLeg() == LEFT ? y : -y);
01128 for (double x = -0.15; x <= 0.15; x+=env_params->cell_size)
01129 {
01130
01131 orig_pos.setX(x);
01132 trans_pos = t * orig_pos;
01133
01134 current_state.setX(trans_pos.getX());
01135 current_state.setY(trans_pos.getY());
01136
01137 if (!WorldModel::instance().update3DData(current_state))
01138 continue;
01139
01140 if (!WorldModel::instance().isAccessible(current_state))
01141 continue;
01142
01143 double dist = std::sqrt(x*x + y*y);
01144 if (pos_diff >= dist && yaw_diff >= std::abs(yaw))
01145 {
01146 best_state = current_state;
01147 pos_diff = dist;
01148 yaw_diff = std::abs(yaw);
01149 solution_found = true;
01150 }
01151 }
01152 }
01153 }
01154
01155 if (solution_found)
01156 s = best_state;
01157
01158 return solution_found;
01159 }
01160
01161 bool FootstepPlanner::checkRobotCollision(const State& left_foot, const State& right_foot, bool& left, bool& right) const
01162 {
01163 left = !WorldModel::instance().isAccessible(left_foot);
01164 right = !WorldModel::instance().isAccessible(right_foot);
01165
01166 if (!left && !right && !WorldModel::instance().isAccessible(left_foot, right_foot))
01167 {
01168 left = true;
01169 right = true;
01170 }
01171
01172 return left || right;
01173 }
01174
01175 bool FootstepPlanner::setStart(const State& left_foot, const State& right_foot, bool ignore_collision)
01176 {
01177
01178 if (std::isnan(left_foot.getRoll())) return false;
01179 if (std::isnan(left_foot.getPitch())) return false;
01180 if (std::isnan(left_foot.getYaw())) return false;
01181 if (std::isnan(right_foot.getRoll())) return false;
01182 if (std::isnan(right_foot.getPitch())) return false;
01183 if (std::isnan(right_foot.getYaw())) return false;
01184
01185 bool left_collision = false;
01186 bool right_collision = false;
01187
01188 if (!ignore_collision && checkRobotCollision(left_foot, right_foot, left_collision, right_collision))
01189 {
01190 start_pose_set_up = false;
01191 return false;
01192 }
01193 else
01194 start_pose_set_up = true;
01195
01196 ivStartFootLeft = left_foot;
01197 ivStartFootRight = right_foot;
01198
01199 ROS_INFO("Start foot poses set to (left: %f %f %f %f) and (right: %f %f %f %f)",
01200 ivStartFootLeft.getX(), ivStartFootLeft.getY(), ivStartFootLeft.getZ(), ivStartFootLeft.getYaw(),
01201 ivStartFootRight.getX(), ivStartFootRight.getY(), ivStartFootRight.getZ(), ivStartFootRight.getYaw());
01202
01203 return true;
01204 }
01205
01206 bool FootstepPlanner::setStart(const msgs::StepPlanRequest& req, bool ignore_collision)
01207 {
01208 State left_foot(req.start.left);
01209 State right_foot(req.start.right);
01210
01211 if (req.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_2D)
01212 {
01213 double z = 0.5*(req.start.left.pose.position.z + req.start.right.pose.position.z);
01214 left_foot.setZ(z);
01215 right_foot.setZ(z);
01216 }
01217
01218 return setStart(left_foot, right_foot, ignore_collision);
01219 }
01220
01221 bool FootstepPlanner::setGoal(const State& left_foot, const State& right_foot, bool ignore_collision)
01222 {
01223
01224 if (std::isnan(left_foot.getRoll())) return false;
01225 if (std::isnan(left_foot.getPitch())) return false;
01226 if (std::isnan(left_foot.getYaw())) return false;
01227 if (std::isnan(right_foot.getRoll())) return false;
01228 if (std::isnan(right_foot.getPitch())) return false;
01229 if (std::isnan(right_foot.getYaw())) return false;
01230
01231 bool left_collision = false;
01232 bool right_collision = false;
01233
01234 if (!ignore_collision && checkRobotCollision(left_foot, right_foot, left_collision, right_collision))
01235 {
01236 goal_pose_set_up = false;
01237 return false;
01238 }
01239 else
01240 goal_pose_set_up = true;
01241
01242 ivGoalFootLeft = left_foot;
01243 ivGoalFootRight = right_foot;
01244
01245 ROS_INFO("Goal foot poses set to (left: %f %f %f %f) and (right: %f %f %f %f)",
01246 ivGoalFootLeft.getX(), ivGoalFootLeft.getY(), ivGoalFootLeft.getZ(), ivGoalFootLeft.getYaw(),
01247 ivGoalFootRight.getX(), ivGoalFootRight.getY(), ivGoalFootRight.getZ(), ivGoalFootRight.getYaw());
01248
01249 return true;
01250 }
01251
01252 bool FootstepPlanner::setGoal(const msgs::StepPlanRequest& req, bool ignore_collision)
01253 {
01254 State left_foot(req.goal.left);
01255 State right_foot(req.goal.right);
01256
01257 if (req.planning_mode == msgs::StepPlanRequest::PLANNING_MODE_2D)
01258 {
01259 double z = 0.5*(req.start.left.pose.position.z + req.start.right.pose.position.z);
01260 geometry_msgs::Vector3 n;
01261
01262 left_foot.setZ(z);
01263 quaternionToNormal(req.start.left.pose.orientation, n);
01264 left_foot.setNormal(n);
01265
01266 right_foot.setZ(z);
01267 quaternionToNormal(req.start.right.pose.orientation, n);
01268 right_foot.setNormal(n);
01269 }
01270
01271 return setGoal(left_foot, right_foot, ignore_collision);
01272 }
01273
01274 State FootstepPlanner::getFootPose(const State& robot, Leg leg, double dx, double dy, double dyaw)
01275 {
01276 double sign = -1.0;
01277 if (leg == LEFT)
01278 sign = 1.0;
01279
01280 double cos_theta = cos(robot.getYaw());
01281 double sin_theta = sin(robot.getYaw());
01282 double shift_x = cos_theta * sign * dx - sin_theta * (0.5 * env_params->foot_seperation + dy);
01283 double shift_y = sin_theta * sign * dx + cos_theta * (0.5 * env_params->foot_seperation + dy);
01284
01285 State foot(robot.getX() + sign * shift_x,
01286 robot.getY() + sign * shift_y,
01287 robot.getZ(),
01288 robot.getRoll(),
01289 robot.getPitch(),
01290 robot.getYaw() + sign * dyaw,
01291 leg);
01292
01293 WorldModel::instance().update3DData(foot);
01294
01295 return foot;
01296 }
01297
01298 State FootstepPlanner::getFootPose(const State& robot, Leg leg)
01299 {
01300 return getFootPose(robot, leg, 0.0, 0.0, 0.0);
01301 }
01302
01303 bool FootstepPlanner::pathIsNew(const std::vector<int>& new_path)
01304 {
01305 if (new_path.size() != ivPlanningStatesIds.size())
01306 return true;
01307
01308 bool unequal = true;
01309 for (unsigned i = 0; i < new_path.size(); ++i)
01310 unequal = new_path[i] != ivPlanningStatesIds[i] && unequal;
01311
01312 return unequal;
01313 }
01314 }