Skip to content

khalidbourr/gz-bundle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gz-bundle

Portable Gazebo SDF bundler. One file, zero setup.

Pack a Gazebo SDF world or model with all its assets into a single .sdfz file.

# Pack
python3 gz_bundle.py world.sdf -o forest3d.sdfz
python3 gz_bundle.py models/robot/model.sdf -o robot.sdfz
 
# Run
python3 forest3d.sdfz

World bundling

world_trimmed.mp4

Model bundling

model_trimmed.mp4

Requirements

  • Python 3.6+ (stdlib only, no pip packages)
  • Gazebo installed
  • fuse-zip (optional, enables zero-copy mount instead of /tmp extraction)
sudo apt install fuse-zip   # optional

Usage

# Pack a world
python3 gz_bundle.py worlds/my_world.sdf -o my_world.sdfz
 
# Pack a model
python3 gz_bundle.py models/tree/model.sdf -o tree.sdfz
 
# Run (self-executing, no gz_bundle.py needed)
python3 my_world.sdfz
 
# Verbose (shows every asset packed)
python3 gz_bundle.py worlds/my_world.sdf -o my_world.sdfz -v
 
# Pass extra args to gz sim
python3 my_world.sdfz -- -v

What gets bundled

my_world.sdfz  (ZIP_STORED, uncompressed)
├── world.sdf            ← rewritten SDF (URIs → relative)
├── __main__.py           ← self-run bootstrap
├── gz_bundle.py          ← bundler embedded for repacking
├── manifest.json
├── models/
│   ├── ground/
│   │   ├── model.sdf
│   │   └── mesh/terrain.obj
│   └── Tree/
│       ├── model.sdf
│       └── mesh/Tree.glb
├── materials/textures/
│   ├── bark_albedo.png
│   └── bark_normal.png
└── plugins/
    └── libgz_terramechanics.so
  • Meshes (.dae, .obj, .stl, .glb, .gltf)
  • PBR textures (albedo, normal, roughness, metalness, emissive)
  • Nested models (full directory trees, recursive)
  • Custom plugins (.so, platform-specific)
  • Model bundles generate a preview world automatically when run

How it works

Pack

world.sdf ──→ gz_bundle ──→ forest3d.sdfz
                  │
                  ├── Resolve model://, file://, relative URIs
                  ├── Collect meshes, textures, PBR maps, plugins
                  ├── Rewrite URIs to relative paths
                  └── Pack into ZIP (uncompressed for fuse-zip)

Run

forest3d.sdfz ──→ python3 ──→ gz sim
                     │
                     ├── Mount (fuse-zip) or extract to /tmp
                     ├── Set GZ_SIM_RESOURCE_PATH + plugin paths
                     └── Launch Gazebo, cleanup on exit

Auto-discovery

No export GZ_SIM_RESOURCE_PATH needed. The bundler finds models by walking up to the project root (.git, package.xml, CMakeLists.txt) and scanning the tree. Works with flat projects, ROS2 packages, and multi-package workspaces.

Known limitations

  • Plugins are platform-specific, which means .so won't work elsewhere (to be arranged)
  • Fuel URIs (https://fuel.gazebosim.org/...) are left as-is and fetched by gz-sim at runtime
  • Built-in plugins (gz-sim-physics-system, etc.) ship with Gazebo

Roadmap

  • Rename .gzworld to .sdfz
  • ZIP_STORED uncompressed; fuse-zip mount
  • World + model bundling
  • URI rewriting in root SDF
  • Parse model.config for non-standard SDF filenames
  • package:// URI support (ROS2)
  • Heightmap support (<heightmap><uri>)
  • Actor animation support (<actor><animation><filename>)
  • Refactor _crawl_sdf: single-pass + decouple parse/resolve/collect
  • Native gz sim world.sdfz (upstream PR)

Contributing

Issues and PRs welcome.

License

MIT

About

gz-bundle: Portable Gazebo world bundler. Packs a .sdf world and all its assets (meshes, PBR textures, models, plugins) into a single self-executable .sdfz file. One file to share, one command to run: no workspace setup, no path configuration.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages