在机器人自主导航中,激光雷达(LiDAR)就像机器人的“眼睛”,实时感知周围环境。本文将带你从零开始,在ROS2环境下完成激光雷达数据的仿真获取、RViz2可视化,并编写C++节点订阅/scan话题,打印正前方障碍物距离。适配Ubuntu 22.04,适合刚入门ROS2的开发者。

渡水无言个人主页渡水无言

专栏传送门: linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》

专栏传送门freertos专栏》《STM32 HAL库专栏》《linux裸机开发专栏

专栏传送门《产品测评专栏》    《Ai智能体专栏)      《ROS开发专栏
⭐️流水不争先,争的是滔滔不绝

博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生

| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生

在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

目录

  1. ROS2激光雷达数据基础
  2. 在RViz2中查看激光雷达数据
  3. 激光雷达数据获取实战
  4. 总结与扩展

一、ROS2激光雷达数据基础

激光雷达通过旋转的激光测距探头,在360°范围内每隔一定角度测量一次距离值。旋转一圈后,即可获得一组均匀的测距采样,这就是激光雷达的输出数据。在ROS2中,激光雷达数据遵循REP‑138标准,话题名为/scan,消息类型为sensor_msgs::msg::LaserScan

LaserScan消息的关键字段如下:

header           # 时间戳与坐标系
angle_min        # 起始角度(弧度)
angle_max        # 终止角度(弧度)
angle_increment  # 角度步长
range_min        # 最小测距(m)
range_max        # 最大测距(m)
ranges[]         # 距离数组(核心数据)
intensities[]    # 信号强度

其中,ranges数组存储了每个角度的障碍物距离,是我们最常使用的字段。 提示:在编写订阅节点时,通常通过ranges数组获取正前方(角度为0)的距离值。

二、在RViz2中查看激光雷达数据

2.1 启动仿真环境

首先,我们需要启动Gazebo仿真环境,加载一个带有激光雷达的机器人模型。执行以下命令:

ros2 launch wpr_simulation2 wpb_simple.launch.py

启动后,你将看到类似下图的仿真场景:

2.2 打开RViz2

RViz2是ROS2提供的图形化工具,可以直观显示传感器数据。打开第二个终端窗口,输入:

source ~/ros2_ws/install/setup.bash
rviz2

执行后,会弹出RViz2主窗口:

2.3 使用RViz2

⚠️ 注意:使用RViz2前,必须确保Gazebo仿真环境已经启动,并且话题/scan有数据发布。验证方法:

ros2 launch wpr_simulation2 wpb_simple.launch.py

确认话题存在后,重新打开RViz2:

rviz2

在RViz2中,先修改Fixed Framebase_linkbase_footprint,然后点击左下角Add按钮,选择RobotModel并确认。接着,在RobotModelDescription Topic下拉框中,选择:

/robot_description

这样就能看到机器人的3D模型了:

接下来,添加激光雷达显示条目。再次点击Add,选择LaserScan

在左侧的LaserScan属性中,将Topic设置为/scan,你会看到前方出现一排红点,代表激光雷达的扫描点:

如果红点太小,可以调整Size参数,增大点的大小:

2.4 RViz与Gazebo的区别和联系

Gazebo是物理仿真环境,负责模拟机器人运动和传感器数据;RViz2是数据可视化工具,用于查看传感器数据。两者通过ROS2话题通信。例如,在Gazebo中添加正方柱体或圆柱体,RViz2中会同步显示激光雷达扫描到的红点:

Gazebo = 真实的赛道 
机器人在这里跑,会撞到墙、会打滑、会被障碍物挡住,一切都是 “真实的”。
RViz = 监控室里的显示屏
你看不到机器人本身,只能看到它的位置、雷达扫到的障碍物、运动轨迹,用来调试和监控。可以直观看到机器人模型和雷达点云,确认数据是否正常

2.5 保存RViz2配置

为了方便下次使用,可以保存当前配置。点击RViz2菜单栏的FileSave Config As

选择保存路径并命名文件:

下次启动RViz2时,点击FileOpen Config,选择之前保存的配置文件即可恢复:

2.6 使用配置文件启动RViz2

也可以直接通过命令行加载配置文件:

rviz2 -d ~/lidar.rviz

执行后,RViz2将直接显示之前保存的配置内容:

三、激光雷达数据获取实战

现在,我们创建一个ROS2功能包lidar_data,编写C++节点订阅/scan话题,并打印正前方障碍物距离。

3.1 创建功能包

在ROS2工作空间中,执行以下命令创建包:

cd ~/ros2_zice/src
ros2 pkg create lidar_pkg

3.2 编写lidar_data.cpp

src目录下创建lidar_data.cpp,代码如下:

#include 
#include 
std::shared_ptr node;
// 雷达回调函数
void LidarCallback(const sensor_msgs::msg::LaserScan::SharedPtr msg)
{
    // 获取雷达数据总个数
    int nNum = msg->ranges.size();
    // 正前方角度对应的索引
    int nMid = nNum / 2;
    // 正前方障碍物距离
    float fMidDist = msg->ranges[nMid];
    // 只打印距离值,nMid 是索引,不用打印
RCLCPP_INFO(node->get_logger(), "前方距离 = %f m", fMidDist);
}
int main(int argc, char** argv)
{
    rclcpp::init(argc, argv);
    node = std::make_shared("lidar_data_node");
    // 订阅 /scan 话题
    auto lidar_sub = node->create_subscription(
        "/scan", 10, LidarCallback);
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

代码说明

  • 订阅/scan话题,回调函数中读取ranges数组的中间元素(即正前方角度对应的距离)。
  • 如果距离为infnan,则输出“No obstacle detected”。
  • 使用RCLCPP_INFO打印到终端。

3.3 配置CMakeLists.txt

编辑CMakeLists.txt,添加编译规则:

cmake_minimum_required(VERSION 3.8)
project(lidar_pkg)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# 查找依赖
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
# 只编译雷达数据获取节点
add_executable(lidar_data src/lidar_data.cpp)
ament_target_dependencies(lidar_data
  rclcpp
  sensor_msgs
)
# 只安装这一个节点
install(TARGETS
  lidar_data
  DESTINATION lib/${PROJECT_NAME}
)
if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  set(ament_cmake_copyright_FOUND TRUE)
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()
ament_package()

提示:如果后续需要增加其他C++节点,可以在add_executabletarget_link_libraries中继续添加。

3.4 配置package.xml

修改package.xml,添加依赖信息:




  lidar_pkg
  0.0.0
  TODO: Package description
  duan
  TODO: License declaration
  ament_cmake
  rclcpp
  sensor_msgs
  ament_lint_auto
  ament_lint_common
  
    ament_cmake
  

3.5 编译软件包

回到工作空间根目录,执行编译:

cd ~/ros2_ws
colcon build
//加载环境
source install/setup.bash

3.6 运行节点

启动仿真环境后,运行节点:

ros2 run lidar_pkg lidar_data

终端将持续打印正前方障碍物距离,效果如下:

✅ 至此,你已经成功完成了激光雷达数据的仿真获取与订阅。

[AFFILIATE_SLOT_1]

四、总结与扩展

本文详细介绍了ROS2激光雷达的数据格式、RViz2可视化方法,以及如何编写C++节点订阅/scan话题获取正前方距离。通过本实战,你掌握了以下技能:

  • 理解LaserScan消息结构,特别是ranges数组的用法。
  • 熟练使用RViz2查看激光雷达数据,并保存/加载配置文件。
  • 编写ROS2 C++节点订阅话题并处理数据。

扩展思考:你可以将此节点与运动控制结合,实现简单的避障功能;或者将数据发送到Python节点进行更复杂的处理(如聚类、SLAM)。此外,许多现代机器人项目也使用TypeScriptGo编写ROS2客户端库,但C++和Python仍是主流。如果你熟悉Java,也可以尝试使用ROS2的Java绑定。

[AFFILIATE_SLOT_2]

希望本文能帮助你快速上手ROS2激光雷达开发。如果你有任何问题或建议,欢迎在评论区留言交流!