├── .github └── workflows │ └── dockerimage.yml ├── LICENSE ├── README.md ├── docker ├── Dockerfile.kinetic └── Dockerfile.melodic ├── gazebo_upgrade.md ├── img └── rviz.png ├── robosense_description ├── CHANGELOG.rst ├── CMakeLists.txt ├── launch │ └── example.launch ├── meshes │ └── robosense_16.dae ├── package.xml ├── rviz │ └── example.rviz ├── urdf │ ├── RS-16.urdf.xacro │ └── example.urdf.xacro └── world │ └── example.world ├── robosense_gazebo_plugins ├── CHANGELOG.rst ├── CMakeLists.txt ├── include │ └── robosense_gazebo_plugins │ │ └── GazeboRosRoboSenseLaser.h ├── package.xml └── src │ └── GazeboRosRoboSenseLaser.cpp └── robosense_simulator └── robosense_simulator ├── CHANGELOG.rst ├── CMakeLists.txt └── package.xml /.github/workflows/dockerimage.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI kinetic/melodic 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | kinetic: 12 | 13 | runs-on: ubuntu-16.04 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Build the Docker image kinetic 18 | run: docker build . --file docker/Dockerfile.kinetic --tag my-image-name:$(date +%s) 19 | 20 | melodic: 21 | 22 | runs-on: ubuntu-18.04 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Build the Docker image melodic 27 | run: docker build . --file docker/Dockerfile.melodic --tag my-image-name:$(date +%s) 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2020, ENSTA PARIS. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of Dataspeed Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Robosense Simulator 2 | URDF description and Gazebo plugins to simulate Robosense laser scanners. Cloned and adapted from [velodyne_simulator](https://bitbucket.org/DataspeedInc/velodyne_simulator) 3 | 4 | ![Docker Image CI kinetic/melodic](https://github.com/tomlogan501/robosense_simulator/workflows/Docker%20Image%20CI%20kinetic/melodic/badge.svg) 5 | 6 | ![rviz screenshot](img/rviz.png) 7 | 8 | # Features 9 | * URDF with colored meshes 10 | * Gazebo plugin based on [gazebo_plugins/gazebo_ros_block_laser](https://github.com/ros-simulation/gazebo_ros_pkgs/blob/kinetic-devel/gazebo_plugins/src/gazebo_ros_block_laser.cpp) 11 | * Publishes PointCloud2 with same structure (x, y, z, intensity, ring) 12 | * Simulated Gaussian noise 13 | * GPU acceleration ([with a modern Gazebo build](gazebo_upgrade.md)) 14 | * Supported models: 15 | * [RS-LiDAR-16](robosense_description/urdf/RS-16.urdf.xacro) 16 | * Pull requests for other models are welcome 17 | * Experimental support for clipping low-intensity returns 18 | 19 | # Parameters 20 | * ```*origin``` URDF transform from parent link. 21 | * ```parent``` URDF parent link name. Default ```base_link``` 22 | * ```name``` URDF model name. Also used as tf frame_id for PointCloud2 output. Default ```robosense``` 23 | * ```topic``` PointCloud2 output topic name. Default ```/rs_points``` 24 | * ```hz``` Update rate in hz. Default ```20``` 25 | * ```lasers``` Number of vertical spinning lasers. Default ```RS-16: 16``` 26 | * ```samples``` Number of horizontal rotating samples. Default ```RS-16: 900``` 27 | * ```min_range``` Minimum range value in meters. Default ```0.9``` 28 | * ```max_range``` Maximum range value in meters. Default ```130.0``` 29 | * ```noise``` Gausian noise value in meters. Default ```0.008``` 30 | * ```min_angle``` Minimum horizontal angle in radians. Default ```-3.14``` 31 | * ```max_angle``` Maximum horizontal angle in radians. Default ```3.14``` 32 | * ```gpu``` Use gpu_ray sensor instead of the standard ray sensor. Default ```false``` 33 | * ```min_intensity``` The minimum intensity beneath which returns will be clipped. Can be used to remove low-intensity objects. 34 | 35 | # Known Issues 36 | 37 | # Example Gazebo Robot 38 | ```roslaunch robosense_description example.launch``` 39 | 40 | # Example Gazebo Robot (with GPU) 41 | ```roslaunch robosense_description example.launch gpu:=true``` 42 | -------------------------------------------------------------------------------- /docker/Dockerfile.kinetic: -------------------------------------------------------------------------------- 1 | FROM ros:kinetic-perception 2 | 3 | #Workspace to use 4 | RUN mkdir -p root/catkin_ws/src/ 5 | RUN /bin/bash -c 'cd /root/catkin_ws' 6 | 7 | #Copy code 8 | COPY . root/catkin_ws/src/robosense_simulator 9 | 10 | RUN apt-get update && apt-get upgrade -y && apt-get install -y ros-kinetic-gazebo-ros 11 | 12 | #Launch the compile 13 | RUN /bin/bash -c ' source /opt/ros/kinetic/setup.bash \ 14 | && cd root/catkin_ws\ 15 | && catkin_make -DCMAKE_INSTALL_PREFIX=/opt/ros/kinetic install' 16 | -------------------------------------------------------------------------------- /docker/Dockerfile.melodic: -------------------------------------------------------------------------------- 1 | FROM ros:melodic-perception 2 | 3 | #Workspace to use 4 | RUN mkdir -p root/catkin_ws/src/ 5 | RUN /bin/bash -c 'cd /root/catkin_ws' 6 | 7 | #Copy code 8 | COPY . root/catkin_ws/src/robosense_simulator 9 | 10 | RUN apt-get update && apt-get upgrade -y && apt-get install -y ros-melodic-gazebo-ros 11 | 12 | #Launch the compile 13 | RUN /bin/bash -c ' source /opt/ros/melodic/setup.bash \ 14 | && cd root/catkin_ws\ 15 | && catkin_make' 16 | -------------------------------------------------------------------------------- /gazebo_upgrade.md: -------------------------------------------------------------------------------- 1 | # GPU issues 2 | The GPU problems reported in this [issue](https://bitbucket.org/osrf/gazebo/issues/946/) have been solved with this [pull request](https://bitbucket.org/osrf/gazebo/pull-requests/2955/) for the ```gazebo7``` branch. The Gazebo versions from the ROS apt repository (7.0.0 for Kinetic, 9.0.0 for Melodic) do not have this fix. One solution is to pull up-to-date packages from the OSRF Gazebo apt repository. Another solution is to compile from source: http://gazebosim.org/tutorials?tut=install_from_source 3 | 4 | * The GPU fix was added to ```gazebo7``` in version 7.14.0 5 | * The GPU fix was added to ```gazebo9``` in version 9.4.0 6 | 7 | # Use up-to-date packages from the OSRF Gazebo apt repository 8 | ``` 9 | sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/gazebo-stable.list' 10 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D2486D2DD83DB69272AFE98867170598AF249743 11 | sudo apt update 12 | sudo apt upgrade 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /img/rviz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlogan501/robosense_simulator/a443e50a7cf2764faf8b3966326cb812f2169cf7/img/rviz.png -------------------------------------------------------------------------------- /robosense_description/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package robosense_description 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | -------------------------------------------------------------------------------- /robosense_description/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(robosense_description) 3 | 4 | find_package(catkin REQUIRED) 5 | 6 | catkin_package() 7 | 8 | install(DIRECTORY launch meshes rviz urdf world 9 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 10 | ) 11 | -------------------------------------------------------------------------------- /robosense_description/launch/example.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /robosense_description/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | robosense_description 4 | 1.0.0 5 | 6 | URDF and meshes describing Robosense laser scanners. 7 | 8 | 9 | BSD 10 | Thomas SIMON 11 | Thomas SIMON 12 | http://wiki.ros.org/robosense_description 13 | 15 | 16 | catkin 17 | 18 | urdf 19 | xacro 20 | 21 | 22 | -------------------------------------------------------------------------------- /robosense_description/rviz/example.rviz: -------------------------------------------------------------------------------- 1 | Panels: 2 | - Class: rviz/Displays 3 | Help Height: 78 4 | Name: Displays 5 | Property Tree Widget: 6 | Expanded: 7 | - /Global Options1 8 | - /Status1 9 | Splitter Ratio: 0.5 10 | Tree Height: 719 11 | - Class: rviz/Selection 12 | Name: Selection 13 | - Class: rviz/Tool Properties 14 | Expanded: 15 | - /2D Pose Estimate1 16 | - /2D Nav Goal1 17 | - /Publish Point1 18 | Name: Tool Properties 19 | Splitter Ratio: 0.5886790156364441 20 | - Class: rviz/Views 21 | Expanded: 22 | - /Current View1 23 | Name: Views 24 | Splitter Ratio: 0.5 25 | - Class: rviz/Time 26 | Experimental: false 27 | Name: Time 28 | SyncMode: 0 29 | SyncSource: PointCloud2 30 | Preferences: 31 | PromptSaveOnExit: true 32 | Toolbars: 33 | toolButtonStyle: 2 34 | Visualization Manager: 35 | Class: "" 36 | Displays: 37 | - Alpha: 0.5 38 | Cell Size: 1 39 | Class: rviz/Grid 40 | Color: 160; 160; 164 41 | Enabled: true 42 | Line Style: 43 | Line Width: 0.029999999329447746 44 | Value: Lines 45 | Name: Grid 46 | Normal Cell Count: 0 47 | Offset: 48 | X: 0 49 | Y: 0 50 | Z: 0 51 | Plane: XY 52 | Plane Cell Count: 10 53 | Reference Frame: 54 | Value: true 55 | - Alpha: 1 56 | Autocompute Intensity Bounds: true 57 | Autocompute Value Bounds: 58 | Max Value: 10 59 | Min Value: -10 60 | Value: true 61 | Axis: Z 62 | Channel Name: intensity 63 | Class: rviz/PointCloud2 64 | Color: 255; 255; 255 65 | Color Transformer: Intensity 66 | Decay Time: 0 67 | Enabled: true 68 | Invert Rainbow: false 69 | Max Color: 255; 255; 255 70 | Max Intensity: 0 71 | Min Color: 0; 0; 0 72 | Min Intensity: 0 73 | Name: PointCloud2 74 | Position Transformer: XYZ 75 | Queue Size: 10 76 | Selectable: true 77 | Size (Pixels): 3 78 | Size (m): 0.009999999776482582 79 | Style: Flat Squares 80 | Topic: /rs_points 81 | Unreliable: false 82 | Use Fixed Frame: true 83 | Use rainbow: true 84 | Value: true 85 | - Class: rviz/TF 86 | Enabled: true 87 | Frame Timeout: 15 88 | Frames: 89 | All Enabled: true 90 | base_footprint: 91 | Value: true 92 | base_link: 93 | Value: true 94 | robosense: 95 | Value: true 96 | robosense_base_link: 97 | Value: true 98 | Marker Scale: 1 99 | Name: TF 100 | Show Arrows: true 101 | Show Axes: true 102 | Show Names: true 103 | Tree: 104 | base_footprint: 105 | base_link: 106 | robosense_base_link: 107 | robosense: 108 | {} 109 | Update Interval: 0 110 | Value: true 111 | - Alpha: 1 112 | Class: rviz/RobotModel 113 | Collision Enabled: false 114 | Enabled: true 115 | Links: 116 | All Links Enabled: true 117 | Expand Joint Details: false 118 | Expand Link Details: false 119 | Expand Tree: false 120 | Link Tree Style: Links in Alphabetic Order 121 | base_footprint: 122 | Alpha: 1 123 | Show Axes: false 124 | Show Trail: false 125 | base_link: 126 | Alpha: 1 127 | Show Axes: false 128 | Show Trail: false 129 | Value: true 130 | robosense: 131 | Alpha: 1 132 | Show Axes: false 133 | Show Trail: false 134 | robosense_base_link: 135 | Alpha: 1 136 | Show Axes: false 137 | Show Trail: false 138 | Value: true 139 | Name: RobotModel 140 | Robot Description: robot_description 141 | TF Prefix: "" 142 | Update Interval: 0 143 | Value: true 144 | Visual Enabled: true 145 | Enabled: true 146 | Global Options: 147 | Background Color: 48; 48; 48 148 | Default Light: true 149 | Fixed Frame: base_footprint 150 | Frame Rate: 30 151 | Name: root 152 | Tools: 153 | - Class: rviz/Interact 154 | Hide Inactive Objects: true 155 | - Class: rviz/MoveCamera 156 | - Class: rviz/Select 157 | - Class: rviz/FocusCamera 158 | - Class: rviz/Measure 159 | - Class: rviz/SetInitialPose 160 | Theta std deviation: 0.2617993950843811 161 | Topic: /initialpose 162 | X std deviation: 0.5 163 | Y std deviation: 0.5 164 | - Class: rviz/SetGoal 165 | Topic: /move_base_simple/goal 166 | - Class: rviz/PublishPoint 167 | Single click: true 168 | Topic: /clicked_point 169 | Value: true 170 | Views: 171 | Current: 172 | Class: rviz/Orbit 173 | Distance: 5.06912899017334 174 | Enable Stereo Rendering: 175 | Stereo Eye Separation: 0.05999999865889549 176 | Stereo Focal Distance: 1 177 | Swap Stereo Eyes: false 178 | Value: false 179 | Focal Point: 180 | X: 0 181 | Y: 0 182 | Z: 0 183 | Focal Shape Fixed Size: true 184 | Focal Shape Size: 0.05000000074505806 185 | Invert Z Axis: false 186 | Name: Current View 187 | Near Clip Distance: 0.009999999776482582 188 | Pitch: 0.570398211479187 189 | Target Frame: 190 | Value: Orbit (rviz) 191 | Yaw: 0.6853981018066406 192 | Saved: ~ 193 | Window Geometry: 194 | Displays: 195 | collapsed: false 196 | Height: 1016 197 | Hide Left Dock: false 198 | Hide Right Dock: true 199 | QMainWindow State: 000000ff00000000fd0000000400000000000001560000035afc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d0000035a000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f0000035afc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d0000035a000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e100000197000000030000073a0000003efc0100000002fb0000000800540069006d006501000000000000073a000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000005de0000035a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 200 | Selection: 201 | collapsed: false 202 | Time: 203 | collapsed: false 204 | Tool Properties: 205 | collapsed: false 206 | Views: 207 | collapsed: true 208 | Width: 1850 209 | X: 70 210 | Y: 27 211 | -------------------------------------------------------------------------------- /robosense_description/urdf/RS-16.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 0 0 0 0 0 0 53 | false 54 | ${hz} 55 | 56 | 57 | 58 | ${samples} 59 | 1 60 | ${min_angle} 61 | ${max_angle} 62 | 63 | 64 | ${lasers} 65 | 1 66 | -${15.0*M_PI/180.0} 67 | ${15.0*M_PI/180.0} 68 | 69 | 70 | 71 | ${collision_range} 72 | ${max_range} 73 | 0.001 74 | 75 | 76 | gaussian 77 | 0.0 78 | 0.0 79 | 80 | 81 | 82 | ${topic} 83 | ${name} 84 | ${min_range} 85 | ${max_range} 86 | ${noise} 87 | 88 | 89 | 90 | 91 | 92 | 0 0 0 0 0 0 93 | false 94 | ${hz} 95 | 96 | 97 | 98 | ${samples} 99 | 1 100 | ${min_angle} 101 | ${max_angle} 102 | 103 | 104 | ${lasers} 105 | 1 106 | -${15.0*M_PI/180.0} 107 | ${15.0*M_PI/180.0} 108 | 109 | 110 | 111 | ${collision_range} 112 | ${max_range+1} 113 | 0.001 114 | 115 | 116 | gaussian 117 | 0.0 118 | 0.0 119 | 120 | 121 | 122 | ${topic} 123 | ${name} 124 | ${min_range} 125 | ${max_range} 126 | ${noise} 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /robosense_description/urdf/example.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /robosense_description/world/example.world: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | model://sun 7 | 8 | 9 | 10 | model://ground_plane 11 | 12 | 13 | 14 | -1.5 2.5 0.5 0 -0 0 15 | 16 | 17 | 1 18 | 19 | 0.166667 20 | 0 21 | 0 22 | 0.166667 23 | 0 24 | 0.166667 25 | 26 | 27 | 28 | 29 | 30 | 1 1 1 31 | 32 | 33 | 10 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 1 1 1 51 | 52 | 53 | 54 | 58 | 59 | 60 | 0 61 | 0 62 | 1 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /robosense_gazebo_plugins/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package robosense_gazebo_plugins 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | -------------------------------------------------------------------------------- /robosense_gazebo_plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(robosense_gazebo_plugins) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | sensor_msgs 7 | tf 8 | gazebo_ros 9 | ) 10 | find_package(gazebo REQUIRED) 11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GAZEBO_CXX_FLAGS}") 12 | 13 | catkin_package( 14 | INCLUDE_DIRS include ${GAZEBO_INCLUDE_DIRS} 15 | LIBRARIES gazebo_ros_robosense_laser gazebo_ros_robosense_gpu_laser 16 | CATKIN_DEPENDS roscpp sensor_msgs gazebo_ros 17 | ) 18 | 19 | include_directories( 20 | include 21 | ${catkin_INCLUDE_DIRS} 22 | ${GAZEBO_INCLUDE_DIRS} 23 | ) 24 | 25 | link_directories( 26 | ${GAZEBO_LIBRARY_DIRS} 27 | ) 28 | 29 | add_library(gazebo_ros_robosense_laser src/GazeboRosRoboSenseLaser.cpp) 30 | target_link_libraries(gazebo_ros_robosense_laser 31 | ${catkin_LIBRARIES} 32 | ${GAZEBO_LIBRARIES} 33 | RayPlugin 34 | ) 35 | 36 | add_library(gazebo_ros_robosense_gpu_laser src/GazeboRosRoboSenseLaser.cpp) 37 | target_link_libraries(gazebo_ros_robosense_gpu_laser 38 | ${catkin_LIBRARIES} 39 | ${GAZEBO_LIBRARIES} 40 | GpuRayPlugin 41 | ) 42 | target_compile_definitions(gazebo_ros_robosense_gpu_laser PRIVATE GAZEBO_GPU_RAY=1) 43 | 44 | install(TARGETS gazebo_ros_robosense_laser gazebo_ros_robosense_gpu_laser 45 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 46 | ) 47 | 48 | install(DIRECTORY include/${PROJECT_NAME}/ 49 | DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 50 | ) 51 | -------------------------------------------------------------------------------- /robosense_gazebo_plugins/include/robosense_gazebo_plugins/GazeboRosRoboSenseLaser.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) 2019-2020, ENSTA. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of Dataspeed Inc. nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | #ifndef GAZEBO_ROS_ROBOSENSE_LASER_H_ 36 | #define GAZEBO_ROS_ROBOSENSE_LASER_H_ 37 | 38 | // Use the same source code for CPU and GPU plugins 39 | #ifndef GAZEBO_GPU_RAY 40 | #define GAZEBO_GPU_RAY 0 41 | #endif 42 | 43 | // Custom Callback Queue 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #include 54 | #include 55 | #include 56 | #if GAZEBO_GPU_RAY 57 | #include 58 | #else 59 | #include 60 | #endif 61 | 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | 68 | #if GAZEBO_GPU_RAY 69 | #define GazeboRosRobosenseGpuLaser GazeboRosRobosenseGpuLaser 70 | #define RayPlugin GpuRayPlugin 71 | #define RaySensorPtr GpuRaySensorPtr 72 | #endif 73 | 74 | namespace gazebo 75 | { 76 | 77 | class GazeboRosRobosenseLaser : public RayPlugin 78 | { 79 | /// \brief Constructor 80 | /// \param parent The parent entity, must be a Model or a Sensor 81 | public: GazeboRosRobosenseLaser(); 82 | 83 | /// \brief Destructor 84 | public: ~GazeboRosRobosenseLaser(); 85 | 86 | /// \brief Load the plugin 87 | /// \param take in SDF root element 88 | public: void Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf); 89 | 90 | /// \brief Subscribe on-demand 91 | private: void ConnectCb(); 92 | 93 | /// \brief The parent ray sensor 94 | private: sensors::RaySensorPtr parent_ray_sensor_; 95 | 96 | /// \brief Pointer to ROS node 97 | private: ros::NodeHandle* nh_; 98 | 99 | /// \brief ROS publisher 100 | private: ros::Publisher pub_; 101 | 102 | /// \brief topic name 103 | private: std::string topic_name_; 104 | 105 | /// \brief frame transform name, should match link name 106 | private: std::string frame_name_; 107 | 108 | /// \brief the intensity beneath which points will be filtered 109 | private: double min_intensity_; 110 | 111 | /// \brief Minimum range to publish 112 | private: double min_range_; 113 | 114 | /// \brief Maximum range to publish 115 | private: double max_range_; 116 | 117 | /// \brief Gaussian noise 118 | private: double gaussian_noise_; 119 | 120 | /// \brief Gaussian noise generator 121 | private: static double gaussianKernel(double mu, double sigma) 122 | { 123 | // using Box-Muller transform to generate two independent standard normally distributed normal variables 124 | // see wikipedia 125 | double U = (double)rand() / (double)RAND_MAX; // normalized uniform random variable 126 | double V = (double)rand() / (double)RAND_MAX; // normalized uniform random variable 127 | return sigma * (sqrt(-2.0 * ::log(U)) * cos(2.0 * M_PI * V)) + mu; 128 | } 129 | 130 | /// \brief A mutex to lock access 131 | private: boost::mutex lock_; 132 | 133 | /// \brief For setting ROS name space 134 | private: std::string robot_namespace_; 135 | 136 | // Custom Callback Queue 137 | private: ros::CallbackQueue laser_queue_; 138 | private: void laserQueueThread(); 139 | private: boost::thread callback_laser_queue_thread_; 140 | 141 | // Subscribe to gazebo laserscan 142 | private: gazebo::transport::NodePtr gazebo_node_; 143 | private: gazebo::transport::SubscriberPtr sub_; 144 | private: void OnScan(const ConstLaserScanStampedPtr &_msg); 145 | 146 | }; 147 | 148 | } // namespace gazebo 149 | 150 | #endif /* GAZEBO_ROS_ROBOSENSE_LASER_H_ */ 151 | 152 | -------------------------------------------------------------------------------- /robosense_gazebo_plugins/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | robosense_gazebo_plugins 4 | 1.0.0 5 | 6 | Gazebo plugin to provide simulated data from Robosense laser scanners. 7 | 8 | 9 | BSD 10 | Thomas SIMON 11 | Thomas SIMON 12 | 13 | catkin 14 | 15 | roscpp 16 | sensor_msgs 17 | tf 18 | gazebo_ros 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /robosense_gazebo_plugins/src/GazeboRosRoboSenseLaser.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) 2019-2020, ENSTA. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of Dataspeed Inc. nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #if GAZEBO_GPU_RAY 46 | #include 47 | #else 48 | #include 49 | #endif 50 | #include 51 | #include 52 | 53 | #include 54 | 55 | #include 56 | 57 | #if GAZEBO_GPU_RAY 58 | #define RaySensor GpuRaySensor 59 | #define STR_Gpu "Gpu" 60 | #define STR_GPU_ "GPU " 61 | #else 62 | #define STR_Gpu "" 63 | #define STR_GPU_ "" 64 | #endif 65 | 66 | namespace gazebo 67 | { 68 | // Register this plugin with the simulator 69 | GZ_REGISTER_SENSOR_PLUGIN(GazeboRosRobosenseLaser) 70 | 71 | //////////////////////////////////////////////////////////////////////////////// 72 | // Constructor 73 | GazeboRosRobosenseLaser::GazeboRosRobosenseLaser() : nh_(NULL), gaussian_noise_(0), min_range_(0), max_range_(0) 74 | { 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////// 78 | // Destructor 79 | GazeboRosRobosenseLaser::~GazeboRosRobosenseLaser() 80 | { 81 | //////////////////////////////////////////////////////////////////////////////// 82 | // Finalize the controller / Custom Callback Queue 83 | laser_queue_.clear(); 84 | laser_queue_.disable(); 85 | if (nh_) { 86 | nh_->shutdown(); 87 | delete nh_; 88 | nh_ = NULL; 89 | } 90 | callback_laser_queue_thread_.join(); 91 | } 92 | 93 | //////////////////////////////////////////////////////////////////////////////// 94 | // Load the controller 95 | void GazeboRosRobosenseLaser::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf) 96 | { 97 | // Load plugin 98 | RayPlugin::Load(_parent, _sdf); 99 | 100 | // Initialize Gazebo node 101 | gazebo_node_ = gazebo::transport::NodePtr(new gazebo::transport::Node()); 102 | gazebo_node_->Init(); 103 | 104 | // Get the parent ray sensor 105 | #if GAZEBO_MAJOR_VERSION >= 7 106 | parent_ray_sensor_ = std::dynamic_pointer_cast(_parent); 107 | #else 108 | parent_ray_sensor_ = boost::dynamic_pointer_cast(_parent); 109 | #endif 110 | if (!parent_ray_sensor_) { 111 | gzthrow("GazeboRosRobosense" << STR_Gpu << "Laser controller requires a " << STR_Gpu << "Ray Sensor as its parent"); 112 | } 113 | 114 | robot_namespace_ = "/"; 115 | if (_sdf->HasElement("robotNamespace")) { 116 | robot_namespace_ = _sdf->GetElement("robotNamespace")->Get(); 117 | } 118 | 119 | if (!_sdf->HasElement("frameName")) { 120 | ROS_INFO("Robosense laser plugin missing , defaults to /world"); 121 | frame_name_ = "/world"; 122 | } else { 123 | frame_name_ = _sdf->GetElement("frameName")->Get(); 124 | } 125 | 126 | if (!_sdf->HasElement("min_range")) { 127 | ROS_INFO("Robosense laser plugin missing , defaults to 0"); 128 | min_range_ = 0; 129 | } else { 130 | min_range_ = _sdf->GetElement("min_range")->Get(); 131 | } 132 | 133 | if (!_sdf->HasElement("max_range")) { 134 | ROS_INFO("Robosense laser plugin missing , defaults to infinity"); 135 | max_range_ = INFINITY; 136 | } else { 137 | max_range_ = _sdf->GetElement("max_range")->Get(); 138 | } 139 | 140 | min_intensity_ = std::numeric_limits::lowest(); 141 | if (!_sdf->HasElement("min_intensity")) { 142 | ROS_INFO("Robosense laser plugin missing , defaults to no clipping"); 143 | } else { 144 | min_intensity_ = _sdf->GetElement("min_intensity")->Get(); 145 | } 146 | 147 | if (!_sdf->HasElement("topicName")) { 148 | ROS_INFO("Robosense laser plugin missing , defaults to /points"); 149 | topic_name_ = "/points"; 150 | } else { 151 | topic_name_ = _sdf->GetElement("topicName")->Get(); 152 | } 153 | 154 | if (!_sdf->HasElement("gaussianNoise")) { 155 | ROS_INFO("Robosense laser plugin missing , defaults to 0.0"); 156 | gaussian_noise_ = 0; 157 | } else { 158 | gaussian_noise_ = _sdf->GetElement("gaussianNoise")->Get(); 159 | } 160 | 161 | // Make sure the ROS node for Gazebo has already been initialized 162 | if (!ros::isInitialized()) { 163 | ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. " 164 | << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)"); 165 | return; 166 | } 167 | 168 | // Create node handle 169 | nh_ = new ros::NodeHandle(robot_namespace_); 170 | 171 | // Resolve tf prefix 172 | std::string prefix; 173 | nh_->getParam(std::string("tf_prefix"), prefix); 174 | if (robot_namespace_ != "/") { 175 | prefix = robot_namespace_; 176 | } 177 | boost::trim_right_if(prefix, boost::is_any_of("/")); 178 | frame_name_ = tf::resolve(prefix, frame_name_); 179 | 180 | // Advertise publisher with a custom callback queue 181 | if (topic_name_ != "") { 182 | ros::AdvertiseOptions ao = ros::AdvertiseOptions::create( 183 | topic_name_, 1, 184 | boost::bind(&GazeboRosRobosenseLaser::ConnectCb, this), 185 | boost::bind(&GazeboRosRobosenseLaser::ConnectCb, this), 186 | ros::VoidPtr(), &laser_queue_); 187 | pub_ = nh_->advertise(ao); 188 | } 189 | 190 | // Sensor generation off by default 191 | parent_ray_sensor_->SetActive(false); 192 | 193 | // Start custom queue for laser 194 | callback_laser_queue_thread_ = boost::thread( boost::bind( &GazeboRosRobosenseLaser::laserQueueThread,this ) ); 195 | 196 | #if GAZEBO_MAJOR_VERSION >= 7 197 | ROS_INFO("Robosense %slaser plugin ready, %i lasers", STR_GPU_, parent_ray_sensor_->VerticalRangeCount()); 198 | #else 199 | ROS_INFO("Robosense %slaser plugin ready, %i lasers", STR_GPU_, parent_ray_sensor_->GetVerticalRangeCount()); 200 | #endif 201 | } 202 | 203 | //////////////////////////////////////////////////////////////////////////////// 204 | // Subscribe on-demand 205 | void GazeboRosRobosenseLaser::ConnectCb() 206 | { 207 | boost::lock_guard lock(lock_); 208 | if (pub_.getNumSubscribers()) { 209 | if (!sub_) { 210 | #if GAZEBO_MAJOR_VERSION >= 7 211 | sub_ = gazebo_node_->Subscribe(this->parent_ray_sensor_->Topic(), &GazeboRosRobosenseLaser::OnScan, this); 212 | #else 213 | sub_ = gazebo_node_->Subscribe(this->parent_ray_sensor_->GetTopic(), &GazeboRosRobosenseLaser::OnScan, this); 214 | #endif 215 | } 216 | parent_ray_sensor_->SetActive(true); 217 | } else { 218 | #if GAZEBO_MAJOR_VERSION >= 7 219 | if (sub_) { 220 | sub_->Unsubscribe(); 221 | sub_.reset(); 222 | } 223 | #endif 224 | parent_ray_sensor_->SetActive(false); 225 | } 226 | } 227 | 228 | void GazeboRosRobosenseLaser::OnScan(ConstLaserScanStampedPtr& _msg) 229 | { 230 | #if GAZEBO_MAJOR_VERSION >= 7 231 | const ignition::math::Angle maxAngle = parent_ray_sensor_->AngleMax(); 232 | const ignition::math::Angle minAngle = parent_ray_sensor_->AngleMin(); 233 | 234 | const double maxRange = parent_ray_sensor_->RangeMax(); 235 | const double minRange = parent_ray_sensor_->RangeMin(); 236 | 237 | const int rayCount = parent_ray_sensor_->RayCount(); 238 | const int rangeCount = parent_ray_sensor_->RangeCount(); 239 | 240 | const int verticalRayCount = parent_ray_sensor_->VerticalRayCount(); 241 | const int verticalRangeCount = parent_ray_sensor_->VerticalRangeCount(); 242 | 243 | const ignition::math::Angle verticalMaxAngle = parent_ray_sensor_->VerticalAngleMax(); 244 | const ignition::math::Angle verticalMinAngle = parent_ray_sensor_->VerticalAngleMin(); 245 | #else 246 | math::Angle maxAngle = parent_ray_sensor_->GetAngleMax(); 247 | math::Angle minAngle = parent_ray_sensor_->GetAngleMin(); 248 | 249 | const double maxRange = parent_ray_sensor_->GetRangeMax(); 250 | const double minRange = parent_ray_sensor_->GetRangeMin(); 251 | 252 | const int rayCount = parent_ray_sensor_->GetRayCount(); 253 | const int rangeCount = parent_ray_sensor_->GetRangeCount(); 254 | 255 | const int verticalRayCount = parent_ray_sensor_->GetVerticalRayCount(); 256 | const int verticalRangeCount = parent_ray_sensor_->GetVerticalRangeCount(); 257 | 258 | const math::Angle verticalMaxAngle = parent_ray_sensor_->GetVerticalAngleMax(); 259 | const math::Angle verticalMinAngle = parent_ray_sensor_->GetVerticalAngleMin(); 260 | #endif 261 | 262 | const double yDiff = maxAngle.Radian() - minAngle.Radian(); 263 | const double pDiff = verticalMaxAngle.Radian() - verticalMinAngle.Radian(); 264 | 265 | const double MIN_RANGE = std::max(min_range_, minRange); 266 | const double MAX_RANGE = std::min(max_range_, maxRange); 267 | const double MIN_INTENSITY = min_intensity_; 268 | 269 | // Populate message fields 270 | const uint32_t POINT_STEP = 32; 271 | sensor_msgs::PointCloud2 msg; 272 | msg.header.frame_id = frame_name_; 273 | msg.header.stamp = ros::Time(_msg->time().sec(), _msg->time().nsec()); 274 | msg.fields.resize(5); 275 | msg.fields[0].name = "x"; 276 | msg.fields[0].offset = 0; 277 | msg.fields[0].datatype = sensor_msgs::PointField::FLOAT32; 278 | msg.fields[0].count = 1; 279 | msg.fields[1].name = "y"; 280 | msg.fields[1].offset = 4; 281 | msg.fields[1].datatype = sensor_msgs::PointField::FLOAT32; 282 | msg.fields[1].count = 1; 283 | msg.fields[2].name = "z"; 284 | msg.fields[2].offset = 8; 285 | msg.fields[2].datatype = sensor_msgs::PointField::FLOAT32; 286 | msg.fields[2].count = 1; 287 | msg.fields[3].name = "intensity"; 288 | msg.fields[3].offset = 16; 289 | msg.fields[3].datatype = sensor_msgs::PointField::FLOAT32; 290 | msg.fields[3].count = 1; 291 | msg.fields[4].name = "ring"; 292 | msg.fields[4].offset = 20; 293 | msg.fields[4].datatype = sensor_msgs::PointField::UINT16; 294 | msg.fields[4].count = 1; 295 | msg.data.resize(verticalRangeCount * rangeCount * POINT_STEP); 296 | 297 | int i, j; 298 | uint8_t *ptr = msg.data.data(); 299 | for (i = 0; i < rangeCount; i++) { 300 | for (j = 0; j < verticalRangeCount; j++) { 301 | 302 | // Range 303 | double r = _msg->scan().ranges(i + j * rangeCount); 304 | // Intensity 305 | double intensity = _msg->scan().intensities(i + j * rangeCount); 306 | // Ignore points that lay outside range bands or optionally, beneath a 307 | // minimum intensity level. 308 | if ((MIN_RANGE >= r) || (r >= MAX_RANGE) || (intensity < MIN_INTENSITY) ) { 309 | continue; 310 | } 311 | 312 | // Noise 313 | if (gaussian_noise_ != 0.0) { 314 | r += gaussianKernel(0,gaussian_noise_); 315 | } 316 | 317 | // Get angles of ray to get xyz for point 318 | double yAngle; 319 | double pAngle; 320 | 321 | if (rangeCount > 1) { 322 | yAngle = i * yDiff / (rangeCount -1) + minAngle.Radian(); 323 | } else { 324 | yAngle = minAngle.Radian(); 325 | } 326 | 327 | if (verticalRayCount > 1) { 328 | pAngle = j * pDiff / (verticalRangeCount -1) + verticalMinAngle.Radian(); 329 | } else { 330 | pAngle = verticalMinAngle.Radian(); 331 | } 332 | 333 | // pAngle is rotated by yAngle: 334 | if ((MIN_RANGE < r) && (r < MAX_RANGE)) { 335 | *((float*)(ptr + 0)) = r * cos(pAngle) * cos(yAngle); 336 | *((float*)(ptr + 4)) = r * cos(pAngle) * sin(yAngle); 337 | #if GAZEBO_MAJOR_VERSION > 2 338 | *((float*)(ptr + 8)) = r * sin(pAngle); 339 | #else 340 | *((float*)(ptr + 8)) = -r * sin(pAngle); 341 | #endif 342 | *((float*)(ptr + 16)) = intensity; 343 | #if GAZEBO_MAJOR_VERSION > 2 344 | *((uint16_t*)(ptr + 20)) = j; // ring 345 | #else 346 | *((uint16_t*)(ptr + 20)) = verticalRangeCount - 1 - j; // ring 347 | #endif 348 | ptr += POINT_STEP; 349 | } 350 | } 351 | } 352 | 353 | // Populate message with number of valid points 354 | msg.point_step = POINT_STEP; 355 | msg.row_step = ptr - msg.data.data(); 356 | msg.height = 1; 357 | msg.width = msg.row_step / POINT_STEP; 358 | msg.is_bigendian = false; 359 | msg.is_dense = true; 360 | msg.data.resize(msg.row_step); // Shrink to actual size 361 | 362 | // Publish output 363 | pub_.publish(msg); 364 | } 365 | 366 | // Custom Callback Queue 367 | //////////////////////////////////////////////////////////////////////////////// 368 | // Custom callback queue thread 369 | void GazeboRosRobosenseLaser::laserQueueThread() 370 | { 371 | while (nh_->ok()) { 372 | laser_queue_.callAvailable(ros::WallDuration(0.01)); 373 | } 374 | } 375 | 376 | } // namespace gazebo 377 | 378 | -------------------------------------------------------------------------------- /robosense_simulator/robosense_simulator/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package robosense_simulator 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | -------------------------------------------------------------------------------- /robosense_simulator/robosense_simulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(robosense_simulator) 3 | find_package(catkin REQUIRED) 4 | catkin_metapackage() 5 | -------------------------------------------------------------------------------- /robosense_simulator/robosense_simulator/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | robosense_simulator 4 | 1.0.0 5 | 6 | Metapackage allowing easy installation of Robosense simulation components. 7 | 8 | 9 | BSD 10 | Thomas SIMON 11 | Thomas SIMON 12 | http://wiki.ros.org/robosense_simulator 13 | 15 | 16 | catkin 17 | 18 | robosense_description 19 | robosense_gazebo_plugins 20 | 21 | 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------