Table of Contents
A repository bundling multiple Gazebo (ignition) world files. It is structured so that furniture can be freely customized.
The following features are currently supported:
- Launching worlds with fixed furniture layouts
- Random placement of YCB objects
- Placement-surface configuration via YAML
- Placement-surface size/height estimation from a furniture model's
model.sdf - Multi-surface specification for shelves (e.g.
plate1/plate2/plate3) - Object-category restriction via
allowed_categories - Automatic spawning of
gz_human_simhuman models viahuman_count - Additional spawning of objects/people from GPSR commands
- Human teleop launch for follow-type GPSR tasks
- Saving generated worlds
- Runtime regeneration of random objects via ROS 2 services
[!TODO] Planned: place and re-color furniture interactively through a GUI.
This section explains how to set up this repository.
First prepare the following environment, then proceed to the installation step.
| System | Version |
|---|---|
| Ubuntu | 24.04 (Noble Numbat) |
| ROS | Jazzy |
| Gazebo | ignition |
Note
For how to install Ubuntu and ROS, refer to the SOBIT Manual.
- Move to the
srcfolder of your ROS workspace.$ cd ~/colcon_ws/src/
- Clone this repository.
$ git clone -b humble-devel https://github.com/TeamSOBITS/sobits_gazebo_worlds.git
- Move into the repository.
$ cd sobits_gazebo_worlds/ - Install the dependencies.
$ bash install.sh
- Build the package.
$ cd ~/colcon_ws/ $ colcon build --symlink-install
-
Specify the world file
Setworld_file_pathin world.launch.py.
World files live in this folder. -
Launch the world.launch.py launch file.
$ ros2 launch sobits_gazebo_worlds world.launch.py
This starts Gazebo.
-
[Optional] Try driving a robot inside the Gazebo environment
From a Gazebo-compatible robot repository, point it to the Gazebo world file.
Note that you can also set the robot's initial pose.
Using random_world.launch.py, you can generate and launch a world that randomly places YCB objects and people on top of the fixed furniture base.
$ ros2 launch sobits_gazebo_worlds random_world.launch.pyThe main arguments are as follows.
| Argument | Description |
|---|---|
base_world |
Base world file |
placement_config |
Placement-surface YAML |
models_root |
Root directory of the YCB models |
seed |
Random seed |
object_count |
Number of YCB objects to place randomly |
human_count |
Number of human models to spawn |
human_model |
Human model name, e.g. person_standing |
task_command |
Command string that triggers extra spawns based on a GPSR task sentence |
gpsr_groq_model |
Model name used via groq_ros |
save_world |
Whether to save the generated world |
output_world_name |
Name of the saved world; if the extension is omitted, .world.xacro is appended automatically |
Example:
$ ros2 launch sobits_gazebo_worlds random_world.launch.py \
object_count:=15 \
human_count:=3 \
seed:=42Example that saves the generated world:
$ ros2 launch sobits_gazebo_worlds random_world.launch.py \
save_world:=true \
output_world_name:=rcjo2025_version_1In this case it is saved to worlds/rcjo2025_version_1.world.xacro.
Example that spawns extra items from a GPSR command:
$ ros2 launch sobits_gazebo_worlds random_world.launch.py \
task_command:="Grasp an apple on the tall table in the living room and place it on the shelf in study_room." \
object_count:=15 \
human_count:=2To use this feature, the groq_action server of groq_ros must be running beforehand.
Objects are added according to the room_name#furniture_name defined in the placement-area YAML, and people are added near the furniture of the target room via gz_human_sim.
Example of a follow-type task:
$ ros2 launch sobits_gazebo_worlds random_world.launch.py \
task_command:="Follow Alex in the bedroom." \
object_count:=15In this case the target person is launched with enable_teleop:=true and can be operated via sobits_teleop.
With random_world.launch.py, ROS 2 services are available to delete and regenerate only the randomly placed YCB objects after launch.
You can update the random layout without restarting Gazebo or the robot.
Available services:
| Service | Type | Description |
|---|---|---|
/random_world/regenerate |
std_srvs/srv/Trigger |
Delete the current random objects and regenerate them |
/sobits_gazebo_worlds/change_world |
std_srvs/srv/Trigger |
Same behavior as /random_world/regenerate |
/random_world/clear |
std_srvs/srv/Trigger |
Delete only the current random objects |
Basic usage:
-
First launch a random world.
$ ros2 launch sobits_gazebo_worlds random_world.launch.py
-
Delete all random objects.
$ ros2 service call /random_world/clear std_srvs/srv/Trigger {} -
Generate a new random layout.
$ ros2 service call /random_world/regenerate std_srvs/srv/Trigger {}
/random_world/regenerate targets only the randomly placed YCB objects.
The robot itself, the fixed furniture, and the base world are not deleted.
To regenerate deterministically, change the random_world_manager parameters before calling the service.
$ ros2 param set /random_world_manager seed "123"
$ ros2 param set /random_world_manager object_count 20
$ ros2 service call /random_world/regenerate std_srvs/srv/Trigger {}To return to non-deterministic regeneration:
$ ros2 param set /random_world_manager seed ""Main runtime parameters:
| Parameter | Description |
|---|---|
seed |
Non-deterministic when empty; specify an integer string to reproduce a layout |
object_count |
Number of YCB objects placed on regeneration |
pause_physics_during_reconfigure |
Whether to pause physics during deletion/re-spawning |
Important
This runtime-regeneration feature assumes that random_world.launch.py is running.
ros2 launch sobit_home_bringup gz_minimal.launch.py and ros2 launch sobits_gazebo_worlds random_world.launch.py both start Gazebo, so do not use them on the same simulation at the same time.
Note
To use the same feature on the gz_minimal.launch.py side, you need to add bridges for /world/<world_name>/create, /remove, and /control, plus random_world_manager.py, against the existing Gazebo instance.
How to create a new world.
[TODO] Make it easy to place furniture through a GUI.
Placement areas are specified in YAML files under config/placement.
Example:
placement_areas:
- name: living_room#long_table
edge_margin: 0.08
min_object_spacing: 0.13
- name: study_room#shelf
surface_name: plate1
# allowed_categories: [kitchen_item]
edge_margin: 0.05
min_object_spacing: 0.10The main keys are as follows.
| Key | Description |
|---|---|
name |
Furniture include name in the world |
surface_name |
Surface name used for shelves etc.; defaults to top if unspecified |
edge_margin |
Safety margin [m] excluded from the furniture edge |
min_object_spacing |
Minimum distance [m] between objects on the same surface |
allowed_categories |
Allowed YCB categories; all categories if unspecified |
selection_weight |
Weight that makes a surface more likely to be chosen |
max_objects |
Maximum number of objects that can be placed on the surface |
You usually do not need to write size or z.
They are estimated automatically from the furniture's model.sdf and its pose in the world.
Launch with the YAML you created.
$ ros2 launch sobits_gazebo_worlds random_world.launch.py \
base_world:=/home/rg-station-03/colcon_ws/src/sobits_gazebo_worlds/worlds/rcjo2025_arena.world.xacro \
placement_config:=/home/rg-station-03/colcon_ws/src/sobits_gazebo_worlds/config/placement/rcjo2025_arena.yaml \
object_count:=20 \
human_count:=2Human models are automatically sampled from the free area on the floor_plane and placed so they do not overlap furniture.
People added by GPSR tasks are likewise placed around the target room while avoiding collisions.
World files live in worlds/ and furniture models in models/.
Worlds are written as .world.xacro and can be launched directly (fixed layout) or fed to
the random-placement launch as a base world. The models fall into two families:
- Legacy / shared models (unprefixed) such as
long_table,tall_table,dining_table,shelf,sofa,bed,kachaka_shelf— used by the older arenas and by the random-placement system. - Real-furniture GLB models (
rcw26_*) — embedded-texture GLB meshes scaled to real-world dimensions, described below.
Furniture with defined placement surfaces (used by the random-placement system):
long_tabletall_tabledining_tablecountershelftopplate1plate2plate3
Notes:
- When a furniture surface is defined as a
boxshape, its size is estimated automatically. - Some mesh furniture such as
sofa/bed/kachaka_shelfuses a conservative internal footprint for human spawning.
The source GLBs live in real_furniture/ (untracked). To add one:
- Fix the GLB so it renders in Gazebo ogre2. Raw GLBs from the source set are broken
three ways and must all be fixed (edit in place with
pygltflib, nottrimesh, which rescales the geometry to a cube):- Add per-vertex
NORMAL— without normals there is no lighting and the mesh renders black. - Set
metallicFactor = 0— a fully-metallic surface with no environment map renders black. - Add a texture sampler (and strip
baseColorFactor/emissiveFactor/alphaMode, setdoubleSided=true) — without a sampler the texture is not bound and the mesh renders white.
- Add per-vertex
- Package it as
models/rcw26_<name>/withmodel.config,model.sdf, andmeshes/<name>.glb. GLBs are Y-up and unit-normalized, somodel.sdfappliesroll=1.5708(Y-up -> Z-up) and a uniform<scale> = target_height / GLB_Y_extent, with the collision/visual raised byheight/2to rest on the floor. - Reference it in a world with
<uri>model://rcw26_<name></uri>.
Note
For the floor, include the existing wrc_ground_plane model rather than authoring a
custom plane — its material carries the <diffuse> term that makes the wood texture
render (a bare <plane> + albedo_map renders black).
- Random YCB placement on top of fixed furniture
- Human-model spawning via
gz_human_sim - GUI-based furniture placement editing
See the Issues page to check current bugs and feature requests.
