Skip to content

[bug] Ray Caster Does Not Move with the Robot in Isaac Lab #2029

Description

@MiraiMoe

Describe the bug

I encountered an issue when using Isaac Lab's Ray Caster: it does not move along with the robot. I enabled debug_vis and observed that the point cloud remains static, even though my robot moves as expected.

Image

My robot is modified from the official cf2x (as shown in the screenshot). I can control it properly using API functions. However, while the camera moves with the robot, the Ray Caster remains fixed.

Image

Steps to reproduce

  1. Extract and use the provided model: crazyflie_final_new.zip.
  2. Replace the usd_path in my code with:
usd_path=r"/home/username/crazyflie_final_new.usd"
  1. Run the provided script and observe the issue.
  2. Enable debug_vis and notice that the Ray Caster's point cloud does not move, while the robot moves correctly.
  3. The camera follows the UAV correctly, but the Ray Caster remains static.

Sensor Configuration

Here is my sensor configuration:

camera = CameraCfg(
    prim_path="{ENV_REGEX_NS}/Robot/crazyflie/body/front_cam",
    update_period=0.1,
    height=480,
    width=640,
    data_types=["rgb", "distance_to_image_plane"],
    spawn=sim_utils.PinholeCameraCfg(
        focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1.0e5)
    ),
    offset=CameraCfg.OffsetCfg(pos=(0.15, 0.0, 0.15), rot=(-0.707, 0.707, 0, 0), convention="world"),
)

height_scanner = RayCasterCfg(
    prim_path="{ENV_REGEX_NS}/Robot/crazyflie/body",
    update_period=1 / 60,
    offset=RayCasterCfg.OffsetCfg(pos=(0, 0, 0)),
    attach_yaw_only=True,
    pattern_cfg=patterns.LidarPatternCfg(
        channels=100, vertical_fov_range=[-90, 90], horizontal_fov_range=[-90, 90], horizontal_res=1.0
    ),
    debug_vis=True,
    mesh_prim_paths=["/World/ground"],
)

Expected Behavior

The Ray Caster should move along with the robot, similar to the camera.


System Info

  • Isaac Sim Version: [4.5.0]
  • OS: [e.g. Ubuntu 22.04]
  • GPU: [e.g. RTX 4070Ti]
  • CUDA: [e.g. 12.4]
  • GPU Driver: [e.g. 550.120]

Code to Reproduce

Here is my full code that demonstrates the issue, I wrote this code based on the tutorial of Isaac Lab:

# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""
This script demonstrates how to add and simulate on-board sensors for a robot.

We add the following sensors on the quadruped robot, ANYmal-C (ANYbotics):

* USD-Camera: This is a camera sensor that is attached to the robot's base.
* Height Scanner: This is a height scanner sensor that is attached to the robot's base.
* Contact Sensor: This is a contact sensor that is attached to the robot's feet.

.. code-block:: bash

    # Usage
    ./isaaclab.sh -p scripts/tutorials/04_sensors/add_sensors_on_robot.py --enable_cameras

"""

"""Launch Isaac Sim Simulator first."""

import argparse

from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Tutorial on adding sensors on a robot.")
parser.add_argument("--num_envs", type=int, default=1, help="Number of environments to spawn.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
args_cli.enable_cameras = True
# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app

"""Rest everything follows."""

import torch

import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sensors import CameraCfg, ContactSensorCfg, RayCasterCfg, patterns
from isaaclab.utils import configclass
from isaaclab_assets import CRAZYFLIE_NEW_CFG, CRAZYFLIE_CFG
from isaaclab.terrains import TerrainImporterCfg, TerrainImporter, TerrainGeneratorCfg, HfDiscreteObstaclesTerrainCfg
from isaaclab.actuators import ImplicitActuatorCfg

@configclass
class SensorsSceneCfg(InteractiveSceneCfg):
    """Design the scene with sensors on the robot."""

    # ground plane
    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=sim_utils.GroundPlaneCfg())

    # lights
    dome_light = AssetBaseCfg(
        prim_path="/World/Light", spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
    )

    terrain = TerrainImporterCfg(
        prim_path="/World/ground",
        terrain_type="plane",
        collision_group=-1,
        physics_material=sim_utils.RigidBodyMaterialCfg(
            friction_combine_mode="multiply",
            restitution_combine_mode="multiply",
            static_friction=1.0,
            dynamic_friction=1.0,
            restitution=0.0,
        ),
        debug_vis=False,
    )

    # robot
    robot: ArticulationCfg = ArticulationCfg(
        prim_path="{ENV_REGEX_NS}/Robot",
        spawn=sim_utils.UsdFileCfg(
            usd_path=r"/home/username/crazyflie_final_new.usd",
            activate_contact_sensors=True,
            rigid_props=sim_utils.RigidBodyPropertiesCfg(
                disable_gravity=False,
                max_depenetration_velocity=10.0,
                enable_gyroscopic_forces=True,
            ),
            collision_props=sim_utils.CollisionPropertiesCfg(
                collision_enabled=True,
            ),
            mass_props=sim_utils.MassPropertiesCfg(mass=0.3),
            articulation_props=sim_utils.ArticulationRootPropertiesCfg(
                enabled_self_collisions=False,
                solver_position_iteration_count=4,
                solver_velocity_iteration_count=0,
                sleep_threshold=0.005,
                stabilization_threshold=0.001,
            ),
            copy_from_source=False,
        ),
        init_state=ArticulationCfg.InitialStateCfg(
            pos=(0.0, 0.0, 3),
        ),
        actuators={
            "dummy": ImplicitActuatorCfg(
                joint_names_expr=[".*"],
                stiffness=0.0,
                damping=0.0,
            ),
        },
    )
    # sensors
    camera = CameraCfg(
        prim_path="{ENV_REGEX_NS}/Robot/crazyflie/body/front_cam",
        update_period=0.1,
        height=480,
        width=640,
        data_types=["rgb", "distance_to_image_plane"],
        spawn=sim_utils.PinholeCameraCfg(
            focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1.0e5)
        ),
        offset=CameraCfg.OffsetCfg(pos=(0.15, 0.0, 0.15), rot=(-0.707, 0.707, 0, 0), convention="world"),
    )
    height_scanner = RayCasterCfg(
        prim_path="{ENV_REGEX_NS}/Robot/crazyflie/body",
        update_period=1 / 60,
        offset=RayCasterCfg.OffsetCfg(pos=(0, 0, 0)),
        attach_yaw_only=True,
        pattern_cfg=patterns.LidarPatternCfg(
            channels=100, vertical_fov_range=[-90, 90], horizontal_fov_range=[-90, 90], horizontal_res=1.0
        ),
        debug_vis=True,
        mesh_prim_paths=["/World/ground"],
    )



def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
    """Run the simulator."""
    # Define simulation stepping
    sim_dt = sim.get_physics_dt()
    sim_time = 0.0
    count = 0
    # Fetch relevant parameters to make the quadcopter hover in place
    body_ids = scene["robot"].find_bodies("body")[0]
    robot_mass = scene["robot"].root_physx_view.get_masses().sum()
    gravity = torch.tensor(sim.cfg.gravity, device=sim.device).norm()

    # Simulate physics
    while simulation_app.is_running():
        # Reset
        if count % 500 == 0:
            # reset counters
            sim_time = 0.0
            count = 0
            # reset dof state
            joint_pos, joint_vel = scene["robot"].data.default_joint_pos, scene["robot"].data.default_joint_vel
            scene["robot"].write_joint_state_to_sim(joint_pos, joint_vel)
            scene["robot"].write_root_pose_to_sim(scene["robot"].data.default_root_state[:, :7])
            scene["robot"].write_root_velocity_to_sim(scene["robot"].data.default_root_state[:, 7:])
            scene["robot"].reset()
            # reset command
            print(">>>>>>>> Reset!")
            # apply action to the robot (make the robot float in place)
        thrust = torch.zeros(scene["robot"].num_instances, 1, 3, device=sim.device)
        moment = torch.zeros(scene["robot"].num_instances, 1, 3, device=sim.device)
        thrust[:, 0, 2] = robot_mass * gravity * 1.1
        moment[:, 0, :] = 0
        scene["robot"].set_external_force_and_torque(thrust, moment, body_ids=body_ids)
        scene["robot"].write_data_to_sim()
        # perform step
        sim.step()
        # update sim-time
        sim_time += sim_dt
        count += 1
        # update buffers
        scene["robot"].update(sim_dt)
        # print information from the sensors
        print("-------------------------------")
        print(scene["camera"])
        print("Received shape of rgb   image: ", scene["camera"].data.output["rgb"].shape)
        print("Received shape of depth image: ", scene["camera"].data.output["distance_to_image_plane"].shape)
        print("-------------------------------")
        print(scene["height_scanner"])
        print("Received max height value: ", torch.max(scene["height_scanner"].data.ray_hits_w[..., -1]).item())
        print("-------------------------------")


def main():
    """Main function."""

    # Initialize the simulation context
    sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device)
    sim = sim_utils.SimulationContext(sim_cfg)
    # Set main camera
    sim.set_camera_view(eye=[10, 10, 10], target=[2.5, 0.0, 0.0])
    # design scene
    scene_cfg = SensorsSceneCfg(num_envs=args_cli.num_envs, env_spacing=5.0)
    scene = InteractiveScene(scene_cfg)

    # Play the simulator
    sim.reset()
    print("[INFO]: Setup complete...")
    # Run the simulator
    run_simulator(sim, scene)


if __name__ == "__main__":
    # run the main function
    main()
    # close sim app
    simulation_app.close()

crazyflie_final_new.zip

Additional context

  • The Ray Caster is attached to "/World/envs/env_.*/Robot/crazyflie/body" but does not inherit motion.
  • The camera follows the UAV correctly, but the Ray Caster remains fixed.
  • I suspect the issue might be due to how the Ray Caster's transformation is updated.

Checklist

  • I have checked that there is no similar issue in the repo (required)
  • I have checked that the issue is not in running Isaac Sim itself and is related to the repo

Acceptance Criteria

  • The Ray Caster follows the robot’s movement correctly
  • The issue is reproduced and resolved in an upcoming update

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