00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00052 struct MapLocation {
00053 unsigned int x;
00054 unsigned int y;
00055 };
00056
00061 class Costmap2D {
00062 friend class CostmapTester;
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
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
00358
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
00415 if(*marked == 0){
00416
00417 double distance = distanceLookup(mx, my, src_x, src_y);
00418
00419
00420 if(distance > cell_inflation_radius_)
00421 return;
00422
00423
00424 updateCellCost(index, costLookup(mx, my, src_x, src_y));
00425
00426
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
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
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
00582 double dist = sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
00583 double scale = std::min(1.0, max_length / dist);
00584
00585
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
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
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
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