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

渡水无言:个人主页渡水无言
❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》
❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》《linux裸机开发专栏》
❄专栏传送门:《产品测评专栏》 《Ai智能体专栏) 《ROS开发专栏》
⭐️流水不争先,争的是滔滔不绝博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生
| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生
在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

目录
- ROS2激光雷达数据基础
- 在RViz2中查看激光雷达数据
- 激光雷达数据获取实战
- 总结与扩展
一、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 Frame为base_link或base_footprint,然后点击左下角Add按钮,选择RobotModel并确认。接着,在RobotModel的Description 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菜单栏的File → Save Config As:

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

下次启动RViz2时,点击File → Open 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数组的中间元素(即正前方角度对应的距离)。 - 如果距离为
inf或nan,则输出“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_executable和target_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)。此外,许多现代机器人项目也使用TypeScript或Go编写ROS2客户端库,但C++和Python仍是主流。如果你熟悉Java,也可以尝试使用ROS2的Java绑定。
[AFFILIATE_SLOT_2]希望本文能帮助你快速上手ROS2激光雷达开发。如果你有任何问题或建议,欢迎在评论区留言交流!
浙公网安备 33010602011771号