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 #include <iostream>
00032 #include <cmath>
00033
00034 #include <ros/ros.h>
00035
00036 #include <gtest/gtest.h>
00037
00038 #include <occupancy_grid_utils/combine_grids.h>
00039 #include <occupancy_grid_utils/coordinate_conversions.h>
00040
00041 const double PI = 3.14159265;
00042 const double TOL = 1e-6;
00043
00044 typedef boost::shared_ptr<nav_msgs::OccupancyGrid> GridPtr;
00045 typedef boost::shared_ptr<nav_msgs::OccupancyGrid const> GridConstPtr;
00046
00047
00048
00049 bool approxEqual (const double x, const double y);
00050 int val (const nav_msgs::OccupancyGrid& g, const occupancy_grid_utils::coord_t x, const occupancy_grid_utils::coord_t y);
00051 geometry_msgs::Point makePoint (const double x, const double y);
00052 geometry_msgs::Pose makePose (const double x, const double y, const double theta);
00053 void setVal (nav_msgs::OccupancyGrid* g, const occupancy_grid_utils::coord_t x, const occupancy_grid_utils::coord_t y, const signed char v);
00054
00055 namespace geometry_msgs {
00056 bool operator== (const Polygon& p1, const Polygon& p2);
00057
00058 bool operator== (const Polygon& p1, const Polygon& p2)
00059 {
00060 if (p1.points.size() != p2.points.size())
00061 return false;
00062 for (unsigned i=0; i<p1.points.size(); i++)
00063 if (!approxEqual(p1.points[i].x, p2.points[i].x) ||
00064 !approxEqual(p1.points[i].y, p2.points[i].y) ||
00065 !approxEqual(p1.points[i].z, p2.points[i].z))
00066 return false;
00067 return true;
00068 }
00069
00070 }
00071
00072 bool approxEqual (const double x, const double y)
00073 {
00074 return std::abs(x-y)<TOL;
00075 }
00076
00077 int val (const nav_msgs::OccupancyGrid& g, const occupancy_grid_utils::coord_t x, const occupancy_grid_utils::coord_t y)
00078 {
00079 const occupancy_grid_utils::Cell c(x, y);
00080 ROS_ASSERT (occupancy_grid_utils::withinBounds(g.info, c));
00081 return g.data[cellIndex(g.info, c)];
00082 }
00083
00084 geometry_msgs::Point makePoint (const double x, const double y)
00085 {
00086 geometry_msgs::Point p;
00087 p.x = x;
00088 p.y = y;
00089 return p;
00090 }
00091
00092 geometry_msgs::Pose makePose (const double x, const double y, const double theta)
00093 {
00094 geometry_msgs::Pose p;
00095 p.position.x = x;
00096 p.position.y = y;
00097 p.orientation = tf::createQuaternionMsgFromYaw(theta);
00098 return p;
00099 }
00100
00101 void setVal (nav_msgs::OccupancyGrid* g, const occupancy_grid_utils::coord_t x, const occupancy_grid_utils::coord_t y, const signed char v)
00102 {
00103 const occupancy_grid_utils::Cell c(x, y);
00104 ROS_ASSERT (occupancy_grid_utils::withinBounds(g->info, c));
00105 g->data[cellIndex(g->info, c)]=v;
00106 }
00107
00108 TEST(GridUtils, CoordinateConversions)
00109 {
00110
00111 nav_msgs::MapMetaData info;
00112 info.resolution = 0.1f;
00113 info.origin = makePose(2, -1, PI/4);
00114 info.height = 50;
00115 info.width = 80;
00116
00117
00118 EXPECT_EQ (804u, occupancy_grid_utils::cellIndex(info, occupancy_grid_utils::Cell(4, 10)));
00119 EXPECT_EQ (occupancy_grid_utils::Cell(8, 1), occupancy_grid_utils::pointCell(info, makePoint(2.5, -0.35)));
00120 EXPECT_EQ (88u, occupancy_grid_utils::pointIndex(info, makePoint(2.5, -0.35)));
00121 EXPECT_EQ (occupancy_grid_utils::Cell(-8, 7), occupancy_grid_utils::pointCell(info, makePoint(1, -1)));
00122 EXPECT_THROW (occupancy_grid_utils::pointIndex(info, makePoint(1, -1)), std::out_of_range);
00123 EXPECT_THROW (occupancy_grid_utils::cellIndex(info, occupancy_grid_utils::Cell(100, 100)), std::out_of_range);
00124
00125
00126 const double side = std::sqrt(2)/2;
00127 geometry_msgs::Polygon expected;
00128 expected.points.resize(4);
00129 expected.points[0].x = static_cast<float>(2 + .1*side);
00130 expected.points[0].y = static_cast<float>(-1 + .3*side);
00131 expected.points[1].x = static_cast<float>(2);
00132 expected.points[1].y = static_cast<float>(-1 + .4*side);
00133 expected.points[2].x = static_cast<float>(2 + .1*side);
00134 expected.points[2].y = static_cast<float>(-1 + .5*side);
00135 expected.points[3].x = static_cast<float>(2 + .2*side);
00136 expected.points[3].y = static_cast<float>(-1 + .4*side);
00137 EXPECT_EQ(expected, cellPolygon(info, occupancy_grid_utils::Cell(2, 1)));
00138 }
00139
00140 TEST(GridUtils, CombineGrids)
00141 {
00142 GridPtr g1(new nav_msgs::OccupancyGrid());
00143 GridPtr g2(new nav_msgs::OccupancyGrid());
00144
00145 g1->info.origin = makePose(2, 1, 0);
00146 g2->info.origin = makePose(3, 0, PI/4);
00147 g1->info.resolution = 0.5;
00148 g2->info.resolution = 0.5;
00149 g1->info.height = 4;
00150 g1->info.width = 6;
00151 g2->info.height = 4;
00152 g2->info.width = 4;
00153 g1->data.resize(24);
00154 g2->data.resize(16);
00155
00156 fill(g1->data.begin(), g1->data.end(), -1);
00157 fill(g2->data.begin(), g2->data.end(), -1);
00158
00159 setVal(g2.get(), 1, 0, 0);
00160 setVal(g2.get(), 0, 3, 50);
00161 setVal(g2.get(), 2, 0, 42);
00162 setVal(g2.get(), 0, 2, 11);
00163 setVal(g2.get(), 3, 2, 0);
00164 setVal(g2.get(), 3, 0, 110);
00165
00166 setVal(g1.get(), 5, 3, 100);
00167 setVal(g1.get(), 3, 0, 24);
00168 setVal(g1.get(), 0, 0, 66);
00169 setVal(g1.get(), 4, 0, 90);
00170
00171 std::vector<GridConstPtr> grids;
00172 grids.push_back(g1);
00173 grids.push_back(g2);
00174 GridPtr combined = occupancy_grid_utils::combineGrids(grids, g1->info.resolution/2.0);
00175
00176 EXPECT_PRED2(approxEqual, 3-std::sqrt(2), combined->info.origin.position.x);
00177 EXPECT_PRED2(approxEqual, 0, combined->info.origin.position.y);
00178 EXPECT_EQ(0.25, combined->info.resolution);
00179 EXPECT_EQ(std::round((2+std::sqrt(2))/0.25), combined->info.width);
00180 EXPECT_EQ(12u, combined->info.height);
00181
00182
00183
00184 EXPECT_EQ(-1, val(*combined, 11, 2));
00185 EXPECT_EQ(-1, val(*combined, 2, 0));
00186 EXPECT_EQ(-1, val(*combined, 5, 0));
00187 EXPECT_EQ(0, val(*combined, 7, 2));
00188 EXPECT_EQ(66, val(*combined, 1, 6));
00189 EXPECT_EQ(100, val(*combined, 11, 11));
00190 EXPECT_EQ(-1, val(*combined, 2, 11));
00191 EXPECT_EQ(11, val(*combined, 3, 2));
00192 EXPECT_EQ(42, val(*combined, 7, 4));
00193 EXPECT_EQ(66, val(*combined, 2, 4));
00194 EXPECT_EQ(0, val(*combined, 6, 8));
00195 EXPECT_EQ(90, val(*combined, 10, 5));
00196 }
00197
00198 int main (int argc, char** argv)
00199 {
00200 ros::Time::init();
00201 testing::InitGoogleTest(&argc, argv);
00202 return RUN_ALL_TESTS();
00203 }