Skip to content

ROS 2 Migration: Spawn and delete

chapulina edited this page Aug 14, 2019 · 9 revisions


In ROS 1, services for spawning and deleting models and lights into simulation were provided by the gazebo_ros_api_plugin. In ROS 2, this feature is provided by the gazebo_ros_factory plugin.

Read more about the migration of gazebo_ros_api_plugin at ROS 2 Migration: gazebo_ros_api_plugin.


  • All spawn and delete service topics and messages have been renamed to better reflect the functionality, by including the word "entity", which encompasses both models and lights in Gazebo.

  • There are no longer two separate services to spawn SDF and URDF files. Both are handled by the same service.

  • In ROS 1, the model_name field was required in the SpawnModel service. In ROS 2, the name field is optional:

    • If set, the service will fail to spawn an entity if there's already an entity with this name
    • If not set, the service won't check whether the name is already used. In case it is, Gazebo will automatically append numbers to the entity name.
  • In ROS 1, there were two separate services for deleting models and lights, which called the same Gazebo service under the hood. In ROS 2, deleting both models and lights can be done with the same service.

Service names spawn_sdf_model spawn_entity
spawn_urdf_model spawn_entity
delete_model delete_entity
delete_light delete_entity
Service types gazebo_msgs/SpawnModel gazebo_msgs/SpawnEntity
gazebo_msgs/DeleteModel gazebo_msgs/DeleteEntity
gazebo_msgs/DeleteLight gazebo_msgs/DeleteEntity
Fields model_name name (optional)
light_name name (optional)
model_xml xml
robot_namespace (optional) robot_namespace (optional)
initial_pose (optional) initial_pose (optional)
reference_frame (optional) reference_frame (optional)

Example usage

First, run Gazebo with the plugin:

gazebo --verbose -s

Spawn SDF models

Now call the spawn service from the command line, for example, to spawn a static SDF model:

ros2 service call /spawn_entity 'gazebo_msgs/SpawnEntity' '{name: "sdf_ball", xml: "<?xml version=\"1.0\" ?><sdf version=\"1.5\"><model name=\"will_be_ignored\"><static>true</static><link name=\"link\"><visual name=\"visual\"><geometry><sphere><radius>1.0</radius></sphere></geometry></visual></link></model></sdf>"}'

Spawn SDF lights

To spawn an SDF light, try for example:

ros2 service call /spawn_entity 'gazebo_msgs/SpawnEntity' '{name: "bulb", xml: "<?xml version=\"1.0\" ?><sdf version=\"1.5\"><light name=\"will_be_ignored\" type=\"directional\"></light></sdf>"}'

Spawn URDF robot

Now try this URDF robot:

ros2 service call /spawn_entity 'gazebo_msgs/SpawnEntity' '{name: "urdf_ball", xml: "<?xml version=\"1.0\" ?><robot name=\"will_be_ignored\"><link name=\"link\"><visual><geometry><sphere radius=\"1.0\"/></geometry></visual><inertial><mass value=\"1\"/><inertia ixx=\"1\" ixy=\"0.0\" ixz=\"0.0\" iyy=\"1\" iyz=\"0.0\" izz=\"1\"/></inertial></link></robot>"}'

name field when spawning

Notice that since the name field was set in all examples above, the entity's name in the XML description (will_be_ignored) is always ignored.

Let's try to spawn another model without setting the name field. Run the following command a few times:

ros2 service call /spawn_entity 'gazebo_msgs/SpawnEntity' '{xml: "<?xml version=\"1.0\" ?><sdf version=\"1.5\"><model name=\"another_model\"><static>true</static><link name=\"link\"><visual name=\"visual\"><geometry><sphere><radius>1.0</radius></sphere></geometry></visual></link></model></sdf>"}'

You'll see that the first model spawned is called another_model, and subsequent ones are called another_model_0, another_model_1, etc.

robot_namespace field when spawning

Just like in ROS 1, in ROS 2 the service provides the option of adding / changing the ROS namespace for all gazebo_ros-powered plugins in the entity being spawned.

However, note that while the convention in ROS 1 was to have a <robotNamespace> tag under <plugin>, in ROS 2, a <ros><namespace> tag is added instead.

This change shouldn't affect developers who are calling the service, but it may affect plugin developers who are relying on the <robotNamespace> tag in their own plugins. When porting your plugins to ROS 2, be sure to let gazebo_ros::Node handle the namespace for you and remove code that expects <robotNamespace>.

Delete models

You can delete the ground plane model, for example, as follows:

ros2 service call /delete_entity 'gazebo_msgs/DeleteEntity' '{name: "ground_plane"}'

Delete lights

You can delete the sun light, for example, as follows:

ros2 service call /delete_entity 'gazebo_msgs/DeleteEntity' '{name: "sun"}'

Implementation details

  • The ROS 1 version of the spawn service relied on a lot of custom code which used TinyXml to parse SDF and URDF files and update their values before sending a Gazebo factory message. The ROS 2 version is significantly shorter because it leverages the SDFormat library's parser to load both SDF and URDF files and manipulate their values.

Spawn Entity Node

In ROS1, gazebo_ros provided a node spawn_model to spawn a model in Gazebo. In ROS2, similar functionalities are offered by Model has been renamed to Entity as SpawnModel service has been renamed to SpawnEntity


  • urdf or sdf arguments are no longer required.
  • Functionalities of set_model_configuration and DeleteEntity on shutdown are not supported currently.
  • unpause requires the gazebo_ros_init plugin to be loaded.


urdf :x:
sdf :x:
model entity
joints not supported currently
bond not supported currently
wait won't work until model_states is ported

All other arguments remain the same. Only the default value of gazebo_namespace has been changed from gazebo to empty.

Example Migration


rosrun gazebo_ros spawn_model -model mymodel -urdf -x 0 -y 0 -z 0 -file /path/to/model/file 


ros2 run gazebo_ros -entity myentity -x 0 -y 0 -z 0 -file /path/to/entity/file

Other examples

From sdtin

cat /path/to/entity/file | ros2 run gazebo_ros -entity new_model -x 0 -y 0 -z 0 -stdin

From the model database

ros2 run gazebo_ros -entity TheArm -x 10 -y 10 -z 10 -R 0.1 -P 0.2 -Y 0.3 -database simple_arm

From a topic

First start the spawn node. It will wait until there are messages on the topic:

ros2 run gazebo_ros -entity a_ball -topic /robot_description

Publish a message with the robot description:

ros2 topic pub -1 --qos-durability transient_local /robot_description 'std_msgs/String' '{data: "<?xml version=\"1.0\" ?><robot name=\"will_be_ignored\"><link name=\"link\"><visual><geometry><sphere radius=\"1.0\"/></geometry></visual><inertial><mass value=\"1\"/><inertia ixx=\"1\" ixy=\"0.0\" ixz=\"0.0\" iyy=\"1\" iyz=\"0.0\" izz=\"1\"/></inertial></link></robot>"}'
You can’t perform that action at this time.