inflation.cpp
Go to the documentation of this file.
00001 
00004 /*****************************************************************************
00005 ** Includes
00006 *****************************************************************************/
00007 
00008 #include <iostream>
00009 #include "../../../include/cost_map_core/operators/inflation.hpp"
00010 
00011 /*****************************************************************************
00012 ** Namespaces
00013 *****************************************************************************/
00014 
00015 namespace cost_map {
00016 
00017 /*****************************************************************************
00018 ** Implementation
00019 *****************************************************************************/
00020 
00021 void Inflate::operator()(const std::string layer_source,
00022                          const std::string layer_destination,
00023                          const float& inflation_radius,
00024                          const InflationComputer& inflation_computer,
00025                          CostMap& cost_map
00026                         ) {
00027   //unsigned char* master_array = cost_map...
00028 
00029   unsigned int size_x = cost_map.getSize().x();
00030   unsigned int size_y = cost_map.getSize().y();
00031   unsigned int size = size_x*size_y;
00032   const cost_map::Matrix& data_source = cost_map.get(layer_source);
00033   cost_map.add(layer_destination, data_source);
00034 
00035   // Rebuild internals
00036   seen_.resize(size_x, size_y);
00037   seen_.setConstant(false);
00038   unsigned int new_cell_inflation_radius = static_cast<unsigned int>(std::max(0.0, std::ceil(inflation_radius / cost_map.getResolution())));
00039   if (new_cell_inflation_radius != cell_inflation_radius_ ) {
00040     cell_inflation_radius_ = new_cell_inflation_radius;
00041     computeCaches(cost_map.getResolution(), inflation_computer);
00042   }
00043 
00044   // eigen is default column storage, so iterate over the rows most quickly
00045   // if we want to make it robust, check for data_source.IsRowMajor
00046   for (unsigned int j = 0, number_of_rows = data_source.rows(), number_of_columns = data_source.cols(); j < number_of_columns; ++j) {
00047     for (unsigned int i = 0; i < number_of_rows; ++i) {
00048       unsigned char cost = data_source(i, j);
00049       if (cost == LETHAL_OBSTACLE) {
00050         unsigned int index = j*number_of_rows + i;
00051         enqueue(cost_map.get(layer_source), cost_map.get(layer_destination), i, j, i, j);
00052       }
00053     }
00054   }
00055   while (!inflation_queue_.empty())
00056   {
00057     // get the highest priority cell and pop it off the priority queue
00058     const CellData& current_cell = inflation_queue_.top();
00059 
00060     unsigned int mx = current_cell.x_;
00061     unsigned int my = current_cell.y_;
00062     unsigned int sx = current_cell.src_x_;
00063     unsigned int sy = current_cell.src_y_;
00064 
00065     // pop once we have our cell info
00066     inflation_queue_.pop();
00067 
00068     // attempt to put the neighbors of the current cell onto the queue
00069     if (mx > 0) {
00070       enqueue(cost_map.get(layer_source), cost_map.get(layer_destination), mx - 1, my, sx, sy);
00071     }
00072     if (my > 0) {
00073       enqueue(cost_map.get(layer_source), cost_map.get(layer_destination), mx, my - 1, sx, sy);
00074     }
00075     if (mx < size_x - 1) {
00076       enqueue(cost_map.get(layer_source), cost_map.get(layer_destination), mx + 1, my, sx, sy);
00077     }
00078     if (my < size_y - 1) {
00079       enqueue(cost_map.get(layer_source), cost_map.get(layer_destination), mx, my + 1, sx, sy);
00080     }
00081   }
00082 }
00083 
00084 void Inflate::enqueue(const cost_map::Matrix& data_source,
00085                       cost_map::Matrix& data_destination,
00086                       unsigned int mx, unsigned int my,
00087                       unsigned int src_x, unsigned int src_y
00088                       )
00089 {
00090   // set the cost of the cell being inserted
00091   if (!seen_(mx, my))
00092   {
00093     // we compute our distance table one cell further than the inflation radius dictates so we can make the check below
00094     double distance = distanceLookup(mx, my, src_x, src_y);
00095 
00096     // we only want to put the cell in the queue if it is within the inflation radius of the obstacle point
00097     if (distance > cell_inflation_radius_) {
00098       return;
00099     }
00100 
00101     // assign the cost associated with the distance from an obstacle to the cell
00102     unsigned char cost = costLookup(mx, my, src_x, src_y);
00103     unsigned char old_cost = data_source(mx, my);
00104 
00105     if (old_cost == NO_INFORMATION && cost >= INSCRIBED_OBSTACLE)
00106       data_destination(mx, my) = cost;
00107     else
00108       data_destination(mx, my) = std::max(old_cost, cost);
00109 
00110     // push the cell data onto the queue and mark
00111     seen_(mx, my) = true;
00112     CellData data(distance, mx, my, src_x, src_y);
00113     inflation_queue_.push(data);
00114   }
00115 }
00116 
00117 double Inflate::distanceLookup(int mx, int my, int src_x, int src_y)
00118 {
00119   unsigned int dx = abs(mx - src_x);
00120   unsigned int dy = abs(my - src_y);
00121   return cached_distances_(dx, dy);
00122 }
00123 
00124 unsigned char Inflate::costLookup(int mx, int my, int src_x, int src_y)
00125 {
00126   unsigned int dx = abs(mx - src_x);
00127   unsigned int dy = abs(my - src_y);
00128   return cached_costs_(dx, dy);
00129 }
00130 
00131 void Inflate::computeCaches(const float& resolution, const InflationComputer& compute_cost)
00132 {
00133   cached_costs_.resize(cell_inflation_radius_ + 2, cell_inflation_radius_ + 2);
00134   cached_distances_.resize(cell_inflation_radius_ + 2, cell_inflation_radius_ + 2);
00135 
00136   for (unsigned int i = 0; i <= cell_inflation_radius_ + 1; ++i) {
00137     for (unsigned int j = 0; j <= cell_inflation_radius_ + 1; ++j) {
00138       cached_distances_(i,j) = std::hypot(i, j);
00139     }
00140   }
00141 
00142   for (unsigned int i = 0; i <= cell_inflation_radius_ + 1; ++i) {
00143     for (unsigned int j = 0; j <= cell_inflation_radius_ + 1; ++j) {
00144       cached_costs_(i, j) = compute_cost(resolution*cached_distances_(i, j));
00145     }
00146   }
00147 }
00148 
00149 /*****************************************************************************
00150 ** Inflation Computers
00151 *****************************************************************************/
00152 
00153 ROSInflationComputer::ROSInflationComputer(
00154     const float& inscribed_radius,
00155     const float& weight)
00156 : inscribed_radius_(inscribed_radius)
00157 , weight_(weight)
00158 {
00159 }
00160 
00161 unsigned char ROSInflationComputer::operator()(const float &distance) const {
00162   unsigned char cost = 0;
00163   if (distance == 0.0)
00164     cost = LETHAL_OBSTACLE;
00165   else if (distance <= inscribed_radius_)
00166     cost = INSCRIBED_OBSTACLE;
00167   else
00168   {
00169     // make sure cost falls off by Euclidean distance
00170     double factor = std::exp(-1.0 * weight_ * (distance - inscribed_radius_));
00171     cost = (unsigned char)((INSCRIBED_OBSTACLE - 1) * factor);
00172   }
00173   return cost;
00174 }
00175 
00176 /*****************************************************************************
00177 ** Deflation
00178 *****************************************************************************/
00179 
00180 Deflate::Deflate(const bool& do_not_strip_inscribed_region)
00181 : do_not_strip_inscribed_region(do_not_strip_inscribed_region)
00182 {
00183 }
00184 
00185 void Deflate::operator()(const std::string layer_source,
00186                          const std::string layer_destination,
00187                          CostMap& cost_map
00188                          )
00189 {
00190   // make a call on the data, just to check that the layer is there
00191   // will throw std::out_of_range if not
00192   cost_map::Matrix data_source = cost_map.get(layer_source);
00193   // add a layer filled with NO_INFORMATION
00194   cost_map.add(layer_destination);
00195   cost_map::Matrix& data_destination = cost_map.get(layer_destination);
00196 
00197   unsigned char cost_threshold = do_not_strip_inscribed_region ? cost_map::INSCRIBED_OBSTACLE : cost_map::LETHAL_OBSTACLE;
00198 
00199   // eigen is by default column major - iterate with the row index changing fastest
00200   for (unsigned int j = 0, number_of_rows = data_source.rows(), number_of_columns = data_source.cols(); j < number_of_columns; ++j) {
00201     for (unsigned int i = 0; i < number_of_rows; ++i) {
00202       unsigned char cost = data_source(i, j);
00203       data_destination(i, j) = (cost >= cost_threshold ) ? cost : cost_map::FREE_SPACE;
00204     }
00205   }
00206 }
00207 
00208 
00209 /*****************************************************************************
00210  ** Trailers
00211  *****************************************************************************/
00212 
00213 } // namespace cost_map


cost_map_core
Author(s): Daniel Stonier
autogenerated on Thu Jun 6 2019 20:27:46