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
00042 #ifndef OCCUPANCY_GRID_UTILS_COMBINE_GRIDS_H
00043 #define OCCUPANCY_GRID_UTILS_COMBINE_GRIDS_H
00044
00045 #include <set>
00046 #include <iterator>
00047 #include <limits>
00048 #include <cmath>
00049
00050 #include <ros/assert.h>
00051 #include <nav_msgs/OccupancyGrid.h>
00052 #include <tf/transform_datatypes.h>
00053
00054 #include <boost/foreach.hpp>
00055
00056 #include <occupancy_grid_utils/coordinate_conversions.h>
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define POLYGON_BOUND(polygon, minmax, xy) \
00069 static_cast<double>(std::minmax(polygon.points[0].xy, \
00070 std::minmax(polygon.points[1].xy, \
00071 std::minmax(polygon.points[2].xy, polygon.points[3].xy))))
00072
00073 namespace occupancy_grid_utils
00074 {
00075
00087 template<typename ForwardIt>
00088 void combineGrids(ForwardIt first, ForwardIt last, double resolution, nav_msgs::OccupancyGrid& result);
00089
00091 template<typename ForwardIt>
00092 void combineGrids (ForwardIt first, ForwardIt last, nav_msgs::OccupancyGrid& result);
00093
00094
00095
00100 nav_msgs::OccupancyGrid::Ptr combineGrids(const std::vector<nav_msgs::OccupancyGrid::ConstPtr>& grids, double resolution);
00101
00106 nav_msgs::OccupancyGrid::Ptr combineGrids(const std::vector<nav_msgs::OccupancyGrid::ConstPtr>& grids);
00107
00108
00109 template<typename ForwardIt>
00110 nav_msgs::MapMetaData getCombinedGridInfo (ForwardIt first, ForwardIt last, const double resolution);
00111 std::set<Cell> intersectingCells (const nav_msgs::MapMetaData& info, const nav_msgs::MapMetaData& info2, const Cell& cell2);
00112 geometry_msgs::Pose transformPose (const tf::Pose trans, const geometry_msgs::Pose p);
00113
00114
00115
00116
00117 template<typename ForwardIt>
00118 nav_msgs::MapMetaData getCombinedGridInfo (ForwardIt first, ForwardIt last, const double resolution)
00119 {
00120 nav_msgs::MapMetaData info;
00121 info.resolution = static_cast<float>(resolution);
00122 tf::Pose trans;
00123 double min_x, max_x, min_y, max_y;
00124 min_x = min_y = std::numeric_limits<double>::infinity();
00125 max_x = max_y = -std::numeric_limits<double>::infinity();
00126
00127 if(first == last) {
00128 return info;
00129 }
00130
00131 const nav_msgs::OccupancyGrid& first_ref = *first;
00132 tf::poseMsgToTF(first_ref.info.origin, trans);
00133
00134
00135 for (ForwardIt grid_it = first; grid_it != last; ++grid_it) {
00136 const nav_msgs::OccupancyGrid& grid = *grid_it;
00137 if (grid.data.empty()) {
00138
00139 continue;
00140 }
00141
00142
00143 nav_msgs::MapMetaData grid_info = grid.info;
00144 grid_info.origin = transformPose(trans.inverse(), grid.info.origin);
00145 geometry_msgs::Polygon polygon = gridPolygon(grid_info);
00146
00147 min_x = std::min(min_x, POLYGON_BOUND(polygon, min, x));
00148 min_y = std::min(min_y, POLYGON_BOUND(polygon, min, y));
00149 max_x = std::max(max_x, POLYGON_BOUND(polygon, max, x));
00150 max_y = std::max(max_y, POLYGON_BOUND(polygon, max, y));
00151 }
00152
00153
00154 if (!std::isfinite(min_x)) {
00155 return info;
00156 }
00157
00158 const double dx = max_x - min_x;
00159 const double dy = max_y - min_y;
00160
00161
00162 ROS_ASSERT((max_x >= min_x) && (max_y >= min_y));
00163
00164 geometry_msgs::Pose pose_in_grid_frame;
00165 pose_in_grid_frame.position.x = min_x;
00166 pose_in_grid_frame.position.y = min_y;
00167 pose_in_grid_frame.orientation.w = 1.0;
00168 info.origin = transformPose(trans, pose_in_grid_frame);
00169 info.height = std::ceil(dy/info.resolution);
00170 info.width = std::ceil(dx/info.resolution);
00171
00172 return info;
00173 }
00174
00175
00176
00177 template<typename ForwardIt>
00178 void combineGrids (ForwardIt first, ForwardIt last, const double resolution, nav_msgs::OccupancyGrid& combined_grid)
00179 {
00180 nav_msgs::MapMetaData grid_info;
00181
00182 if(first == last)
00183 return;
00184
00185
00186 grid_info = getCombinedGridInfo(first, last, resolution);
00187
00188 if (grid_info.width == 0 || grid_info.height == 0) {
00189 return;
00190 }
00191
00192 combined_grid.info = grid_info;
00193 combined_grid.data.resize(combined_grid.info.width*combined_grid.info.height);
00194 fill(combined_grid.data.begin(), combined_grid.data.end(), -1);
00195 ROS_DEBUG_NAMED ("combine_grids", "Combining %zu grids", std::distance(first, last));
00196
00197 for (ForwardIt grid_it = first; grid_it != last; ++grid_it) {
00198 const nav_msgs::OccupancyGrid& grid = *grid_it;
00199 for (coord_t x=0; x<(int)grid.info.width; x++) {
00200 for (coord_t y=0; y<(int)grid.info.height; y++) {
00201 const Cell cell(x, y);
00202 const signed char value=grid.data[cellIndex(grid.info, cell)];
00203
00204
00205 if ((value>=0) && (value<=100)) {
00206 BOOST_FOREACH (const Cell& intersecting_cell,
00207 intersectingCells(combined_grid.info, grid.info, cell)) {
00208 const index_t ind = cellIndex(combined_grid.info, intersecting_cell);
00209 combined_grid.data[ind] = std::max(combined_grid.data[ind], value);
00210 }
00211 }
00212 }
00213 }
00214 }
00215
00216 ROS_DEBUG_NAMED ("combine_grids", "Done combining grids");
00217 }
00218
00219 template<typename ForwardIt>
00220 void combineGrids (ForwardIt first, ForwardIt last, nav_msgs::OccupancyGrid& result)
00221 {
00222 if(first == last)
00223 return;
00224 const nav_msgs::OccupancyGrid& first_ref = *first;
00225 combineGrids(first, last, first_ref.info.resolution, result);
00226 }
00227
00228 }
00229
00230
00231 #undef POLYGON_BOUND
00232
00233 #endif // include guard