GenericSensor Python API

Hello,

I’m trying to create a GenericSensor and feed it a list of zeniths and azimuths. I’m having trouble acquiring the sensor interface. The sensor does not seem to exist at the path. Strangely, if I move the code for acquiring the sensor interface to another tab in the script editor, it is able to find it. Is there a specified order/method for creating this sensor then acquiring the interface?

rom omni.isaac.range_sensor._range_sensor import acquire_generic_sensor_interface
import time

generic_sensor_interface = acquire_generic_sensor_interface()
result, prim = omni.kit.commands.execute(
						"RangeSensorCreateGeneric",
						path="/GenericSensor",
						parent=None,
						min_range=0.4,
						max_range=10000.0,
						draw_points=False,
						draw_lines=False,
						sampling_rate=60,
					)
					
if generic_sensor_interface.is_generic_sensor("/World/GenericSensor"):
    print("generic sensor is valid")

Thanks!

Hi @advaiths1

It seems that it is necessary to wait for at least one frame for the sensor to be initialized.
For example:

import asyncio
from omni.isaac.range_sensor._range_sensor import acquire_generic_sensor_interface

generic_sensor_interface = acquire_generic_sensor_interface()

async def my_task():
    result, prim = omni.kit.commands.execute(
                            "RangeSensorCreateGeneric",
                            path="/GenericSensor",
                            parent=None,
                            min_range=0.4,
                            max_range=10000.0,
                            draw_points=False,
                            draw_lines=False,
                            sampling_rate=60,
                        )

    await omni.kit.app.get_app().next_update_async()

    if generic_sensor_interface.is_generic_sensor("/World/GenericSensor"):
        print("generic sensor is valid")

asyncio.ensure_future(my_task())
1 Like

Hi,

Thanks! That seemed to work.

Similarly, for reading the data from the sensor, is this asynchronous approach necessary? For example, I sent a batch of azimuths, zeniths to the sensor. Can I just call self.sensor.get_hit_pos_data(sensorPath) and accumulate the returns until self.sensor.send_next_batch(sensorPath) returns True again?

Hi @advaiths1

I lack the information to confirm this with absolute certainty but it seems (based on the examples I have found in the code) that such invocations can be performed both asynchronously and non-asynchronously.

For example,

  • In exts/omni.isaac.range_sensor/omni/isaac/range_sensor/scripts/samples/generic_info.py it is called “non-asynchronously”…
  • While in the testing file exts/omni.isaac.range_sensor/omni/isaac/range_sensor/tests/test_generic.py it is called inside an async function.

I recommend you to ask in the forum dedicated to Omniverse Isaac Sim to get better support :)

1 Like

Welcome @advaiths1! @toni.sm, thanks for jumping in and answering these questions. I’ve moved the topic to the Omniverse Isaac forum to continue the conversation there.

1 Like

Hi @mati-nvidia ,

Sorry for the confusion.

My main question is that there aren’t any examples for using the sensor in a standalone python script. One in exts/omni.isaac.range_sensor/omni/isaac/range_sensor/scripts/samples/generic_info.py demonstrates the use within a GUI application and the other is an async test file. Is there any special setup for using the GenericSensor interface as standalone? This is how I’m currently using it and it never enters this function after calling asyncio.ensure_future(sss.raster_scan()) in a different file.

async def raster_scan(self):
		print("entering raster")
		self.timeline.play()
		pattern = np.stack((self.thetas, self.phis))
		pattern = np.tile(pattern, (1, int(2.4e5/pattern.shape[1])*2))
		framerate = 60
		seconds =1 
		for frame in range(int(framerate * seconds)):
			await omni.kit.app.get_app().next_update_async()
            # set the pattern while running
			if self.generic_sensor_interface.send_next_batch(self.sensor_path):
				self.generic_sensor_interface.set_next_batch_rays(
						self.sensor_path, pattern)
		self.timeline.pause()
		hits = self.generic_sensor_interface.get_hit_pos_data(self.sensor_path)
		slants = self.generic_sensor_interface.get_linear_depth_data(self.sensor_path)

Hi,

To convert the GUI application example to a standalone script for the sensor, the general idea is putting everything in the _on_editor_step() into the standalone script’s simulation loop. Everything in _on_editor_step() is executed every simluation step, which corrensponds to each loop of the simluation step in Standalone python scripts.

All the other sensor setup parts of the generic_info.py, namely setting up the sensor pattern and spawn the actual sensor should be done before and outside the simulation loop.