costmap_2d.h
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2008, Willow Garage, Inc.
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/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the Willow Garage 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 * Author: Eitan Marder-Eppstein
00036 *********************************************************************/
00037 #ifndef COSTMAP_COSTMAP_2D_H_
00038 #define COSTMAP_COSTMAP_2D_H_
00039 
00040 #include <vector>
00041 #include <queue>
00042 #include <cmath>
00043 #include <costmap_2d/observation.h>
00044 #include <costmap_2d/cell_data.h>
00045 #include <costmap_2d/cost_values.h>
00046 #include <boost/thread.hpp>
00047 
00048 namespace costmap_2d {
00049   class Costmap2DConfig;
00050 
00051   //convenient for storing x/y point pairs
00052   struct MapLocation {
00053     unsigned int x;
00054     unsigned int y;
00055   };
00056 
00061   class Costmap2D {
00062     friend class CostmapTester; //Need this for gtest to work correctly
00063     public:
00084       Costmap2D(unsigned int cells_size_x, unsigned int cells_size_y, 
00085           double resolution, double origin_x, double origin_y, double inscribed_radius = 0.0,
00086           double circumscribed_radius = 0.0, double inflation_radius = 0.0, double max_obstacle_range = 0.0,
00087           double max_obstacle_height = 0.0, double max_raytrace_range = 0.0, double weight = 25.0,
00088           const std::vector<unsigned char>& static_data = std::vector<unsigned char>(0), unsigned char lethal_threshold = 0,
00089           bool track_unknown_space = false, unsigned char unknown_cost_value = 0);
00090 
00095       Costmap2D(const Costmap2D& map);
00096 
00102       Costmap2D& operator=(const Costmap2D& map);
00103 
00112       void copyCostmapWindow(const Costmap2D& map, double win_origin_x, double win_origin_y, double win_size_x, double win_size_y);
00113 
00117       Costmap2D();
00118 
00122       virtual ~Costmap2D();
00123 
00124       void reconfigure(costmap_2d::Costmap2DConfig &config, const costmap_2d::Costmap2DConfig& last_config);
00125 
00126       virtual void finishConfiguration(costmap_2d::Costmap2DConfig &config);
00127 
00135       virtual void resetMapOutsideWindow(double wx, double wy, double w_size_x, double w_size_y);
00136 
00145       void reinflateWindow(double wx, double wy, double w_size_x, double w_size_y, bool clear = true);
00146 
00155       virtual void clearNonLethal(double wx, double wy, double w_size_x, double w_size_y, bool clear_no_info = false);
00156 
00162       void updateWorld(double robot_x, double robot_y, 
00163           const std::vector<Observation>& observations, const std::vector<Observation>& clearing_observations);
00164 
00171       unsigned char getCost(unsigned int mx, unsigned int my) const;
00172 
00179       void setCost(unsigned int mx, unsigned int my, unsigned char cost);
00180 
00188       void mapToWorld(unsigned int mx, unsigned int my, double& wx, double& wy) const;
00189 
00198       bool worldToMap(double wx, double wy, unsigned int& mx, unsigned int& my) const;
00199 
00208       void worldToMapNoBounds(double wx, double wy, int& mx, int& my) const;
00209 
00216       inline unsigned int getIndex(unsigned int mx, unsigned int my) const{
00217         return my * size_x_ + mx;
00218       }
00219 
00226       inline void indexToCells(unsigned int index, unsigned int& mx, unsigned int& my) const{
00227         my = index / size_x_;
00228         mx = index - (my * size_x_);
00229       }
00230 
00235       const unsigned char* getCharMap() const;
00236 
00241       unsigned int getSizeInCellsX() const;
00242 
00247       unsigned int getSizeInCellsY() const;
00248 
00253       double getSizeInMetersX() const;
00254 
00259       double getSizeInMetersY() const;
00260 
00265       double getOriginX() const;
00266 
00271       double getOriginY() const;
00272 
00277       double getResolution() const;
00278     
00283       double getInscribedRadius() const { return inscribed_radius_; }
00284     
00289       double getCircumscribedRadius() const { return circumscribed_radius_; }
00290     
00295       double getInflationRadius() const { return inflation_radius_; }
00296 
00303       bool setConvexPolygonCost(const std::vector<geometry_msgs::Point>& polygon, unsigned char cost_value);
00304 
00310       void polygonOutlineCells(const std::vector<MapLocation>& polygon, std::vector<MapLocation>& polygon_cells);
00311 
00317       void convexFillCells(const std::vector<MapLocation>& polygon, std::vector<MapLocation>& polygon_cells);
00318 
00319 
00325       virtual void updateOrigin(double new_origin_x, double new_origin_y);
00326 
00334       bool isCircumscribedCell(unsigned int x, unsigned int y) const;
00335 
00341       inline unsigned char computeCost(double distance) const {
00342         unsigned char cost = 0;
00343         if(distance == 0)
00344           cost = LETHAL_OBSTACLE;
00345         else if(distance <= cell_inscribed_radius_)
00346           cost = INSCRIBED_INFLATED_OBSTACLE;
00347         else {
00348           //make sure cost falls off by Euclidean distance
00349           double euclidean_distance = distance * resolution_;
00350           double factor = exp(-1.0 * weight_ * (euclidean_distance - inscribed_radius_));
00351           cost = (unsigned char) ((INSCRIBED_INFLATED_OBSTACLE - 1) * factor);
00352         }
00353         return cost;
00354       }
00355     
00356       /***
00357        * @brief Get the lower bound of cost for cells inside the circumscribed radius
00358        * @return the circumscribed_cost_lb_ attribute, which gets initialized to computeCost(cell_circumscribed_radius_)
00359        */
00360       inline unsigned char getCircumscribedCost() const {
00361         return circumscribed_cost_lb_;
00362       }
00363 
00368       void saveMap(std::string file_name);
00369 
00374       void saveRawMap(std::string file_name);
00375 
00384       void updateStaticMapWindow(double win_origin_x, double win_origin_y, 
00385           unsigned int data_size_x, unsigned int data_size_y, 
00386           const std::vector<unsigned char>& static_data);
00387 
00396       void replaceFullMap(double win_origin_x, double win_origin_y,
00397           unsigned int data_size_x, unsigned int data_size_y,
00398           const std::vector<unsigned char>& static_data);
00399 
00400 
00401     protected:
00411       inline void enqueue(unsigned int index, unsigned int mx, unsigned int my, 
00412           unsigned int src_x, unsigned int src_y, std::priority_queue<CellData>& inflation_queue){
00413         unsigned char* marked = &markers_[index];
00414         //set the cost of the cell being inserted
00415         if(*marked == 0){
00416           //we compute our distance table one cell further than the inflation radius dictates so we can make the check below
00417           double distance = distanceLookup(mx, my, src_x, src_y);
00418 
00419           //we only want to put the cell in the queue if it is within the inflation radius of the obstacle point
00420           if(distance > cell_inflation_radius_)
00421             return;
00422 
00423           //assign the cost associated with the distance from an obstacle to the cell
00424           updateCellCost(index, costLookup(mx, my, src_x, src_y));
00425 
00426           //push the cell data onto the queue and mark
00427           CellData data(distance, index, mx, my, src_x, src_y);
00428           inflation_queue.push(data);
00429           *marked = 1;
00430         }
00431       }
00432 
00447       template <typename data_type>
00448       void copyMapRegion(data_type* source_map, unsigned int sm_lower_left_x, unsigned int sm_lower_left_y, unsigned int sm_size_x,
00449           data_type* dest_map, unsigned int dm_lower_left_x, unsigned int dm_lower_left_y, unsigned int dm_size_x,
00450           unsigned int region_size_x, unsigned int region_size_y){
00451         //we'll first need to compute the starting points for each map
00452         data_type* sm_index = source_map + (sm_lower_left_y * sm_size_x + sm_lower_left_x);
00453         data_type* dm_index = dest_map + (dm_lower_left_y * dm_size_x + dm_lower_left_x);
00454 
00455         //now, we'll copy the source map into the destination map
00456         for(unsigned int i = 0; i < region_size_y; ++i){
00457           memcpy(dm_index, sm_index, region_size_x * sizeof(data_type));
00458           sm_index += sm_size_x;
00459           dm_index += dm_size_x;
00460         }
00461       }
00462 
00468       unsigned int cellDistance(double world_dist);
00469 
00473       virtual void deleteMaps();
00474 
00478       virtual void resetMaps();
00479 
00483       void deleteKernels();
00484 
00490       virtual void initMaps(unsigned int size_x, unsigned int size_y);
00491 
00497       void copyKernels(const Costmap2D& map, unsigned int cell_inflation_radius);
00498 
00507       void reshapeStaticMap(double win_origin_x, double win_origin_y,
00508           unsigned int data_size_x, unsigned int data_size_y, const std::vector<unsigned char>& static_data);
00509 
00518       void replaceStaticMapWindow(double win_origin_x, double win_origin_y, 
00519           unsigned int data_size_x, unsigned int data_size_y, 
00520           const std::vector<unsigned char>& static_data);
00521 
00522     private:
00528       virtual void updateObstacles(const std::vector<Observation>& observations, std::priority_queue<CellData>& inflation_queue);
00529 
00534       void raytraceFreespace(const std::vector<Observation>& clearing_observations);
00535 
00540       virtual void raytraceFreespace(const Observation& clearing_observation);
00541 
00551       void resetInflationWindow(double wx, double wy, double w_size_x, double w_size_y,
00552           std::priority_queue<CellData>& inflation_queue, bool clear = true );
00553 
00557       void computeCaches();
00558 
00568       template <class ActionType>
00569         inline void raytraceLine(ActionType at, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int max_length = UINT_MAX){
00570           int dx = x1 - x0;
00571           int dy = y1 - y0;
00572 
00573           unsigned int abs_dx = abs(dx);
00574           unsigned int abs_dy = abs(dy);
00575 
00576           int offset_dx = sign(dx);
00577           int offset_dy = sign(dy) * size_x_;
00578 
00579           unsigned int offset = y0 * size_x_ + x0;
00580 
00581           //we need to chose how much to scale our dominant dimension, based on the maximum length of the line
00582           double dist = sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
00583           double scale = std::min(1.0,  max_length / dist);
00584 
00585           //if x is dominant
00586           if(abs_dx >= abs_dy){
00587             int error_y = abs_dx / 2;
00588             bresenham2D(at, abs_dx, abs_dy, error_y, offset_dx, offset_dy, offset, (unsigned int)(scale * abs_dx));
00589             return;
00590           }
00591 
00592           //otherwise y is dominant
00593           int error_x = abs_dy / 2;
00594           bresenham2D(at, abs_dy, abs_dx, error_x, offset_dy, offset_dx, offset, (unsigned int)(scale * abs_dy));
00595 
00596         }
00597 
00601       template <class ActionType>
00602         inline void bresenham2D(ActionType at, unsigned int abs_da, unsigned int abs_db, int error_b, int offset_a, int offset_b, 
00603             unsigned int offset, unsigned int max_length){
00604           unsigned int end = std::min(max_length, abs_da);
00605           for(unsigned int i = 0; i < end; ++i){
00606             at(offset);
00607             offset += offset_a;
00608             error_b += abs_db;
00609             if((unsigned int)error_b >= abs_da){
00610               offset += offset_b;
00611               error_b -= abs_da;
00612             }
00613           }
00614           at(offset);
00615         }
00616 
00621       void inflateObstacles(std::priority_queue<CellData>& inflation_queue);
00622 
00628       inline void updateCellCost(unsigned int index, unsigned char cost){
00629         unsigned char* cell_cost = &costmap_[index];
00630         if(*cell_cost != NO_INFORMATION)
00631           *cell_cost = std::max(cost, *cell_cost);
00632         else if(cost == LETHAL_OBSTACLE)
00633           *cell_cost = cost;
00634       }
00635 
00644       inline char costLookup(int mx, int my, int src_x, int src_y){
00645         unsigned int dx = abs(mx - src_x);
00646         unsigned int dy = abs(my - src_y);
00647         return cached_costs_[dx][dy];
00648       }
00649 
00658       inline double distanceLookup(int mx, int my, int src_x, int src_y){
00659         unsigned int dx = abs(mx - src_x);
00660         unsigned int dy = abs(my - src_y);
00661         return cached_distances_[dx][dy];
00662       }
00663 
00664       inline int sign(int x){
00665         return x > 0 ? 1.0 : -1.0;
00666       }
00667 
00668       boost::recursive_mutex configuration_mutex_;
00669     protected:
00670       unsigned int size_x_;
00671       unsigned int size_y_;
00672       double resolution_;
00673       double origin_x_;
00674       double origin_y_;
00675       unsigned char* static_map_;
00676       unsigned char* costmap_;
00677       unsigned char* markers_;
00678       double max_obstacle_range_;
00679       double max_obstacle_height_;
00680       double max_raytrace_range_;
00681       unsigned char** cached_costs_;
00682       double** cached_distances_;
00683       double inscribed_radius_, circumscribed_radius_, inflation_radius_;
00684       double cell_inscribed_radius_;
00685       unsigned int cell_circumscribed_radius_, cell_inflation_radius_;
00686       double weight_;
00687       unsigned char circumscribed_cost_lb_, lethal_threshold_;
00688       bool track_unknown_space_;
00689       unsigned char unknown_cost_value_;
00690       std::priority_queue<CellData> inflation_queue_;
00691 
00692       //functors for raytracing actions
00693       class ClearCell {
00694         public:
00695           ClearCell(unsigned char* costmap) : costmap_(costmap) {}
00696           inline void operator()(unsigned int offset){
00697             costmap_[offset] = 0;
00698           }
00699         private:
00700           unsigned char* costmap_;
00701       };
00702 
00703       class MarkCell {
00704         public:
00705           MarkCell(unsigned char* costmap) : costmap_(costmap) {}
00706           inline void operator()(unsigned int offset){
00707             costmap_[offset] = LETHAL_OBSTACLE;
00708           }
00709         private:
00710           unsigned char* costmap_;
00711       };
00712 
00713       class PolygonOutlineCells {
00714         public:
00715           PolygonOutlineCells(const Costmap2D& costmap, const unsigned char* char_map, std::vector<MapLocation>& cells) 
00716             : costmap_(costmap), char_map_(char_map), cells_(cells){}
00717 
00718           //just push the relevant cells back onto the list
00719           inline void operator()(unsigned int offset){
00720             MapLocation loc;
00721             costmap_.indexToCells(offset, loc.x, loc.y);
00722             cells_.push_back(loc);
00723           }
00724 
00725         private:
00726           const Costmap2D& costmap_;
00727           const unsigned char* char_map_;
00728           std::vector<MapLocation>& cells_;
00729       };
00730   };
00731 };
00732 
00733 #endif


costmap_2d
Author(s): Eitan Marder-Eppstein
autogenerated on Mon Oct 6 2014 02:44:46