An open API service indexing awesome lists of open source software.

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

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:



Rmagine Gazebo Plugin YT 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
```