obstacle_tests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
35 #include <costmap_2d/costmap_2d.h>
39 #include <set>
40 #include <gtest/gtest.h>
41 
42 using namespace costmap_2d;
43 
44 /*
45  * For reference, the static map looks like this:
46  *
47  * 0 0 0 0 0 0 0 254 254 254
48  *
49  * 0 0 0 0 0 0 0 254 254 254
50  *
51  * 0 0 0 254 254 254 0 0 0 0
52  *
53  * 0 0 0 0 0 0 0 0 0 0
54  *
55  * 0 0 0 0 0 0 0 0 0 0
56  *
57  * 0 0 0 0 254 0 0 254 254 254
58  *
59  * 0 0 0 0 254 0 0 254 254 254
60  *
61  * 0 0 0 0 0 0 0 254 254 254
62  *
63  * 0 0 0 0 0 0 0 0 0 0
64  *
65  * 0 0 0 0 0 0 0 0 0 0
66  *
67  * upper left is 0,0, lower right is 9,9
68  */
69 
73 TEST(costmap, testRaytracing){
75 
76  LayeredCostmap layers("frame", false, false); // Not rolling window, not tracking unknown
77  addStaticLayer(layers, tf); // This adds the static map
78  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
79 
80  // Add a point at 0, 0, 0
81  addObservation(olayer, 0.0, 0.0, MAX_Z/2, 0, 0, MAX_Z/2);
82 
83  // This actually puts the LETHAL (254) point in the costmap at (0,0)
84  layers.updateMap(0,0,0); // 0, 0, 0 is robot pose
85  //printMap(*(layers.getCostmap()));
86 
87  int lethal_count = countValues(*(layers.getCostmap()), LETHAL_OBSTACLE);
88 
89  // We expect just one obstacle to be added (20 in static map)
90  ASSERT_EQ(lethal_count, 21);
91 }
92 
96 TEST(costmap, testRaytracing2){
98  LayeredCostmap layers("frame", false, false);
99  addStaticLayer(layers, tf);
100  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
101 
102  //If we print map now, it is 10x10 all value 0
103  //printMap(*(layers.getCostmap()));
104 
105  // Update will fill in the costmap with the static map
106  layers.updateMap(0,0,0);
107 
108  //If we print the map now, we get the static map
109  //printMap(*(layers.getCostmap()));
110 
111  // Static map has 20 LETHAL cells (see diagram above)
112  int obs_before = countValues(*(layers.getCostmap()), LETHAL_OBSTACLE);
113  ASSERT_EQ(obs_before, 20);
114 
115  // The sensor origin will be <0,0>. So if we add an obstacle at 9,9,
116  // we would expect cells <0, 0> thru <8, 8> to be traced through
117  // however the static map is not cleared by obstacle layer
118  addObservation(olayer, 9.5, 9.5, MAX_Z/2, 0.5, 0.5, MAX_Z/2);
119  layers.updateMap(0, 0, 0);
120 
121  // If we print map now, we have static map + <9,9> is LETHAL
122  //printMap(*(layers.getCostmap()));
123  int obs_after = countValues(*(layers.getCostmap()), LETHAL_OBSTACLE);
124 
125  // Change from previous test:
126  // No obstacles from the static map will be cleared, so the
127  // net change is +1.
128  ASSERT_EQ(obs_after, obs_before + 1);
129 
130  // Fill in the diagonal, <7,7> and <9,9> already filled in, <0,0> is robot
131  for(int i = 0; i < olayer->getSizeInCellsY(); ++i)
132  {
133  olayer->setCost(i, i, LETHAL_OBSTACLE);
134  }
135  // This will updateBounds, which will raytrace the static observation added
136  // above, thus clearing out the diagonal again!
137  layers.updateMap(0, 0, 0);
138 
139  // Map now has diagonal except <0,0> filled with LETHAL (254)
140  //printMap(*(layers.getCostmap()));
141  int with_static = countValues(*(layers.getCostmap()), LETHAL_OBSTACLE);
142 
143  // Should thus be the same
144  ASSERT_EQ(with_static, obs_after);
145  // If 21 are filled, 79 should be free
146  ASSERT_EQ(79, countValues(*(layers.getCostmap()), costmap_2d::FREE_SPACE));
147 }
148 
152 TEST(costmap, testWaveInterference){
154 
155  // Start with an empty map, no rolling window, tracking unknown
156  LayeredCostmap layers("frame", false, true);
157  layers.resizeMap(10, 10, 1, 0, 0);
158  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
159 
160  // If we print map now, it is 10x10, all cells are 255 (NO_INFORMATION)
161  //printMap(*(layers.getCostmap()));
162 
163  // Lay out 3 obstacles in a line - along the diagonal, separated by a cell.
164  addObservation(olayer, 3.0, 3.0, MAX_Z);
165  addObservation(olayer, 5.0, 5.0, MAX_Z);
166  addObservation(olayer, 7.0, 7.0, MAX_Z);
167  layers.updateMap(0,0,0);
168 
169  Costmap2D* costmap = layers.getCostmap();
170  // 3 obstacle cells are filled, <1,1>,<2,2>,<4,4> and <6,6> are now free
171  // <0,0> is footprint and is free
172  //printMap(*costmap);
173  ASSERT_EQ(3, countValues(*costmap, costmap_2d::LETHAL_OBSTACLE));
174  ASSERT_EQ(92, countValues(*costmap, costmap_2d::NO_INFORMATION));
175  ASSERT_EQ(5, countValues(*costmap, costmap_2d::FREE_SPACE));
176 }
177 
181 TEST(costmap, testZThreshold){
183  // Start with an empty map
184  LayeredCostmap layers("frame", false, true);
185  layers.resizeMap(10, 10, 1, 0, 0);
186 
187  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
188 
189  // A point cloud with 2 points falling in a cell with a non-lethal cost
190  addObservation(olayer, 0.0, 5.0, 0.4);
191  addObservation(olayer, 1.0, 5.0, 2.2);
192 
193  layers.updateMap(0,0,0);
194 
195  Costmap2D* costmap = layers.getCostmap();
196  ASSERT_EQ(countValues(*costmap, costmap_2d::LETHAL_OBSTACLE), 1);
197 }
198 
199 
203 TEST(costmap, testDynamicObstacles){
205  LayeredCostmap layers("frame", false, false);
206  addStaticLayer(layers, tf);
207 
208  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
209 
210  // Add a point cloud and verify its insertion. There should be only one new one
211  addObservation(olayer, 0.0, 0.0);
212  addObservation(olayer, 0.0, 0.0);
213  addObservation(olayer, 0.0, 0.0);
214 
215  layers.updateMap(0,0,0);
216 
217  Costmap2D* costmap = layers.getCostmap();
218  // Should now have 1 insertion and no deletions
219  ASSERT_EQ(countValues(*costmap, costmap_2d::LETHAL_OBSTACLE), 21);
220 
221  // Repeating the call - we should see no insertions or deletions
222  ASSERT_EQ(countValues(*costmap, costmap_2d::LETHAL_OBSTACLE), 21);
223 }
224 
225 
229 TEST(costmap, testMultipleAdditions){
231  LayeredCostmap layers("frame", false, false);
232  addStaticLayer(layers, tf);
233 
234  ObstacleLayer* olayer = addObstacleLayer(layers, tf);
235 
236  // A point cloud with one point that falls within an existing obstacle
237  addObservation(olayer, 9.5, 0.0);
238  layers.updateMap(0,0,0);
239  Costmap2D* costmap = layers.getCostmap();
240  //printMap(*costmap);
241 
242  ASSERT_EQ(countValues(*costmap, costmap_2d::LETHAL_OBSTACLE), 20);
243 
244 }
245 
246 
247 int main(int argc, char** argv){
248  ros::init(argc, argv, "obstacle_tests");
249  testing::InitGoogleTest(&argc, argv);
250  return RUN_ALL_TESTS();
251 }
void setCost(unsigned int mx, unsigned int my, unsigned char cost)
Set the cost of a cell in the costmap.
Definition: costmap_2d.cpp:197
unsigned int countValues(costmap_2d::Costmap2D &costmap, unsigned char value, bool equal=true)
const double MAX_Z(1.0)
void resizeMap(unsigned int size_x, unsigned int size_y, double resolution, double origin_x, double origin_y, bool size_locked=false)
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
Definition: costmap_2d.cpp:435
costmap_2d::ObstacleLayer * addObstacleLayer(costmap_2d::LayeredCostmap &layers, tf2_ros::Buffer &tf)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
static const unsigned char FREE_SPACE
Definition: cost_values.h:45
TEST(costmap, testRaytracing)
static const unsigned char LETHAL_OBSTACLE
Definition: cost_values.h:43
static const unsigned char NO_INFORMATION
Definition: cost_values.h:42
void addObservation(costmap_2d::ObstacleLayer *olayer, double x, double y, double z=0.0, double ox=0.0, double oy=0.0, double oz=MAX_Z)
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.h:60
Instantiates different layer plugins and aggregates them into one score.
void updateMap(double robot_x, double robot_y, double robot_yaw)
Update the underlying costmap with new data. If you want to update the map outside of the update loop...
int main(int argc, char **argv)
void addStaticLayer(costmap_2d::LayeredCostmap &layers, tf2_ros::Buffer &tf)


costmap_2d
Author(s): Eitan Marder-Eppstein, David V. Lu!!, Dave Hershberger, contradict@gmail.com
autogenerated on Wed Jun 22 2022 02:07:03