https://github.com/uos/rmagine_gazebo_plugins
Ray Casting-Based Range Sensor Simulation in Gazebo using Rmagine
https://github.com/uos/rmagine_gazebo_plugins
gazebo intel-embree nvidia-optix nvidia-rtx ouster raytracing ros velodyne
Last synced: 5 months ago
JSON representation
Ray Casting-Based Range Sensor Simulation in Gazebo using Rmagine
- Host: GitHub
- URL: https://github.com/uos/rmagine_gazebo_plugins
- Owner: uos
- License: bsd-3-clause
- Created: 2022-10-03T12:25:20.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-06-15T10:08:44.000Z (about 1 year ago)
- Last Synced: 2025-06-15T11:21:29.145Z (about 1 year ago)
- Topics: gazebo, intel-embree, nvidia-optix, nvidia-rtx, ouster, raytracing, ros, velodyne
- Language: C++
- Homepage:
- Size: 861 KB
- Stars: 21
- Watchers: 7
- Forks: 1
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[[Code](https://github.com/uos/rmagine_gazebo_plugins)] [[Wiki](https://github.com/uos/rmagine_gazebo_plugins/wiki)]
> [!IMPORTANT]
> Requires: Gazebo Classic, ROS 2 (Humble)
# rmagine_gazebo_plugins (WIP)
Range sensor plugins for Gazebo using the sensor simulation library [rmagine](https://github.com/uos/rmagine).
With rmagine's OptiX backend it is possible to simulate depth sensor data directly on your RTX graphics card. With Embree backend you can simulate any provided sensor online on your CPU.
Embree and OptiX are libraries for raytracing and build BVH acceleration structures on the scene for faster ray traversals.
After building these acceleration structures, you can simulate depth sensors on CPU or GPU without getting perfomance issues even in large Gazebo worlds.
Youtube-Video:
## Examples
After compiling
### `example.launch.xml`
```console
ros2 launch rmagine_gazebo_plugins example.launch.xml
```
Simulates a 3d lidar at 20hz on Embree backend.
To use OptiX backend, run
```console
ros2 launch rmagine_gazebo_plugins example.launch.xml rmagine:=optix
```
Open RViz set fixed frame to `base_footprint` and visualize topic `laser3d/pcl`.
### `rotating_scanner.launch.xml`
```console
ros2 launch rmagine_gazebo_plugins rotating_laser.launch.xml
```
or with OptiX backend
```console
ros2 launch rmagine_gazebo_plugins rotating_laser.launch.xml rmagine:=optix
```
Open RViz set fixed frame to `base_footprint` and visualize topic `laser2d/scan`.
In Gazebo-GUI find the `laser2d` link at model `robot_sensor`.
To let the scanner rotate go to Gazebo-GUI:
1. Right-click on the `laser2d` link at model `robot_sensor`
2. Click "Apply Force/Torque"
3. Set Torque to y=0.5
4. Click "Apply Torque"
Now the scanner cylinder should rotate in Gazebo as well as in RViz.
## Usage
### 1. Installatio
#### Rmagine
Follow instructions of Rmagine library installation. Compile with Embree or OptiX backends for CPU or GPU support respectively.
You can clone rmagine into your ROS workspace's src folder: `colcon_ws/src`.
#### Compilation
Clone this repository to your ROS workspace (src folder), `colcon_ws/src`:
```console
git clone git@github.com:uos/rmagine_gazebo_plugins.git
```
In `colcon_ws` folder compile with
```console
colcon build
```
Depending on which backends were installed during Rmagine installation the following plugins are built:
1. Embree
- World-Plugins: `rmagine_embree_map_gzplugin`
- Sensor-Plugins: `rmagine_embree_spherical`
2. OptiX
- World-Plugins: `rmagine_optix_map_gzplugin`
- Sensor-Plugins: `rmagine_optix_spherical`
### 2. Sensor Registration
The rmagine sensors are implemented as new gazebo sensors. They need to be registered first. To do that, you need to add `librmagine_embree_sensors_gzregister.so` or `librmagine_optix_sensors_gzregister.so` to the arguments of the gazebo execution call.
**Embree Example**
1. Gazebo executable:
```console
gazebo -s librmagine_embree_sensors_gzregister.so
```
2. ROS 2 launch file
```xml
```
> [!NOTE]
> See launch files in this repository for more details.
### 3. Map Plugins
Embree sensor plugins require one Embree map plugin running.
OptiX sensor plugins require one OptiX map plugin running.
In world-files the map plugins can be enabled as follows:
```xml
...
```
The map plugins construct a acceleration structure over the Gazebo scene.
As soon as the gazebo scene changes, the acceleration structure is updated accordingly.
Some other examples are located in the worlds folder.
To increase the performance sdf entities can be marked to be ignored by the map plugins.
For example, if you know that your 3D lidar never scans the robot it is attached to, you may consider excluding the entire robot of the map plugins.
To achieve that in world-files just add an `rmagine_ignore` tag to the model:
```xml
...
...
...
```
How to add ignores in urdf-files will be explained in the next section.
### 4. Sensors
**2D Laser**
```xml
0 0 0 0 0 0
true
60
${-M_PI}
${1.0 * M_PI / 180.0}
360
0.0
10.0
gaussian
0.0
0.01
```
**3D Laser**
```xml
0 0 0 0 0 0
true
60
${-M_PI}
${1.0 * M_PI / 180.0}
360
${-60.0 * M_PI / 180.0}
${1.0 * M_PI / 180.0}
120
0.0
80.0
gaussian
0.0
0.01
```
As in world-files, ignores can be added to URDF files:
```xml
...
```
### 5. Noise
Currently noise models are implemented as preprocessing steps directly on the simulated ranges data. Any of the following noise models can be chained to generate complex combined noise models.
1. Gaussian Noise
Apply gaussian noise $N(\mu, \sigma)$ to simulated ranges.
| Parameter | Description |
|:---------:|:-------------:|
| `mean` | Mean $\mu$ of normal distributed noise |
| `stddev` | standard deviation $\sigma$ of normal distributed noise |
Example:
```xml
gaussian
0.0
0.01
```
2. Relative Gaussian Noise
Apply gaussian noise $N(\mu, \sigma_r)$ to simulated ranges. Here, the standard deviation varies depending on distance.
| Parameter | Description |
|:---------:|:-------------:|
| `mean` | Mean $\mu$ of normal distributed noise |
| `stddev` | standard deviation $\sigma$ of normal distributed noise |
| `range_exp` | range exponent $c$ to compute range based stddev: $ \sigma_r = \sigma \cdot r^{c} $ |
Example:
```xml
rel_gaussian
0.0
0.002
1.0
```
3. Uniform Dust Noise
Apply uniform dust noise to simulated ranges. Assuming some small particles could be hit by the range sensor that are not modeled by the scene, use this noise type.
Parameters:
| Parameter | Description |
|:---------:|:-------------:|
| `hit_prob` | Probability of a ray hitting a particle in one meter free space. |
| `return_prob` | Probability of a ray hitting dust returns to sender depending on particle distance |
Example:
```xml
uniform_dust
0.0000001
0.5
```
**Noise Chaining**
Example of using the gaussian model first and the uniform dust model second:
```xml
gaussian
0.0
0.002
uniform_dust
0.0000001
0.5
```
## ROS Plugin
This plugin generates ROS-messages of the simulated data and writes them to specified ROS-topics.
The following ROS-Adapter are available dependend on your sensor type:
`librmagine_optix_ros_gzplugin.so`
- sensor types: `rmagine_optix_spherical`
`librmagine_embree_ros_gzplugin.so`
- sensor types: `rmagine_embree_spherical`
Supported `output` messages are:
- `sensor_msgs/msg/LaserScan`
- `sensor_msgs/msg/PointCloud`
- `sensor_msgs/msg/PointCloud2`
Examples - this time using OptiX.
**2D Laser**
```xml
0 0 0 0 0 0
true
60
${-M_PI}
${1.0 * M_PI / 180.0}
360
0.0
10.0
gaussian
0.0
0.01
laser2d
sensor_msgs/LaserScan
laser2d/scan
sensor_msgs/PointCloud
laser2d/pcl
```
**3D Laser**
```xml
0 0 0 0 0 0
true
60
${-M_PI}
${1.0 * M_PI / 180.0}
360
${-60.0 * M_PI / 180.0}
${1.0 * M_PI / 180.0}
120
0.0
80.0
gaussian
0.0
0.01
laser3d
sensor_msgs/PointCloud
laser3d/pcl
sensor_msgs/PointCloud2
laser3d/pcl2
```
## Work in Progress
This is a pre-release. There is still some work to do for the first stable release:
- Implemented: SphericalModel. TODO: PinholeModel, O1DnModel, OnDnModel
- Tests: More tests on different devices. Let me know, if you had problems integrating the rmagine_gazebo_plugins into your project.
Nice-to-Have:
- Add segmenting functionallity: Store labeled sensor data from a list of poses in a commonly used file format
Known Issues:
- Sometimes the Gazebo simulation needs to be started twice in order to get everything started (blocking threads?)
- "Core dumped" on exit:
```bash
[Dbg] [rmagine_embree_map_gzplugin.cpp:52] [RmagineEmbreeMap] Destroyed.
terminate called after throwing an instance of 'boost::wrapexcept'
terminate called recursively
what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
Aborted (core dumped)
```
### Known Bug-Fixes:
On my system, Gazebo finds all rmagine libraries automatically. If that is not the case for you, try appending your ROS workspace `your_ws` to the Gazebo search pathes:
```console
export GAZEBO_PLUGIN_PATH=~/your_ws/devel/lib:$GAZEBO_PLUGIN_PATH
```