@@ -254,14 +254,22 @@ def test_rigid_tactile_sensors_gravity_force(show_viewer, tol, n_envs):
254254@pytest .mark .parametrize ("n_envs" , [0 , 2 ])
255255def test_raycaster_hits (show_viewer , tol , n_envs ):
256256 """Test if the Raycaster sensor with GridPattern rays pointing to ground returns the correct distance."""
257- NUM_RAYS_XY = 3
258- SPHERE_POS = (4.0 , 0.0 , 1.0 )
257+ NUM_RAYS_XY = ( 3 , 5 )
258+ SPHERE_POS = (2.5 , 0.5 , 1.0 )
259259 BOX_SIZE = 0.05
260260 RAYCAST_BOX_SIZE = 0.1
261- RAYCAST_GRID_SIZE = 1.0
261+ RAYCAST_GRID_SIZE_X = 1.0
262262 RAYCAST_HEIGHT = 1.0
263263
264264 scene = gs .Scene (
265+ viewer_options = gs .options .ViewerOptions (
266+ camera_pos = (- 3.0 , RAYCAST_GRID_SIZE_X * (NUM_RAYS_XY [1 ] / NUM_RAYS_XY [0 ]), 2 * RAYCAST_HEIGHT ),
267+ camera_lookat = (1.5 , RAYCAST_GRID_SIZE_X * (NUM_RAYS_XY [1 ] / NUM_RAYS_XY [0 ]), RAYCAST_HEIGHT ),
268+ ),
269+ vis_options = gs .options .VisOptions (
270+ rendered_envs_idx = (0 ,),
271+ env_separate_rigid = False ,
272+ ),
265273 profiling_options = gs .options .ProfilingOptions (
266274 show_FPS = False ,
267275 ),
@@ -279,7 +287,7 @@ def test_raycaster_hits(show_viewer, tol, n_envs):
279287 spherical_raycaster = scene .add_sensor (
280288 gs .sensors .Raycaster (
281289 pattern = gs .sensors .raycaster .SphericalPattern (
282- n_points = ( NUM_RAYS_XY , NUM_RAYS_XY ) ,
290+ n_points = NUM_RAYS_XY ,
283291 ),
284292 entity_idx = spherical_sensor .idx ,
285293 return_world_frame = False ,
@@ -297,12 +305,13 @@ def test_raycaster_hits(show_viewer, tol, n_envs):
297305 fixed = True ,
298306 ),
299307 )
300- grid_res = RAYCAST_GRID_SIZE / (NUM_RAYS_XY - 1 )
308+ grid_res = RAYCAST_GRID_SIZE_X / (NUM_RAYS_XY [0 ] - 1 )
309+ grid_size_y = grid_res * (NUM_RAYS_XY [1 ] - 1 )
301310 grid_raycaster = scene .add_sensor (
302311 gs .sensors .Raycaster (
303312 pattern = gs .sensors .raycaster .GridPattern (
304313 resolution = grid_res ,
305- size = (1.0 , 1.0 ),
314+ size = (RAYCAST_GRID_SIZE_X , grid_size_y ),
306315 direction = (0.0 , 0.0 , - 1.0 ), # pointing downwards to ground
307316 ),
308317 entity_idx = grid_sensor .idx ,
@@ -322,7 +331,7 @@ def test_raycaster_hits(show_viewer, tol, n_envs):
322331 obstacle_2 = scene .add_entity (
323332 gs .morphs .Box (
324333 size = (BOX_SIZE , BOX_SIZE , BOX_SIZE ),
325- pos = (RAYCAST_GRID_SIZE , RAYCAST_GRID_SIZE , RAYCAST_HEIGHT + RAYCAST_BOX_SIZE + BOX_SIZE ),
334+ pos = (RAYCAST_GRID_SIZE_X , grid_size_y , RAYCAST_HEIGHT + RAYCAST_BOX_SIZE + BOX_SIZE ),
326335 ),
327336 )
328337
@@ -331,11 +340,10 @@ def test_raycaster_hits(show_viewer, tol, n_envs):
331340 batch_shape = (n_envs ,) if n_envs > 0 else ()
332341
333342 # Validate grid raycast
334- # TODO: Check use different (global) offset positions for each environments
335343 for obstacle_pos , sensor_pos , hit_ij in (
336- (None , None , (- 1 , - 1 )),
337- ((grid_res , grid_res , BOX_SIZE ), None , (- 1 , - 1 )),
338- (None , (RAYCAST_GRID_SIZE , RAYCAST_GRID_SIZE , RAYCAST_HEIGHT + 0.5 * RAYCAST_BOX_SIZE ), (0 , 0 )),
344+ (None , None , (- 1 , - 2 )),
345+ ((grid_res , grid_res , BOX_SIZE ), None , (- 1 , - 2 )),
346+ (None , (* ( grid_res * ( e - 2 ) for e in NUM_RAYS_XY ) , RAYCAST_HEIGHT + 0.5 * RAYCAST_BOX_SIZE ), (1 , 0 )),
339347 ):
340348 # Update obstacle and/or sensor position if necessary
341349 if obstacle_pos is not None :
@@ -350,37 +358,41 @@ def test_raycaster_hits(show_viewer, tol, n_envs):
350358 # Fetch updated sensor data
351359 grid_hits = grid_raycaster .read ().points
352360 grid_distances = grid_raycaster .read ().distances
353- assert grid_distances .shape == (* batch_shape , NUM_RAYS_XY , NUM_RAYS_XY )
361+ assert grid_distances .shape == (* batch_shape , * NUM_RAYS_XY )
354362
355363 # Check hits
356364 grid_sensor_origin = grid_sensor .get_pos ()
357- x = torch .linspace (- 0.5 , 0.5 , NUM_RAYS_XY ) + grid_sensor_origin [..., [0 ]]
358- y = torch .linspace (- 0.5 , 0.5 , NUM_RAYS_XY ) + grid_sensor_origin [..., [1 ]]
359- # xg, yg = torch.meshgrid(x, y, indexing="xy ")
360- xg = x .unsqueeze (- 2 ).expand ((* batch_shape , NUM_RAYS_XY , - 1 ))
361- yg = y .unsqueeze (- 1 ).expand ((* batch_shape , - 1 , NUM_RAYS_XY ))
362- zg = torch .zeros ((* batch_shape , NUM_RAYS_XY , NUM_RAYS_XY ))
365+ x = torch .linspace (- 0.5 , 0.5 , NUM_RAYS_XY [ 0 ]) * RAYCAST_GRID_SIZE_X + grid_sensor_origin [..., [0 ]]
366+ y = torch .linspace (- 0.5 , 0.5 , NUM_RAYS_XY [ 1 ]) * grid_size_y + grid_sensor_origin [..., [1 ]]
367+ # xg, yg = torch.meshgrid(x, y, indexing="ij ")
368+ xg = x .unsqueeze (- 1 ).expand ((* batch_shape , - 1 , NUM_RAYS_XY [ 1 ] ))
369+ yg = y .unsqueeze (- 2 ).expand ((* batch_shape , NUM_RAYS_XY [ 0 ], - 1 ))
370+ zg = torch .zeros ((* batch_shape , * NUM_RAYS_XY ))
363371 zg [(..., * hit_ij )] = obstacle_pos [..., 2 ] + 0.5 * BOX_SIZE
364372 grid_hits_ref = torch .stack ([xg , yg , zg ], dim = - 1 )
365373 assert_allclose (grid_hits , grid_hits_ref , tol = gs .EPS )
366374
367375 # Check distances
368- grid_distances_ref = torch .full ((* batch_shape , NUM_RAYS_XY , NUM_RAYS_XY ), RAYCAST_HEIGHT )
376+ grid_distances_ref = torch .full ((* batch_shape , * NUM_RAYS_XY ), RAYCAST_HEIGHT )
369377 grid_distances_ref [(..., * hit_ij )] = RAYCAST_HEIGHT - obstacle_pos [..., 2 ] - 0.5 * BOX_SIZE
370378 assert_allclose (grid_distances , grid_distances_ref , tol = gs .EPS )
371379
372380 # Validate spherical raycast
373381 spherical_distances = spherical_raycaster .read ().distances
374- assert spherical_distances .shape == (* batch_shape , NUM_RAYS_XY , NUM_RAYS_XY )
382+ assert spherical_distances .shape == (* batch_shape , * NUM_RAYS_XY )
375383 # Note that the tolerance must be large bevcause the sphere geometry is discretized
376384 assert_allclose (spherical_distances , RAYCAST_HEIGHT , tol = 5e-3 )
377385
378386 # Simulate for a while and check again that the ray is casted properly
387+ offset = torch .from_numpy (np .random .rand (* batch_shape , 3 )).to (dtype = gs .tc_float , device = gs .device )
388+ for entity in (grid_sensor , obstacle_1 , obstacle_2 ):
389+ entity .set_pos (entity .get_pos () + offset )
379390 for _ in range (100 ):
380391 scene .step ()
381392
382393 grid_distances = grid_raycaster .read ().distances
383- grid_distances_ref = torch .full ((* batch_shape , NUM_RAYS_XY , NUM_RAYS_XY ), RAYCAST_HEIGHT )
384- grid_distances_ref [..., ( NUM_RAYS_XY - 1 ) // 2 , ( NUM_RAYS_XY - 1 ) // 2 ] = RAYCAST_HEIGHT - BOX_SIZE
394+ grid_distances_ref = torch .full ((* batch_shape , * NUM_RAYS_XY ), RAYCAST_HEIGHT )
395+ grid_distances_ref [( ..., - 1 , - 2 ) ] = RAYCAST_HEIGHT - BOX_SIZE
385396 grid_distances_ref [(..., * hit_ij )] = RAYCAST_HEIGHT - BOX_SIZE
397+ grid_distances_ref += offset [..., 2 ].reshape ((* (- 1 for e in batch_shape ), 1 , 1 ))
386398 assert_allclose (grid_distances , grid_distances_ref , tol = 1e-3 )
0 commit comments