A minimal, self-contained Gazebo Sim (Ignition) system plugin used for learning how to build, compile, and integrate custom systems in Gazebo Sim 8.
This serves as a clean template for future WE-Autopilot simulation work (vehicle dynamics, controllers, sensor models, etc.).
This repo demonstrates how to:
- Create a Gazebo System Plugin in C++
- Load it through an SDF world
- Pass parameters (e.g.
<model_name>) - Access a model’s pose via the EntityComponentManager
- Print simulation data at 1 Hz
Project layout: . ├── src/ │ └── SampleSystem.cc # The plugin source code ├── worlds/ │ └── minimal.world # Test world that loads the plugin ├── CMakeLists.txt # Build configuration ├── .gitignore ├── README.md └── (optional) .vscode/ # VS Code build/run setup
- Ubuntu 22.04 LTS or Ubuntu 24.04 LTS
sudo apt update
sudo apt install -y build-essential cmake git ninja-buildOnce all dependencies are installed and your ROS 2 Jazzy environment is sourced, you can build the plugin.
From the repository root directory:
cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build -jThis will configure CMake, compile the plugin, and output a shared library file:
build/libSampleSystem.soIf you edit the source code (src/SampleSystem.cc) or CMakeLists.txt, just rebuild:
cmake --build build -jTo remove all compiled artifacts and start fresh:
rm -rf buildOnce the plugin has been successfully built, it can be loaded and tested inside Gazebo Sim 8.
Gazebo needs to know where the compiled shared library (.so file) is located.
From the repository root, run:
export GZ_SIM_SYSTEM_PLUGIN_PATH="$(pwd)/build"This command must be run in every new terminal session before launching Gazebo, unless you add it to your .bashrc.
Run the following command to open the sample world and start the simulation:
gz sim worlds/minimal.world -r -v 4Flags explained: -r → starts the simulation immediately (unpaused) -v 4 → enables detailed log output
If the simulation GUI opens in a paused state, press
If everything is set up correctly, you should see output similar to this in your terminal:
[Msg] [SampleSystem] model_name = car
[Msg] [SampleSystem] Found model 'car' entity=123
[Msg] [SampleSystem] t=1.0 pose=[0 0 0.5 | 0 0 0]This confirms that: The plugin was loaded successfully. The <model_name> parameter was read correctly. The system is running and printing the model pose every second.
If you close the terminal or reboot, remember to re-run:
source /opt/ros/jazzy/setup.bash
export GZ_SIM_SYSTEM_PLUGIN_PATH="$(pwd)/build"
gz sim worlds/minimal.world -r -v 4The SampleSystem plugin demonstrates the basic structure of a Gazebo System Plugin.
A system plugin runs inside the Gazebo simulation loop and interacts with entities (models, links, sensors, etc.) through the Entity Component Manager (ECM).
The plugin defines a C++ class that inherits from the following Gazebo interfaces:
| Interface | Purpose |
|---|---|
ISystemConfigure |
Called once when the world loads. Used to read parameters (e.g. <model_name>) or initialize variables. |
ISystemPostUpdate |
Called after every physics update. Used to read data (like poses, velocities, etc.) or log output. |
Example registration macro:
GZ_ADD_PLUGIN(sample_system::SampleSystem,
gz::sim::System,
sample_system::SampleSystem::ISystemConfigure,
sample_system::SampleSystem::ISystemPostUpdate)This tells Gazebo to load SampleSystem as a plugin and connect it to the simulation update cycle. 5.2 Main functions Configure(): Runs once when the simulation starts. Reads the <model_name> parameter from the world SDF file. Searches the world for an entity (model) with that name.
PostUpdate(): Runs every simulation tick (after physics update). Once the model is found, it reads and prints the model’s current pose. The output is throttled to once per second to avoid flooding the console.
When Gazebo loads the world: The plugin reads the model name (car) from the SDF. It finds the corresponding model entity in the simulation. Every simulated second, it prints the model’s position and orientation to the terminal.
This verifies that: The plugin is properly compiled and registered. Gazebo is calling your plugin each frame. Communication between the plugin and simulation entities is working correctly.
Below are the most frequent issues encountered when building or running Gazebo system plugins, along with their causes and solutions.
| Error Message | Cause | Fix |
|---|---|---|
Unknown CMake command "gz_find_package" |
Gazebo’s CMake utilities are not included. | Make sure the following line exists in your CMakeLists.txt:find_package(gz-cmake3 REQUIRED)Also ensure your ROS 2 environment is sourced: source /opt/ros/jazzy/setup.bash |
Could NOT find gz-sim8 |
Missing Gazebo Sim development libraries. | Install them with:sudo apt install libgz-sim8-dev libgz-common5-dev libgz-plugin2-dev libgz-cmake3-dev |
CMake Error: No CMakeLists.txt found |
You’re running cmake from the wrong directory. |
Run build commands from the project root:cmake -S . -B build |
Undefined reference to gz::sim |
Mismatch between plugin version and Gazebo version. | Update CMakeLists.txt to explicitly use:find_package(gz-sim8 REQUIRED) |
| Error Message | Cause | Fix |
|---|---|---|
Failed to load system plugin ... Could not find shared library |
Gazebo can’t locate your compiled .so file. |
Export your plugin path before launching Gazebo:export GZ_SIM_SYSTEM_PLUGIN_PATH=$(pwd)/build |
Segmentation fault |
Plugin not properly linked or model not found. | Ensure the <model_name> in your world file matches an actual model name in the simulation. |
No console output |
Simulation paused by default. | Add -r to your gz sim command, or click |
Failed to resolve plugin name |
Typo in plugin name or registration macro. | Check your plugin name in both:SampleSystem.cc (inside GZ_ADD_PLUGIN) and in the SDF world file. |
Could not open a connection to your authentication agent |
SSH agent not active when pushing code. | Start it manually:eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519 |
If the build system becomes inconsistent or you encounter persistent linker errors, reset your build environment:
rm -rf build
cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build -jBefore running gz sim, verify:
source /opt/ros/jazzy/setup.bash export GZ_SIM_SYSTEM_PLUGIN_PATH=$(pwd)/build ls build/libSampleSystem.so