Hello everyone,
I’m currently working on a project using NVIDIA Isaac Sim to synchronize a simulated robot with data from a ROS2 bagfile recorded from a real robot. The synchronization of the robot’s movements works perfectly; however, I encounter significant slowdowns in the simulation as soon as a PointCloud2 subscriber starts receiving messages.
Here’s the code snippet I’m using:
import argparse
from utils.file_operations import read_yaml
from utils.transforms import update_object_dict_with_transforms, process_transform, check_pose_deviation
# ---------------------------------------------------------------------------- #
# Read the YAML configuration file #
# ---------------------------------------------------------------------------- #
parser = argparse.ArgumentParser()
parser.add_argument("--config_file", help="Path to the configuration file", default="config/params.yaml")
args = parser.parse_args()
config = read_yaml(args.config_file)
# ---------------------------------------------------------------------------- #
# Start The SimulationApp #
# ---------------------------------------------------------------------------- #
import isaacsim
from omni.isaac.kit import SimulationApp
simulation_app = SimulationApp(launch_config=config.launch_config)
import numpy as np
import warnings
import threading
import omni.client
import omni.kit.commands
import omni.kit.app
import omni.timeline
import omni.usd
from omni.isaac.core import World
from omni.isaac.core.utils.extensions import enable_extension
from omni.isaac.core.utils.stage import add_reference_to_stage
from omni.isaac.core.prims import XFormPrim
from pxr import UsdPhysics, PhysxSchema
# enable ROS2 bridge extension
enable_extension("omni.isaac.ros2_bridge")
simulation_app.update()
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import PointCloud2
from sensor_msgs_py import point_cloud2
warnings.filterwarnings("ignore")
class IsaacSim(Node):
def __init__(self):
super().__init__('IsaacSim')
# setting up the world
self.world_setup()
# load environment and robot
self.load_env()
self.load_robot()
# reset ros world
self.ros_world.reset()
def world_setup(self):
self.timeline = omni.timeline.get_timeline_interface()
self.ros_world = World(stage_units_in_meters=1.0)
self.add_physics_scene()
def add_physics_scene(self):
self.stage = omni.usd.get_context().get_stage()
self.physics_scene = UsdPhysics.Scene.Define(self.stage, "/physicsScene")
physx_scene = PhysxSchema.PhysxSceneAPI.Apply(self.stage.GetPrimAtPath("/physicsScene"))
physx_scene.GetEnableCCDAttr().Set(False)
physx_scene.GetEnableGPUDynamicsAttr().Set(False)
physx_scene.GetCollisionSystemAttr().Set("PCM")
physx_scene.GetSolverTypeAttr().Set("TGS")
physx_scene.GetBroadphaseTypeAttr().Set("MBP")
physx_scene.GetTimeStepsPerSecondAttr().Set(480)
def load_env(self):
env_url = "/root/ws/environments/" + config.environment_config.environment_usd
add_reference_to_stage(usd_path=env_url, prim_path="/Environment")
self.ros_world.scene.add(XFormPrim(prim_path="/Environment", name="Environment"))
def load_robot(self):
robot_url = "/root/ws/robots/USD/" + config.robot_config.robot_usd
add_reference_to_stage(usd_path=robot_url, prim_path="/kairosAB")
self.ros_world.scene.add(XFormPrim(prim_path="/kairosAB", name="kairosAB"))
def run_simulation(self):
self.timeline.play()
while simulation_app.is_running():
self.ros_world.step(render=True)
if self.ros_world.is_playing():
pass
# cleanup
self.timeline.stop()
self.destroy_node()
simulation_app.close()
class PointCloudSubscriber(Node):
def __init__(self,):
super().__init__('point_cloud_sub')
self.subscription_point_cloud = self.create_subscription(PointCloud2, "/kairosAB/ouster/points", self.point_cloud_callback, 100)
def point_cloud_callback(self, msg):
print("Received")
points_msg = np.array(list(point_cloud2.read_points(msg, field_names=("x", "y", "z"), skip_nans=True)))
print("Finished processing")
print("_________________")
def main():
rclpy.init()
node1 = IsaacSim()
node2 = PointCloudSubscriber()
executor = rclpy.executors.MultiThreadedExecutor()
executor.add_node(node1)
executor.add_node(node2)
# Spin in a separate thread
executor_thread = threading.Thread(target=executor.spin, daemon=True)
executor_thread.start()
node1.run_simulation()
rclpy.shutdown()
executor_thread.join()
if __name__ == '__main__':
main()
I’ve tried implementing multi-threading to address the issue, but unfortunately, the problem persists. Below is a video demonstrating how the simulation slows down once the first PointCloud2 message is received and processed:
I would like the PointCloud2 subscriber to operate independently from the simulation to prevent any slowdowns. Does anyone have any suggestions or solutions on how I can achieve this?
Any help would be greatly appreciated!
Thank you,
Lukas