Skip to content

Imaging Sonar not working on RTX 5070 laptop. Fix found #41

@Hardwarize

Description

@Hardwarize

Describe the bug
The Imaging Sonar information screen do not show the sonar captures.

To Reproduce
Load OceanSim "Sensor Example" and activate "Imaging Sonar" sensor. In the IsaacSim console print an error like this:

2026-03-10T07:55:35Z [157,000ms] [Error] [omni.kit.app._impl] [py stderr]:     annotator_output, do_synchronize = AnnotatorCache.get_data(

2026-03-10T07:55:35Z [157,001ms] [Error] [omni.kit.app._impl] [py stderr]:                                        ^^^^^^^^^^^^^^^^^^^^^^^^

2026-03-10T07:55:35Z [157,001ms] [Error] [omni.kit.app._impl] [py stderr]:   File "c:\isaac-sim_o/kit/kernel/py\carb\profiler\__init__.py", line 99, in wrapper

2026-03-10T07:55:35Z [157,001ms] [Error] [omni.kit.app._impl] [py stderr]:     r = f(*args, **kwds)

2026-03-10T07:55:35Z [157,002ms] [Error] [omni.kit.app._impl] [py stderr]:         ^^^^^^^^^^^^^^^^

2026-03-10T07:55:35Z [157,002ms] [Error] [omni.kit.app._impl] [py stderr]:   File "c:/isaac-sim_o/extscache/omni.replicator.core-1.12.27+107.3.3.wx64.r.cp311/omni/replicator/core/scripts/utils/annotator_utils.py", line 518, in get_data

2026-03-10T07:55:35Z [157,002ms] [Error] [omni.kit.app._impl] [py stderr]:     data, do_synchronize = cls._get_data_from_ptr(annotator_id, data_params, do_copy)

2026-03-10T07:55:35Z [157,003ms] [Error] [omni.kit.app._impl] [py stderr]:                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2026-03-10T07:55:35Z [157,003ms] [Error] [omni.kit.app._impl] [py stderr]:   File "c:\isaac-sim_o/kit/kernel/py\carb\profiler\__init__.py", line 99, in wrapper

2026-03-10T07:55:35Z [157,003ms] [Error] [omni.kit.app._impl] [py stderr]:     r = f(*args, **kwds)

2026-03-10T07:55:35Z [157,003ms] [Error] [omni.kit.app._impl] [py stderr]:         ^^^^^^^^^^^^^^^^

2026-03-10T07:55:35Z [157,004ms] [Error] [omni.kit.app._impl] [py stderr]:   File "c:/isaac-sim_o/extscache/omni.replicator.core-1.12.27+107.3.3.wx64.r.cp311/omni/replicator/core/scripts/utils/annotator_utils.py", line 585, in _get_data_from_ptr

2026-03-10T07:55:35Z [157,004ms] [Error] [omni.kit.app._impl] [py stderr]:     wp.copy(cached_array, array)

2026-03-10T07:55:35Z [157,004ms] [Error] [omni.kit.app._impl] [py stderr]:   File "c:/isaac-sim_o/extscache/omni.warp.core-1.8.2+wx64/warp/context.py", line 6928, in copy

2026-03-10T07:55:35Z [157,006ms] [Error] [omni.kit.app._impl] [py stderr]:     raise RuntimeError(f"Warp copy error: {runtime.get_error_string()}")

2026-03-10T07:55:35Z [157,006ms] [Error] [omni.kit.app._impl] [py stderr]: RuntimeError: Warp copy error: Warp CUDA error 1: invalid argument (in function memcpy_d2d, C:\g\213697506\warp\native\warp.cu:785)

Additionaly the imaging sonar screen just show the message "Run the scenario for image to be received"

Expected behavior
The Imaging Sonar screen should show the sonar information

Desktop (please complete the following information):

  • Windows 11
  • Issac Sim 5.1.0
  • Nvidia GeForce RTX 5070 Laptop GPU

Fix Found
Add some modifications to SensorExample_python/scenario.py in order to control the fps in the sonar

# Omniverse import
import numpy as np
from pxr import Gf, PhysxSchema

# Isaac sim import
from isaacsim.core.prims import SingleRigidPrim
from isaacsim.core.utils.prims import get_prim_path


class MHL_Sensor_Example_Scenario():
    def __init__(self):
        self._rob = None
        self._sonar = None
        self._cam = None
        self._DVL = None
        self._baro = None

        self._ctrl_mode = None

        self._running_scenario = False
        self._time = 0.0

        # NEW: Throttle variables
        self._last_sonar_time = 0.0
        self._sonar_update_interval = 0.1  # 0.1 seconds = 10 FPS for the sonar

        # Add a frame counter
        self._frame_count = 0

    def setup_scenario(self, rob, sonar, cam, DVL, baro, ctrl_mode):
        self._rob = rob
        self._frame_count = 0 # Reset on setup
        self._sonar = sonar
        self._cam = cam
        self._DVL = DVL
        self._baro = baro
        self._ctrl_mode = ctrl_mode
        if self._sonar is not None:
            self._sonar.sonar_initialize(include_unlabelled=True)
        if self._cam is not None:
            self._cam.initialize()
        if self._DVL is not None:
            self._DVL_reading = [0.0, 0.0, 0.0]
        if self._baro is not None:
            self._baro_reading = 101325.0 # atmospheric pressure (Pa)
        
        
        print(f"Scenario setup with control mode: {ctrl_mode}")
        # Apply the physx force schema if manual control
        if ctrl_mode == "Manual control":
            from ...utils.keyboard_cmd import keyboard_cmd

            self._rob_forceAPI = PhysxSchema.PhysxForceAPI.Apply(self._rob)
            self._force_cmd = keyboard_cmd(base_command=np.array([0.0, 0.0, 0.0]),
                                      input_keyboard_mapping={
                                        # forward command
                                        "W": [10.0, 0.0, 0.0],
                                        # backward command
                                        "S": [-10.0, 0.0, 0.0],
                                        # leftward command
                                        "A": [0.0, 10.0, 0.0],
                                        # rightward command
                                        "D": [0.0, -10.0, 0.0],
                                         # rise command
                                        "UP": [0.0, 0.0, 10.0],
                                        # sink command
                                        "DOWN": [0.0, 0.0, -10.0],
                                      })
            self._torque_cmd = keyboard_cmd(base_command=np.array([0.0, 0.0, 0.0]),
                                      input_keyboard_mapping={
                                        # yaw command (left)
                                        "J": [0.0, 0.0, 10.0],
                                        # yaw command (right)
                                        "L": [0.0, 0.0, -10.0],
                                        # pitch command (up)
                                        "I": [0.0, -10.0, 0.0],
                                        # pitch command (down)
                                        "K": [0.0, 10.0, 0.0],
                                        # row command (left)
                                        "LEFT": [-10.0, 0.0, 0.0],
                                        # row command (negative)
                                        "RIGHT": [10.0, 0.0, 0.0],
                                      })
            
        self._running_scenario = True
    # This function will only be called if ctrl_mode==waypoints and waypoints files are changed
    def setup_waypoints(self, waypoint_path, default_waypoint_path):
        def read_data_from_file(file_path):
            # Initialize an empty list to store the floats
            data = []
            
            # Open the file in read mode
            with open(file_path, 'r') as file:
                # Read each line in the file
                for line in file:
                    # Strip any leading/trailing whitespace and split the line by spaces
                    float_strings = line.strip().split()
                    
                    # Convert the list of strings to a list of floats
                    floats = [float(x) for x in float_strings]
                    
                    # Append the list of floats to the data list
                    data.append(floats)
            
            return data
        try:
            self.waypoints = read_data_from_file(waypoint_path)
            print('Waypoints loaded successfully.')
            print(f'Waypoint[0]: {self.waypoints[0]}')
        except:
            self.waypoints = read_data_from_file(default_waypoint_path)
            print('Fail to load this waypoints. Back to default waypoints.')

        
    def teardown_scenario(self):
        import omni.replicator.core as rep
        # Because these two sensors create annotator cache in GPU,
        # close() will detach annotator from render product and clear the cache.
        if self._sonar is not None:
            self._sonar.close()
        if self._cam is not None:
            self._cam.close()
        

        rep.orchestrator.stop()


        # In some Isaac Sim versions, you also need to clear the registry 
        # to prevent KeyError on the next run:
        try:
            rep.AnnotatorRegistry.clear()
        except AttributeError:
            pass # Ignore if your version of Replicator doesn't require this

        # clear the keyboard subscription
        if self._ctrl_mode=="Manual control":
            self._force_cmd.cleanup()
            self._torque_cmd.cleanup()

        self._rob = None
        self._sonar = None
        self._cam = None
        self._DVL = None
        self._baro = None
        self._running_scenario = False
        self._time = 0.0


    def update_scenario(self, step: float):

        
        if not self._running_scenario:
            return
        
        self._time += step
        # --- DYNAMIC THROTTLED WARMUP ---
        # Only ask for Sonar data if 0.1 seconds have passed
        if self._time - self._last_sonar_time >= self._sonar_update_interval:
            if self._sonar is not None:
                try:
                    self._sonar.make_sonar_data()
                    self._last_sonar_time = self._time # Reset the clock
                except KeyError:
                    pass # Still warming up, skip this frame
        
        # You can do the exact same throttle for the camera if it's lagging!
        if self._cam is not None:
            try:
                self._cam.render()
            except KeyError:
                pass
        # ----------------------------

        
        if self._sonar is not None:
            self._sonar.make_sonar_data()
        if self._cam is not None:
            self._cam.render()
        if self._DVL is not None:
            self._DVL_reading = self._DVL.get_linear_vel()
        if self._baro is not None:
            self._baro_reading = self._baro.get_pressure()

        if self._ctrl_mode=="Manual control":
            force_cmd = Gf.Vec3f(*self._force_cmd._base_command)
            torque_cmd = Gf.Vec3f(*self._torque_cmd._base_command)
            self._rob_forceAPI.CreateForceAttr().Set(force_cmd)
            self._rob_forceAPI.CreateTorqueAttr().Set(torque_cmd)
        elif self._ctrl_mode=="Waypoints":
            if len(self.waypoints) > 0:
                waypoints = self.waypoints[0]
                self._rob.GetAttribute('xformOp:translate').Set(Gf.Vec3f(waypoints[0], waypoints[1], waypoints[2]))
                self._rob.GetAttribute('xformOp:orient').Set(Gf.Quatd(waypoints[3], waypoints[4], waypoints[5], waypoints[6]))
                self.waypoints.pop(0)
            else:
                print('Waypoints finished')                
        elif self._ctrl_mode=="Straight line":
            SingleRigidPrim(prim_path=get_prim_path(self._rob)).set_linear_velocity(np.array([0.5,0,0])) 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions