water_cannon_plugin is a Gazebo Harmonic (gz-sim8) model system plugin
that represents a water stream as a sequence of physical spherical droplets.
Each droplet has collision geometry, water-density inertia, and gravity. It is
spawned at a configurable offset from a nozzle link and launched along that
link's local +X axis. The droplet also inherits the nozzle's linear velocity
at the spawn point.
The plugin does not model fluid flow, splashes, or target scoring. Its output is a stream of short-lived rigid bodies.
The plugin is attached to the model that owns the nozzle link. Set
nozzle_link to the link from which water should be fired, and orient that
link so its local +X axis points out of the nozzle.
<model name="my_robot">
<!-- Other links and joints... -->
<link name="water_nozzle_link">
<!-- Put the link frame at the nozzle, with +X pointing outward. -->
</link>
<plugin filename="WaterCannonSystem"
name="water_cannon::WaterCannonSystem">
<nozzle_link>water_nozzle_link</nozzle_link>
<muzzle_velocity>8.0</muzzle_velocity>
<fire_rate>10.0</fire_rate>
<droplet_radius>0.025</droplet_radius>
<droplet_lifetime>10.0</droplet_lifetime>
<spawn_offsetx>0.10</spawn_offsetx>
<spawn_offsety>0.0</spawn_offsety>
<spawn_offsetz>0.0</spawn_offsetz>
</plugin>
</model>The plugin element belongs directly under <model>, not under <link>.
nozzle_link is how the plugin selects the link to follow. Use a positive
spawn_offsetx large enough to place a new droplet beyond the nozzle's
collision geometry.
All distances are in metres and simulation time is in seconds.
| Element | Default | Meaning |
|---|---|---|
nozzle_link |
nozzle_link |
Name of the link whose pose and velocity define the nozzle. |
muzzle_velocity |
8.0 |
Launch speed along the nozzle link's local +X axis, in m/s. May be zero. |
fire_rate |
10.0 |
Requested droplet frequency in simulation time, in Hz. At most one droplet is spawned per simulation update. |
droplet_radius |
0.025 |
Radius of each spherical droplet. |
droplet_lifetime |
10.0 |
Time before a spawned droplet is removed. |
spawn_offsetx |
0.0 |
Spawn offset along the nozzle link's local X axis. |
spawn_offsety |
0.0 |
Spawn offset along the nozzle link's local Y axis. |
spawn_offsetz |
0.0 |
Spawn offset along the nozzle link's local Z axis. |
All numeric values must be finite. muzzle_velocity must be non-negative;
fire_rate, droplet_radius, and droplet_lifetime must be greater than zero.
Invalid startup configuration prevents the cannon from loading.
The cannon starts disabled. There is intentionally no startup enabled SDF
element; enable it through the Gazebo Transport service after the simulation
starts.
For a model named my_robot, the plugin advertises:
/model/my_robot/water_cannon/enable
Enable firing with:
gz service -s /model/my_robot/water_cannon/enable \
--reqtype gz.msgs.Param \
--reptype gz.msgs.Boolean \
--timeout 2000 \
--req 'params { key: "enabled" value { type: BOOLEAN bool_value: true } }'Disable it by sending the same request with bool_value: false.
The same service can update firing parameters while the simulation is running:
gz service -s /model/my_robot/water_cannon/enable \
--reqtype gz.msgs.Param \
--reptype gz.msgs.Boolean \
--timeout 2000 \
--req '
params { key: "enabled" value { type: BOOLEAN bool_value: true } }
params { key: "muzzle_velocity" value { type: DOUBLE double_value: 12.0 } }
params { key: "fire_rate" value { type: DOUBLE double_value: 20.0 } }
params { key: "droplet_radius" value { type: DOUBLE double_value: 0.02 } }
params { key: "droplet_lifetime" value { type: DOUBLE double_value: 5.0 } }
params { key: "spawn_offsetx" value { type: DOUBLE double_value: 0.15 } }
params { key: "spawn_offsety" value { type: DOUBLE double_value: 0.0 } }
params { key: "spawn_offsetz" value { type: DOUBLE double_value: 0.0 } }
'Every request field is optional; omitted values keep their current setting.
nozzle_link cannot be changed at runtime. Runtime numeric values follow the
same validation rules as SDF values, and an invalid field rejects the whole
request. Radius changes affect newly spawned droplets, while lifetime changes
also affect droplets that already exist.
Build the package with your ROS 2 workspace, then source that workspace before starting Gazebo:
colcon build --packages-select water_cannon_plugin
source install/setup.bashSourcing is required because the package's environment hook adds its installed
library directory to GZ_SIM_SYSTEM_PLUGIN_PATH. Without that hook, Gazebo may
report that it cannot find WaterCannonSystem.

