grid_map_scan_adders_test.cpp
Go to the documentation of this file.
1 #include <gtest/gtest.h>
2 
3 #include "../../../src/core/maps/grid_map_scan_adders.h"
4 
5 #include <memory>
6 
7 #include "../mock_grid_cell.h"
8 #include "../../../src/core/maps/const_occupancy_estimator.h"
9 #include "../../../src/core/maps/plain_grid_map.h"
10 #include "../../../src/core/math_utils.h"
11 #include "../../../src/utils/data_generation/grid_map_patcher.h"
12 #include "../../../src/utils/data_generation/laser_scan_generator.h"
13 #include "../../../src/utils/data_generation/map_primitives.h"
14 
15 //============================================================================//
16 //=== Tests ===//
17 //============================================================================//
18 
19 //----------------------------------------------------------------------------//
20 // Plain scan integration
21 
22 constexpr Occupancy Occup = {1.0, 1.0}, Empty = {0.0, 1.0};
23 
24 class PlainScanIntegrationTest : public ::testing::Test {
25 protected:
26  static constexpr int MAP_WIDTH = 100, MAP_HEIGHT = 100;
27  static constexpr double MAP_SCALE = 1;
28 
29 protected:
30 
32  : cell_proto{std::make_shared<MockGridCell>()}
33  , src_map{cell_proto, {MAP_WIDTH, MAP_HEIGHT, MAP_SCALE}}
34  , dst_map{cell_proto, {MAP_WIDTH, MAP_HEIGHT, MAP_SCALE}}
35  , pose{0, 0, 0} {}
36 
37  std::shared_ptr<GridMapScanAdder> plain_adder() const {
38  auto oe = std::make_shared<ConstOccupancyEstimator>(Occup, Empty);
40  return builder.set_occupancy_estimator(oe)
41  .build();
42  }
43 
44  bool map_was_modified(const GridMap &map) const {
45  auto unknown_prob = static_cast<double>(*cell_proto);
46  auto raw_coord = GridMap::Coord{0, 0};
47  // FIXME: code duplication. Implement coords "iterator".
48  for (raw_coord.x = 0; raw_coord.x < map.width(); ++raw_coord.x) {
49  for (raw_coord.y = 0; raw_coord.y < map.width(); ++raw_coord.y) {
50  auto coord = map.internal2external(raw_coord);
51  if (!are_equal(unknown_prob, map[coord])) {
52  return true;
53  }
54  }
55  }
56  return false;
57  }
58 
59  bool map_includes(const GridMap &outer, const GridMap &inner) const {
60  auto unknown_prob = static_cast<double>(*cell_proto);
61  if (outer.width() != inner.width() || outer.height() != inner.height() ||
62  outer.scale() != inner.scale() || outer.origin() != inner.origin()) {
63  return false;
64  }
65 
66  auto raw_coord = GridMap::Coord{0, 0};
67  for (raw_coord.x = 0; raw_coord.x < inner.width(); ++raw_coord.x) {
68  for (raw_coord.y = 0; raw_coord.y < inner.width(); ++raw_coord.y) {
69  auto coord = inner.internal2external(raw_coord);
70  if (are_equal(unknown_prob, inner[coord])) { continue; }
71  if (!are_equal(inner[coord], outer[coord])) { return false; }
72  }
73  }
74  return true;
75  }
76 
77  bool map_contains_scan(const GridMap &map, const LaserScan2D &scan) {
78  for (auto &sp : scan.points()) {
79  const auto &wp = sp.move_origin(pose.point(), scan.trig_provider);
80  const auto coord = map.world_to_cell(wp);
81  if (!are_equal(1.0, map[coord])) { return false; }
82  }
83  return true;
84  }
85 
86 protected:
87  std::shared_ptr<GridCell> cell_proto;
90 };
91 
92 TEST_F(PlainScanIntegrationTest, smokeScanAdditionTest) {
93  // setup map, pose, scan
94  auto cecum = CecumTextRasterMapPrimitive{50, 50,
96  GridMapPatcher{}.apply_text_raster(src_map, cecum.to_stream());
97  pose += RobotPoseDelta{src_map.scale() / 2, src_map.scale() / 2, deg2rad(90)};
98 
99  constexpr auto lsp = to_lsp(MAP_WIDTH * 2, 270, 100);
100  auto scan = LaserScanGenerator{lsp}.laser_scan_2D(src_map, pose, 1);
101 
102  // test
103  plain_adder()->append_scan(dst_map, pose, scan, 1.0 /* quality */, 0);
104  ASSERT_TRUE(map_was_modified(dst_map));
105 
106  scan.trig_provider->set_base_angle(pose.theta);
107  ASSERT_TRUE(map_contains_scan(dst_map, scan));
108  ASSERT_TRUE(map_includes(src_map, dst_map));
109 }
110 
111 //----------------------------------------------------------------------------//
112 // Distance-based wall blurring (hole-width from tinySLAM)
113 
115 protected:
116  static constexpr int MAP_WIDTH = 50, MAP_HEIGHT = 50;
117  static constexpr double MAP_SCALE = 1;
118 
119 protected:
121  : cell_proto{std::make_shared<MockGridCell>()}
122  , src_map{cell_proto, {MAP_WIDTH, MAP_HEIGHT, MAP_SCALE}}
123  , dst_map{cell_proto, {MAP_WIDTH, MAP_HEIGHT, MAP_SCALE}}
124  , pose{0, 0, 0} {}
125 
126  std::shared_ptr<GridMapScanAdder> adder(double blurring_width) const {
127  auto oe = std::make_shared<ConstOccupancyEstimator>(Occup, Empty);
129  return builder.set_occupancy_estimator(oe)
130  .set_blur_distance(blurring_width)
131  .build();
132  }
133 
134 protected:
135  std::shared_ptr<GridCell> cell_proto;
138 };
139 
140 TEST_F(DistanceBasedWallBlurringTest, smokeDistanceBaseBlurringTest) {
141  constexpr auto Obstacle_Coord = GridMap::Coord{20, 0};
142  // setup pose and map
143  pose += RobotPoseDelta{src_map.scale() / 2, src_map.scale() / 2, 0};
144  auto aoo = AreaOccupancyObservation{true, {1.0, 1.0}, {0, 0}, 1.0};
145  src_map.update(Obstacle_Coord, aoo);
146 
147  // setup scan
148  constexpr auto lsp = to_lsp(MAP_WIDTH * 2, 360, 100);
149  auto scan = LaserScanGenerator{lsp}.laser_scan_2D(src_map, pose, 1);
150 
151  // test
152  constexpr double Blur_Distance = 3;
153  adder(Blur_Distance)->append_scan(dst_map, pose, scan, 1.0, 0);
154  ASSERT_TRUE(map_was_modified(dst_map));
155 
156  scan.trig_provider->set_base_angle(pose.theta);
157  ASSERT_TRUE(map_contains_scan(dst_map, scan));
158 
159  double prev_prob = 0;
160  auto beam_coord = dst_map.world_to_cell(pose.point());
161  unsigned occupied_cells = 0;
162  while (beam_coord.x <= Obstacle_Coord.x) {
163  if (prev_prob == 0) {
164  ASSERT_TRUE(0 <= dst_map[beam_coord]);
165  } else {
166  ASSERT_TRUE(prev_prob < dst_map[beam_coord]);
167  }
168  prev_prob = dst_map[beam_coord];
169  occupied_cells += 0 < prev_prob ? 1 : 0;
170  ++beam_coord.x;
171  }
172  ASSERT_TRUE(1 < occupied_cells);
173 }
174 
175 //============================================================================//
176 
177 int main (int argc, char *argv[]) {
178  ::testing::InitGoogleTest(&argc, argv);
179  return RUN_ALL_TESTS();
180 }
static constexpr auto to_lsp(double max_dist, double fow_deg, unsigned pts_nm)
Coord world_to_cell(const Point2D &pt) const
CONSTEXPR bool are_equal(const T &a, const T &b, const T &eps)
Definition: math_utils.h:17
double theta
Definition: robot_pose.h:131
int main(int argc, char *argv[])
void update(const Coord &area_id, const AreaOccupancyObservation &aoo) override
Updates area with a given observation.
bool map_includes(const GridMap &outer, const GridMap &inner) const
bool map_was_modified(const GridMap &map) const
bool map_contains_scan(const GridMap &map, const LaserScan2D &scan)
virtual DiscretePoint2D origin() const
static WallDistanceBlurringScanAdderBuilder builder()
constexpr Occupancy Occup
std::shared_ptr< GridMapScanAdder > plain_adder() const
std::shared_ptr< GridMapScanAdder > adder(double blurring_width) const
void apply_text_raster(MapType &dst_map, std::istream &src_raster, const DiscretePoint2D &dst_offset, int w_zoom=1, int h_zoom=1)
Coord internal2external(const Coord &coord) const
const Points & points() const
Definition: sensor_data.h:148
LaserScan2D laser_scan_2D(const GridMap &map, const RobotPose &pose, double occ_threshold=1)
std::shared_ptr< GridCell > cell_proto
std::shared_ptr< TrigonometryProvider > trig_provider
Definition: sensor_data.h:171
static constexpr double MAP_SCALE
virtual int height() const
constexpr double deg2rad(double angle_deg)
Definition: math_utils.h:56
constexpr Occupancy Empty
auto point() const
Definition: robot_pose.h:129
TEST_F(PlainScanIntegrationTest, smokeScanAdditionTest)
virtual double scale() const
virtual int width() const
std::shared_ptr< GridCell > cell_proto


slam_constructor
Author(s): JetBrains Research, OSLL team
autogenerated on Mon Jun 10 2019 15:08:25