@@ -135,7 +135,7 @@ class ObstacleLayerFineResolutionTest : public ObstacleLayerTest
135135 */
136136TEST_F (ObstacleLayerTest, testPointWithinCellMaxRange)
137137{
138- // Add observation: point at (0.5 , 0.0)
138+ // Add observation: point at (0.55 , 0.0)
139139 // obstacle_max_range = 1.0m
140140 addObservation (obstacle_layer_, 0.55 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
141141 true , true , 100.0 , 0.0 , 1.0 , 0.0 );
@@ -153,7 +153,7 @@ TEST_F(ObstacleLayerTest, testPointWithinCellMaxRange)
153153 */
154154TEST_F (ObstacleLayerTest, testPointBeyondCellMaxRange)
155155{
156- // Add observation: point at (1.5 , 0.0)
156+ // Add observation: point at (1.55 , 0.0)
157157 // obstacle_max_range = 1.0m
158158 addObservation (obstacle_layer_, 1.55 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
159159 true , true , 100.0 , 0.0 , 1.0 , 0.0 );
@@ -171,7 +171,7 @@ TEST_F(ObstacleLayerTest, testPointBeyondCellMaxRange)
171171 */
172172TEST_F (ObstacleLayerTest, testPointWithinCellMinRange)
173173{
174- // Add observation: point at (0.3 , 0.0)
174+ // Add observation: point at (0.35 , 0.0)
175175 // obstacle_min_range = 0.5m, obstacle_max_range = 10.0m
176176 addObservation (obstacle_layer_, 0.35 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
177177 true , true , 100.0 , 0.0 , 10.0 , 0.5 );
@@ -189,15 +189,35 @@ TEST_F(ObstacleLayerTest, testPointWithinCellMinRange)
189189 */
190190TEST_F (ObstacleLayerTest, testDiagonalDistanceWithinRange)
191191{
192- // Add observation: point at (0.7 , 0.7 )
192+ // Add observation: point at (0.701 , 0.701 )
193193 // obstacle_max_range = 1.0m
194- // Cell distance: max(|7-0|, |7-0|) = 7 cells < 10 cells, so should be marked
195- addObservation (obstacle_layer_, 0.75 , 0.75 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
196- true , true , 100.0 , 0.0 , 1.0 , 0.0 );
194+ // obstacle range = sqrt(7^2 + 7^2) = 9.9 cells
195+ addObservation (obstacle_layer_, 0.701 , 0.701 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
196+ true , true , 100.0 , 0.0 , 1.0 , 0.0 );
197+ update ();
198+ unsigned int mx, my;
199+ obstacle_layer_->worldToMap (0.701 , 0.701 , mx, my);
200+ unsigned char cost = obstacle_layer_->getCost (mx, my);
201+
202+ ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
203+ }
204+
205+ /* *
206+ * Test that point beyond obstacle max range but in same cell as max range is
207+ * marked as obstacle.
208+ */
209+ TEST_F (ObstacleLayerTest, testPointBeyondRangeButInSameCellAsMaxRange) {
210+ // Observation at (0.79, 0.0)
211+ // obstacle_max_range = 0.72m
212+ // obstacle range = 0.79m, > 0.72m but at same cell distance as max range so
213+ // should be marked as obstacle, since it could be cleared by raytracing with
214+ // the same max range.
215+ addObservation (obstacle_layer_, 0.79 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
216+ true , true , 100.0 , 0.0 , 0.72 , 0.0 );
197217 update ();
198218
199219 unsigned int mx, my;
200- obstacle_layer_->worldToMap (0.75 , 0.75 , mx, my);
220+ obstacle_layer_->worldToMap (0.79 , 0.0 , mx, my);
201221 unsigned char cost = obstacle_layer_->getCost (mx, my);
202222
203223 ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
@@ -208,15 +228,16 @@ TEST_F(ObstacleLayerTest, testDiagonalDistanceWithinRange)
208228 */
209229TEST_F (ObstacleLayerTest, testDiagonalDistanceBeyondRange)
210230{
211- // Add observation: point at (1.2, 1.2)
212- // obstacle_max_range = 1.0m
213- // Cell distance: max(|12-0|, |12-0|) = 12 cells > 10 cells, so should NOT be marked
214- addObservation (obstacle_layer_, 1.25 , 1.25 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
215- true , true , 100.0 , 0.0 , 1.0 , 0.0 );
231+ // Add observation: point at (1.0, 1.0)
232+ // obstacle_max_range = 1.2m
233+ // Distance: sqrt(10^2 + 10^2) = 14.14 cells, 14 cells > 12 cells, so should
234+ // NOT be marked
235+ addObservation (obstacle_layer_, 1.0 , 1.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
236+ true , true , 100.0 , 0.0 , 1.2 , 0.0 );
216237 update ();
217238
218239 unsigned int mx, my;
219- obstacle_layer_->worldToMap (1.25 , 1.25 , mx, my);
240+ obstacle_layer_->worldToMap (1.0 , 1.0 , mx, my);
220241 unsigned char cost = obstacle_layer_->getCost (mx, my);
221242
222243 ASSERT_NE (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
@@ -232,7 +253,6 @@ TEST_F(ObstacleLayerTest, testPointAtCellMaxRangeBoundary)
232253 addObservation (obstacle_layer_, 1.0 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
233254 true , true , 100.0 , 0.0 , 1.0 , 0.0 );
234255 update ();
235-
236256 unsigned int mx, my;
237257 obstacle_layer_->worldToMap (1.0 , 0.0 , mx, my);
238258 unsigned char cost = obstacle_layer_->getCost (mx, my);
@@ -258,38 +278,19 @@ TEST_F(ObstacleLayerTest, testPointAtCellMinRangeBoundary)
258278 ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
259279}
260280
261- /* *
262- * Test asymmetric distance: point with different delta_x and delta_y
263- */
264- TEST_F (ObstacleLayerTest, testAsymmetricDistance)
265- {
266- // Add observation: point at (0.8, 0.3)
267- // obstacle_max_range = 1.0m
268- // Cell distance: max(|8-0|, |3-0|) = max(8, 3) = 8 cells < 10 cells, so should be marked
269- addObservation (obstacle_layer_, 0.85 , 0.55 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
270- true , true , 100.0 , 0.0 , 1.0 , 0.0 );
271- update ();
272-
273- unsigned int mx, my;
274- obstacle_layer_->worldToMap (0.85 , 0.55 , mx, my);
275- unsigned char cost = obstacle_layer_->getCost (mx, my);
276-
277- ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
278- }
279-
280281/* *
281282 * Test with different resolution
282283 */
283284TEST_F (ObstacleLayerFineResolutionTest, testDifferentResolution)
284285{
285- // Add observation: point at (0.5, 0.0)
286- // obstacle_max_range = 0.5m = 10 cells at 0.05m resolution
287- addObservation (obstacle_layer_, 0.52 , 0.32 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
288- true , true , 100.0 , 0.0 , 0.5 , 0.0 );
286+ // Add observation: point at (0.52, 0.28)
287+ // Resolution: 0.05m/cell
288+ // Cell index: (10, 5)
289+ addObservation (obstacle_layer_, 0.52 , 0.28 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
290+ true , true , 100.0 , 0.0 , 1.0 , 0.0 );
289291 update ();
290292
291- // x = 0.5 / 0.05 = 10; y = 0.3 / 0.05 = 6;
292- unsigned char cost = obstacle_layer_->getCost (10 , 6 );
293+ unsigned char cost = obstacle_layer_->getCost (10 , 5 );
293294 ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
294295}
295296
@@ -298,16 +299,15 @@ TEST_F(ObstacleLayerFineResolutionTest, testDifferentResolution)
298299 */
299300TEST_F (ObstacleLayerTest, testOriginOffset)
300301{
301- // Add observation: point at (5.5, 2.5 ) with origin at (5.0, 2.0 )
302+ // Add observation: point at (1.75, 1.85 ) with origin at (0.5, 1.5 )
302303 // obstacle_max_range = 2.0m
303304 addObservation (obstacle_layer_, 1.75 , 1.85 , MAX_Z / 2 , 0.5 , 1.5 , MAX_Z / 2 ,
304- true , true , 100.0 , 0.0 , 2.0 , 0.0 );
305+ true , true , 100.0 , 0.0 , 2.0 , 0.0 );
305306 update ();
306307
307308 unsigned int mx, my;
308309 obstacle_layer_->worldToMap (1.75 , 1.85 , mx, my);
309310 unsigned char cost = obstacle_layer_->getCost (mx, my);
310-
311311 ASSERT_EQ (cost, nav2_costmap_2d::LETHAL_OBSTACLE);
312312}
313313
@@ -325,14 +325,13 @@ TEST_F(ObstacleLayerTest, testRaytraceDoesNotClearEndpointCell)
325325 obstacle_layer_->setCost (x, my_end, nav2_costmap_2d::LETHAL_OBSTACLE);
326326 }
327327
328- // Add observation at (1.01 , 0.0)
328+ // Add observation at (1.05 , 0.0)
329329 // This is beyond the obstacle_max_range of 0.5m so should not be marked.
330330 // raytrace_max_range = 2.0m
331331 // So raytrace should clear cells up to but NOT including the endpoint
332332 addObservation (obstacle_layer_, 1.05 , 0.0 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
333333 true , true , 2.0 , 0.0 , 0.5 , 0.0 );
334334 update ();
335-
336335 // The endpoint cell should still be LETHAL_OBSTACLE (not cleared)
337336 unsigned char cost_endpoint = obstacle_layer_->getCost (mx_end, my_end);
338337 ASSERT_EQ (cost_endpoint, nav2_costmap_2d::LETHAL_OBSTACLE);
@@ -345,7 +344,8 @@ TEST_F(ObstacleLayerTest, testRaytraceDoesNotClearEndpointCell)
345344}
346345
347346/* *
348- * Test that raytracing clears cells along the path and the endpoint is marked as LETHAL_OBSTACLE
347+ * Test that raytracing clears cells along the path and the endpoint is marked
348+ * as obstacle.
349349 */
350350TEST_F (ObstacleLayerTest, testRaytraceClearsPathAndMarksEndpoint)
351351{
@@ -388,7 +388,7 @@ TEST_F(ObstacleLayerTest, testDiagonalRaytraceDoesNotClearEndpoint)
388388 obstacle_layer_->worldToMap (0.45 , 0.45 , mx_mid, my_mid);
389389 obstacle_layer_->setCost (mx_mid, my_mid, nav2_costmap_2d::LETHAL_OBSTACLE);
390390
391- // Add observation at (0.7 , 0.7 )
391+ // Add observation at (0.75 , 0.75 )
392392 addObservation (obstacle_layer_, 0.75 , 0.75 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
393393 true , true , 2.0 , 0.0 , 100.0 , 0.0 );
394394 update ();
@@ -402,6 +402,31 @@ TEST_F(ObstacleLayerTest, testDiagonalRaytraceDoesNotClearEndpoint)
402402 ASSERT_EQ (cost_mid, nav2_costmap_2d::FREE_SPACE);
403403}
404404
405+ /* *
406+ * Test diagonal clearing up to max range
407+ */
408+ TEST_F (ObstacleLayerTest, testClearDiagonalDistance) {
409+ // Mark all points as obstacles
410+ for (unsigned int x = 0 ; x < obstacle_layer_->getSizeInCellsX (); x++) {
411+ for (unsigned int y = 0 ; y < obstacle_layer_->getSizeInCellsY (); y++) {
412+ obstacle_layer_->setCost (x, y, nav2_costmap_2d::LETHAL_OBSTACLE);
413+ }
414+ }
415+ // Add observation at (1.55, 1.55) with max clearing range of 1.0m
416+ // This should clear the diagonal distance up to range of 1.0m, cells (0, 0)
417+ // to (7, 7)
418+ addObservation (obstacle_layer_, 1.55 , 1.55 , MAX_Z / 2 , 0.0 , 0.0 , MAX_Z / 2 ,
419+ true , true , 1.0 , 0.0 , 100.0 , 0.0 );
420+ update ();
421+
422+ for (unsigned int i = 0 ; i < 8 ; i++) {
423+ ASSERT_EQ (obstacle_layer_->getCost (i, i), nav2_costmap_2d::FREE_SPACE);
424+ }
425+ ASSERT_EQ (countValues (*obstacle_layer_, nav2_costmap_2d::FREE_SPACE), 8 );
426+ ASSERT_EQ (countValues (*obstacle_layer_, nav2_costmap_2d::LETHAL_OBSTACLE),
427+ 20 * 20 - 8 );
428+ }
429+
405430/* *
406431 * Test edge case: observation very close to origin
407432 * Resolution: 0.1m/cell
0 commit comments