diff --git a/ros2/src/ydlidar_ros2_driver/CMakeLists.txt b/ros2/src/ydlidar_ros2_driver/CMakeLists.txt
new file mode 100644
index 0000000..af4e2b2
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/CMakeLists.txt
@@ -0,0 +1,88 @@
+# Copyright(c) 2020 eaibot limited.
+cmake_minimum_required(VERSION 3.5)
+project(ydlidar_ros2_driver C CXX)
+
+##################ros2#############################################
+# Default to C++14
+if(NOT CMAKE_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD 14)
+endif()
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ add_compile_options(-Wall -Wextra -Wpedantic)
+endif()
+
+####################find package#####################################
+find_package(ament_cmake REQUIRED)
+find_package(rclcpp REQUIRED)
+find_package(rmw REQUIRED)
+find_package(sensor_msgs REQUIRED)
+find_package(visualization_msgs REQUIRED)
+find_package(geometry_msgs REQUIRED)
+find_package(std_srvs REQUIRED)
+
+############## YDLIDAR SDK START#####################################
+#find ydlidar_sdk package
+find_package(ydlidar_sdk REQUIRED)
+############## YDLIDAR SDK END#####################################
+
+#Include directories
+include_directories(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_SOURCE_DIR}/src
+ ${YDLIDAR_SDK_INCLUDE_DIRS})
+
+#link library directories
+link_directories(${YDLIDAR_SDK_LIBRARY_DIRS})
+
+#---------------------------------------------------------------------------------------
+# generate excutable and add libraries
+#---------------------------------------------------------------------------------------
+add_executable(${PROJECT_NAME}_node
+ src/${PROJECT_NAME}_node.cpp)
+#---------------------------------------------------------------------------------------
+# link libraries
+#--------------------------------------------------------------------------------------
+ament_target_dependencies(${PROJECT_NAME}_node
+ "rclcpp"
+ "sensor_msgs"
+ "visualization_msgs"
+ "geometry_msgs"
+ "std_srvs"
+ )
+
+target_link_libraries(${PROJECT_NAME}_node
+ ${YDLIDAR_SDK_LIBRARIES})
+
+#---------------------------------------------------------------------------------------
+# generate excutable and add libraries
+#---------------------------------------------------------------------------------------
+add_executable(${PROJECT_NAME}_client
+ src/${PROJECT_NAME}_client.cpp)
+#---------------------------------------------------------------------------------------
+# link libraries
+#--------------------------------------------------------------------------------------
+ament_target_dependencies(${PROJECT_NAME}_client
+ "rclcpp"
+ "sensor_msgs"
+ "visualization_msgs"
+ "geometry_msgs"
+ "std_srvs"
+ )
+
+#---------------------------------------------------------------------------------------
+# Install
+#---------------------------------------------------------------------------------------
+install(TARGETS
+ ${PROJECT_NAME}_node ${PROJECT_NAME}_client
+ DESTINATION lib/${PROJECT_NAME})
+
+install(DIRECTORY launch params startup config
+ DESTINATION share/${PROJECT_NAME})
+
+if(BUILD_TESTING)
+ find_package(ament_lint_auto REQUIRED)
+ ament_lint_auto_find_test_dependencies()
+endif()
+
+ament_package()
+
diff --git a/ros2/src/ydlidar_ros2_driver/LICENSE.txt b/ros2/src/ydlidar_ros2_driver/LICENSE.txt
new file mode 100644
index 0000000..e69de29
diff --git a/ros2/src/ydlidar_ros2_driver/README.md b/ros2/src/ydlidar_ros2_driver/README.md
new file mode 100644
index 0000000..9b5d49b
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/README.md
@@ -0,0 +1,187 @@
+
+# YDLIDAR ROS2 Driver
+
+ydlidar_ros2_driver is a new ros package, which is designed to gradually become the standard driver package for ydlidar devices in the ros2 environment.
+
+## How to [install ROS2](https://index.ros.org/doc/ros2/Installation)
+[ubuntu](https://index.ros.org/doc/ros2/Installation/Dashing/Linux-Install-Debians/)
+
+[windows](https://index.ros.org/doc/ros2/Installation/Dashing/Windows-Install-Binary/)
+
+## How to Create a ROS2 workspace
+[Create a workspace](https://index.ros.org/doc/ros2/Tutorials/Colcon-Tutorial/#create-a-workspace)
+
+
+## Compile & Install YDLidar SDK
+
+ydlidar_ros2_driver depends on YDLidar-SDK library. If you have never installed YDLidar-SDK library or it is out of date, you must first install YDLidar-SDK library. If you have installed the latest version of YDLidar-SDK, skip this step and go to the next step.
+
+1. Download or clone the [YDLIDAR/YDLidar-SDK](https://github.com/YDLIDAR/YDLidar-SDK) repository on GitHub.
+2. Compile and install the YDLidar-SDK under the ***build*** directory following `README.md` of YDLIDAR/YDLidar-SDK.
+
+## Clone ydlidar_ros2_driver
+
+1. Clone ydlidar_ros2_driver package for github :
+
+ `git clone https://github.com/YDLIDAR/ydlidar_ros2_driver.git ydlidar_ros2_ws/src/ydlidar_ros2_driver`
+
+2. Build ydlidar_ros2_driver package :
+
+ ```
+ cd ydlidar_ros2_ws
+ colcon build --symlink-install
+ ```
+ Note: install colcon [see](https://index.ros.org/doc/ros2/Tutorials/Colcon-Tutorial/#install-colcon)
+
+ 
+
+ >Note: If the following error occurs, Please install [YDLIDAR/YDLidar-SDK](https://github.com/YDLIDAR/YDLidar-SDK) first.
+
+ 
+
+3. Package environment setup :
+
+ `source ./install/setup.bash`
+
+ Note: Add permanent workspace environment variables.
+ It's convenientif the ROS2 environment variables are automatically added to your bash session every time a new shell is launched:
+ ```
+ $echo "source ~/ydlidar_ros2_ws/install/setup.bash" >> ~/.bashrc
+ $source ~/.bashrc
+ ```
+4. Confirmation
+ To confirm that your package path has been set, printenv the `grep -i ROS` variable.
+ ```
+ $ printenv | grep -i ROS
+ ```
+ You should see something similar to:
+ `OLDPWD=/home/tony/ydlidar_ros2_ws/install`
+
+5. Create serial port Alias [optional]
+ ```
+ $chmod 0777 src/ydlidar_ros2_driver/startup/*
+ $sudo sh src/ydlidar_ros2_driver/startup/initenv.sh
+ ```
+ Note: After completing the previous operation, replug the LiDAR again.
+
+## Configure LiDAR [paramters](params/ydlidar.yaml)
+```
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 230400
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 9
+ abnormal_check_count: 4
+ resolution_fixed: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 64.0
+ range_min: 0.01
+ frequency: 10.0
+ invalid_range_is_inf: false
+```
+
+## Run ydlidar_ros2_driver
+
+##### Run ydlidar_ros2_driver using launch file
+
+The command format is :
+
+ `ros2 launch ydlidar_ros2_driver [launch file].py`
+
+1. Connect LiDAR uint(s).
+ ```
+ ros2 launch ydlidar_ros2_driver ydlidar_launch.py
+ ```
+ or
+
+ ```
+ launch $(ros2 pkg prefix ydlidar_ros2_driver)/share/ydlidar_ros2_driver/launch/ydlidar.py
+ ```
+2. RVIZ
+ ```
+ ros2 launch ydlidar_ros2_driver ydlidar_launch_view.py
+ ```
+ 
+
+3. echo scan topic
+ ```
+ ros2 run ydlidar_ros2_driver ydlidar_ros2_driver_client or ros2 topic echo /scan
+ ```
+
+##### Launch file introduction
+
+The driver offers users a wealth of options when using different launch file. The launch file directory
+
+is `"ydlidar_ros2_ws/src/ydlidar_ros2_driver/launch"`. All launch files are listed as below :
+
+| launch file | features |
+| ------------------------- | ------------------------------------------------------------ |
+| ydlidar.py | Connect to defualt paramters
Publish LaserScan message on `scan` topic |
+| ydlidar_launch.py | Connect ydlidar.yaml Lidar specified by configuration parameters
Publish LaserScan message on `scan` topic |
+| ydlidar_launch_view.py | Connect ydlidar.yaml Lidar specified by configuration parameters and setup RVIZ
Publish LaserScan message on `scan` topic |
+
+
+
+## Publish Topic
+| Topic | Type | Description |
+|----------------------|-------------------------|--------------------------------------------------|
+| `scan` | sensor_msgs/LaserScan | 2D laser scan of the 0-angle ring |
+
+## Subscribe Service
+| Service | Type | Description |
+|----------------------|-------------------------|--------------------------------------------------|
+| `stop_scan` | std_srvs::Empty | turn off lidar |
+| `start_scan` | std_srvs::Empty | turn on lidar |
+
+
+
+## Configure ydlidar_ros_driver internal parameter
+
+The ydlidar_ros2_driver internal parameters are in the launch file, they are listed as below :
+
+| Parameter name | Data Type | detail |
+| -------------- | ------- | ------------------------------------------------------------ |
+| port | string | Set Lidar the serial port or IP address
it can be set to `/dev/ttyUSB0`, `192.168.1.11`, etc.
default: `/dev/ydlidar` |
+| frame_id | string | Lidar TF coordinate system name.
default: `laser_frame` |
+| ignore_array | string | LiDAR filtering angle area
eg: `-90, -80, 30, 40` |
+| baudrate | int | Lidar baudrate or network port.
default: `230400` |
+| lidar_type | int | Set lidar type
0 -- TYPE_TOF
1 -- TYPE_TRIANGLE
2 -- TYPE_TOF_NET
default: `1` |
+| device_type | int | Set device type
0 -- YDLIDAR_TYPE_SERIAL
1 -- YDLIDAR_TYPE_TCP
2 -- YDLIDAR_TYPE_UDP
default: `0` |
+| sample_rate | int | Set Lidar Sample Rate.
default: `9` |
+| abnormal_check_count | int | Set the number of abnormal startup data attempts.
default: `4` |
+| fixed_resolution | bool | Fixed angluar resolution.
default: `true` |
+| reversion | bool | Reversion LiDAR.
default: `true` |
+| inverted | bool | Inverted LiDAR.
false -- ClockWise.
true -- CounterClockWise
default: `true` |
+| auto_reconnect | bool | Automatically reconnect the LiDAR.
true -- hot plug.
default: `true` |
+| isSingleChannel | bool | Whether LiDAR is a single-channel.
default: `false` |
+| intensity | bool | Whether LiDAR has intensity.
true -- G2 LiDAR.
default: `false` |
+| support_motor_dtr | bool | Whether the Lidar can be started and stopped by Serial DTR.
default: `false` |
+| angle_min | float | Minimum Valid Angle.
default: `-180` |
+| angle_max | float | Maximum Valid Angle.
default: `180` |
+| range_min | float | Minimum Valid range.
default: `0.1` |
+| range_max | float | Maximum Valid range.
default: `16.0` |
+| frequency | float | Set Scanning Frequency.
default: `10.0` |
+| invalid_range_is_inf | bool | Invalid Range is inf.
true -- inf.
false -- 0.0.
default: `false` |
+More paramters details, see [here](details.md)
+
+## Contact EAI
+
+
+If you have any extra questions, please feel free to [contact us](http://www.ydlidar.cn/cn/contact)
+
+
+
+
+
+
diff --git a/ros2/src/ydlidar_ros2_driver/config/ydlidar.rviz b/ros2/src/ydlidar_ros2_driver/config/ydlidar.rviz
new file mode 100644
index 0000000..7c9e799
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/config/ydlidar.rviz
@@ -0,0 +1,177 @@
+Panels:
+ - Class: rviz_common/Displays
+ Help Height: 78
+ Name: Displays
+ Property Tree Widget:
+ Expanded:
+ - /Global Options1
+ - /Status1
+ - /LaserScan1/Topic1
+ Splitter Ratio: 0.5
+ Tree Height: 617
+ - Class: rviz_common/Selection
+ Name: Selection
+ - Class: rviz_common/Tool Properties
+ Expanded:
+ - /2D Goal Pose1
+ - /Publish Point1
+ Name: Tool Properties
+ Splitter Ratio: 0.5886790156364441
+ - Class: rviz_common/Views
+ Expanded:
+ - /Current View1
+ Name: Views
+ Splitter Ratio: 0.5
+Visualization Manager:
+ Class: ""
+ Displays:
+ - Alpha: 0.5
+ Cell Size: 1
+ Class: rviz_default_plugins/Grid
+ Color: 160; 160; 164
+ Enabled: true
+ Line Style:
+ Line Width: 0.029999999329447746
+ Value: Lines
+ Name: Grid
+ Normal Cell Count: 0
+ Offset:
+ X: 0
+ Y: 0
+ Z: 0
+ Plane: XY
+ Plane Cell Count: 10
+ Reference Frame:
+ Value: true
+ - Alpha: 1
+ Autocompute Intensity Bounds: true
+ Autocompute Value Bounds:
+ Max Value: 10
+ Min Value: -10
+ Value: true
+ Axis: Z
+ Channel Name: intensity
+ Class: rviz_default_plugins/LaserScan
+ Color: 239; 41; 41
+ Color Transformer: FlatColor
+ Decay Time: 0
+ Enabled: true
+ Invert Rainbow: false
+ Max Color: 255; 255; 255
+ Max Intensity: 1012
+ Min Color: 0; 0; 0
+ Min Intensity: 1008
+ Name: LaserScan
+ Position Transformer: XYZ
+ Selectable: true
+ Size (Pixels): 3
+ Size (m): 0.05999999865889549
+ Style: Flat Squares
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: System Default
+ Value: /scan
+ Use Fixed Frame: true
+ Use rainbow: true
+ Value: true
+ - Class: rviz_default_plugins/TF
+ Enabled: true
+ Frame Timeout: 15
+ Frames:
+ All Enabled: true
+ base_link:
+ Value: true
+ laser_frame:
+ Value: true
+ Marker Scale: 1
+ Name: TF
+ Show Arrows: true
+ Show Axes: true
+ Show Names: false
+ Tree:
+ base_link:
+ laser_frame:
+ {}
+ Update Interval: 0
+ Value: true
+ Enabled: true
+ Global Options:
+ Background Color: 48; 48; 48
+ Fixed Frame: laser_frame
+ Frame Rate: 30
+ Name: root
+ Tools:
+ - Class: rviz_default_plugins/Interact
+ Hide Inactive Objects: true
+ - Class: rviz_default_plugins/MoveCamera
+ - Class: rviz_default_plugins/Select
+ - Class: rviz_default_plugins/FocusCamera
+ - Class: rviz_default_plugins/Measure
+ Line color: 128; 128; 0
+ - Class: rviz_default_plugins/SetInitialPose
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /initialpose
+ - Class: rviz_default_plugins/SetGoal
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /goal_pose
+ - Class: rviz_default_plugins/PublishPoint
+ Single click: true
+ Topic:
+ Depth: 5
+ Durability Policy: Volatile
+ History Policy: Keep Last
+ Reliability Policy: Reliable
+ Value: /clicked_point
+ Transformation:
+ Current:
+ Class: rviz_default_plugins/TF
+ Value: true
+ Views:
+ Current:
+ Class: rviz_default_plugins/Orbit
+ Distance: 10
+ Enable Stereo Rendering:
+ Stereo Eye Separation: 0.05999999865889549
+ Stereo Focal Distance: 1
+ Swap Stereo Eyes: false
+ Value: false
+ Focal Point:
+ X: 0
+ Y: 0
+ Z: 0
+ Focal Shape Fixed Size: true
+ Focal Shape Size: 0.05000000074505806
+ Invert Z Axis: false
+ Name: Current View
+ Near Clip Distance: 0.009999999776482582
+ Pitch: 1.5103975534439087
+ Target Frame:
+ Value: Orbit (rviz)
+ Yaw: 6.163581848144531
+ Saved: ~
+Window Geometry:
+ Displays:
+ collapsed: false
+ Height: 846
+ Hide Left Dock: false
+ Hide Right Dock: false
+ QMainWindow State: 000000ff00000000fd000000040000000000000156000002f4fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002f4000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002f4fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002f4000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d006501000000000000045000000000000000000000023f000002f400000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
+ Selection:
+ collapsed: false
+ Tool Properties:
+ collapsed: false
+ Views:
+ collapsed: false
+ Width: 1200
+ X: 67
+ Y: 60
diff --git a/ros2/src/ydlidar_ros2_driver/details.md b/ros2/src/ydlidar_ros2_driver/details.md
new file mode 100644
index 0000000..04b1edb
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/details.md
@@ -0,0 +1,133 @@
+# ROS Paramters Table
+
+## Dataset
+
+| LIDAR | Model | Baudrate | SampleRate(K) | Range(m) | Frequency(HZ) | Intenstiy(bit) | SingleChannel | voltage(V)
+ |
|---|
| F4 | 1 | 115200 | 4 | 0.12~12 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| S4 | 4 | 115200 | 4 | 0.10~8.0 | 5~12 (PWM) | false | false | 4.8~5.2
+ |
|---|
| S4B | 4/11 | 153600 | 4 | 0.10~8.0 | 5~12(PWM) | true(8) | false | 4.8~5.2
+ |
|---|
| S2 | 4/12 | 115200 | 3 | 0.10~8.0 | 4~8(PWM) | false | true | 4.8~5.2
+ |
|---|
| G4 | 5 | 230400 | 9/8/4 | 0.28/0.26/0.1~16 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| X4 | 6 | 128000 | 5 | 0.12~10 | 5~12(PWM) | false | false | 4.8~5.2
+ |
|---|
| X2/X2L | 6 | 115200 | 3 | 0.10~8.0 | 4~8(PWM) | false | true | 4.8~5.2
+ |
|---|
| G4PRO | 7 | 230400 | 9/8/4 | 0.28/0.26/0.1~16 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| F4PRO | 8 | 230400 | 4/6 | 0.12~12 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| R2 | 9 | 230400 | 5 | 0.12~16 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G6 | 13 | 512000 | 18/16/8 | 0.28/0.26/0.1~25 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G2A | 14 | 230400 | 5 | 0.12~12 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G2 | 15 | 230400 | 5 | 0.28~16 | 5~12 | true(8) | false | 4.8~5.2
+ |
|---|
| G2C | 16 | 115200 | 4 | 0.1~12 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G4B | 17 | 512000 | 10 | 0.12~16 | 5~12 | true(10) | false | 4.8~5.2
+ |
|---|
| G4C | 18 | 115200 | 4 | 0.1~12 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G1 | 19 | 230400 | 9 | 0.28~16 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G5 | 20 | 230400 | 9/8/4 | 0.28/0.26/0.1~16 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| G7 | 21 | 512000 | 18/16/8 | 0.28/0.26/0.1~25 | 5~12 | false | false | 4.8~5.2
+ |
|---|
| TX8 | 100 | 115200 | 4 | 0.05~8 | 4~8(PWM) | false | true | 4.8~5.2
+ |
|---|
| TX20 | 100 | 115200 | 4 | 0.05~20 | 4~8(PWM) | false | true | 4.8~5.2
+ |
|---|
| TG15 | 100 | 512000 | 20/18/10 | 0.05~30 | 3~16 | false | false | 4.8~5.2
+ |
|---|
| TG30 | 101 | 512000 | 20/18/10 | 0.05~30 | 3~16 | false | false | 4.8~5.2
+ |
|---|
| TG50 | 102 | 512000 | 20/18/10 | 0.05~50 | 3~16 | false | false | 4.8~5.2
+ |
|---|
| T15 | 200 | 8000 | 20 | 0.05~30 | 5~35 | true | false | 4.8~5.2
+ |
|---|
+
+## Baudrate Table
+
+| LiDAR | baudrate |
+|-----------------------------------------------|-----------------------|
+|F4/S2/X2/X2L/S4/TX8/TX20/G4C | 115200 |
+|X4 | 128000 |
+|S4B | 153600 |
+|G1/G2/R2/G4/G5/G4PRO/F4PRO | 230400 |
+|G6/G7/TG15/TG30/TG50 | 512000 |
+|T5/T15 | 8000 (network port) |
+
+
+## SingleChannel Table
+
+| LiDAR | isSingleChannel |
+|-----------------------------------------------------------|-----------------------|
+|G1/G2/G4/G5/G6/G7/F4/F4PRO/S4/S4B/X4/R2/G4C | false |
+|S2/X2/X2L | true |
+|TG15/TG30/TG50 | false |
+|TX8/TX20 | true |
+|T5/T15 | false (optional) |
+
+
+## LidarType Table
+
+| LiDAR | lidar_type |
+|-----------------------------------------------------------------------|-----------------------|
+|G1/G2/G4/G5/G6/G7/F4/F4PRO/S4/S4B/X4/R2/G4C/S2/X2/X2L | TYPE_TRIANGLE |
+|TG15/TG30/TG50/TX8/TX20 | TYPE_TOF |
+|T5/T15 | TYPE_TOF_NET |
+
+## DeviceType Table
+
+| LiDAR | lidar_type |
+|-----------------------------------------------------------------------|-----------------------|
+|G1/G2/G4/G5/G6/G7/F4/F4PRO/S4/S4B/X4/R2/G4C/S2/X2/X2L | YDLIDAR_TYPE_SERIAL |
+|TG15/TG30/TG50/TX8/TX20 | YDLIDAR_TYPE_SERIAL |
+|T5/T15 | YDLIDAR_TYPE_TCP |
+
+
+## Sampling Rate Table
+
+| LiDAR | sample_rate |
+|-----------------------------|------------------------|
+|G4/G5/F4 | 4,8,9 |
+|F4PRO | 4,6 |
+|G6/G7 | 8,16,18 |
+|G2/R2/X4 | 5 |
+|G1 | 9 |
+|S4/S4B/G4C/TX8/TX20 | 4 |
+|S2 | 3 |
+|TG15/TG30/TG50 | 10,18,20 |
+|T5/T15 | 20 |
+
+
+## Frequency Table
+
+| LiDAR | frequency |
+|-----------------------------------------------|------------------------|
+|G1/G2/R2/G6/G7/G4/G5/G4PRO/F4/F4PRO | 5-12Hz |
+|S4/S4B/S2/TX8/TX20/X4 | Not Support |
+|TG15/TG30/TG50 | 3-16Hz |
+|T5/T15 | 5-35Hz |
+
+Note: For unsupported LiDARs, adjusting the scanning frequency requires external access to PWM speed control.
+
+## Reversion Table
+
+ | LiDAR | reversion
+ |
|---|
| G1/G2/G2A/G2C/F4/F4PRO/R2 | true
+ |
|---|
| G4/G5/G4PRO/G4B/G4C/G6/G7 | true
+ |
|---|
| TG15/TG30/TG50 | true
+ |
|---|
| T5/T15 | true
+ |
|---|
| S2/X2/X2L/X4/S4/S4B | false
+ |
|---|
| TX8/TX20 | false
+ |
|---|
+
+## Intensity Table
+
+ | LiDAR | intensity
+ |
|---|
| S4B/G2/G4B | true
+ |
|---|
| G4/G5/G4C/G4PRO/F4/F4PRO/G6/G7 | false
+ |
|---|
| G1/G2A/G2C/R2 | false
+ |
|---|
| S2/X2/X2L/X4 | false
+ |
|---|
| TG15/TG30/TG50 | false
+ |
|---|
| TX8/TX20 | false
+ |
|---|
| T5/T15 | true
+ |
|---|
| | false
+ |
|---|
+
+## DTR Support Table
+
+
+ | LiDAR | support_motor_dtr
+ |
|---|
| S4/S4B/S2/X2/X2L/X4 | true
+ |
|---|
| TX8/TX20 | true
+ |
|---|
| G4/G5/G4C/G4PRO/F4/F4PRO/G6/G7 | false
+ |
|---|
| G1/G2A/G2C/R2/G2/G4B | false
+ |
|---|
| TG15/TG30/TG50 | false
+ |
|---|
| T5/T15 | false
+ |
|---|
diff --git a/ros2/src/ydlidar_ros2_driver/images/EAI.png b/ros2/src/ydlidar_ros2_driver/images/EAI.png
new file mode 100644
index 0000000..5dee9e2
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/EAI.png differ
diff --git a/ros2/src/ydlidar_ros2_driver/images/YDLidar.jpg b/ros2/src/ydlidar_ros2_driver/images/YDLidar.jpg
new file mode 100644
index 0000000..d764165
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/YDLidar.jpg differ
diff --git a/ros2/src/ydlidar_ros2_driver/images/cmake_error.png b/ros2/src/ydlidar_ros2_driver/images/cmake_error.png
new file mode 100644
index 0000000..169970a
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/cmake_error.png differ
diff --git a/ros2/src/ydlidar_ros2_driver/images/finished.png b/ros2/src/ydlidar_ros2_driver/images/finished.png
new file mode 100644
index 0000000..260c306
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/finished.png differ
diff --git a/ros2/src/ydlidar_ros2_driver/images/rviz.png b/ros2/src/ydlidar_ros2_driver/images/rviz.png
new file mode 100644
index 0000000..c2a016b
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/rviz.png differ
diff --git a/ros2/src/ydlidar_ros2_driver/images/view.png b/ros2/src/ydlidar_ros2_driver/images/view.png
new file mode 100644
index 0000000..ad821de
Binary files /dev/null and b/ros2/src/ydlidar_ros2_driver/images/view.png differ
diff --git a/ros2/src/ydlidar_ros2_driver/launch/ydlidar.py b/ros2/src/ydlidar_ros2_driver/launch/ydlidar.py
new file mode 100644
index 0000000..3a80766
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/launch/ydlidar.py
@@ -0,0 +1,29 @@
+from launch.exit_handler import ignore_exit_handler, restart_exit_handler
+from ros2run.api import get_executable_path
+
+
+def launch(launch_descriptor, argv):
+ ld = launch_descriptor
+ package = 'ydlidar_ros2_driver'
+ ld.add_process(
+ cmd=[get_executable_path(package_name=package, executable_name='ydlidar_ros2_driver_node')],
+ name='ydlidar_ros2_driver_node',
+ exit_handler=restart_exit_handler,
+ )
+ package = 'tf2_ros'
+ ld.add_process(
+ # The XYZ/Quat numbers for base_link -> laser_frame are taken from the
+ # turtlebot URDF in
+ # https://github.com/turtlebot/turtlebot/blob/931d045/turtlebot_description/urdf/sensors/astra.urdf.xacro
+ cmd=[
+ get_executable_path(
+ package_name=package, executable_name='static_transform_publisher'),
+ '0', '0', '0.02',
+ '0', '0', '0', '1',
+ 'base_link',
+ 'laser_frame'
+ ],
+ name='static_tf_pub_laser',
+ exit_handler=restart_exit_handler,
+ )
+ return ld
diff --git a/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch.py b/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch.py
new file mode 100644
index 0000000..0e61325
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python3
+# Copyright 2020, EAIBOT
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_index_python.packages import get_package_share_directory
+
+from launch import LaunchDescription
+from launch_ros.actions import LifecycleNode
+from launch_ros.actions import Node
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch.actions import LogInfo
+
+import lifecycle_msgs.msg
+import os
+
+
+def generate_launch_description():
+ share_dir = get_package_share_directory('ydlidar_ros2_driver')
+ parameter_file = LaunchConfiguration('params_file')
+ node_name = 'ydlidar_ros2_driver_node'
+
+ params_declare = DeclareLaunchArgument('params_file',
+ default_value=os.path.join(
+ share_dir, 'params', 'TminiPro.yaml'),
+ description='FPath to the ROS2 parameters file to use.')
+
+ driver_node = LifecycleNode(package='ydlidar_ros2_driver',
+ executable='ydlidar_ros2_driver_node',
+ name='ydlidar_ros2_driver_node',
+ output='screen',
+ emulate_tty=True,
+ parameters=[parameter_file],
+ namespace='/',
+ )
+ # tf2_node = Node(package='tf2_ros',
+ # executable='static_transform_publisher',
+ # name='static_tf_pub_laser',
+ # arguments=['0', '0', '0.00','0', '0', '0', '1','base_link','laser_frame'],
+ # )
+
+ return LaunchDescription([
+ params_declare,
+ driver_node,
+ # tf2_node,
+ ])
diff --git a/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch_view.py b/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch_view.py
new file mode 100644
index 0000000..b6306a2
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/launch/ydlidar_launch_view.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+# Copyright 2020, EAIBOTd
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_index_python.packages import get_package_share_directory
+
+from launch import LaunchDescription
+from launch_ros.actions import LifecycleNode
+from launch_ros.actions import Node
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch.actions import LogInfo
+
+import lifecycle_msgs.msg
+import os
+
+
+def generate_launch_description():
+ share_dir = get_package_share_directory('ydlidar_ros2_driver')
+ rviz_config_file = os.path.join(share_dir, 'config','ydlidar.rviz')
+ parameter_file = LaunchConfiguration('params_file')
+ node_name = 'ydlidar_ros2_driver_node'
+
+ params_declare = DeclareLaunchArgument('params_file',
+ default_value=os.path.join(
+ share_dir, 'params', 'TminiPro.yaml'),
+ description='FPath to the ROS2 parameters file to use.')
+
+ driver_node = LifecycleNode(package='ydlidar_ros2_driver',
+ executable='ydlidar_ros2_driver_node',
+ name='ydlidar_ros2_driver_node',
+ output='screen',
+ emulate_tty=True,
+ parameters=[parameter_file],
+ namespace='/',
+ )
+ tf2_node = Node(package='tf2_ros',
+ executable='static_transform_publisher',
+ name='static_tf_pub_laser',
+ arguments=['0', '0', '0.02','0', '0', '0', '1','base_link','laser_frame'],
+ )
+ # rviz2_node = Node(package='rviz2',
+ # executable='rviz2',
+ # name='rviz2',
+ # arguments=['-d', rviz_config_file],
+ # )
+
+ return LaunchDescription([
+ params_declare,
+ driver_node,
+ tf2_node,
+ #rviz2_node,
+ ])
diff --git a/ros2/src/ydlidar_ros2_driver/package.xml b/ros2/src/ydlidar_ros2_driver/package.xml
new file mode 100644
index 0000000..d2f73cc
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/package.xml
@@ -0,0 +1,33 @@
+
+
+
+ ydlidar_ros2_driver
+ 1.0.1
+
+ The ROS2 device driver for YDLIDAR LIDARS
+
+ Tony
+ MIT
+
+ ament_cmake
+
+ rclcpp
+ sensor_msgs
+ visualization_msgs
+ geometry_msgs
+ std_srvs
+
+ rclcpp
+ sensor_msgs
+ visualization_msgs
+ geometry_msgs
+ std_srvs
+
+ ament_cmake_gtest
+ ament_lint_auto
+ ament_lint_common
+
+
+ ament_cmake
+
+
diff --git a/ros2/src/ydlidar_ros2_driver/params/G1.yaml b/ros2/src/ydlidar_ros2_driver/params/G1.yaml
new file mode 100644
index 0000000..5366f27
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/G1.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 230400
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 9
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 16.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/G2.yaml b/ros2/src/ydlidar_ros2_driver/params/G2.yaml
new file mode 100644
index 0000000..7a28662
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/G2.yaml
@@ -0,0 +1,24 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 230400
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 4
+ intensity_bit: 10
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: true
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 16.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/G6.yaml b/ros2/src/ydlidar_ros2_driver/params/G6.yaml
new file mode 100644
index 0000000..da6d3db
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/G6.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 512000
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 18
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 25.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/GS2.yaml b/ros2/src/ydlidar_ros2_driver/params/GS2.yaml
new file mode 100644
index 0000000..8dea53f
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/GS2.yaml
@@ -0,0 +1,24 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 921600
+ lidar_type: 3
+ device_type: 0
+ sample_rate: 9
+ intensity_bit: 0
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 1.0
+ range_min: 0.025
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/TEA.yaml b/ros2/src/ydlidar_ros2_driver/params/TEA.yaml
new file mode 100644
index 0000000..da25c8b
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/TEA.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: 192.168.0.11
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 8090
+ lidar_type: 0
+ device_type: 1
+ sample_rate: 20
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: true
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 50.0
+ range_min: 0.01
+ frequency: 20.0
+ invalid_range_is_inf: false
\ No newline at end of file
diff --git a/ros2/src/ydlidar_ros2_driver/params/TG.yaml b/ros2/src/ydlidar_ros2_driver/params/TG.yaml
new file mode 100644
index 0000000..cf65e8c
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/TG.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 512000
+ lidar_type: 0
+ device_type: 0
+ sample_rate: 20
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 50.0
+ range_min: 0.01
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/TminiPro.yaml b/ros2/src/ydlidar_ros2_driver/params/TminiPro.yaml
new file mode 100644
index 0000000..595155e
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/TminiPro.yaml
@@ -0,0 +1,24 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttylzulaser
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 230400
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 4
+ intensity_bit: 8
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: true
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 12.0
+ range_min: 0.10
+ frequency: 10.0
+ invalid_range_is_inf: true
diff --git a/ros2/src/ydlidar_ros2_driver/params/X2.yaml b/ros2/src/ydlidar_ros2_driver/params/X2.yaml
new file mode 100644
index 0000000..961a451
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/X2.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 115200
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 3
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: true
+ intensity: false
+ support_motor_dtr: true
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 12.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/X4-Pro.yaml b/ros2/src/ydlidar_ros2_driver/params/X4-Pro.yaml
new file mode 100644
index 0000000..8e49fb9
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/X4-Pro.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 128000
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 5
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: true
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 12.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/X4.yaml b/ros2/src/ydlidar_ros2_driver/params/X4.yaml
new file mode 100644
index 0000000..716f2f8
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/X4.yaml
@@ -0,0 +1,23 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 128000
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 5
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: true
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 12.0
+ range_min: 0.1
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/params/ydlidar.yaml b/ros2/src/ydlidar_ros2_driver/params/ydlidar.yaml
new file mode 100644
index 0000000..c576896
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/params/ydlidar.yaml
@@ -0,0 +1,24 @@
+ydlidar_ros2_driver_node:
+ ros__parameters:
+ port: /dev/ttyUSB0
+ frame_id: laser_frame
+ ignore_array: ""
+ baudrate: 230400
+ lidar_type: 1
+ device_type: 0
+ sample_rate: 9
+ intensity_bit: 0
+ abnormal_check_count: 4
+ fixed_resolution: true
+ reversion: true
+ inverted: true
+ auto_reconnect: true
+ isSingleChannel: false
+ intensity: false
+ support_motor_dtr: false
+ angle_max: 180.0
+ angle_min: -180.0
+ range_max: 64.0
+ range_min: 0.01
+ frequency: 10.0
+ invalid_range_is_inf: false
diff --git a/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_client.cpp b/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_client.cpp
new file mode 100644
index 0000000..7bac433
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_client.cpp
@@ -0,0 +1,42 @@
+/*
+ * YDLIDAR SYSTEM
+ * YDLIDAR ROS 2 Node Client
+ *
+ * Copyright 2017 - 2020 EAI TEAM
+ * http://www.eaibot.com
+ *
+ */
+
+#include "rclcpp/rclcpp.hpp"
+#include "sensor_msgs/msg/laser_scan.hpp"
+#include
+
+#define RAD2DEG(x) ((x)*180./M_PI)
+
+static void scanCb(sensor_msgs::msg::LaserScan::SharedPtr scan) {
+ int count = scan->scan_time / scan->time_increment;
+ printf("[YDLIDAR INFO]: I heard a laser scan %s[%d]:\n", scan->header.frame_id.c_str(), count);
+ printf("[YDLIDAR INFO]: angle_range : [%f, %f]\n", RAD2DEG(scan->angle_min),
+ RAD2DEG(scan->angle_max));
+
+ for (int i = 0; i < count; i++) {
+ float degree = RAD2DEG(scan->angle_min + scan->angle_increment * i);
+ printf("[YDLIDAR INFO]: angle-distance : [%f, %f]\n", degree, scan->ranges[i]);
+ }
+}
+
+int main(int argc, char **argv) {
+ rclcpp::init(argc, argv);
+
+ auto node = rclcpp::Node::make_shared("ydlidar_ros2_driver_client");
+
+ auto lidar_info_sub = node->create_subscription(
+ "scan", rclcpp::SensorDataQoS(), scanCb);
+
+ rclcpp::spin(node);
+
+ rclcpp::shutdown();
+
+
+ return 0;
+}
diff --git a/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_node.cpp b/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_node.cpp
new file mode 100644
index 0000000..144ecd4
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/src/ydlidar_ros2_driver_node.cpp
@@ -0,0 +1,266 @@
+/*
+ * YDLIDAR SYSTEM
+ * YDLIDAR ROS 2 Node
+ *
+ * Copyright 2017 - 2020 EAI TEAM
+ * http://www.eaibot.com
+ *
+ */
+
+#ifdef _MSC_VER
+#ifndef _USE_MATH_DEFINES
+#define _USE_MATH_DEFINES
+#endif
+#endif
+
+#include "src/CYdLidar.h"
+#include
+#include
+#include
+#include
+#include "sensor_msgs/msg/point_cloud.hpp"
+#include "rclcpp/clock.hpp"
+#include "rclcpp/rclcpp.hpp"
+#include "rclcpp/time_source.hpp"
+#include "sensor_msgs/msg/laser_scan.hpp"
+#include "std_srvs/srv/empty.hpp"
+#include
+#include
+#include
+#include
+#include
+
+#define ROS2Verision "1.0.1"
+
+
+int main(int argc, char *argv[]) {
+ rclcpp::init(argc, argv);
+
+ auto node = rclcpp::Node::make_shared("ydlidar_ros2_driver_node");
+
+ RCLCPP_INFO(node->get_logger(), "[YDLIDAR INFO] Current ROS Driver Version: %s\n", ((std::string)ROS2Verision).c_str());
+
+ CYdLidar laser;
+ std::string str_optvalue = "/dev/ydlidar";
+ node->declare_parameter("port", str_optvalue);
+ node->get_parameter("port", str_optvalue);
+ ///lidar port
+ laser.setlidaropt(LidarPropSerialPort, str_optvalue.c_str(), str_optvalue.size());
+
+ ///ignore array
+ str_optvalue = "";
+ node->declare_parameter("ignore_array", str_optvalue);
+ node->get_parameter("ignore_array", str_optvalue);
+ laser.setlidaropt(LidarPropIgnoreArray, str_optvalue.c_str(), str_optvalue.size());
+
+ std::string frame_id = "laser_frame";
+ node->declare_parameter("frame_id", frame_id);
+ node->get_parameter("frame_id", frame_id);
+
+ //////////////////////int property/////////////////
+ /// lidar baudrate
+ int optval = 230400;
+ node->declare_parameter("baudrate", optval);
+ node->get_parameter("baudrate", optval);
+ laser.setlidaropt(LidarPropSerialBaudrate, &optval, sizeof(int));
+ /// tof lidar
+ optval = TYPE_TRIANGLE;
+ node->declare_parameter("lidar_type", optval);
+ node->get_parameter("lidar_type", optval);
+ laser.setlidaropt(LidarPropLidarType, &optval, sizeof(int));
+ /// device type
+ optval = YDLIDAR_TYPE_SERIAL;
+ node->declare_parameter("device_type", optval);
+ node->get_parameter("device_type", optval);
+ laser.setlidaropt(LidarPropDeviceType, &optval, sizeof(int));
+ /// sample rate
+ optval = 9;
+ node->declare_parameter("sample_rate", optval);
+ node->get_parameter("sample_rate", optval);
+ laser.setlidaropt(LidarPropSampleRate, &optval, sizeof(int));
+ /// abnormal count
+ optval = 4;
+ node->declare_parameter("abnormal_check_count", optval);
+ node->get_parameter("abnormal_check_count", optval);
+ laser.setlidaropt(LidarPropAbnormalCheckCount, &optval, sizeof(int));
+
+ /// Intenstiy bit count
+ optval = 8;
+ node->declare_parameter("intensity_bit", optval);
+ node->get_parameter("intensity_bit", optval);
+ laser.setlidaropt(LidarPropIntenstiyBit, &optval, sizeof(int));
+
+ //////////////////////bool property/////////////////
+ /// fixed angle resolution
+ bool b_optvalue = false;
+ node->declare_parameter("fixed_resolution", b_optvalue);
+ node->get_parameter("fixed_resolution", b_optvalue);
+ laser.setlidaropt(LidarPropFixedResolution, &b_optvalue, sizeof(bool));
+ /// rotate 180
+ b_optvalue = true;
+ node->declare_parameter("reversion", b_optvalue);
+ node->get_parameter("reversion", b_optvalue);
+ laser.setlidaropt(LidarPropReversion, &b_optvalue, sizeof(bool));
+ /// Counterclockwise
+ b_optvalue = true;
+ node->declare_parameter("inverted", b_optvalue);
+ node->get_parameter("inverted", b_optvalue);
+ laser.setlidaropt(LidarPropInverted, &b_optvalue, sizeof(bool));
+ b_optvalue = true;
+ node->declare_parameter("auto_reconnect", b_optvalue);
+ node->get_parameter("auto_reconnect", b_optvalue);
+ laser.setlidaropt(LidarPropAutoReconnect, &b_optvalue, sizeof(bool));
+ /// one-way communication
+ b_optvalue = false;
+ node->declare_parameter("isSingleChannel", b_optvalue);
+ node->get_parameter("isSingleChannel", b_optvalue);
+ laser.setlidaropt(LidarPropSingleChannel, &b_optvalue, sizeof(bool));
+ /// intensity
+ b_optvalue = false;
+ node->declare_parameter("intensity", b_optvalue);
+ node->get_parameter("intensity", b_optvalue);
+ laser.setlidaropt(LidarPropIntenstiy, &b_optvalue, sizeof(bool));
+ /// Motor DTR
+ b_optvalue = false;
+ node->declare_parameter("support_motor_dtr", b_optvalue);
+ node->get_parameter("support_motor_dtr", b_optvalue);
+ laser.setlidaropt(LidarPropSupportMotorDtrCtrl, &b_optvalue, sizeof(bool));
+
+ //////////////////////float property/////////////////
+ /// unit: °
+ float f_optvalue = 180.0f;
+ node->declare_parameter("angle_max", f_optvalue);
+ node->get_parameter("angle_max", f_optvalue);
+ laser.setlidaropt(LidarPropMaxAngle, &f_optvalue, sizeof(float));
+ f_optvalue = -180.0f;
+ node->declare_parameter("angle_min", f_optvalue);
+ node->get_parameter("angle_min", f_optvalue);
+ laser.setlidaropt(LidarPropMinAngle, &f_optvalue, sizeof(float));
+ /// unit: m
+ f_optvalue = 64.f;
+ node->declare_parameter("range_max", f_optvalue);
+ node->get_parameter("range_max", f_optvalue);
+ laser.setlidaropt(LidarPropMaxRange, &f_optvalue, sizeof(float));
+ f_optvalue = 0.1f;
+ node->declare_parameter("range_min", f_optvalue);
+ node->get_parameter("range_min", f_optvalue);
+ laser.setlidaropt(LidarPropMinRange, &f_optvalue, sizeof(float));
+ /// unit: Hz
+ f_optvalue = 10.f;
+ node->declare_parameter("frequency", f_optvalue);
+ node->get_parameter("frequency", f_optvalue);
+ laser.setlidaropt(LidarPropScanFrequency, &f_optvalue, sizeof(float));
+
+ bool invalid_range_is_inf = false;
+ node->declare_parameter("invalid_range_is_inf", invalid_range_is_inf);
+ node->get_parameter("invalid_range_is_inf", invalid_range_is_inf);
+
+
+ bool ret = laser.initialize();
+ if (ret) {
+ ret = laser.turnOn();
+ } else {
+ RCLCPP_ERROR(node->get_logger(), "%s\n", laser.DescribeError());
+ }
+
+ auto laser_pub = node->create_publisher("scan", rclcpp::SensorDataQoS());
+ auto pc_pub = node->create_publisher("point_cloud", rclcpp::SensorDataQoS());
+
+ auto stop_scan_service =
+ [&laser](const std::shared_ptr request_header,
+ const std::shared_ptr req,
+ std::shared_ptr response) -> bool
+ {
+ return laser.turnOff();
+ };
+
+ auto stop_service = node->create_service("stop_scan",stop_scan_service);
+
+ auto start_scan_service =
+ [&laser](const std::shared_ptr request_header,
+ const std::shared_ptr req,
+ std::shared_ptr response) -> bool
+ {
+ return laser.turnOn();
+ };
+
+ auto start_service = node->create_service("start_scan",start_scan_service);
+
+ rclcpp::WallRate loop_rate(20);
+
+ while (ret && rclcpp::ok()) {
+
+ LaserScan scan;//
+
+ if (laser.doProcessSimple(scan)) {
+
+ auto scan_msg = std::make_shared();
+ auto pc_msg = std::make_shared();
+ scan_msg->header.stamp = node->now();//this->now();
+ //scan_msg->header.stamp.sec = RCL_NS_TO_S(scan.stamp);
+ //scan_msg->header.stamp.nanosec = scan.stamp - RCL_S_TO_NS(scan_msg->header.stamp.sec);
+ scan_msg->header.frame_id = frame_id;
+ pc_msg->header = scan_msg->header;
+ scan_msg->angle_min = scan.config.min_angle;
+ scan_msg->angle_max = scan.config.max_angle;
+ scan_msg->angle_increment = scan.config.angle_increment;
+ scan_msg->scan_time = scan.config.scan_time;
+ scan_msg->time_increment = scan.config.time_increment;
+ scan_msg->range_min = scan.config.min_range;
+ scan_msg->range_max = scan.config.max_range;
+
+ int size = (scan.config.max_angle - scan.config.min_angle)/ scan.config.angle_increment + 1;
+ const float invalid_range_value =
+ invalid_range_is_inf ? std::numeric_limits::infinity() : 0.0f;
+ scan_msg->ranges.assign(size, invalid_range_value);
+ scan_msg->intensities.assign(size, 0.0f);
+
+ pc_msg->channels.resize(2);
+ int idx_intensity = 0;
+ pc_msg->channels[idx_intensity].name = "intensities";
+ int idx_timestamp = 1;
+ pc_msg->channels[idx_timestamp].name = "stamps";
+
+ for(size_t i=0; i < scan.points.size(); i++) {
+ int index = std::ceil((scan.points[i].angle - scan.config.min_angle)/scan.config.angle_increment);
+ if(index >=0 && index < size) {
+ if (scan.points[i].range >= scan.config.min_range) {
+ scan_msg->ranges[index] = scan.points[i].range;
+ scan_msg->intensities[index] = scan.points[i].intensity;
+ }
+ }
+
+ if (scan.points[i].range >= scan.config.min_range &&
+ scan.points[i].range <= scan.config.max_range) {
+ geometry_msgs::msg::Point32 point;
+ point.x = scan.points[i].range * cos(scan.points[i].angle);
+ point.y = scan.points[i].range * sin(scan.points[i].angle);
+ point.z = 0.0;
+ pc_msg->points.push_back(point);
+ pc_msg->channels[idx_intensity].values.push_back(scan.points[i].intensity);
+ pc_msg->channels[idx_timestamp].values.push_back(i * scan.config.time_increment);
+ }
+
+ }
+
+ laser_pub->publish(*scan_msg);
+ pc_pub->publish(*pc_msg);
+
+ } else {
+ RCLCPP_ERROR(node->get_logger(), "Failed to get scan");
+ }
+ if(!rclcpp::ok()) {
+ break;
+ }
+ rclcpp::spin_some(node);
+ loop_rate.sleep();
+ }
+
+
+ RCLCPP_INFO(node->get_logger(), "[YDLIDAR INFO] Now YDLIDAR is stopping .......");
+ laser.turnOff();
+ laser.disconnecting();
+ rclcpp::shutdown();
+
+ return 0;
+}
diff --git a/ros2/src/ydlidar_ros2_driver/startup/initenv.sh b/ros2/src/ydlidar_ros2_driver/startup/initenv.sh
new file mode 100755
index 0000000..9b5c1d0
--- /dev/null
+++ b/ros2/src/ydlidar_ros2_driver/startup/initenv.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo 'KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar"' >/etc/udev/rules.d/ydlidar.rules
+
+echo 'KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar"' >/etc/udev/rules.d/ydlidar-V2.rules
+
+echo 'KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar"' >/etc/udev/rules.d/ydlidar-2303.rules
+
+service udev reload
+sleep 2
+service udev restart
+