A Gazebo system plugin for simulating LEDs using visuals and lights. Define LED modes (blinking patterns, colors, intensity) in SDF and switch between them at runtime via a Gazebo Transport topic (bridgable with ROS 2).
Demo from led_plugin.sdf — 2 robots and a tower lamp with different LED groups/modes.
Demo from dance_party.sdf — a disco light model for a dance party.
The Tom model is from Sketchfab, animated with Mixamo/Blender. Also on Gazebo Fuel.
- Visual + Light LEDs: Define LEDs using visuals, lights, or both
- Named modes: Describe LED behaviors (idle, warning, emergency, etc.) with multi-step sequences
- Selective activation: Modes can target specific LEDs via
<active_leds>or all LEDs by default - Always-on support: Static LED states via
always_on="true" - Runtime mode switching: Change modes via a Gazebo Transport topic (ROS 2 bridgable)
- Reset/Off: Send
"reset"or"off"to turn all LEDs to default state - Case-insensitive: Mode name matching is case-insensitive
Requirements: Gazebo Harmonic+, Ubuntu 24.04, colcon
cd your_workspace_dir
git clone https://github.com/jasmeet0915/gz_sim_led_plugin.git src/gz_led_plugin
colcon build --packages-select gz_led_plugin
source install/setup.bashRun examples:
gz sim -v 4 src/gz_led_plugin/examples/gazebo/led_plugin.sdf
# or
gz sim -v 4 src/gz_led_plugin/examples/gazebo/dance_party.sdfFrom the led_plugin.sdf tower lamp model:
<plugin name="led" filename="libLedPlugin.so">
<led_group_name>tower_lamp</led_group_name>
<led name="emergency_led">
<visual_name>lamp_red::lamp_red_visual</visual_name>
<light_name>lamp_red::emergency_light</light_name>
<default_state>
<color>0.3 0.0 0.0 1</color>
<intensity>0.0</intensity>
</default_state>
</led>
<led name="ready_led">
<visual_name>lamp_green::lamp_green_visual</visual_name>
<light_name>lamp_green::ready_light</light_name>
<default_state>
<color>0.0 0.3 0.0 1</color>
<intensity>0.0</intensity>
</default_state>
</led>
<startup_mode>ready</startup_mode>
<mode name="ready">
<active_leds>
<led>ready_led</led>
</active_leds>
<step always_on="false">
<color>0.0 1.0 0.0 1</color>
<intensity>2.0</intensity>
<on_time>1.0</on_time>
</step>
<step always_on="false">
<color>0.0 0.3 0.0 1</color>
<intensity>0.0</intensity>
<on_time>1.0</on_time>
</step>
</mode>
<mode name="emergency">
<active_leds>
<led>emergency_led</led>
</active_leds>
<step always_on="false">
<color>1.0 0.0 0.0 1</color>
<intensity>2.0</intensity>
<on_time>1.0</on_time>
</step>
<step always_on="false">
<color>0.3 0.0 0.0 1</color>
<intensity>0.0</intensity>
<on_time>1.0</on_time>
</step>
</mode>
</plugin>| Element | Description |
|---|---|
<led_group_name> |
Namespace for the mode change topic. Defaults to led_{model_name} |
<led name="..."> |
Define an LED with <visual_name>, <light_name>, and optional <default_state> |
<startup_mode> |
Mode to activate on startup. Defaults to first defined mode |
<mode name="..."> |
Named mode with optional <active_leds> and one or more <step> elements |
<step> |
always_on (attr), <color>, <intensity>, <on_time> (seconds) |
Gazebo CLI (publish to topic):
gz topic -t /tower_lamp/change_led_mode -m gz.msgs.StringMsg -p "data: 'emergency'"Reset/turn off LEDs:
gz topic -t /tower_lamp/change_led_mode -m gz.msgs.StringMsg -p "data: 'off'"ROS 2 (via ros_gz_bridge):
Bridge the topic (see example launch file):
Node(
package='ros_gz_bridge',
executable='parameter_bridge',
arguments=['/led_robot/change_led_mode@std_msgs/msg/String]gz.msgs.StringMsg'],
)Then publish from ROS 2:
ros2 topic pub --once /led_robot/change_led_mode std_msgs/msg/String "{data: 'emergency'}"Two things to keep in mind when using this plugin with URDF:
URDF-to-SDF conversion merges links connected by fixed joints into a single link by default. Add this for your fixed joint you want to preserve:
<gazebo reference="top_to_front_led_joint">
<preserveFixedJoint>true</preserveFixedJoint>
</gazebo>The URDF→SDF conversion appends _visual and _collision suffixes to visual and collision names. So if your URDF visual is named back_led_visual, the SDF name becomes back_led_visual_visual. Account for this in the plugin config:
<!-- URDF has: <visual name="back_led_visual"> -->
<!-- SDF converts to: back_led_visual_visual -->
<led name="back_led">
<visual_name>back_led::back_led_visual_visual</visual_name>
</led>Note: An issue is up for this over at the sdformat repo.
See the ROS example URDF and its gazebo xacro for a complete working example.
For an in-depth guide on this plugin and Gazebo system plugins in general:
Apache License 2.0 — see LICENSE.
Jasmeet Singh — jasmeet0915@gmail.com