{"id":41633808,"url":"https://github.com/uos/rmagine_gazebo_plugins","last_synced_at":"2026-01-24T14:40:13.109Z","repository":{"id":149904990,"uuid":"544895286","full_name":"uos/rmagine_gazebo_plugins","owner":"uos","description":"Ray Casting-Based Range Sensor Simulation in Gazebo using Rmagine","archived":false,"fork":false,"pushed_at":"2025-06-15T10:08:44.000Z","size":882,"stargazers_count":21,"open_issues_count":3,"forks_count":1,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-06-15T11:21:29.145Z","etag":null,"topics":["gazebo","intel-embree","nvidia-optix","nvidia-rtx","ouster","raytracing","ros","velodyne"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-10-03T12:25:20.000Z","updated_at":"2025-06-15T10:08:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"c116a17c-44e1-4cd0-a887-d668c15c6082","html_url":"https://github.com/uos/rmagine_gazebo_plugins","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/uos/rmagine_gazebo_plugins","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uos%2Frmagine_gazebo_plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uos%2Frmagine_gazebo_plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uos%2Frmagine_gazebo_plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uos%2Frmagine_gazebo_plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uos","download_url":"https://codeload.github.com/uos/rmagine_gazebo_plugins/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uos%2Frmagine_gazebo_plugins/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28729983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gazebo","intel-embree","nvidia-optix","nvidia-rtx","ouster","raytracing","ros","velodyne"],"created_at":"2026-01-24T14:40:12.207Z","updated_at":"2026-01-24T14:40:13.103Z","avatar_url":"https://github.com/uos.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[[Code](https://github.com/uos/rmagine_gazebo_plugins)] [[Wiki](https://github.com/uos/rmagine_gazebo_plugins/wiki)]\n\n\u003e [!IMPORTANT]\n\u003e Requires: Gazebo Classic, ROS 2 (Humble)\n\n# rmagine_gazebo_plugins (WIP)\n\nRange sensor plugins for Gazebo using the sensor simulation library [rmagine](https://github.com/uos/rmagine). \nWith 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.\nEmbree and OptiX are libraries for raytracing and build BVH acceleration structures on the scene for faster ray traversals.\nAfter building these acceleration structures, you can simulate depth sensors on CPU or GPU without getting perfomance issues even in large Gazebo worlds.\n\nYoutube-Video:\n\n\u003cdiv align=\"center\"\u003e\n\u003ca href=\"http://www.youtube.com/watch?feature=player_embedded\u0026v=IOrBxiW0AmY\n\" target=\"_blank\" \u003e\n  \u003cimg src=\"https://i.ytimg.com/vi/IOrBxiW0AmY/maxresdefault.jpg\" \n  alt=\"Rmagine Gazebo Plugin YT Video\" width=\"80%\" style=\"max-width: 500px\" height=\"auto\" border=\"10\" /\u003e\n\u003c/a\u003e\n\u003c/div\u003e\n\n\n\n## Examples\n\nAfter compiling \n\n### `example.launch.xml`\n\n```console\nros2 launch rmagine_gazebo_plugins example.launch.xml\n```\n\nSimulates a 3d lidar at 20hz on Embree backend.  \nTo use OptiX backend, run\n\n```console\nros2 launch rmagine_gazebo_plugins example.launch.xml rmagine:=optix\n```\n\nOpen RViz set fixed frame to `base_footprint` and visualize topic `laser3d/pcl`.\n\n### `rotating_scanner.launch.xml`\n\n```console\nros2 launch rmagine_gazebo_plugins rotating_laser.launch.xml\n```\n\nor with OptiX backend\n\n```console\nros2 launch rmagine_gazebo_plugins rotating_laser.launch.xml rmagine:=optix\n```\n\nOpen RViz set fixed frame to `base_footprint` and visualize topic `laser2d/scan`.\nIn Gazebo-GUI find the `laser2d` link at model `robot_sensor`.\nTo let the scanner rotate go to Gazebo-GUI:\n1. Right-click on the `laser2d` link at model `robot_sensor`\n2. Click \"Apply Force/Torque\"\n3. Set Torque to y=0.5 \n4. Click \"Apply Torque\"\n\nNow the scanner cylinder should rotate in Gazebo as well as in RViz.\n\n\n## Usage\n\n### 1. Installatio\n\n#### Rmagine\n\nFollow instructions of Rmagine library installation. Compile with Embree or OptiX backends for CPU or GPU support respectively.\nYou can clone rmagine into your ROS workspace's src folder: `colcon_ws/src`.\n\n#### Compilation\nClone this repository to your ROS workspace (src folder), `colcon_ws/src`:\n\n```console\ngit clone git@github.com:uos/rmagine_gazebo_plugins.git\n```\n\nIn `colcon_ws` folder compile with\n\n```console\ncolcon build\n```\n\nDepending on which backends were installed during Rmagine installation the following plugins are built:\n\n1. Embree\n    - World-Plugins: `rmagine_embree_map_gzplugin`\n    - Sensor-Plugins: `rmagine_embree_spherical`\n2. OptiX\n    - World-Plugins: `rmagine_optix_map_gzplugin`\n    - Sensor-Plugins: `rmagine_optix_spherical`\n\n\n### 2. Sensor Registration\n\nThe 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.\n\n\n**Embree Example**\n\n1. Gazebo executable:\n\n```console\ngazebo -s librmagine_embree_sensors_gzregister.so\n```\n\n2. ROS 2 launch file\n\n```xml\n\u003cexecutable cmd=\"gzserver -s librmagine_embree_sensors_gzregister.so ...\" /\u003e\n\u003cexecutable cmd=\"gzclient\" /\u003e\n```\n\n\u003e [!NOTE]\n\u003e See launch files in this repository for more details.\n\n### 3. Map Plugins\n\nEmbree sensor plugins require one Embree map plugin running.\nOptiX sensor plugins require one OptiX map plugin running.\nIn world-files the map plugins can be enabled as follows:\n\n```xml\n\u003cworld\u003e\n...\n\n\u003c!-- Embree Map Plugin --\u003e\n\u003cplugin name='rmagine_embree_map' filename='librmagine_embree_map_gzplugin.so'\u003e\n\u003c/plugin\u003e\n\n\u003c!-- Optix Map Plugin --\u003e\n\u003cplugin name='rmagine_optix_map' filename='librmagine_optix_map_gzplugin.so'\u003e\n\u003c/plugin\u003e\n\n\u003c/world\u003e\n```\n\nThe map plugins construct a acceleration structure over the Gazebo scene.\nAs soon as the gazebo scene changes, the acceleration structure is updated accordingly.\nSome other examples are located in the worlds folder.\n\nTo increase the performance sdf entities can be marked to be ignored by the map plugins.\nFor 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.\n\nTo achieve that in world-files just add an `rmagine_ignore` tag to the model:\n\n```xml\n\u003cworld\u003e\n\n\u003c!-- Exclude single model from map --\u003e\n\u003cmodel name='plane1_model'\u003e\n    \u003crmagine_ignore/\u003e\n    ...\n\u003c/model\u003e\n\n\u003c!-- Or exclude single link from map --\u003e\n\u003cmodel name=\"plane2_model\"\u003e\n  ...\n  \u003clink name=\"plane2_link\"\u003e\n    ...\n    \u003crmagine_ignore/\u003e\n  \u003c/link\u003e\n\n\u003c/model\u003e\n\n\u003c/world\u003e\n```\n\nHow to add ignores in urdf-files will be explained in the next section.\n\n### 4. Sensors\n\n**2D Laser**\n\n```xml\n\u003cgazebo reference=\"laser2d\"\u003e\n    \u003csensor type=\"rmagine_embree_spherical\" name=\"laser2d\"\u003e\n      \u003cpose\u003e0 0 0 0 0 0\u003c/pose\u003e\n      \u003calways_on\u003etrue\u003c/always_on\u003e\n      \u003cupdate_rate\u003e60\u003c/update_rate\u003e\n\n      \u003cray\u003e\n        \u003cscan\u003e\n          \u003chorizontal\u003e\n            \u003cmin_angle\u003e${-M_PI}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e360\u003c/samples\u003e\n          \u003c/horizontal\u003e\n        \u003c/scan\u003e\n\n        \u003crange\u003e\n          \u003cmin\u003e0.0\u003c/min\u003e\n          \u003cmax\u003e10.0\u003c/max\u003e\n        \u003c/range\u003e\n\n        \u003cnoise\u003e\n          \u003ctype\u003egaussian\u003c/type\u003e\n          \u003cmean\u003e0.0\u003c/mean\u003e\n          \u003cstddev\u003e0.01\u003c/stddev\u003e\n        \u003c/noise\u003e\n        \n      \u003c/ray\u003e\n    \u003c/sensor\u003e\n\u003c/gazebo\u003e\n```\n\n**3D Laser**\n\n```xml\n\u003cgazebo reference=\"laser3d\"\u003e\n    \u003csensor type=\"rmagine_embree_spherical\" name=\"laser3d\"\u003e\n      \u003cpose\u003e0 0 0 0 0 0\u003c/pose\u003e\n      \u003calways_on\u003etrue\u003c/always_on\u003e\n      \u003cupdate_rate\u003e60\u003c/update_rate\u003e\n\n      \u003cray\u003e\n        \u003cscan\u003e\n          \u003chorizontal\u003e\n            \u003cmin_angle\u003e${-M_PI}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e360\u003c/samples\u003e\n          \u003c/horizontal\u003e\n          \u003cvertical\u003e\n            \u003cmin_angle\u003e${-60.0 * M_PI / 180.0}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e120\u003c/samples\u003e\n          \u003c/vertical\u003e\n        \u003c/scan\u003e\n\n        \u003crange\u003e\n          \u003cmin\u003e0.0\u003c/min\u003e\n          \u003cmax\u003e80.0\u003c/max\u003e\n        \u003c/range\u003e\n\n        \u003cnoise\u003e\n          \u003ctype\u003egaussian\u003c/type\u003e\n          \u003cmean\u003e0.0\u003c/mean\u003e\n          \u003cstddev\u003e0.01\u003c/stddev\u003e\n        \u003c/noise\u003e\n      \u003c/ray\u003e\n    \u003c/sensor\u003e\n\u003c/gazebo\u003e\n```\n\nAs in world-files, ignores can be added to URDF files:\n\n```xml\n\u003crobot\u003e\n...\n\n\u003c!-- Ignore the entire robote--\u003e\n\u003cgazebo\u003e\n    \u003crmagine_ignore/\u003e\n\u003c/gazebo\u003e\n\n\u003c!-- Ignore a link. Useful if you want to ignore the scanner visual --\u003e\n\u003cgazebo reference=\"my_scanner_link\"\u003e\n    \u003crmagine_ignore/\u003e\n\u003c/gazebo\u003e\n\u003c/robot\u003e\n```\n\n### 5. Noise\n\nCurrently 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.\n\n1. Gaussian Noise\n\nApply gaussian noise $N(\\mu, \\sigma)$ to simulated ranges.\n\n| Parameter |  Description  |\n|:---------:|:-------------:|\n| `mean` | Mean $\\mu$ of normal distributed noise |\n| `stddev` | standard deviation $\\sigma$ of normal distributed noise |\n\nExample:\n\n```xml\n\u003cnoise\u003e\n  \u003ctype\u003egaussian\u003c/type\u003e\n  \u003cmean\u003e0.0\u003c/mean\u003e\n  \u003cstddev\u003e0.01\u003c/stddev\u003e\n\u003c/noise\u003e\n```\n\n2. Relative Gaussian Noise\n\nApply gaussian noise $N(\\mu, \\sigma_r)$ to simulated ranges. Here, the standard deviation varies depending on distance.\n\n\n| Parameter |  Description  |\n|:---------:|:-------------:|\n| `mean` | Mean $\\mu$ of normal distributed noise |\n| `stddev` | standard deviation $\\sigma$ of normal distributed noise |\n| `range_exp` | range exponent $c$ to compute range based stddev: $ \\sigma_r = \\sigma \\cdot r^{c} $ |\n\n\nExample:\n\n```xml\n\u003cnoise\u003e\n  \u003ctype\u003erel_gaussian\u003c/type\u003e\n  \u003cmean\u003e0.0\u003c/mean\u003e\n  \u003cstddev\u003e0.002\u003c/stddev\u003e\n  \u003crange_exp\u003e1.0\u003c/range_exp\u003e\n\u003c/noise\u003e\n```\n\n3. Uniform Dust Noise\n\nApply 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. \n\nParameters:\n\n| Parameter |  Description  |\n|:---------:|:-------------:|\n| `hit_prob` | Probability of a ray hitting a particle in one meter free space. |\n| `return_prob` | Probability of a ray hitting dust returns to sender depending on particle distance |\n\nExample:\n\n```xml\n\u003cnoise\u003e\n  \u003ctype\u003euniform_dust\u003c/type\u003e\n  \u003chit_prob\u003e0.0000001\u003c/hit_prob\u003e\n  \u003creturn_prob\u003e0.5\u003c/return_prob\u003e\n\u003c/noise\u003e \n```\n\n\n**Noise Chaining**\n\nExample of using the gaussian model first and the uniform dust model second:\n\n```xml\n\u003cnoise\u003e\n  \u003ctype\u003egaussian\u003c/type\u003e\n  \u003cmean\u003e0.0\u003c/mean\u003e\n  \u003cstddev\u003e0.002\u003c/stddev\u003e\n\u003c/noise\u003e\n\n\u003cnoise\u003e\n  \u003ctype\u003euniform_dust\u003c/type\u003e\n  \u003chit_prob\u003e0.0000001\u003c/hit_prob\u003e\n  \u003creturn_prob\u003e0.5\u003c/return_prob\u003e\n\u003c/noise\u003e \n```\n\n\n## ROS Plugin\n\nThis plugin generates ROS-messages of the simulated data and writes them to specified ROS-topics.\nThe following ROS-Adapter are available dependend on your sensor type:\n\n\n`librmagine_optix_ros_gzplugin.so`\n- sensor types: `rmagine_optix_spherical`\n\n`librmagine_embree_ros_gzplugin.so`\n- sensor types: `rmagine_embree_spherical`\n\n\n\nSupported `output` messages are:\n- `sensor_msgs/msg/LaserScan`\n- `sensor_msgs/msg/PointCloud`\n- `sensor_msgs/msg/PointCloud2`\n\nExamples - this time using OptiX.\n\n**2D Laser**\n\n```xml\n\u003cgazebo reference=\"laser2d\"\u003e\n    \u003csensor type=\"rmagine_optix_spherical\" name=\"laser2d\"\u003e\n      \u003cpose\u003e0 0 0 0 0 0\u003c/pose\u003e\n      \u003calways_on\u003etrue\u003c/always_on\u003e\n      \u003cupdate_rate\u003e60\u003c/update_rate\u003e\n\n      \u003cray\u003e\n        \u003cscan\u003e\n          \u003chorizontal\u003e\n            \u003cmin_angle\u003e${-M_PI}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e360\u003c/samples\u003e\n          \u003c/horizontal\u003e\n        \u003c/scan\u003e\n\n        \u003crange\u003e\n          \u003cmin\u003e0.0\u003c/min\u003e\n          \u003cmax\u003e10.0\u003c/max\u003e\n        \u003c/range\u003e\n\n        \u003cnoise\u003e\n          \u003ctype\u003egaussian\u003c/type\u003e\n          \u003cmean\u003e0.0\u003c/mean\u003e\n          \u003cstddev\u003e0.01\u003c/stddev\u003e\n        \u003c/noise\u003e\n        \n      \u003c/ray\u003e\n\n      \u003cplugin name=\"rmagine_ros_laser2d\" filename=\"librmagine_optix_ros_gzplugin.so\"\u003e\n          \u003cframe\u003elaser2d\u003c/frame\u003e\n          \u003coutputs\u003e\n            \u003coutput name=\"scan\"\u003e\n              \u003cmsg\u003esensor_msgs/LaserScan\u003c/msg\u003e\n              \u003ctopic\u003elaser2d/scan\u003c/topic\u003e\n            \u003c/output\u003e\n\n            \u003coutput name=\"pcl\"\u003e\n              \u003cmsg\u003esensor_msgs/PointCloud\u003c/msg\u003e\n              \u003ctopic\u003elaser2d/pcl\u003c/topic\u003e\n            \u003c/output\u003e\n          \u003c/outputs\u003e\n      \u003c/plugin\u003e\n    \u003c/sensor\u003e\n\u003c/gazebo\u003e\n```\n\n**3D Laser**\n\n```xml\n\u003cgazebo reference=\"laser3d\"\u003e\n    \u003csensor type=\"rmagine_optix_spherical\" name=\"laser3d\"\u003e\n      \u003cpose\u003e0 0 0 0 0 0\u003c/pose\u003e\n      \u003calways_on\u003etrue\u003c/always_on\u003e\n      \u003cupdate_rate\u003e60\u003c/update_rate\u003e\n\n      \u003cray\u003e\n        \u003cscan\u003e\n          \u003chorizontal\u003e\n            \u003cmin_angle\u003e${-M_PI}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e360\u003c/samples\u003e\n          \u003c/horizontal\u003e\n          \u003cvertical\u003e\n            \u003cmin_angle\u003e${-60.0 * M_PI / 180.0}\u003c/min_angle\u003e\n            \u003cincrement\u003e${1.0 * M_PI / 180.0}\u003c/increment\u003e\n            \u003csamples\u003e120\u003c/samples\u003e\n          \u003c/vertical\u003e\n        \u003c/scan\u003e\n\n        \u003crange\u003e\n          \u003cmin\u003e0.0\u003c/min\u003e\n          \u003cmax\u003e80.0\u003c/max\u003e\n        \u003c/range\u003e\n\n        \u003cnoise\u003e\n          \u003ctype\u003egaussian\u003c/type\u003e\n          \u003cmean\u003e0.0\u003c/mean\u003e\n          \u003cstddev\u003e0.01\u003c/stddev\u003e\n        \u003c/noise\u003e\n      \u003c/ray\u003e\n\n      \u003cplugin name=\"rmagine_ros_laser3d\" filename=\"librmagine_optix_ros_gzplugin.so\"\u003e\n          \u003cframe\u003elaser3d\u003c/frame\u003e\n          \u003coutputs\u003e\n            \u003coutput name=\"pcl\"\u003e\n              \u003cmsg\u003esensor_msgs/PointCloud\u003c/msg\u003e\n              \u003ctopic\u003elaser3d/pcl\u003c/topic\u003e\n            \u003c/output\u003e\n\n            \u003coutput name=\"pcl2\"\u003e\n              \u003cmsg\u003esensor_msgs/PointCloud2\u003c/msg\u003e\n              \u003ctopic\u003elaser3d/pcl2\u003c/topic\u003e\n            \u003c/output\u003e\n          \u003c/outputs\u003e\n      \u003c/plugin\u003e\n    \u003c/sensor\u003e\n\u003c/gazebo\u003e\n```\n\n## Work in Progress\n\nThis is a pre-release. There is still some work to do for the first stable release:\n\n- Implemented: SphericalModel. TODO: PinholeModel, O1DnModel, OnDnModel\n- Tests: More tests on different devices. Let me know, if you had problems integrating the rmagine_gazebo_plugins into your project.\n\nNice-to-Have:\n- Add segmenting functionallity: Store labeled sensor data from a list of poses in a commonly used file format\n\nKnown Issues:\n\n- Sometimes the Gazebo simulation needs to be started twice in order to get everything started (blocking threads?)\n- \"Core dumped\" on exit:\n```bash\n[Dbg] [rmagine_embree_map_gzplugin.cpp:52] [RmagineEmbreeMap] Destroyed.\nterminate called after throwing an instance of 'boost::wrapexcept\u003cboost::lock_error\u003e'\nterminate called recursively\n  what():  boost: mutex lock failed in pthread_mutex_lock: Invalid argument\nAborted (core dumped)\n```\n\n\n### Known Bug-Fixes:\n\nOn 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:\n\n```console\nexport GAZEBO_PLUGIN_PATH=~/your_ws/devel/lib:$GAZEBO_PLUGIN_PATH\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuos%2Frmagine_gazebo_plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuos%2Frmagine_gazebo_plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuos%2Frmagine_gazebo_plugins/lists"}