footstep_graph.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2015, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #include "jsk_footstep_planner/footstep_graph.h"
00037 #include <sstream>
00038 
00039 namespace jsk_footstep_planner
00040 {
00041   void FootstepGraph::setBasicSuccessors(
00042     std::vector<Eigen::Affine3f> left_to_right_successors)
00043   {
00044     successors_from_left_to_right_ = left_to_right_successors;
00045     for (size_t i = 0; i < successors_from_left_to_right_.size(); i++) {
00046       Eigen::Affine3f transform = successors_from_left_to_right_[i];
00047       float roll, pitch, yaw;
00048       pcl::getEulerAngles(transform, roll, pitch, yaw);
00049       Eigen::Vector3f translation = transform.translation();
00050       Eigen::Affine3f flipped_transform
00051         = Eigen::Translation3f(translation[0], -translation[1], translation[2])
00052         * Eigen::Quaternionf(Eigen::AngleAxisf(-yaw, Eigen::Vector3f::UnitZ()));
00053       successors_from_right_to_left_.push_back(flipped_transform);
00054     }
00055 
00056     // max_successor_distance_
00057     for (size_t i = 0; i < successors_from_left_to_right_.size(); i++) {
00058       Eigen::Affine3f transform = successors_from_left_to_right_[i];
00059       double dist = transform.translation().norm();
00060       if (dist > max_successor_distance_) {
00061         max_successor_distance_ = dist;
00062       }
00063       double rot = Eigen::AngleAxisf(transform.rotation()).angle();
00064       if (rot > max_successor_rotation_) {
00065         max_successor_rotation_ = rot;
00066       }
00067     }
00068   }
00069 
00070   bool FootstepGraph::isGoal(StatePtr state)
00071   {
00072     FootstepState::Ptr goal = getGoal(state->getLeg());
00073     if (publish_progress_) {
00074       jsk_footstep_msgs::FootstepArray msg;
00075       msg.header.frame_id = "odom";
00076       msg.header.stamp = ros::Time::now();
00077       msg.footsteps.push_back(*state->toROSMsg());
00078       pub_progress_.publish(msg);
00079     }
00080     Eigen::Affine3f pose = state->getPose();
00081     Eigen::Affine3f goal_pose = goal->getPose();
00082     Eigen::Affine3f transformation = pose.inverse() * goal_pose;
00083     return (pos_goal_thr_ > transformation.translation().norm()) &&
00084       (rot_goal_thr_ > std::abs(Eigen::AngleAxisf(transformation.rotation()).angle()));
00085   }
00086 
00087   std::string FootstepGraph::infoString() const
00088   {
00089     std::stringstream ss;
00090     ss << "footstep_graph" << std::endl;
00091     ss << "  pos_goal_thr: " << pos_goal_thr_ << std::endl;
00092     ss << "  rot_goal_thr: " << rot_goal_thr_ << std::endl;
00093     ss << "  use_pointcloud_model: " << use_pointcloud_model_ << std::endl;
00094     ss << "  lazy_projection: " << lazy_projection_ << std::endl;
00095     ss << "  local_movement: " << local_movement_ << std::endl;
00096     ss << "  transition_limit: " << transition_limit_ << std::endl;
00097     ss << "  local_move_x: " << local_move_x_ << std::endl;
00098     ss << "  local_move_y: " << local_move_y_ << std::endl;
00099     ss << "  local_move_theta: " << local_move_theta_ << std::endl;
00100     ss << "  local_move_x_num: " << local_move_x_num_ << std::endl;
00101     ss << "  local_move_y_num: " << local_move_y_num_ << std::endl;
00102     ss << "  local_move_theta_num: " << local_move_theta_num_ << std::endl;
00103     ss << "  resolution: ["
00104        << resolution_[0] << ", "
00105        << resolution_[1] << ", "
00106        << resolution_[2] << "]"
00107        << std::endl;
00108     ss << "  plane_estimation_max_iterations: " << plane_estimation_max_iterations_ << std::endl;
00109     ss << "  plane_estimation_min_inliers: " << plane_estimation_min_inliers_ << std::endl;
00110     ss << "  plane_estimation_outlier_threshold: " << plane_estimation_outlier_threshold_ << std::endl;
00111     ss << "  support_check_x_sampling: " << support_check_x_sampling_ << std::endl;
00112     ss << "  support_check_y_sampling: " << support_check_y_sampling_ << std::endl;
00113     ss << "  support_check_vertex_neighbor_threshold: " << support_check_vertex_neighbor_threshold_ << std::endl;
00114     
00115     return ss.str();
00116   }
00117   
00118   std::vector<FootstepState::Ptr>
00119   FootstepGraph::localMoveFootstepState(FootstepState::Ptr in)
00120   {
00121     std::vector<FootstepState::Ptr> moved_states;
00122     moved_states.reserve(local_move_x_num_ * local_move_y_num_ * local_move_theta_num_ * 8);
00123     for (size_t xi = - local_move_x_num_; xi <= local_move_x_num_; xi++) {
00124       for (size_t yi = - local_move_y_num_; yi <= local_move_y_num_; yi++) {
00125         for (size_t thetai = - local_move_theta_num_; thetai <= local_move_theta_num_; thetai++) {
00126           Eigen::Affine3f trans(Eigen::Translation3f(local_move_x_ / local_move_x_num_ * xi,
00127                                                      local_move_y_ / local_move_y_num_ * yi,
00128                                                      0)
00129                                 * Eigen::AngleAxisf(local_move_theta_ / local_move_theta_num_ * thetai,
00130                                                     Eigen::Vector3f::UnitZ()));
00131           moved_states.push_back(
00132             FootstepState::Ptr(new FootstepState(in->getLeg(),
00133                                                  in->getPose() * trans,
00134                                                  in->getDimensions(),
00135                                                  in->getResolution())));
00136         }
00137       }
00138     }
00139     return moved_states;
00140   }
00141   
00142   std::vector<FootstepGraph::StatePtr>
00143   FootstepGraph::successors(StatePtr target_state)
00144   {
00145     std::vector<Eigen::Affine3f> transformations;
00146     int next_leg;
00147     if (target_state->getLeg() == jsk_footstep_msgs::Footstep::LEFT) {
00148       transformations = successors_from_left_to_right_;
00149       next_leg = jsk_footstep_msgs::Footstep::RIGHT;
00150     }
00151     else if (target_state->getLeg() == jsk_footstep_msgs::Footstep::RIGHT) {
00152       transformations = successors_from_right_to_left_;
00153       next_leg = jsk_footstep_msgs::Footstep::LEFT;
00154     }
00155     else {
00156       // TODO: error
00157     }
00158 
00159     std::vector<FootstepGraph::StatePtr> ret;
00160     Eigen::Affine3f base_pose = target_state->getPose();
00161     for (size_t i = 0; i < transformations.size(); i++) {
00162       Eigen::Affine3f transform = transformations[i];
00163       FootstepGraph::StatePtr next(new FootstepState(next_leg,
00164                                                      base_pose * transform,
00165                                                      target_state->getDimensions(),
00166                                                      resolution_));
00167       if (use_pointcloud_model_ && !lazy_projection_) {
00168         // Update footstep position by projection
00169         unsigned int error_state;
00170         next = projectFootstep(next, error_state);
00171         if (!next && localMovement() && error_state == projection_state::close_to_success) {
00172           std::vector<StatePtr> locally_moved_nodes
00173             = localMoveFootstepState(next);
00174           for (size_t j = 0; j < locally_moved_nodes.size(); j++) {
00175             if (transition_limit_) {
00176               if (transition_limit_->check(target_state, locally_moved_nodes[j])) {
00177                 ret.push_back(locally_moved_nodes[j]);
00178               }
00179             }
00180             else {
00181               ret.push_back(locally_moved_nodes[j]);
00182             }
00183           }
00184         }
00185       }
00186       if (next) {
00187         if (transition_limit_) {
00188           if (transition_limit_->check(target_state, next)) {
00189             ret.push_back(next);
00190           }
00191         }
00192         else {
00193           ret.push_back(next);
00194         }
00195       }
00196     }
00197     return ret;
00198   }
00199 
00200 
00201   FootstepState::Ptr FootstepGraph::projectFootstep(FootstepState::Ptr in)
00202   {
00203     unsigned int error_state;
00204     return projectFootstep(in, error_state);
00205   }
00206   
00207   FootstepState::Ptr FootstepGraph::projectFootstep(FootstepState::Ptr in,
00208                                                     unsigned int& error_state)
00209   {
00210     FootstepState::Ptr projected_footstep = in->projectToCloud(
00211       *tree_model_,
00212       pointcloud_model_,
00213       grid_search_,
00214       *tree_model_2d_,
00215       pointcloud_model_2d_,
00216       Eigen::Vector3f(0, 0, 1),
00217       error_state,
00218       plane_estimation_outlier_threshold_,
00219       plane_estimation_max_iterations_,
00220       plane_estimation_min_inliers_,
00221       support_check_x_sampling_,
00222       support_check_y_sampling_,
00223       support_check_vertex_neighbor_threshold_);
00224     
00225     return projected_footstep;
00226   }
00227   
00228   bool FootstepGraph::projectGoal()
00229   {
00230     unsigned int error_state;
00231     FootstepState::Ptr left_projected = projectFootstep(left_goal_state_);
00232     FootstepState::Ptr right_projected = projectFootstep(right_goal_state_);
00233     if (left_projected && right_projected) {
00234       left_goal_state_ = left_projected;
00235       right_goal_state_ = right_projected;
00236       return true;
00237     }
00238     else {
00239       return false;
00240     }
00241   }
00242   
00243   bool FootstepGraph::projectStart()
00244   {
00245     unsigned int error_state;
00246     FootstepState::Ptr projected = projectFootstep(start_state_);
00247     if (projected) {
00248       start_state_ = projected;
00249       return true;
00250     }
00251     return false;
00252   }
00253 
00254   double footstepHeuristicZero(
00255     SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph)
00256   {
00257     return 0;
00258   }
00259   
00260   double footstepHeuristicStraight(
00261     SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph)
00262   {
00263     FootstepState::Ptr state = node->getState();
00264     FootstepState::Ptr goal = graph->getGoal(state->getLeg());
00265     Eigen::Vector3f state_pos(state->getPose().translation());
00266     Eigen::Vector3f goal_pos(goal->getPose().translation());
00267     return (std::abs((state_pos - goal_pos).norm() / graph->maxSuccessorDistance()));
00268   }
00269   
00270   double footstepHeuristicStraightRotation(
00271     SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph)
00272   {
00273     FootstepState::Ptr state = node->getState();
00274     FootstepState::Ptr goal = graph->getGoal(state->getLeg());
00275     Eigen::Affine3f transform = state->getPose().inverse() * goal->getPose();
00276     return (std::abs(transform.translation().norm() / graph->maxSuccessorDistance()) +
00277                std::abs(Eigen::AngleAxisf(transform.rotation()).angle()) / graph->maxSuccessorRotation());
00278   }
00279 
00280   double footstepHeuristicStepCost(
00281     SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph,
00282     double first_rotation_weight,
00283     double second_rotation_weight)
00284   {
00285     FootstepState::Ptr state = node->getState();
00286     FootstepState::Ptr goal = graph->getGoal(state->getLeg());
00287     Eigen::Vector3f goal_pos(goal->getPose().translation());
00288     Eigen::Vector3f diff_pos(goal_pos - state->getPose().translation());
00289     Eigen::Quaternionf first_rot;
00290     // Eigen::Affine3f::rotation is too slow because it calls SVD decomposition
00291     first_rot.setFromTwoVectors(state->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX(),
00292                                 diff_pos.normalized());
00293 
00294     Eigen::Quaternionf second_rot;
00295     second_rot.setFromTwoVectors(diff_pos.normalized(),
00296                                  goal->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX());
00297     // is it correct??
00298     double first_theta = acos(first_rot.w()) * 2;
00299     double second_theta = acos(second_rot.w()) * 2;
00300     if (isnan(first_theta)) {
00301       first_theta = 0;
00302     }
00303     if (isnan(second_theta)) {
00304       second_theta = 0;
00305     }
00306     // acos := [0, M_PI]
00307     if (first_theta > M_PI) {
00308       first_theta = 2.0 * M_PI - first_theta;
00309     }
00310     if (second_theta > M_PI) {
00311       second_theta = 2.0 * M_PI - second_theta;
00312     }
00313     //return (Eigen::Vector2f(diff_pos[0], diff_pos[1]).norm() / graph->maxSuccessorDistance()) + std::abs(diff_pos[2]) / 0.2 +
00314     return (diff_pos.norm() / graph->maxSuccessorDistance()) + std::abs(diff_pos[2]) / 0.2 + 
00315       (first_theta * first_rotation_weight + second_theta * second_rotation_weight) / graph->maxSuccessorRotation();
00316   }
00317 
00318 }


jsk_footstep_planner
Author(s): Ryohei Ueda
autogenerated on Wed Sep 16 2015 04:37:56