I want to filter a point cloud obtained via the RtxSensorCpuIsaacCreateRTXLidarScanBuffer
annotator based on the objectId
of the hit.
Relevant docs that I read:
- RTX Lidar Synthetic Data — Omniverse IsaacSim latest documentation
- Using Sensors: LIDAR — Omniverse IsaacSim latest documentation
- Isaac Sensor Extension [omni.isaac.sensor] — isaac_sim 2023.1.1-rc.7 documentation
The meshes in question are set up as follows:
terrain_prim = prims.create_prim(
prim_path="/background",
position=(0, 0, 0),
orientation=euler_angles_to_quat([math.pi / 2, 0, 0]),
usd_path=str(file_path.parent / "terrain.usd"),
)
UsdPhysics.CollisionAPI.Apply(terrain_prim)
primType = ["Cube", "Sphere"]
stage_obj = omni.usd.get_context().get_stage()
for i in range(2):
prim = stage_obj.DefinePrim("/World/" + primType[i], primType[i])
UsdGeom.XformCommonAPI(prim).SetTranslate(
Gf.Vec3d(*((-1.0, -2.0 + i * 4.0, 0.0) + init_translation))
)
UsdGeom.XformCommonAPI(prim).SetScale((1, 1, 1))
collisionAPI = UsdPhysics.CollisionAPI.Apply(prim)
# Add semantic label
sem = Semantics.SemanticsAPI.Apply(prim, "Semantics")
sem.CreateSemanticTypeAttr()
sem.CreateSemanticDataAttr()
sem.GetSemanticTypeAttr().Set("class")
sem.GetSemanticDataAttr().Set(primType[i])
I set up the sensor like so:
self.lidar = LidarRtx(
prim_path=self.sensor_path,
translation=[-0.32, 0.0, 0.25],
config_file_name="OS0_128ch10hz512res.json",
)
render_product_path = self.lidar.get_render_product_path()
writer = rep.writers.get("RtxLidar" + "DebugDrawPointCloud")
writer.attach([render_product_path])
self.annotator = rep.AnnotatorRegistry.get_annotator(
"RtxSensorCpuIsaacCreateRTXLidarScanBuffer",
init_params={
"outputObjectId": True,
}
)
self.annotator.attach([render_product_path])
Filtering the collected data I observe that the objectId
contains extra points:
data = self.annotator.get_data()
point_cloud_L = torch.from_numpy(
data["data"]
)
object_ids = data["objectId"]
unique_object_ids = np.unique(object_ids)
full_prim_paths_to_obj_id = {}
for object_id in unique_object_ids:
full_prim_path = acquire_syntheticdata_interface().get_uri_from_instance_segmentation_id(object_id)
full_prim_paths_to_obj_id[full_prim_path] = object_id
mask = (object_ids != full_prim_paths_to_obj_id['/World/Sphere'])
point_cloud_L_filtered = point_cloud_L[mask]
The original point cloud has 35512 points, while the filtered point cloud has 30762 points. However, some points belong to other semantic classes and all points that belong to the ‘/World/Sphere’ primitive are filtered out. Is this the result of a wrong setup?
All of the classes:
{'': 0, '/background/Mesh': 1, '/World/Sphere': 2, '/World/Cube': 3}
My scene:
Original point cloud:
The filtered points:
Overlaid original (black) and filtered (red) points: