Skip to content

Latest commit

 

History

History
352 lines (281 loc) · 15.2 KB

File metadata and controls

352 lines (281 loc) · 15.2 KB

Using Cables

Isaac Lab exposes 1D cable / rod assets on the Newton backend. A cable is authored as a single open UsdGeom.BasisCurves prim carrying the PhysicsCurvesDeformableSimAPI schema, and is simulated by Newton's VBD solver as a chain of per-segment capsule bodies joined by JointType.CABLE joints, with thickness, density, stretch stiffness, and bend stiffness.

Cable support is experimental. The spawner cfg, asset class, and material defaults may change while Newton cable support is under active development.

Note

Cables are only supported on the Newton backend, and only under its VBD solver. :class:`~isaaclab.assets.CableObject` is a backend-dispatched factory: selecting PhysX or OpenUSD PhysX raises the factory import error at construction, so a misconfigured scene fails fast instead of loading the curve as inert geometry.

Quick Start: The Cable Demo

Before adding cables to a task, run the standalone demo to confirm that the spawner, the VBD solver, collision, and the Kit / Fabric viewport sync all work in your environment:

# Default Newton VBD physics with the Kit visualizer.
uv run --extra isaacsim python scripts/demos/cables.py

# Explicit Newton VBD physics with the Newton visualizer.
uv run python scripts/demos/cables.py --physics newton_vbd --visualizer newton

# No visualizer and a larger cable pile.
uv run python scripts/demos/cables.py --visualizer none --num_cables 40 --num_segments 15

The demo accepts newton_vbd as its only --physics option. Its --visualizer option accepts kit, newton, rerun, viser, and none; when omitted, the demo uses kit. Use --num_cables and --num_segments to change the pile size and cable resolution. Use --max_steps to stop after a fixed number of simulation steps; its negative default runs until the selected visualizer closes or the process is interrupted.

The demo spawns a pile of randomly oriented cables onto a ground plane under standalone Newton VBD, lets them collide and settle, and periodically restores them to their spawn state. Source: scripts/demos/cables.py.

Authoring a Cable

A cable is configured with a :class:`~isaaclab.sim.spawners.shapes.CableCfg` plus a :class:`~isaaclab.sim.spawners.materials.CableMaterialCfg`. Adjacent pairs in positions become individual segments, each materialized as a capsule body of diameter :attr:`CableMaterialCfg.thickness` and joined to its neighbour by a Newton cable joint. N control points produce N-1 segment bodies and N-2 cable joints; the root segment is free-floating.

Parameter Description
positions Control points in the cable-local frame [m]. Requires at least three finite points, with consecutive points separated by more than 1e-8 m.
physics_material Required :class:`~isaaclab.sim.spawners.materials.CableMaterialCfg`; see Cable Material Parameters below. Thickness is also written to the curve's widths attribute so the visual radius matches the physics.
collision_props Optional collision properties. When omitted, the cable is collision-free; when set (typically [UsdPhysicsCollisionCfg(collision_enabled=True)]), the cable collides with the ground and other cables. See Collision below.
visual_material Optional :class:`~isaaclab.sim.spawners.materials.VisualMaterialCfg` for the curve's appearance.
visual_material_path Sub-path of the visual material under the cable geometry prim. Defaults to "material".
physics_material_path Sub-path of the physics material under the cable geometry prim. Defaults to "physics_material".
import isaaclab.sim as sim_utils

cable_spawn = sim_utils.CableCfg(
    positions=[(index * 0.1, 0.0, 0.0) for index in range(10)],
    visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.7, 0.2, 0.2)),
    physics_material=sim_utils.CableMaterialCfg(
        thickness=0.03,
        density=1000.0,
        stretch_stiffness=1.0e9,
        bend_stiffness=1.0e6,
    ),
    collision_props=[sim_utils.UsdPhysicsCollisionCfg(collision_enabled=True)],
)

This authors a straight 0.9 m red cable along the cable-local x-axis: 9 capsule segments (0.1 m long, 0.03 m diameter) joined by 8 cable joints. See Loading Cables from USD for how the curve becomes Newton physics.

Wrap the spawner in a :class:`~isaaclab.assets.CableObjectCfg` to get a runtime asset whose per-segment state can be read, written, and restored:

from isaaclab.assets import CableObject, CableObjectCfg

cable = CableObject(
    cfg=CableObjectCfg(
        prim_path="/World/Env_0/Cable",
        spawn=cable_spawn,
        init_state=CableObjectCfg.InitialStateCfg(pos=(0.0, 0.0, 0.5)),
    )
)

The inherited init_state sets the cable root's spawn pose in each environment.

Picking a Solver

Cables can only be simulated under Newton's VBD solver, which is the only solver that steps JointType.CABLE joints. A cable-only scene uses a standalone :class:`~isaaclab_newton.physics.VBDSolverCfg`:

from isaaclab_newton.physics import NewtonCfg, VBDSolverCfg

sim_cfg = sim_utils.SimulationCfg(
    dt=0.01,
    device=args_cli.device,
    physics=NewtonCfg(solver_cfg=VBDSolverCfg(iterations=20), num_substeps=8),
)

Mixed rigid + cable scenes (for example a robot manipulating a cable) run the cable under a :class:`~isaaclab_contrib.coupling.CouplerProxyCfg` entry: define a named VBD entry that owns the cable segments and couple it to the rigid entry. See :doc:`using-vbd-solver`.

Cable Material Parameters

:class:`~isaaclab.sim.spawners.materials.CableMaterialCfg` defines the cable's geometry and stiffness. All values are validated at author time; nonfinite or out-of-range values raise :class:`ValueError` before any prim is created. The attributes are authored in the standard physics: namespace and read back by Newton's importer.

Parameter Description
thickness Full cable thickness (diameter) [m]. Must be finite and positive. Newton uses radius = thickness / 2 for the capsule cross-section, the bending second moment of area, and the collision radius. Default 0.001.
density Cable density [kg/m^3]. Must be finite and positive. Newton derives per-segment mass from the density and the capsule volume. Default 1000.0.
stretch_stiffness Axial (stretch) elastic modulus E [Pa], i.e. force per area. Must be finite and nonnegative. Newton converts it to the rod's per-joint axial stiffness E * A / L, where A is the circular cross-section area and L is the mean segment rest length. Higher values reduce elongation but need more solver iterations or substeps. Default 1.0e9.
bend_stiffness Bending elastic modulus E [Pa]. Must be finite and nonnegative. Newton converts it to the per-joint bend stiffness E * I / L, where I is the second moment of area of the circular cross-section. 0.0 gives a limp rope; increase for a stiff hose or wire. Default 1.0e6.
shear_stiffness Transverse shear elastic modulus [Pa]. Must be finite and nonnegative. Optional: when left at None the attribute is not authored and the solver falls back to :attr:`stretch_stiffness`. Default None.
twist_stiffness Torsional elastic modulus [Pa]. Must be finite and nonnegative. Optional: when left at None the attribute is not authored and the solver falls back to :attr:`bend_stiffness`. Default None.

Note

A Newton cable joint has four degrees of freedom: linear stretch and shear, and angular bend and twist. Leaving :attr:`shear_stiffness` or :attr:`twist_stiffness` unset does not mean the cable has no shear or twist resistance; it means the solver reuses the stretch and bend moduli for them. Set them explicitly to decouple torsion from bending, for example a hose that bends easily but resists twisting. Authoring 0.0 is distinct from leaving them unset: it removes that resistance.

Damping is not exposed. The AOUSD deformable schema defines damping alongside the moduli, but Isaac Lab does not author it.

To target a specific axial E * A or bending E * I, invert these relations to pick the modulus; scripts/demos/cables.py does this from a target stiffness and the segment geometry.

Warning

Newton derives one stretch/bend stiffness pair for the whole cable, using the mean segment length as L. Author :attr:`positions` with roughly uniform spacing: with a strongly uneven spacing the per-joint stiffness is wrong for the outlier segments, since stiffness scales as 1 / L. A segment much longer than the mean comes out too stiff, and a much shorter one too soft.

Collision

Collision is opt-in through collision_props. When enabled, the importer applies adjacent-segment-only collision filtering: directly connected segments (which share a joint anchor and would otherwise jitter) are filtered, while every other pair collides. As a result:

  • The cable collides with the ground and with other cables.
  • Non-adjacent segments of the same cable collide, so a cable can self-arrest when it loops back on itself.
  • Only immediate neighbours are filtered, matching Newton's cable-pile behaviour.

When collision_props is omitted, the cable imports as a dynamics-only rod and does not collide.

Runtime State

:class:`~isaaclab.assets.CableObject` exposes per-segment world state through its data container and integrates with :class:`~isaaclab.scene.InteractiveScene`, scene.get_state / scene.reset_to, and the reset_scene_to_default event term.

  • cable.data.segment_pose_w shape (num_instances, num_segments, 7), position [m] followed by quaternion (x, y, z, w).
  • cable.data.segment_velocity_w shape (num_instances, num_segments, 6), linear [m/s] followed by angular [rad/s].
  • cable.data.default_segment_pose_w / default_segment_velocity_w capture the spawn state for restoration.

Write per-segment state back with the indexed or masked setters. The masked form is CUDA-graph capturable:

cable.write_segment_pose_to_sim_index(
    segment_pose=cable.data.default_segment_pose_w,
)
cable.write_segment_velocity_to_sim_index(
    segment_velocity=cable.data.default_segment_velocity_w,
)

Writes update Newton's maximal-coordinate body state directly (both simulation states) and flag the affected environments for a solver reset, without running forward kinematics.

Kit / Fabric Visualization

Cables render in the Kit viewport as UsdGeom.BasisCurves. At render cadence the curve points are refreshed from Newton's cable segment endpoints so the rendered shape always matches the simulation. Use the default --visualizer kit flag, as in the demo.

Note

Curve points are synchronized through CPU Fabric because the RTX Hydra delegate does not read GPU-backed Fabric arrays for BasisCurves (NVBug 6502662). The on-device sync path can be restored once that bug is fixed. Periodic curves are skipped by the sync.

Loading Cables from USD

Physics is authored in place on the curve: :func:`~isaaclab.sim.spawners.shapes.spawn_cable` applies the PhysicsCurvesDeformableSimAPI schema and binds a deformable-curve material, and Newton imports the curve natively through ModelBuilder.add_usd. Topology comes from the curve's own points and curveVertexCounts; no custom edge attribute is required, and imported and replicated cables use the same path.

A cable can therefore also be loaded from an external USD (for example one authored in a DCC tool) via :class:`~isaaclab.sim.spawners.from_files.UsdFileCfg`, provided the curve in that USD already carries:

  • a single open, linear, nonperiodic UsdGeom.BasisCurves under the loaded prim,
  • the PhysicsCurvesDeformableSimAPI applied schema, and
  • a bound deformable-curve material (PhysicsCurvesDeformableMaterialAPI) supplying thickness, density, stretchStiffness, and bendStiffness in the physics: namespace.

A raw exported curve without the physics schema and material will not be recognized as a cable (the importer falls back to a default radius and warns, or skips the curve). Author it through :func:`~isaaclab.sim.spawners.shapes.spawn_cable`, or apply the schema and material to the imported prim before construction.

Limitations

  • Newton + VBD only. Other backends and other Newton solvers are not supported.
  • One standalone, unwelded cable per object. :class:`~isaaclab.assets.CableObject` requires "one standalone, unwelded cable articulation per simulation world": exactly one BasisCurves prim carrying PhysicsCurvesDeformableSimAPI under prim_path, holding a single open curve that is not welded to another cable. Multi-curve BasisCurves prims, periodic (closed) curves, and hard coincident curve-to-curve PhysicsAttachment welds all fail during initialization.
  • Cable ends can be pinned, not clamped. A PhysicsAttachment to an xform target lowers to a ball joint, so it constrains position only and the cable pivots freely at the anchor. Rigid plugs and end fittings that must transfer orientation are not representable. The joint is also created only when the attachment stiffness is unauthored or infinite; a finite stiffness is kept as metadata and no joint is created. Both cases are import warnings rather than errors, so the cable initializes normally with the attachment missing. Check the importer output when an attachment appears to have no effect.
  • No damping knobs. The four stiffness moduli are exposed; their damping counterparts are not.
  • Uniform point spacing assumed. One stiffness pair is derived from the mean segment length, so uneven spacing mistunes the outlier segments.
  • CPU-only render sync (NVBug 6502662); periodic curves are not synced.

Note

Topologies the runtime object rejects still simulate: the Newton model is built from the whole USD stage, so every curve carrying PhysicsCurvesDeformableSimAPI is imported whether or not a :class:`~isaaclab.assets.CableObject` wraps it. Drive them through :class:`~isaaclab_newton.physics.NewtonManager` get_model() / get_state_0() and your own newton.selection.ArticulationView. There is no Isaac Lab asset wrapper for those cases.

For the public API, see :class:`~isaaclab.assets.CableObject`, :class:`~isaaclab.sim.spawners.shapes.CableCfg`, and :class:`~isaaclab.sim.spawners.materials.CableMaterialCfg`.