运行环境:RDK X5,rdk_os_3.5.0-2026-4-9,tros 2.5.2
单独运行ros2 launch mipi_cam mipi_cam_dual_channel.launch.py,通过ros2 bag record录制,出现多帧时间异常,这个问题要怎么解决。
运行环境:RDK X5,rdk_os_3.5.0-2026-4-9,tros 2.5.2
单独运行ros2 launch mipi_cam mipi_cam_dual_channel.launch.py,通过ros2 bag record录制,出现多帧时间异常,这个问题要怎么解决。
根据你的问题描述和图表分析,这是典型的 MIPI 双通道时间戳异常问题。从你的图表可以看到大量帧的时间戳偏离正常值(蓝色点远高于橙色基准线)。
这个问题在 RDK X5 上使用 GS130WI 双目相机时比较常见,主要原因:
# 降低帧率测试稳定性
ros2 launch mipi_cam mipi_cam_dual_channel.launch.py mipi_image_framerate:=15.0
# 或降低分辨率
ros2 launch mipi_cam mipi_cam_dual_channel.launch.py mipi_image_width:=1280 mipi_image_height:=720
# 使用压缩格式减少 I/O 压力
ros2 bag record -a --compression-mode file --compression-format zstd
# 或只录制必要的话题
ros2 bag record /mipi_left/image_raw /mipi_right/image_raw --compression-mode file
# 1. 监控系统资源
top -d 1
# 2. 查看 CPU 频率是否被限制
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# 3. 设置为性能模式
sudo bash -c "echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor"
# 4. 检查内存使用
free -h
参考 双目相机触发模式文档:
# 确保相机背面开关设置为 EXT 模式(不是 LPWM)
# 然后通过 GPIO 控制触发信号
# 查看当前触发配置
cat /sys/class/gpio/gpio*/value
# 检查当前版本
cat /etc/version
# 如果版本较旧,建议升级到最新镜像
# 下载地址:https://developer.d-robotics.cc/rdk_doc/Quick_start/download/
录制完成后检查时间戳:
# 查看 bag 包信息
ros2 bag info <your_bag_file>
# 使用自定义脚本分析时间戳
ros2 topic echo /mipi_left/image_raw --no-arr | grep header
如果上述方案无效,请提供:
top 命令的系统负载截图建议将排查过程和社区反馈整理后发帖,帮助其他开发者避坑!
图像异常模式是:图像记录暂停约 0.4-0.74 s,恢复后先写入 1-2 帧“旧 header 时间”的图像,然后马上写入当前图像,所以程序分析到的是 400-650 ms 的 header 间隔
根据你的补充描述,这是典型的 I/O 阻塞导致缓冲区堆积 + 时间戳回填 问题。
正常流程:
采集 → 时间戳 T1 → 发布 → 录制 (间隔 ~33ms@30fps)
异常流程:
采集 → 时间戳 T1 → 发布阻塞 (I/O 忙)
采集 → 时间戳 T2 → 发布阻塞
采集 → 时间戳 T3 → 发布阻塞
↓ I/O 恢复
快速发布 T1, T2, T3 → 时间戳间隔异常 (400-700ms)
核心原因:ros2 bag record 的同步写入阻塞了 ROS2 中间件的发布队列,导致图像帧在驱动层堆积,恢复后批量释放。
# 使用异步写入模式 + 压缩,大幅降低 I/O 阻塞
ros2 bag record /mipi_left/image_raw /mipi_right/image_raw \
--compression-mode file \
--compression-format zstd \
--max-cache-size 1024 \
--max-bag-size 1024
关键参数说明:
--max-cache-size 1024:设置 1GB 内存缓存,避免直接写磁盘--compression-format zstd:压缩率高且速度快在你的图像订阅节点中添加 QoS 配置:
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy
# 图像订阅使用 BEST_EFFORT,允许丢帧但不阻塞
qos_profile = QoSProfile(
depth=3, # 减小队列深度,避免堆积
reliability=ReliabilityPolicy.BEST_EFFORT,
history=HistoryPolicy.KEEP_LAST,
durability=QoSDurabilityPolicy.VOLATILE
)
subscriber = node.create_subscription(
Image,
'/mipi_left/image_raw',
callback,
qos_profile=qos_profile
)
同时修改录制命令:
# 录制时也指定 QoS
ros2 bag record /mipi_left/image_raw /mipi_right/image_raw \
--qos-profile-overrides-path /path/to/qos_override.yaml
qos_override.yaml 内容:
/mipi_left/image_raw:
reliability: best_effort
durability: volatile
depth: 3
/mipi_right/image_raw:
reliability: best_effort
durability: volatile
depth: 3
# 先测试 15fps + 720p 是否稳定
ros2 launch mipi_cam mipi_cam_dual_channel.launch.py \
mipi_image_framerate:=15.0 \
mipi_image_width:=1280 \
mipi_image_height:=720
如果稳定,逐步提高参数找到临界点。
# 1. 创建内存盘(如果内存充足)
sudo mkdir -p /mnt/ramdisk
sudo mount -t tmpfs -o size=2G tmpfs /mnt/ramdisk
# 2. 录制到内存盘
ros2 bag record -a --output-path /mnt/ramdisk/bag_$(date +%Y%m%d_%H%M%S)
# 3. 录制完成后复制到持久存储
cp -r /mnt/ramdisk/bag_* /path/to/permanent/storage/
# 1. 查看当前 I/O 调度器
cat /sys/block/mmcblk0/queue/scheduler
# 2. 改为 deadline 或 noop(适合嵌入式)
echo deadline | sudo tee /sys/block/mmcblk0/queue/scheduler
# 3. 设置 CPU 为性能模式
sudo bash -c "echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor"
# 4. 禁用 CPU 节能
sudo bash -c "echo 0 > /sys/devices/system/cpu/cpuidle/enabled"
# 新开终端监控
ros2 topic delay /mipi_left/image_raw
ros2 topic delay /mipi_right/image_raw
正常情况:average delay: 0.03s (30fps)
异常情况:average delay: 0.5s+
# 创建分析脚本 analyze_timestamps.py
import rosbag2_py
from rclpy.serialization import deserialize_message
from sensor_msgs.msg import Image
reader = rosbag2_py.SequentialReader()
reader.open(rosbag2_py.StorageOptions(uri='your_bag', storage_id='sqlite3'),
rosbag2_py.ConverterOptions('cdr', 'cdr'))
timestamps = []
while reader.has_next():
topic, data, timestamp = reader.read_next()
if 'image_raw' in topic:
msg = deserialize_message(data, Image)
timestamps.append(msg.header.stamp.sec + msg.header.stamp.nanosec / 1e9)
# 计算帧间隔
intervals = [timestamps[i+1] - timestamps[i] for i in range(len(timestamps)-1)]
print(f"平均间隔:{sum(intervals)/len(intervals)*1000:.2f}ms")
print(f"最大间隔:{max(intervals)*1000:.2f}ms")
print(f"间隔>100ms 的帧数:{sum(1 for i in intervals if i > 0.1)}")
| 检查项 | 命令 | 正常值 |
|---|---|---|
| CPU 频率 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq |
> 1.0GHz |
| 磁盘写入速度 | dd if=/dev/zero of=test bs=1M count=100 conv=fdatasync |
> 50MB/s |
| ROS2 队列深度 | ros2 topic info /mipi_left/image_raw -v |
检查 subscriber 数量 |
| 内存使用 | free -h |
可用 > 500MB |
如果问题仍然存在,请提供:
ros2 topic delay /mipi_left/image_raw 的实时输出top 截图(按 P 按 CPU 排序)建议将最终解决方案同步到 原帖,帮助其他遇到相同问题的开发者!