在 ROS 中保存 `/scan` 数据(来自 RPLIDAR 等激光雷达)通常有两种常用方法:**ROS Bag 文件**(`.bag`)或**转换为文本格式**(如 CSV、JSON)。以下是具体操作步骤和 Python 读取示例:
---
### 方法 1:使用 ROS Bag 直接保存原始数据
#### 1. 记录 `/scan` 话题
通过 `rosbag record` 命令保存实时数据:
```bash
# 启动 ROS 核心
roscore
# 在新终端中运行雷达节点(假设雷达驱动已安装)
roslaunch rplidar_ros rplidar.launch
# 记录 /scan 话题到名为 "lidar_data.bag" 的文件
rosbag record -O lidar_data.bag /scan
```
#### 2. 回放并使用 Python 读取
安装 Python ROS 依赖(若未安装):
```bash
pip install rospkg rosbag pyyaml
```
Python 读取 `.bag` 文件的示例代码:
```python
import rosbag
from sensor_msgs.msg import LaserScan
# 读取 .bag 文件
bag = rosbag.Bag('lidar_data.bag')
# 遍历所有 /scan 消息
for topic, msg, t in bag.read_messages(topics=['/scan']):
# 提取激光雷达数据
ranges = msg.ranges # 距离数组(单位:米)
angles = [msg.angle_min + i * msg.angle_increment for i in range(len(ranges))] # 角度数组(弧度)
# 处理数据(示例:打印第一个点的距离)
print(f"时间戳: {t.to_sec()}, 第一个点距离: {ranges[0]} 米")
bag.close()
```
---
### 方法 2:保存为 CSV/JSON 格式(更易处理)
#### 1. Python 脚本实时订阅并保存
编写一个 ROS 节点脚本(如 `save_scan.py`):
```python
#!/usr/bin/env python
import rospy
from sensor_msgs.msg import LaserScan
import csv
import time
def scan_callback(msg):
# 提取数据
timestamp = msg.header.stamp.to_sec()
ranges = list(msg.ranges) # 转为列表
angles = [msg.angle_min + i * msg.angle_increment for i in range(len(ranges))]
# 保存为 CSV
with open('scan_data.csv', 'a', newline='') as csvfile:
writer = csv.writer(csvfile)
# 写入时间戳和每个点的角度、距离
for angle, distance in zip(angles, ranges):
writer.writerow([timestamp, angle, distance])
if __name__ == '__main__':
rospy.init_node('scan_saver')
rospy.Subscriber('/scan', LaserScan, scan_callback)
rospy.spin()
```
#### 2. 运行脚本
```bash
chmod +x save_scan.py
./save_scan.py
```
#### 3. 读取 CSV 并处理
用 Python 读取生成的 `scan_data.csv`:
```python
import pandas as pd
# 读取 CSV
df = pd.read_csv('scan_data.csv', header=None, names=['timestamp', 'angle', 'distance'])
# 示例:过滤无效数据(假设无效值为 0)
df = df[df['distance'] > 0]
# 转换为极坐标点(x, y)
df['x'] = df['distance'] * np.cos(df['angle'])
df['y'] = df['distance'] * np.sin(df['angle'])
print(df.head())
```
---
### 关键说明
1. **数据格式选择**:
- **ROS Bag**:保留完整的 ROS 消息结构,适合复杂场景或需要回放原始数据。
- **CSV/JSON**:轻量级、易读,适合直接进行数据分析或机器学习。
2. **LaserScan 消息字段**:
```python
msg.header.stamp # 时间戳
msg.angle_min # 起始角度(弧度)
msg.angle_max # 终止角度(弧度)
msg.angle_increment # 角度分辨率(弧度/点)
msg.ranges # 距离数组(单位:米)
msg.intensities # 强度数组(可选)
```
3. **注意事项**:
- 激光雷达的无效值通常为 `0` 或 `inf`,需在代码中过滤。
- 如果数据量较大,CSV 可能效率较低,建议使用二进制格式(如 HDF5)。
如果需要进一步处理(如可视化或实时显示),可以使用 `matplotlib` 或 `ROS RVIZ` 工具。