Auto OMap from USDs#
Occupancy maps gate collision-free pose sampling during training. Historically
they were hand-authored in the Isaac Sim editor — slow, error-prone, and a
blocker for SAGE-driven scene generation. The
scripts/generate_omap_from_usd.py
CLI generates an OMap directly from a USD scene in one shot.
Generate an OMap#
python scripts/generate_omap_from_usd.py \
compass/rl_env/exts/mobility_es/mobility_es/usd/<scene>/<scene>.usd
(Inside an activated dev shell, python already
points at Isaac Sim’s bundled Python; on bare-metal install, prefix with
${ISAACLAB_PATH}/isaaclab.sh -p.)
By default the script writes the PNG + ROS YAML pair to <usd_dir>/omap/
next to the input USD — exactly where
OccupancyMapCollisionChecker
auto-discovers it when no explicit OMAP_PATHS entry exists.
Origin convention#
There are two OMap conventions in the codebase:
Legacy bundled COMPASS maps use a custom top-left YAML origin. These are the maps already listed as plain string paths in
OMAP_PATHS.New maps generated by
scripts/generate_omap_from_usd.pyuse the Isaac Sim / ROS occupancy-map convention: the YAMLoriginis the bottom-left map corner in world coordinates.
The generator follows Isaac Sim’s ROS export behavior. It rotates the raw Isaac OMap buffer by 180 degrees before writing the PNG:
np.flipud(np.fliplr(img))
The saved PNG therefore has columns increasing with world +X and rows
increasing toward world -Y, while the YAML origin is written as
(xmin, ymin, 0.0). This matches ROS map_server / Isaac Sim’s
“ROS Occupancy Map Parameters File” convention.
OccupancyMapCollisionChecker keeps backward compatibility with the old maps:
OMAP_PATHSentries that are plain strings are interpreted as legacytop-leftmaps.Auto-discovered maps at
<usd_dir>/omap/occupancy_map.yamlare interpreted as generated ROSbottom-leftmaps.If a ROS-convention map must be registered explicitly in
OMAP_PATHS, use a dict entry:
OMAP_PATHS = {
"MyScene": {
"path": "/path/to/omap/occupancy_map.yaml",
"origin_convention": "bottom-left",
},
}
If you have an auto-discovered map generated by an older version of the script, regenerate it. Older generated maps used the legacy top-left interpretation and will be read incorrectly by the current auto-discovery path.
Common flags#
Flag |
Default |
Meaning |
|---|---|---|
|
|
Where the PNG + YAML land |
|
|
meters / pixel |
|
|
Height slab the rasterizer projects |
|
derived from USD bbox + 1 m padding |
World-space |
|
|
Padding (m) around the auto-derived bbox |
|
|
PNG stem |
|
|
World-space flood-fill seed; reachable cells from this point become free |
Run python scripts/generate_omap_from_usd.py --help for the complete list.
Loader auto-discovery#
OccupancyMapCollisionChecker (compass/rl_env/exts/.../utils/occupancy_map.py)
checks OMAP_PATHS first; if it has no entry for the scene, it falls back to
<dirname(spawn.usd_path)>/omap/occupancy_map.yaml — the same path the
generator writes to. No OMAP_PATHS registration is needed for new
scenes.
Slab tuning for taller embodiments#
The default [0.1, 0.62] height slab works for Carter, Spot, G1. Tall
humanoids (H1) clear about 1.3 m; bump --z-max 1.4 so the rasterizer
captures higher obstacles. The slab is the only embodiment-specific knob
and is exposed at the CLI rather than baked into per-embodiment maps.