Skip to content

Is Beam Broken

SUMMARY

Is Beam Broken reports whether anything is standing in the sensor's beam. A multi-beam curtain counts as broken when any one of its beams is, so it answers the same question a single beam does.

Available on: IsaacSim LightBeam.

The Skill

python
broken = sensor.is_beam_broken()

The Code

python
"""
Watches a lightbeam sensor in a running Isaac Sim stage until the beam breaks.

Supports Isaac Sim only. The sensor is sampled from the last physics step, so
the simulation timeline must be playing -- a stopped simulation has no
reading to give.

Usage:
    python is_beam_broken.py --prim_path <PRIM_PATH>
    python is_beam_broken.py --prim_path <PRIM_PATH> --watch_seconds 20
    python is_beam_broken.py --prim_path <PRIM_PATH> --load_usd

Note:
    Open Isaac Sim and add a lightbeam sensor prim before running this. If
    there is none in the stage yet, follow
    https://docs.isaacsim.omniverse.nvidia.com/5.1.0/sensors/isaacsim_sensors_physx_lightbeam.html
    to create one, or pass --load_usd to add one to the open stage -- this
    keeps whatever is already in the stage. Place an object with a collider
    in front of the beam before running this to see it detected.
"""

import argparse
import time

from loguru import logger

from telekinesis.medulla.sensors import isaacsim

POLL_SECONDS = 0.1
PRINT_SECONDS = 1.0


def main(prim_path: str, watch_seconds: float, load_usd: bool) -> None:
    """Watches a lightbeam sensor until its beam breaks or time runs out."""

    if load_usd:
        # ===================== Load Demo Scene (Optional) ===========================
        from telekinesis import datatypes, isaacsim_client

        client = isaacsim_client.IsaacSimClient(
            api_key="",
            base_url="http://127.0.0.1:8766",
            websocket_base_url="ws://127.0.0.1:8766",
        )
        asset = datatypes.USD.from_url(
            "https://assets.telekinesis.ai/usd/sensors/simple_light_beam_sensor.zip"
        )
        client.stage.add_to_scene(uri=asset.path.as_posix(),
                                  prim_path="/World/simple_light_beam_sensor")

    # ===================== Create Sensor ======================================
    sensor = isaacsim.LightBeamSensor(name="my_simulated_lightbeam")

    try:
        # ===================== Connect Sensor ==================================
        sensor.connect(simulation_prim_path=prim_path)

        # ==================== Run Skill ============================================
        logger.info(f"Watching lightbeam sensor {sensor.name}.")
        deadline = time.monotonic() + watch_seconds
        last_print = 0.0
        while time.monotonic() < deadline:
            if sensor.is_beam_broken():
                logger.success("Object detected: beam broken.")
                break
            now = time.monotonic()
            if now - last_print >= PRINT_SECONDS:
                logger.info("No object detected: beam not broken.")
                last_print = now
            time.sleep(POLL_SECONDS)
        else:
            logger.info("Nothing broke the beam.")
    except (ConnectionError, RuntimeError) as e:
        logger.error(f"Error occurred: {e}")
    finally:
        sensor.disconnect()


if __name__ == "__main__":
    p = argparse.ArgumentParser(description="Watch a lightbeam sensor in Isaac Sim")
    p.add_argument(
        "--prim_path",
        type=str,
        default="/World/simple_light_beam_sensor/LightBeam_Sensor",
        help='Isaac Sim lightbeam sensor prim path, e.g. '
        '"/World/simple_light_beam_sensor/LightBeam_Sensor"')
    p.add_argument("--watch_seconds", type=float, default=10.0,
                   help="How long to watch the sensor before giving up")
    p.add_argument("--load_usd", action=argparse.BooleanOptionalAction, default=False,
                   help="Add the bundled demo lightbeam sensor to the open "
                        "stage at /World/simple_light_beam_sensor before "
                        "connecting. Use this if you don't already have one "
                        "in the stage.")
    args = p.parse_args()

    main(prim_path=args.prim_path, watch_seconds=args.watch_seconds, load_usd=args.load_usd)

Running the Example

bash
python is_beam_broken.py --prim_path /World/simple_light_beam_sensor/LightBeam_Sensor

To load the bundled demo sensor into the stage first:

bash
python is_beam_broken.py --load_usd

For all options:

bash
python is_beam_broken.py --help

Parameter Configuration

is_beam_broken takes no parameters.

Returns

TypeDescription
boolWhether at least one beam is broken. False before the sensor has produced its first reading.

Raises

ExceptionCondition
RuntimeErrorThe sensor is not connected, or the reading cannot be taken.

Where to Use the Skill

Is Beam Broken requires an active connection — see Connection and Disconnection. Poll it in a loop to detect an object entering the beam.