Virtual Gantry Extension#

About#

The Virtual Gantry suspends a robot from an anchor point during bring-up and policy testing, like a crane holding the robot so it does not fall over while you test your policy.

It is a runtime constraint only: a one-sided spring-damper “rope” applied as a per-physics-step external wrench to a single articulation body. The rope applies no force until the body drops past the rope length, then it pulls the body back toward the anchor.

This extension is enabled by default. If it is ever disabled, it can be re-enabled from the Extension Manager by searching for isaacsim.robot_setup.virtual_gantry and isaacsim.robot_setup.virtual_gantry.ui.

Suspending a Robot#

  1. Add a robot to the stage.

  2. Create the gantry from the menu: Create > Robotics > Virtual Gantry. This authors an IsaacVirtualGantry prim, placed above the selected prim by default. The prim is an Xform, and its world position is the rope anchor.

    Note

    The gantry prim carries no geometry, so it is not visible in the viewport and cannot be clicked there. Select it in the Stage panel; the transform gizmo then appears at the anchor position, and the anchor can be moved with the gizmo or by editing Transform > Translate in the property panel. The rope line and anchor marker are only drawn while the simulation is playing.

  3. Select the gantry prim and, in the property panel, set the two relationships:

    • Attach Body - the articulation link the rope pulls on, typically the torso or pelvis.

    • Articulation - the robot’s articulation-root prim.

    Note

    If either relationship is unset or cannot be resolved, the gantry prim is skipped silently: no rope is created and no error is reported. If pressing Play produces no rope, check these two relationships first.

  4. Press Play. The robot is caught by the rope once it drops past the rope length.

Properties#

Property

Description

Rope Length

Slack rope length in meters. -1 auto-derives it from the attach body’s height on the first physics step.

Stiffness

Rope spring stiffness kp, in N/m. Default 5000.

Damping

Rope damping kd, in N*s/m. Default 800. Applied only while the rope is extending.

Body Offset

Attach point offset in the body’s local frame, in meters. Default (0, 0, 0.3).

Min Rope Length

Lower clamp for the rope length, in meters.

EMA Alpha

Smoothing factor for the rope extension-rate estimate.

Enabled

Whether the rope applies force. Read every physics step.

Visualize

Draw the rope line and anchor marker as an overlay.

Status

Runtime rope state, written back by the runtime: Slack, Taut or Disabled.

Attach Body

The articulation link the rope pulls on.

Articulation

The robot’s articulation-root prim.

Edits made in the property panel apply to the running rope immediately; there is no need to stop and restart the timeline.

Hotkeys#

The viewport must have keyboard focus for these to fire.

Key

Action

G

Toggle every gantry on the stage on or off.

[

Shorten the rope by 5 mm.

]

Lengthen the rope by 5 mm.

The [ and ] adjustments are transient: they change the running rope without writing back to the prim. Disabling and re-enabling the gantry re-derives the rope and catches the robot where it currently is, rather than restoring the last adjusted height.

Driving the Gantry from Code#

Creating the Gantry Prim#

import omni.usd
from isaacsim.robot_setup.virtual_gantry import create_virtual_gantry

stage = omni.usd.get_context().get_stage()

# Authors an IsaacVirtualGantry prim. Its world position is the rope anchor,
# so place it above the robot. When an articulation is already on the stage it
# is auto-wired; otherwise wire it yourself (see below).
gantry_prim = create_virtual_gantry(stage, parent_path="/", anchor_z=2.0)
print(f"created {gantry_prim.GetPath()}")

Wiring it to a Robot#

The runtime picks up a gantry prim once both relationships resolve, so a prim created before the robot starts driving a rope as soon as it is wired.

import isaacsim.robot_setup.virtual_gantry_schema as gantry_schema

R = gantry_schema.Relations

# The link the rope pulls on (e.g. the torso or pelvis).
gantry_prim.GetRelationship(R.GANTRY_ATTACH_BODY.name).SetTargets(["/Robot/torso_link"])
# The robot's articulation-root prim.
gantry_prim.GetRelationship(R.GANTRY_ARTICULATION.name).SetTargets(["/Robot"])

Tuning the Rope#

A = gantry_schema.Attributes

# Slack rope length in meters; -1 auto-derives from the body's height on the
# first physics step.
gantry_prim.GetAttribute(A.GANTRY_ROPE_LENGTH.name).Set(-1.0)
# Spring stiffness kp (N/m) and damping kd (N*s/m). Damping is one-sided: it
# only acts while the rope is extending.
gantry_prim.GetAttribute(A.GANTRY_STIFFNESS.name).Set(5000.0)
gantry_prim.GetAttribute(A.GANTRY_DAMPING.name).Set(800.0)
# Attach point offset in the body's local frame (m).
gantry_prim.GetAttribute(A.GANTRY_BODY_OFFSET.name).Set((0.0, 0.0, 0.3))
# Draw the rope line and anchor marker.
gantry_prim.GetAttribute(A.GANTRY_VISUALIZE.name).Set(True)

Toggling and Reading State#

# The runtime reads this attribute every physics step, so toggling it takes
# effect on the next step. This is what the Enable / Disable buttons and the
# G hotkey do.
gantry_prim.GetAttribute(A.GANTRY_ENABLED.name).Set(False)
gantry_prim.GetAttribute(A.GANTRY_ENABLED.name).Set(True)

# The runtime writes the rope state back: "Slack", "Taut" or "Disabled".
status = gantry_prim.GetAttribute(A.GANTRY_STATUS.name).Get()
print(f"rope status: {status}")

Adjusting a Running Rope#

Most of the gantry is driven through USD attributes, so no handle to the runtime is needed. The exception is the transient rope-length adjustment behind the [ and ] hotkeys, which mutates the live rope without touching the prim.

from isaacsim.robot_setup.virtual_gantry import get_manager

# The live manager, or None when the extension is not running. Resolve it on
# use rather than caching it: it is rebuilt on stage close and timeline stop.
manager = get_manager()
if manager is not None:
    # Lengthen every managed rope by 5 mm. This adjustment is transient -- it
    # is not written back to the prim, so a disable -> enable re-derives the
    # rope and catches the robot where it currently is.
    manager.adjust_rope_length_all(0.005)

Notes#

  • Multiple gantries are supported. The runtime re-scans the stage periodically, so gantries created mid-session are picked up without a stop and restart.

  • The anchor uses the gantry prim’s position only. Its orientation is reserved for a future 6-DOF “soft fixture” mode.

  • Every time the gantry is enabled, the anchor prim re-anchors above the attach body’s current position, so a disable → fall → enable sequence catches the robot in place instead of yanking it back to the prim’s original spot.

  • The rope line and anchor marker are drawn as an ephemeral overlay; nothing is authored into the stage, and they do not appear in renders or in a saved USD.

  • Disable the rope once a policy is balancing on its own.