# How DART Integrates with Gazebo for Physics Simulation: A Complete Technical Guide

> Learn how DART integrates with Gazebo for advanced physics simulation. This guide details the automated workflow for building and testing DART's latest APIs with gz-physics.

- Repository: [DART: Dynamic Animation and Robotics Toolkit/dart](https://github.com/dartsim/dart)
- Tags: how-to-guide
- Published: 2026-02-28

---

**DART integrates with Gazebo through a runtime-loadable `dartsim` plugin consumed by gz-physics, maintained via an automated workflow that downloads, patches, builds, and tests the integration against DART's latest APIs.**

The Dynamic Animation and Robotics Toolkit (DART) provides optional but fully supported integration with Gazebo, the popular robotics simulator. This integration allows Gazebo to use DART as its physics backend through the gz-physics abstraction layer, enabling accurate rigid-body dynamics and collision detection within Gazebo simulations.

## The Architecture of DART-Gazebo Integration

### Runtime Plugin Loading via gz-physics

Gazebo (version ≥ gz-sim 9) uses **gz-physics** as its physics engine abstraction layer. DART integrates by exposing a `dartsim` plugin that gz-physics loads at runtime. When Gazebo requests physics simulation, gz-physics dynamically loads `libgz-physics-dartsim-plugin` and binds DART's API to Gazebo's simulation loop.

### Backward Compatibility Shims

To maintain binary compatibility with gz-physics, DART retains specific API signatures that would otherwise be deprecated. In [`dart/simulation/world.cpp`](https://github.com/dartsim/dart/blob/main/dart/simulation/world.cpp) at line 189, DART maintains the `CollisionDetector::getType()` method returning `const std::string&` specifically for gz-physics compatibility.

Similarly, DART preserves deprecated solver types like `BoxedLcpConstraintSolver` because gz-physics performs `dynamic_cast` operations on the solver returned by `World::getConstraintSolver()`. These shims are documented in [`docs/onboarding/build-system.md`](https://github.com/dartsim/dart/blob/main/docs/onboarding/build-system.md) (lines 733-785) under the "Gazebo Integration Feature" section.

## The Integration Workflow: From Source to Runtime

The DART repository automates the entire Gazebo integration pipeline through a series of `pixi` tasks defined in [`pixi.toml`](https://github.com/dartsim/dart/blob/main/pixi.toml). This workflow ensures DART 7.0 remains compatible with gz-physics 9.0.0.

### Step 1: Download gz-physics Source

The workflow begins by cloning the upstream gz-physics repository at the specific branch `gz-physics9_9.0.0`. This is handled by the `download-gz` task in [`pixi.toml`](https://github.com/dartsim/dart/blob/main/pixi.toml) (line 1779).

### Step 2: Patch CMake Version Requirements

Before building, DART patches gz-physics to accept DART 7.0. The script [`scripts/patch_gz_physics.py`](https://github.com/dartsim/dart/blob/main/scripts/patch_gz_physics.py) (lines 3-24) modifies the CMake configuration to bump the required DART package version, ensuring the downstream build recognizes the installed DART libraries.

### Step 3: Configure with Vendored Dependencies

The `config-gz` task (line 1815) configures the gz-physics build with a special CMake include file `gz_physics_force_vendor_gtest.cmake`. This forces gz-physics to use its vendored GoogleTest headers rather than system versions, preventing link-time mismatches between DART's testing infrastructure and gz-physics.

### Step 4: Build the DART Plugin

The `build-gz` task (line 1838) compiles `libgz-physics-dartsim-plugin`, linking against the DART libraries produced by the main DART build. This produces the shared library that Gazebo loads at runtime.

### Step 5: Run Integration Tests

The `test-gz` task (line 1851) executes gz-physics' own test suite against the DART plugin. This validates that physics simulation, collision detection, and constraint solving behave correctly through the gz-physics abstraction.

### Step 6: Runtime Loading

At runtime, Gazebo's gz-physics layer searches for the `dartsim` plugin by name. When found, it loads `libgz-physics-dartsim-plugin` and binds DART's `World`, `Skeleton`, and collision detection systems to the Gazebo simulation loop.

## Building the DART Plugin for Gazebo

To reproduce the integration locally, use the automated pixi workflow:

```bash

# Enable the Gazebo integration environment

pixi run -e gazebo download-gz      # Clones gz-physics9_9.0.0

pixi run -e gazebo patch-gz         # Patches CMake for DART 7.0 compatibility

pixi run -e gazebo config-gz        # Configures with vendored gtest

pixi run -e gazebo build-gz         # Builds libgz-physics-dartsim-plugin

pixi run -e gazebo test-gz          # Runs gz-physics test suite

```

For custom plugins that depend on DART within Gazebo, use this CMake pattern:

```cmake
cmake_minimum_required(VERSION 3.16)
project(my_gazebo_dart_plugin)

find_package(DART 7.0 REQUIRED COMPONENTS dynamics io)
find_package(gz-physics REQUIRED)

add_library(my_dart_plugin SHARED src/my_plugin.cpp)
target_link_libraries(my_dart_plugin PRIVATE DART::dart)
gz_add_plugin(my_dart_plugin)

```

## Continuous Integration and Testing

The DART repository validates Gazebo integration through [`.github/workflows/ci_gz_physics.yml`](https://github.com/dartsim/dart/blob/main/.github/workflows/ci_gz_physics.yml). This workflow executes the full pixi task sequence on every pull request, ensuring that changes to DART's API do not break the gz-physics plugin. The CI job specifically tests the plugin at line 72 of the workflow file, running the same `test-gz` command used in local development.

## Summary

- **DART integrates with Gazebo** through a runtime plugin (`libgz-physics-dartsim-plugin`) consumed by gz-physics.
- **Automated workflow** in [`pixi.toml`](https://github.com/dartsim/dart/blob/main/pixi.toml) handles downloading, patching, building, and testing gz-physics against DART 7.0.
- **Backward compatibility** is maintained through specific API shims in [`dart/simulation/world.cpp`](https://github.com/dartsim/dart/blob/main/dart/simulation/world.cpp) and preserved deprecated classes like `BoxedLcpConstraintSolver`.
- **CI validation** occurs via [`.github/workflows/ci_gz_physics.yml`](https://github.com/dartsim/dart/blob/main/.github/workflows/ci_gz_physics.yml) on every pull request.
- **Runtime loading** happens when Gazebo's gz-physics layer dynamically loads the DART plugin and binds it to the simulation loop.

## Frequently Asked Questions

### How does Gazebo load DART as a physics engine?

Gazebo uses gz-physics as an abstraction layer that dynamically loads physics engine plugins at runtime. When configured to use DART, gz-physics searches for and loads `libgz-physics-dartsim-plugin`, which links against DART's libraries and exposes DART's `World`, collision detection, and constraint solving capabilities through the gz-physics API.

### Why does DART maintain deprecated API signatures for Gazebo integration?

DART preserves specific deprecated signatures—such as `CollisionDetector::getType()` returning `const std::string&` and the `BoxedLcpConstraintSolver` class—because gz-physics performs `dynamic_cast` operations and expects specific binary interfaces. These backward-compatibility shims, documented in [`docs/onboarding/build-system.md`](https://github.com/dartsim/dart/blob/main/docs/onboarding/build-system.md), ensure that DART 7.0 remains compatible with existing gz-physics releases without requiring downstream changes.

### What is the purpose of the patch script in the DART-Gazebo integration workflow?

The [`scripts/patch_gz_physics.py`](https://github.com/dartsim/dart/blob/main/scripts/patch_gz_physics.py) script modifies gz-physics' CMake configuration to accept DART 7.0 by bumping the required DART package version. This patching is necessary because upstream gz-physics may specify an older DART version requirement; the script ensures the downstream build recognizes and links against the DART libraries built from the current repository source.

### How can I verify that DART's Gazebo integration works correctly on my system?

You can run the automated integration tests using the pixi workflow defined in [`pixi.toml`](https://github.com/dartsim/dart/blob/main/pixi.toml). Execute `pixi run -e gazebo test-gz` to run gz-physics' full test suite against the DART plugin. This command validates physics simulation, collision detection, and constraint solving through the gz-physics abstraction, ensuring the integration functions correctly with your DART build.