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
00041 #ifndef OCCUPANCY_GRID_UTILS_COORDINATE_CONVERSIONS_H
00042 #define OCCUPANCY_GRID_UTILS_COORDINATE_CONVERSIONS_H
00043
00044 #include <occupancy_grid_utils/exceptions.h>
00045 #include <tf/transform_datatypes.h>
00046 #include <nav_msgs/OccupancyGrid.h>
00047 #include <geometry_msgs/Polygon.h>
00048 #include <ros/assert.h>
00049 #include <cstdlib>
00050 #include <ostream>
00051
00052 namespace occupancy_grid_utils
00053 {
00054
00055
00056
00057
00058
00059 typedef uint32_t index_t;
00060 typedef int16_t coord_t;
00061
00062 struct Cell
00063 {
00064 Cell(const coord_t x=0, const coord_t y=0) : x(x), y(y) {}
00065 coord_t x;
00066 coord_t y;
00067
00068 bool operator== (const Cell& c) const;
00069 bool operator< (const Cell& c) const;
00070 };
00071
00072
00073
00074 const int8_t UNOCCUPIED=0;
00075 const int8_t OCCUPIED=100;
00076 const int8_t UNKNOWN=255;
00077
00078
00082 index_t cellIndex (const nav_msgs::MapMetaData& info, const Cell& c);
00083
00085 Cell indexCell (const nav_msgs::MapMetaData& info, index_t ind);
00086
00090 Cell pointCell (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p);
00091
00096 index_t pointIndex (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p);
00097
00099 geometry_msgs::Point cellCenter (const nav_msgs::MapMetaData& info, const Cell& c);
00100
00102 geometry_msgs::Polygon cellPolygon (const nav_msgs::MapMetaData& info, const Cell& c);
00103
00105 bool withinBounds (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p);
00106
00108 bool withinBounds (const nav_msgs::MapMetaData& info, const Cell& c);
00109
00111 geometry_msgs::Polygon gridPolygon (const nav_msgs::MapMetaData& info);
00112
00113
00114
00115
00116
00117 inline
00118 index_t cellIndex (const nav_msgs::MapMetaData& info, const Cell& c)
00119 {
00120 if (!withinBounds(info, c))
00121 throw CellOutOfBoundsException(c.x, c.y);
00122 return c.x + c.y*info.width;
00123 }
00124
00125 inline
00126 Cell indexCell (const nav_msgs::MapMetaData& info, const index_t ind)
00127 {
00128 const div_t result = div((int) ind, (int) info.width);
00129 return Cell(result.rem, result.quot);
00130 }
00131
00132
00133 inline
00134 tf::Transform mapToWorld (const nav_msgs::MapMetaData& info)
00135 {
00136 tf::Transform world_to_map;
00137 tf::poseMsgToTF (info.origin, world_to_map);
00138 return world_to_map;
00139 }
00140
00141 inline
00142 tf::Transform worldToMap (const nav_msgs::MapMetaData& info)
00143 {
00144 return mapToWorld(info).inverse();
00145 }
00146
00147 inline
00148 Cell pointCell (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p)
00149 {
00150 tf::Point pt;
00151 tf::pointMsgToTF(p, pt);
00152 tf::Point p2 = worldToMap(info)*pt;
00153 return Cell(floor(p2.x()/info.resolution), floor(p2.y()/info.resolution));
00154 }
00155
00156 inline
00157 index_t pointIndex (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p)
00158 {
00159 return cellIndex(info, pointCell(info, p));
00160 }
00161
00162 inline
00163 geometry_msgs::Point cellCenter (const nav_msgs::MapMetaData& info, const Cell& c)
00164 {
00165 tf::Point pt((c.x+0.5)*info.resolution, (c.y+0.5)*info.resolution, 0.0);
00166 geometry_msgs::Point p;
00167 tf::pointTFToMsg(mapToWorld(info)*pt, p);
00168 return p;
00169 }
00170
00171 inline
00172 geometry_msgs::Polygon cellPolygon (const nav_msgs::MapMetaData& info, const Cell& c)
00173 {
00174 const float dx[4] = {0.0, 0.0, 1.0, 1.0};
00175 const float dy[4] = {0.0, 1.0, 1.0, 0.0};
00176
00177 const tf::Transform trans = mapToWorld(info);
00178 geometry_msgs::Polygon p;
00179 p.points.resize(4);
00180 for (unsigned i=0; i<4; i++) {
00181 tf::Point pt((c.x+dx[i])*info.resolution, (c.y+dy[i])*info.resolution, 0.0);
00182 tf::Point transformed = trans*pt;
00183 p.points[i].x = transformed.x();
00184 p.points[i].y = transformed.y();
00185 p.points[i].z = transformed.z();
00186 }
00187 return p;
00188 }
00189
00190 inline
00191 geometry_msgs::Polygon gridPolygon (const nav_msgs::MapMetaData& info)
00192 {
00193 const float x[4] = {0.0, 0.0, 1.0, 1.0};
00194 const float y[4] = {0.0, 1.0, 1.0, 0.0};
00195
00196 const tf::Transform trans = mapToWorld(info);
00197 geometry_msgs::Polygon p;
00198 p.points.resize(4);
00199
00200 for (unsigned i=0; i<4; i++) {
00201 tf::Point pt(x[i]*info.resolution*info.width, y[i]*info.resolution*info.height, 0.0);
00202 tf::Point transformed=trans*pt;
00203 p.points[i].x = transformed.x();
00204 p.points[i].y = transformed.y();
00205 p.points[i].z = transformed.z();
00206 }
00207 return p;
00208 }
00209
00210 inline
00211 bool Cell::operator== (const Cell& c) const
00212 {
00213 return ((this->x == c.x) && (this->y == c.y));
00214 }
00215
00216 inline
00217 bool Cell::operator< (const Cell& c) const
00218 {
00219 return ((this->x < c.x) || ((this->x == c.x) && (this->y < c.y)));
00220 }
00221
00222 inline
00223 std::ostream& operator<< (std::ostream& str, const Cell& c)
00224 {
00225 str << "(" << c.x << ", " << c.y << ")";
00226 return str;
00227 }
00228
00229 inline
00230 bool withinBounds (const nav_msgs::MapMetaData& info, const geometry_msgs::Point& p)
00231 {
00232 return withinBounds(info, pointCell(info, p));
00233 }
00234
00235 inline
00236 bool withinBounds (const nav_msgs::MapMetaData& info, const Cell& c)
00237 {
00238 return (c.x >= 0) && (c.y >= 0) && (c.x < (coord_t) info.width) && (c.y < (coord_t) info.height);
00239 }
00240
00241 }
00242
00243 #endif // include guard