当前位置: 首页 > news >正文

树莓派5-ubuntu24.04 LTS 使用python构建雷达驱动包

1.环境:

(1)树莓派5,安装的系统环境为:ubuntu24.04 LTS,ros环境为:ros-jazzy-desktop

(2)雷达:YDLIDAR X3 Pro,波特率:115200

由于最近要使用树莓派+激光雷达实现slam建图,尝试过以下两个路径安装的激光雷达都没有用,各种报错无法读取雷达数据,大概可能的兼容性的问题。

git clone https://github.com/YDLIDAR/ydlidar_ros2.git

git clone https://github.com/YDLIDAR/ydlidar_ros2_driver.git

于是就使用python进行直接手撸一个,不使用git上他们开源的,特此记录一下踩坑记录

2.开始构建(确保已经安装了 ros2环境)

确保 ROS 2 环境已激活,例如我这里创建的ros2工作空间为:~/ros2_ws,先到这个路径的src目录下去:

cd ~/ros2_ws/src

然后执行下面的命令激活

source install/setup.bash

然后创建雷达驱动功能包,例如我这里创建的名称为:ydlidar_python_driver 

ros2 pkg create ydlidar_python_driver --build-type ament_python --dependencies rclpy sensor_msgs geometry_msgs pyserial

创建完成后,进入到该目录下去,看到的结构为:

ydlidar_python_driver/
├── ydlidar_python_driver/       # 核心代码目录
│   ├── __init__.py
│   └── lidar_driver_node.py     # 后续创建的驱动节点(核心文件)
├── resource/
│   └── ydlidar_python_driver
├── test/                        # 测试文件目录
├── package.xml                  # 依赖与包信息配置
├── setup.cfg                    # Python 包配置
└── setup.py                     # 编译配置(关键)

3.在 /home/lyl/ros2_ws/src/ydlidar_python_driver/ydlidar_python_driver 这个路径下,新建一个py文件名为:ydlidar_x3_pro.py,复制下面的代码粘贴进去

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import LaserScan
import serial
import struct
import timeclass YDLidarX3ProNode(Node):def __init__(self):super().__init__("ydlidar_x3_pro_node")self.declare_parameter("port", "/dev/ttyUSB0")self.declare_parameter("baudrate", 115200)self.declare_parameter("frame_id", "laser_frame")# 获取参数self.port = self.get_parameter("port").valueself.baudrate = self.get_parameter("baudrate").valueself.frame_id = self.get_parameter("frame_id").value# 创建发布者(发布 /scan 话题)self.scan_pub = self.create_publisher(LaserScan, "scan", 10)# 初始化串口try:self.ser = serial.Serial(port=self.port,baudrate=self.baudrate,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0.1)self.get_logger().info(f"✅ 串口连接成功:{self.port} ({self.baudrate})")except Exception as e:self.get_logger().error(f"❌ 串口连接失败:{str(e)}")rclpy.shutdown()return# 定时读取串口数据(20Hz)self.timer = self.create_timer(0.05, self.read_serial_data)# 激光扫描参数(X3 Pro 官方参数)self.angle_min = -3.14159  # -180°(弧度)self.angle_max = 3.14159   # 180°(弧度)self.angle_increment = 0.01745  # 1°(弧度)self.range_min = 0.05      # 最小测距 0.05mself.range_max = 12.0      # 最大测距 12mself.scan_time = 0.1       # 扫描周期 0.1s(10Hz)# 初始化测距数据数组(360 个点,对应 0-360°)self.ranges = [self.range_max] * 360self.intensities = [0] * 360def read_serial_data(self):# 读取串口数据(X3 Pro 单帧数据约 1000 字节)if self.ser.in_waiting > 100:data = self.ser.read(self.ser.in_waiting)self.parse_data(data)def parse_data(self, data):# X3 Pro 数据帧格式:0x55 0xAA 开头,后续为角度+距离+强度idx = 0while idx < len(data) - 10:# 查找帧头(0x55 0xAA)if data[idx] == 0x55 and data[idx+1] == 0xAA:# 解析角度(2 字节)、距离(2 字节)、强度(1 字节)if idx + 6 <= len(data):angle = struct.unpack("<H", data[idx+2:idx+4])[0] / 100.0  # 角度:0-360°distance = struct.unpack("<H", data[idx+4:idx+6])[0] / 1000.0  # 距离:mintensity = data[idx+6]  # 强度:0-255# 转换为数组索引(0-359)angle_idx = int(round(angle)) % 360# 过滤无效数据if self.range_min <= distance <= self.range_max:self.ranges[angle_idx] = distanceself.intensities[angle_idx] = intensityelse:self.ranges[angle_idx] = self.range_maxself.intensities[angle_idx] = 0idx += 7  # 帧长度:7 字节(帧头 2 + 角度 2 + 距离 2 + 强度 1)else:idx += 1else:idx += 1# 发布激光扫描数据self.publish_scan()def publish_scan(self):scan_msg = LaserScan()scan_msg.header.stamp = self.get_clock().now().to_msg()scan_msg.header.frame_id = self.frame_idscan_msg.angle_min = self.angle_minscan_msg.angle_max = self.angle_maxscan_msg.angle_increment = self.angle_incrementscan_msg.scan_time = self.scan_timescan_msg.time_increment = self.scan_time / 360.0scan_msg.range_min = self.range_minscan_msg.range_max = self.range_maxscan_msg.ranges = self.rangesscan_msg.intensities = self.intensitiesself.scan_pub.publish(scan_msg)def main(args=None):rclpy.init(args=args)node = YDLidarX3ProNode()rclpy.spin(node)node.ser.close()node.destroy_node()rclpy.shutdown()if __name__ == "__main__":main()

这段代码主要实现了雷达串口通信、数据解析、ROS 2 激光点云 / 扫描消息发布,适配常见 YDLIDAR 型号如:X3,X4等。

4.修改 /home/lyl/ros2_ws/src/ydlidar_python_driver 这个路径下的 setup.py文件中的console_scripts,让 ROS 2 识别驱动节点。

from setuptools import setuppackage_name = 'ydlidar_python_driver'setup(name=package_name,version='0.0.0',packages=[package_name],data_files=[('share/ament_index/resource_index/packages',['resource/' + package_name]),('share/' + package_name, ['package.xml']),],install_requires=['setuptools'],zip_safe=True,maintainer='lyl',maintainer_email='lyl@example.com',description='Python driver for YDLIDAR X3 Pro (ROS2 Jazzy)',license='Apache-2.0',tests_require=['pytest'],entry_points={'console_scripts': [# 关键:添加节点入口,允许 ros2 run 启动'ydlidar_x3_pro_node = ydlidar_python_driver.ydlidar_x3_pro:main',],},
)

5.修改 /home/lyl/ros2_ws/src/ydlidar_python_driver 路径下的 package.xml 文件,补充依赖信息,例如:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3"><name>ydlidar_python_driver</name><version>0.0.0</version><description>TODO: Package description</description><maintainer email="lyl@todo.todo">lyl</maintainer><license>TODO: License declaration</license><depend>rclpy</depend><depend>sensor_msgs</depend><depend>geometry_msgs</depend><depend>pyserial</depend><test_depend>ament_copyright</test_depend><test_depend>ament_flake8</test_depend><test_depend>ament_pep257</test_depend><test_depend>python3-pytest</test_depend><export><build_type>ament_python</build_type></export>
</package>

6.编译功能包

cd ~/ros2_ws

然后

colcon build --packages-select ydlidar_python_driver  # 只编译当前功能包

编译完成后,重启激活环境,再测试就正常了

这里只是大概记录的雷达相关的,要完整的使用ros2建图,还需要创建机器人导航功能包:robot_navigation 流程与上面的一样,我这里就不重复记录了,直接贴上对应要修改的文件内容,确保已经创建了 robot_navigation 的目录结构

7.修改 /home/lyl/ros2_ws/src/robot_navigation 路径下的 setup.py文件

import os
import glob
from setuptools import setuppackage_name = 'robot_navigation'setup(name=package_name,version='0.0.0',packages=[package_name],data_files=[('share/ament_index/resource_index/packages',['resource/' + package_name]),('share/' + package_name, ['package.xml']),(os.path.join('share', package_name, 'launch'), glob.glob('launch/*.py')),(os.path.join('share', package_name, 'config'), glob.glob('config/*.yaml')),(os.path.join('share', package_name, 'maps'), glob.glob('maps/*')),],install_requires=['setuptools'],zip_safe=True,maintainer='lyl',maintainer_email='lyl@example.com',description='Robot navigation package for SLAM and path planning',license='Apache License 2.0',tests_require=['pytest'],entry_points={'console_scripts': [],},
)

还有

package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3"><name>robot_navigation</name><version>0.0.0</version><description>TODO: Package description</description><maintainer email="lyl@todo.todo">lyl</maintainer><license>TODO: License declaration</license><depend>rclpy</depend><depend>launch_ros</depend><depend>nav2_bringup</depend><depend>slam_toolbox</depend><test_depend>ament_copyright</test_depend><test_depend>ament_flake8</test_depend><test_depend>ament_pep257</test_depend><test_depend>python3-pytest</test_depend><export><build_type>ament_python</build_type></export>
</package>

最后去:/home/lyl/ros2_ws/src/robot_navigation/launch 路径下新建一个文件:official_slam_launch.py 粘贴下面代码:

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
import osdef generate_launch_description():# 激光雷达参数lidar_port = LaunchConfiguration('lidar_port', default='/dev/ttyUSB0')lidar_baudrate = LaunchConfiguration('lidar_baudrate', default='115200')# SLAM 核心参数(直接内置,无需外部配置文件)slam_params = {'use_sim_time': False,'scan_topic': '/scan','mode': 'mapping','map_frame': 'map','base_frame': 'base_link','odom_frame': 'odom','minimum_travel_distance': 0.0,'minimum_travel_heading': 0.0,'resolution': 0.05,'max_laser_range': 12.0,'do_loop_closing': False,  # 关闭闭环,减少初始化压力'solver_plugin': 'solver_plugins::CeresSolver'}return LaunchDescription([# 声明启动参数DeclareLaunchArgument('lidar_port', default_value=lidar_port, description='Laser port'),DeclareLaunchArgument('lidar_baudrate', default_value=lidar_baudrate, description='Laser baudrate'),# 1. TF 变换节点(完整链路)Node(package='tf2_ros',executable='static_transform_publisher',arguments=['0', '0', '0', '0', '0', '0', 'odom', 'base_link'],name='tf_odom_base'),Node(package='tf2_ros',executable='static_transform_publisher',arguments=['0', '0', '0.05', '0', '0', '0', 'base_link', 'laser_frame'],name='tf_base_laser'),# 2. 激光雷达节点Node(package='ydlidar_python_driver',executable='ydlidar_x3_pro_node',name='ydlidar_node',parameters=[{'port': lidar_port,'baudrate': lidar_baudrate,'frame_id': 'laser_frame','use_sim_time': False}]),# 3. SLAM Toolbox 节点(官方推荐启动方式)Node(package='slam_toolbox',executable='async_slam_toolbox_node',name='slam_toolbox',parameters=[slam_params],output='screen',arguments=['--ros-args', '--log-level', 'info'])])

8.编译并重新激活

cd ~/ros2_ws
colcon build --packages-select robot_navigation
source install/setup.bash

最后就可以使用以下的命令按照顺序去分分别启动实现建图了

# 启动官方配置(一键完成所有节点初始化)
ros2 launch robot_navigation official_slam_launch.py# 验证 SLAM 节点是否订阅 /scan(必须显示 Subscribers: 1)
命令:ros2 topic info /scan# 验证 SLAM 节点状态(应显示 active)
ros2 service call /slam_toolbox/get_state lifecycle_msgs/srv/GetState若 Subscribers: 1 且状态为 active,说明链路已通,直接进入步骤 2
先执行配置过渡命令:
ros2 service call /slam_toolbox/change_state lifecycle_msgs/srv/ChangeState "{transition: {id: 1, label: 'configure'}}"
激活命令:ros2 service call /slam_toolbox/change_state lifecycle_msgs/srv/ChangeState "{transition: {id: 1, label: 'activate'}}"再次执行查询节点命令:ros2 service call /slam_toolbox/get_state lifecycle_msgs/srv/GetState
看到类似的输出表示激活成功:
response:
lifecycle_msgs.srv.GetState_Response(current_state=lifecycle_msgs.msg.State(id=3, label='active'))使用 rviz2 可视化验证
命令:rviz2 -d ~/ros2_ws/src/robot_navigation/config/slam_rviz.rviz
打开后,移动雷达# 创建地图保存目录(若不存在)
mkdir -p ~/ros2_ws/src/robot_navigation/maps
# 保存地图
ros2 service call /slam_toolbox/save_map slam_toolbox/srv/SaveMap "{name: 'final_map', directory: '~/ros2_ws/src/robot_navigation/maps'}"

在这过程中,可能还有提示有一些依赖需要安装,直接用apt命令去安装就可以了,那些都是容易安装上的,我这里就略过了,我也是新手,有问题大家一起交流啊

http://www.dtcms.com/a/617626.html

相关文章:

  • Django Nginx+uWSGI 安装配置指南
  • php网站建设培训班如何在word里做网站
  • 用Rust从零实现一个迷你Redis服务器
  • 图表设计 网站郑州汉狮做网站的公司
  • 详解高可用 SFTP 服务器搭建,适用于文档管理系统、监控系统数据、NFS、FTP、Git 仓库、Web 静态资源高可用服务器等等应用场景
  • 【故障排查】intel 服务器安装Win server 2019蓝屏解决方法
  • Vue入门到实战(day7):Vuex 与 Vue Router 深度解析,从原理到实战的前端状态与路由管理(附代码案例)
  • 3种数据模型的演变
  • Highcharts常见问题解析(5):可以在服务器上使用 Highcharts 吗?如何正确集成?
  • 用 Node.js 手动搭建 HTTP 服务器:从零开始的 Web 开发之旅!
  • 前端使用 React Query 管理“服务器状态”
  • 佛山cms建站帮人做兼职的网站
  • Spring Boot的web基础配置
  • 下载网站上的表格 怎么做天津市建设工程质量安全监督管理总队网站
  • 【Linux日新月异(八)】CentOS 7系统资源监控与排查深度指南:性能调优全景图
  • word中怎么查看插入的图片占用内存大小来压缩word文件整体大小
  • Flink CDC + MaxCompute用 MaxCompute Connector 打通实时入湖通道
  • 【AI 学习】AI Agent 开发进阶:架构、规划、记忆与工具编排
  • 二十三、Transformer架构详解
  • JAR逆向工程实战对比:传统工具 vs 自动化解决方案
  • 算法学习--离散化
  • 沈阳住房和城乡建设厅网站越南语网站怎么做
  • React + ECharts 实践:构建可交互的数据可视化组件
  • Devconnect 活动报名中!dAI 路线图、跨链 / 预言机创新新动态!Linera 实战+Web3 安全公开课上线!
  • 华为、阿里巴巴、字节跳动 100+ Linux面试问题总结(一)
  • [OpenHarmony6.0][Docker][环境]OHOS6 编译环境构建指南
  • 空包网站建设属于哪类网站排名优化推广厦门
  • async await 的前世今生
  • 外卖项目day02
  • 多电压输出场景下ASP3605负载调整率的一致性验证