combine_grids.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * Copyright (c) 2015-2016, Jiri Horner
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the Jiri Horner nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
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  * internal macro
00060  * @brief Computes specified boundary for polygon
00061  * @details [long description]
00062  *
00063  * @param polygon pologon to work on
00064  * @param minmax Must be 'min' or 'max' will compute minimum or maximum
00065  * respectively
00066  * @param xy Must be 'x' or 'y'. Coordinate.
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 /* for backward compatibility */
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 /* util functions */
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 /* templates */
00115 
00116 // Get the dimensions of a combined grid
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; // needed to support reference_wrapper
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; // needed to support reference_wrapper
00137     if (grid.data.empty()) {
00138       // skip empty grids as nothing will merged for them
00139       continue;
00140     }
00141 
00142     /* get bounding polygon for grid in world frame */
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   // all grids were empty
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   // min and max might be egual if we have only 1 grid
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 // Main function
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   // compute size of merged grid
00186   grid_info = getCombinedGridInfo(first, last, resolution);
00187   // if all grid are empty (zero size) or size could not be computed
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; // needed to support reference_wrapper
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         // Only proceed if the value is not unknown
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; // needed to support reference_wrapper
00225   combineGrids(first, last, first_ref.info.resolution, result);
00226 }
00227 
00228 } // namespace occupancy_grid_utils
00229 
00230 // internal macro
00231 #undef POLYGON_BOUND
00232 
00233 #endif // include guard


map_merge
Author(s): Jiri Horner
autogenerated on Sun Mar 26 2017 03:48:10