Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@ MuJoCo backend implements, so a Strands Agent that drives a MuJoCo world
today switches to Isaac Sim by swapping the backend it constructs.

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_realtime", headless=True))
sim = create_simulation("isaac", render_mode="rtx_realtime", headless=True)
sim.create_world()
sim.add_robot("so100") # procedural; no asset files needed
sim.step(100)
frame = sim.render(camera_name="default")
```

> **Note:** `IsaacSimulation` is also registered as a `strands_robots.backends`
> entry point, but no released `strands-robots` (`>=0.3.8,<0.4`) walks that
> group from `create_simulation` yet, so `create_simulation("isaac")` raises
> `ValueError: Unknown simulation backend: 'isaac'`. Construct `IsaacSimulation`
> directly until the upstream entry-point walker ships
> ([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)).
> **Note:** `create_simulation("isaac", ...)` resolves to this repo's
> `IsaacSimulation` via the `strands_robots.backends` entry point —
> `strands-robots>=0.4.1` walks that group from its `create_simulation`
> factory ([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
> the same UX as `create_simulation("mujoco")`. The kwargs flow into
> `IsaacConfig`. You can still construct `IsaacSimulation(IsaacConfig(...))`
> directly when you want the config object in hand.

> **📚 Documentation:** <https://strands-labs.github.io/robots-sim/>
>
Expand Down Expand Up @@ -75,7 +76,7 @@ agent contract is identical.
```mermaid
graph LR
A[Strands Agent] --> B[Simulation<br/>AgentTool]
B --> C[create_simulation 'isaac'<br/>once upstream walks entry points]
B --> C[create_simulation 'isaac'<br/>walks entry points]
C --> D[Entry-point lookup<br/>strands_robots.backends]
D --> E[IsaacSimulation<br/>this repo]
E --> F[Isaac Sim Kit<br/>SimulationApp]
Expand All @@ -91,10 +92,12 @@ graph LR
```

`strands-robots-sim` registers `IsaacSimulation` as a
`strands_robots.backends` entry point. The intent is that
`create_simulation("isaac")` walks the entry-point group, imports the target
string, and instantiates it — but no released `strands-robots` (`>=0.3.8,<0.4`)
ships that walker yet, so today you construct `IsaacSimulation` directly (see
`strands_robots.backends` entry point. `create_simulation("isaac")` walks the
entry-point group, imports the target string, and instantiates it —
`strands-robots>=0.4.1` ships that walker
([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
so `create_simulation("isaac", ...)` resolves to this repo's `IsaacSimulation`
with nothing more than `pip install strands-robots-sim` (see
[Quick start](#quick-start)). The full plugin contract is documented in
[Architecture](https://strands-labs.github.io/robots-sim/architecture/).

Expand Down Expand Up @@ -126,9 +129,9 @@ Full install matrix in
### Single-env RTX render

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_pathtracing", headless=True))
sim = create_simulation("isaac", render_mode="rtx_pathtracing", headless=True)
sim.create_world()
sim.add_robot("so100") # procedural builder
sim.add_object(name="cube", shape="cuboid",
Expand All @@ -142,8 +145,8 @@ sim.destroy()
### IsaacLab-style fleet (preview)

```python
sim = IsaacSimulation(IsaacConfig(num_envs=1024, headless=True,
render_mode="headless"))
sim = create_simulation("isaac", num_envs=1024, headless=True,
render_mode="headless")
sim.create_world()
sim.add_robot(name="panda", usd_path="/path/to/franka.usda")
# ... RL training loop ...
Expand Down
11 changes: 7 additions & 4 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,10 @@ versions = update one constant (`ISAAC_SIM_DOCKER_IMAGE` /
isaac = "strands_robots_sim.isaac.simulation:IsaacSimulation"
```

Once an upstream `strands-robots` release walks the
`strands_robots.backends` group, `create_simulation("isaac", ...)` will do:
`strands-robots>=0.4.1` walks the `strands_robots.backends` group from its
`create_simulation` factory (shipped via
[`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
so `create_simulation("isaac", ...)` does:

```python
import importlib.metadata
Expand All @@ -281,8 +283,9 @@ cls = ep.load()
return cls(**kwargs)
```

Until then (the pinned floor is `strands-robots>=0.3.8,<0.4`, which has no
such walker), construct the backend directly:
This resolves to this repo's `IsaacSimulation` with nothing more than
`pip install strands-robots-sim`. If you want the `IsaacConfig` object in
hand, you can still construct the backend directly:

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
Expand Down
31 changes: 15 additions & 16 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,21 @@ isaac = "strands_robots_sim.isaac.simulation:IsaacSimulation"
```

When `strands-robots-sim` is installed, `importlib.metadata.entry_points`
sees the `isaac` name. The intended flow is that `create_simulation("isaac", ...)`
upstream walks the `strands_robots.backends` group, finds the `isaac` entry,
imports the target string, and instantiates it.

!!! warning "Discovery is not live in the pinned upstream yet"

No released `strands-robots` (this package pins `>=0.3.8,<0.4`) walks the
`strands_robots.backends` group from its `create_simulation` factory, so
`create_simulation("isaac")` currently raises
`ValueError: Unknown simulation backend: 'isaac'`. Until the upstream
walker ships
([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
construct the backend directly with
`IsaacSimulation(IsaacConfig(...))`. The entry-point declaration here is
forward-compatible plumbing: once upstream walks the group, no change to
this package is required.
sees the `isaac` name. `create_simulation("isaac", ...)` upstream walks the
`strands_robots.backends` group, finds the `isaac` entry, imports the target
string, and instantiates it.

!!! note "Discovery is live in `strands-robots>=0.4.1`"

`strands-robots>=0.4.1` walks the `strands_robots.backends` group from its
`create_simulation` factory (shipped via
[`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
so `create_simulation("isaac", ...)` resolves to this repo's
`IsaacSimulation` with nothing more than `pip install strands-robots-sim`.
The entry-point declaration here is all the plumbing required — no
upstream code change is needed to add a backend. You can still construct
the backend directly with `IsaacSimulation(IsaacConfig(...))` when you want
the config object in hand.

This is the same pattern other packages use to extend `strands-robots`
(future cuRobo / MoveIt2 backends, custom user backends). The upstream
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ not just that the package imports. Run this with Isaac Sim's bundled Python
(`python.sh` / `setup_python_env.sh`-activated venv):

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_realtime", headless=True))
sim = create_simulation("isaac", render_mode="rtx_realtime", headless=True)
sim.create_world() # boots SimulationApp; resolves all extensions
sim.add_robot("so100")
sim.add_object(name="cube", shape="cuboid", position=[0.4, 0.0, 0.05])
Expand Down
32 changes: 16 additions & 16 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ Bring up an Isaac Sim world, drop a robot in, render an RTX frame.
## Hello, RTX

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(
sim = create_simulation(
"isaac",
render_mode="rtx_realtime", # or "rtx_pathtracing" for path-traced
headless=True,
))
)
sim.create_world()
sim.add_robot("so100") # procedural builder, no asset files
sim.add_object(name="cube", shape="cuboid",
Expand All @@ -28,22 +29,21 @@ frame = sim.render(camera_name="front") # {"rgb": (H, W, 3) uint8, "depth
sim.destroy()
```

!!! note "`create_simulation('isaac')` is not wired up yet"
!!! note "`create_simulation('isaac')` resolves via the entry-point group"

`IsaacSimulation` is registered as a `strands_robots.backends` entry
point, but the released `strands-robots` floor (`>=0.3.8,<0.4`) does not
walk that group from `create_simulation`, so
`create_simulation("isaac")` raises
`ValueError: Unknown simulation backend: 'isaac'`. Construct
`IsaacSimulation(IsaacConfig(...))` directly until the upstream walker
ships ([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131));
the kwargs are identical, forwarded into `IsaacConfig`.
point. `strands-robots>=0.4.1` walks that group from `create_simulation`
([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
so `create_simulation("isaac", ...)` resolves to this repo's
`IsaacSimulation` — the same UX as `create_simulation("mujoco")`. The
kwargs are forwarded into `IsaacConfig`. If you want the config object in
hand you can still construct `IsaacSimulation(IsaacConfig(...))` directly.

What happened:

1. `IsaacSimulation(IsaacConfig(...))` constructs the backend directly — the
supported path until `create_simulation("isaac")` resolves through the
`strands_robots.backends` entry point.
1. `create_simulation("isaac", ...)` resolves the backend through the
`strands_robots.backends` entry point and forwards the kwargs into
`IsaacConfig` — the recommended path.
2. `create_world()` spins up a `SimulationApp`, opens a USD stage, and
adds a ground plane.
3. `add_robot("so100")` runs the procedural SO-100 builder — no asset
Expand Down Expand Up @@ -144,9 +144,9 @@ that closes over the `sim` instance — the same pattern

```python
from strands import Agent, tool
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_realtime", headless=True))
sim = create_simulation("isaac", render_mode="rtx_realtime", headless=True)
sim.create_world()
sim.add_robot("so100")

Expand Down
43 changes: 17 additions & 26 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ backend it constructs:
=== "Isaac Sim (this repo, RTX, USD-native)"

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_pathtracing", headless=True))
sim = create_simulation("isaac", render_mode="rtx_pathtracing", headless=True)
sim.create_world()
sim.add_robot("so100") # procedural; no asset files needed
sim.step(100)
Expand All @@ -36,18 +36,12 @@ are all identical across backends — once the `IsaacSimulation` instance
exists, every downstream call is `SimEngine`-shaped regardless of how it was
constructed.

!!! note "Why the direct constructor instead of `create_simulation('isaac')`?"

`strands-robots-sim` registers `IsaacSimulation` as a
`strands_robots.backends` entry point (see [How it works](#how-it-works)),
but the released `strands-robots` floor this package pins
(`>=0.3.8,<0.4`) does **not** yet walk that entry-point group from
`create_simulation` — so `create_simulation("isaac")` raises
`ValueError: Unknown simulation backend: 'isaac'`. Until an upstream
release ships the entry-point walker (tracked in
[`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
construct `IsaacSimulation` directly as shown above. The kwargs are the
same either way: they flow into `IsaacConfig`.
`create_simulation("isaac", ...)` resolves to this repo's `IsaacSimulation`
via the `strands_robots.backends` entry point (see [How it works](#how-it-works)),
exactly like `create_simulation("mujoco")` resolves to the built-in MuJoCo
backend. The kwargs flow straight into `IsaacConfig`. You can still construct
`IsaacSimulation(IsaacConfig(...))` directly if you want the config object in
hand, but the factory is the recommended path.

## When you want this repo

Expand All @@ -67,14 +61,13 @@ contract is the same.
## How it works

`strands-robots-sim` registers `IsaacSimulation` as a
`strands_robots.backends` entry point. The intent is that
`create_simulation("isaac")` resolves to it without `strands-robots` ever
needing a hard dependency on Isaac Sim:
`strands_robots.backends` entry point. `create_simulation("isaac")` resolves
to it without `strands-robots` ever needing a hard dependency on Isaac Sim:

```mermaid
graph LR
A[Strands Agent] --> B[Simulation<br/>AgentTool]
B --> C[create_simulation 'isaac'<br/>once upstream walks entry points]
B --> C[create_simulation 'isaac'<br/>walks entry points]
C --> D[Entry-point lookup<br/>strands_robots.backends]
D --> E[IsaacSimulation<br/>this repo]
E --> F[Isaac Sim Kit<br/>SimulationApp]
Expand All @@ -89,17 +82,15 @@ graph LR
class E,F,G plugin
```

!!! warning "Entry-point discovery is not live yet"
!!! note "Entry-point discovery"

The entry point above is declared and discoverable
(`importlib.metadata.entry_points(group="strands_robots.backends")`
lists `isaac`), but no released `strands-robots` walks that group from
its `create_simulation` factory yet — the pinned floor
(`strands-robots>=0.3.8,<0.4`) only knows the built-in MuJoCo aliases.
So today you construct `IsaacSimulation` directly (see
[Quickstart](#quickstart)); the entry-point path lights up once the
upstream walker ships
([`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)).
lists `isaac`). `strands-robots>=0.4.1` walks that group from its
`create_simulation` factory (shipped via
[`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)),
so `create_simulation("isaac")` resolves to this repo's `IsaacSimulation`
with nothing more than `pip install strands-robots-sim`.

The same plugin shape is what makes the `mujoco` backend in `strands-robots`
and `isaac` here interchangeable: both are `SimEngine` subclasses; the
Expand Down
4 changes: 2 additions & 2 deletions docs/simulation/domain-randomization.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ descriptions of what to perturb each frame, expressed as keyword args to
`replicate(...)`:

```python
from strands_robots_sim.isaac import IsaacSimulation, IsaacConfig
from strands_robots.simulation import create_simulation

sim = IsaacSimulation(IsaacConfig(render_mode="rtx_pathtracing", headless=True))
sim = create_simulation("isaac", render_mode="rtx_pathtracing", headless=True)
sim.create_world()
sim.add_robot(name="panda", usd_path="/path/to/franka.usda")
sim.add_object(name="cube", shape="cuboid",
Expand Down
27 changes: 18 additions & 9 deletions docs/simulation/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,35 @@ sensible defaults:
| `extra` | `{}` | Escape-hatch for experimental options. |

```python
from strands_robots_sim.isaac import IsaacConfig, IsaacSimulation
from strands_robots.simulation import create_simulation

cfg = IsaacConfig(
sim = create_simulation(
"isaac",
num_envs=1,
headless=True,
render_mode="rtx_pathtracing",
physics_dt=1.0 / 240.0,
camera_width=1280,
camera_height=720,
)
sim = IsaacSimulation(cfg)
```

`IsaacSimulation(IsaacConfig(headless=True, render_mode="rtx_realtime"))` is
the supported way to construct the backend today. Once an upstream
`strands-robots` release walks the `strands_robots.backends` entry-point
group, `create_simulation("isaac", headless=True, render_mode="rtx_realtime")`
will be shorthand for the same thing — kwargs are forwarded into
`IsaacConfig` either way (tracked in
`create_simulation("isaac", headless=True, render_mode="rtx_realtime")` is the
recommended way to construct the backend: `strands-robots>=0.4.1` walks the
`strands_robots.backends` entry-point group, so `create_simulation("isaac")`
resolves to this repo's `IsaacSimulation` — the same UX as
`create_simulation("mujoco")` (shipped via
[`strands-labs/robots#131`](https://github.com/strands-labs/robots/issues/131)).
The kwargs are forwarded into `IsaacConfig`. If you want the config object in
hand — e.g. to introspect or `dataclasses.replace(...)` it before construction
— build it explicitly and pass it to the class:

```python
from strands_robots_sim.isaac import IsaacConfig, IsaacSimulation

cfg = IsaacConfig(num_envs=1, headless=True, render_mode="rtx_pathtracing")
sim = IsaacSimulation(cfg)
```

### Environment-variable overrides

Expand Down
6 changes: 4 additions & 2 deletions examples/isaac_gs/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ def set_camera(self, view: str) -> None:

def boot(self) -> None:
"""Create SimulationApp + build the scene. **Main thread only.**"""
from strands_robots_sim.isaac import IsaacConfig, IsaacSimulation
from strands_robots.simulation import create_simulation

from strands_robots_sim.isaac import IsaacSimulation

available, reason = IsaacSimulation.is_available()
if not available:
Expand All @@ -236,7 +238,7 @@ def boot(self) -> None:
from examples.isaac_gs.scene import add_preset_cameras, build_default_scene

logger.info("Booting IsaacSimulation on the main thread (~200 s)...")
sim = IsaacSimulation(IsaacConfig(headless=True, num_envs=1, render_mode="rtx_realtime"))
sim = create_simulation("isaac", headless=True, num_envs=1, render_mode="rtx_realtime")
# Robot-aware: build_default_scene creates the "front" camera, so align
# it with the chosen presets' "front" pose; add_preset_cameras adds the
# rest. Defaults (no robot_usd / presets) = the bundled Franka.
Expand Down
6 changes: 4 additions & 2 deletions examples/isaac_gs/render_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,9 @@ def main() -> None:
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
args = _build_parser().parse_args()

from strands_robots_sim.isaac import IsaacConfig, IsaacSimulation
from strands_robots.simulation import create_simulation

from strands_robots_sim.isaac import IsaacSimulation

# Fail-fast on non-Isaac hosts (cheap probe, no omni import).
available, reason = IsaacSimulation.is_available()
Expand All @@ -238,7 +240,7 @@ def main() -> None:

out_dir = _date_out(args.out)
# rtx_realtime so render() takes the RTX frame path (not headless blanks).
sim = IsaacSimulation(IsaacConfig(headless=True, num_envs=1, render_mode="rtx_realtime"))
sim = create_simulation("isaac", headless=True, num_envs=1, render_mode="rtx_realtime")
try:
build = build_default_scene(
sim,
Expand Down
Loading
Loading