PathCostHeuristic.cpp
Go to the documentation of this file.
00001 /*
00002  * A footstep planner for humanoid robots
00003  *
00004  * Copyright 2010-2011 Johannes Garimort, Armin Hornung, University of Freiburg
00005  * http://www.ros.org/wiki/footstep_planner
00006  *
00007  *
00008  * This program is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, version 3.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 #include <footstep_planner/PathCostHeuristic.h>
00022 
00023 
00024 namespace footstep_planner
00025 {
00026 PathCostHeuristic::PathCostHeuristic(double cell_size,
00027                                      int    num_angle_bins,
00028                                      double step_cost,
00029                                      double diff_angle_cost,
00030                                      double max_step_width,
00031                                      double inflation_radius)
00032 : Heuristic(cell_size, num_angle_bins, PATH_COST),
00033   ivpGrid(NULL),
00034   ivStepCost(step_cost),
00035   ivDiffAngleCost(diff_angle_cost),
00036   ivMaxStepWidth(max_step_width),
00037   ivInflationRadius(inflation_radius),
00038   ivGoalX(-1),
00039   ivGoalY(-1)
00040 {}
00041 
00042 
00043 PathCostHeuristic::~PathCostHeuristic()
00044 {
00045   if (ivpGrid)
00046     resetGrid();
00047 }
00048 
00049 
00050 double
00051 PathCostHeuristic::getHValue(const PlanningState& current,
00052                              const PlanningState& to)
00053 const
00054 {
00055   assert(ivGoalX >= 0 && ivGoalY >= 0);
00056 
00057   if (current == to)
00058     return 0.0;
00059 
00060   unsigned int from_x;
00061   unsigned int from_y;
00062   // could be removed after more testing (then use ...noBounds... again)
00063   ivMapPtr->worldToMapNoBounds(cell_2_state(current.getX(), ivCellSize),
00064                                cell_2_state(current.getY(), ivCellSize),
00065                                from_x, from_y);
00066 
00067   unsigned int to_x;
00068   unsigned int to_y;
00069   // could be removed after more testing (then use ...noBounds... again)
00070   ivMapPtr->worldToMapNoBounds(cell_2_state(to.getX(), ivCellSize),
00071                                cell_2_state(to.getY(), ivCellSize),
00072                                to_x, to_y);
00073 
00074   // cast to unsigned int is safe since ivGoalX/ivGoalY are checked to be >= 0
00075   if ((unsigned int)ivGoalX != to_x || (unsigned int)ivGoalY != to_y)
00076   {
00077     ROS_ERROR("PathCostHeuristic::getHValue to a different value than "
00078               "precomputed, heuristic values will be wrong. You need to call "
00079               "calculateDistances() before!");
00080   }
00081   assert((unsigned int)ivGoalX == to_x && (unsigned int)ivGoalY == to_y);
00082 
00083   double dist = double(ivGridSearchPtr->getlowerboundoncostfromstart_inmm(
00084       from_x, from_y)) / 1000.0;
00085 
00086   double expected_steps = dist / ivMaxStepWidth;
00087   double diff_angle = 0.0;
00088   if (ivDiffAngleCost > 0.0)
00089   {
00090     // get the number of bins between from.theta and to.theta
00091     int diff_angle_disc = (
00092         ((to.getTheta() - current.getTheta()) % ivNumAngleBins) +
00093         ivNumAngleBins) % ivNumAngleBins;
00094     // get the rotation independent from the rotation direction
00095     diff_angle = std::abs(angles::normalize_angle(
00096         angle_cell_2_state(diff_angle_disc, ivNumAngleBins)));
00097   }
00098 
00099   return (dist + expected_steps * ivStepCost + diff_angle * ivDiffAngleCost);
00100 }
00101 
00102 
00103 bool
00104 PathCostHeuristic::calculateDistances(const PlanningState& from,
00105                                       const PlanningState& to)
00106 {
00107   assert(ivMapPtr);
00108 
00109   unsigned int from_x;
00110   unsigned int from_y;
00111   ivMapPtr->worldToMapNoBounds(cell_2_state(from.getX(), ivCellSize),
00112                                cell_2_state(from.getY(), ivCellSize),
00113                                from_x, from_y);
00114 
00115   unsigned int to_x;
00116   unsigned int to_y;
00117   ivMapPtr->worldToMapNoBounds(cell_2_state(to.getX(), ivCellSize),
00118                                cell_2_state(to.getY(), ivCellSize),
00119                                to_x, to_y);
00120 
00121   if ((int)to_x != ivGoalX || (int)to_y != ivGoalY)
00122   {
00123     ivGoalX = to_x;
00124     ivGoalY = to_y;
00125     ivGridSearchPtr->search(ivpGrid, cvObstacleThreshold,
00126                             ivGoalX, ivGoalY, from_x, from_y,
00127                             SBPL_2DGRIDSEARCH_TERM_CONDITION_ALLCELLS);
00128   }
00129 
00130   return true;
00131 }
00132 
00133 
00134 void
00135 PathCostHeuristic::updateMap(gridmap_2d::GridMap2DPtr map)
00136 {
00137   if (ivpGrid) // reset map before change it's sizes (in other case we will get SEGMENT ERROR)
00138     resetGrid();
00139 
00140   ivMapPtr.reset();
00141   ivMapPtr = map;
00142 
00143   ivGoalX = ivGoalY = -1;
00144 
00145   unsigned width = ivMapPtr->getInfo().width;
00146   unsigned height = ivMapPtr->getInfo().height;
00147 
00148   if (ivGridSearchPtr)
00149     ivGridSearchPtr->destroy();
00150   ivGridSearchPtr.reset(new SBPL2DGridSearch(width, height,
00151                                              ivMapPtr->getResolution()));
00152 
00153   ivpGrid = new unsigned char* [width];
00154 
00155   for (unsigned x = 0; x < width; ++x)
00156     ivpGrid[x] = new unsigned char [height];
00157   for (unsigned y = 0; y < height; ++y)
00158   {
00159     for (unsigned x = 0; x < width; ++x)
00160     {
00161       float dist = ivMapPtr->distanceMapAtCell(x,y);
00162       if (dist < 0.0f)
00163         ROS_ERROR("Distance map at %d %d out of bounds", x, y);
00164       else if (dist <= ivInflationRadius)
00165         ivpGrid[x][y] = 255;
00166       else
00167         ivpGrid[x][y] = 0;
00168     }
00169   }
00170 }
00171 
00172 
00173 void
00174 PathCostHeuristic::resetGrid()
00175 {
00176   // CvSize size = ivMapPtr->size(); // here we get (height; width) instead of (width; height)
00177   int width = ivMapPtr->getInfo().width;
00178   for (int x = 0; x < width; ++x)
00179   {
00180     if (ivpGrid[x])
00181     {
00182       delete[] ivpGrid[x];
00183       ivpGrid[x] = NULL;
00184     }
00185   }
00186   delete[] ivpGrid;
00187   ivpGrid = NULL;
00188 }
00189 } // end of namespace


footstep_planner
Author(s): Johannes Garimort, Armin Hornung
autogenerated on Sat Jun 8 2019 20:21:05