ROS机器人-从零开始每日日志记录day5
首次使用深度相机
编译完 ROS 驱动后,成功获取了深度点云信息,遇到以下问题。
问题一:深度点云太多,打开可视化就卡死
原始深度图得到的点云数量大约有百万甚至千万级。如果逐一对这些点进行渲染显示,对于边缘计算的工控机来说简直是噩梦。
如何在减少点数量的同时保留物体特征? 这里我采用的是体素下采样(Voxel Downsampling) 的方式对深度点云进行稀疏化:将点云所在的三维空间划分为若干个边长为 5 cm(可根据需求调整)的体素(Voxel),将同一体素内所有点的坐标取均值,最终仅用一个点来代表该体素内的所有点。
问题二:深度点云坐标转换
坐标系定义:
| 坐标系名称 | 含义 |
|---|---|
color_0 |
RGB 点云坐标系 |
depth_0 |
深度点云坐标系 |
link_0 |
相机刚体(基座)坐标系 |
为什么一个深度相机会有这么多坐标系?
深度相机内部集成了多颗摄像头(RGB 摄像头、红外/深度摄像头等),每颗摄像头有自己独立的光学坐标系;同时相机本体还有一个机械基座坐标系。各坐标系之间存在固定的物理偏移(外参)。
配准模式开启前:
- 深度点云发布在
depth_0坐标系下 - RGB 点云发布在
color_0坐标系下 - 两者通过各自的 TF 变换挂载到
link_0:- 深度:
link_0→depth_0(parent =link_0, child =depth_0) - RGB:
link_0→color_0(parent =link_0, child =color_0)
- 深度:
配准模式开启后:
深度点云与 RGB 点云对齐,统一发布在 color_0 坐标系下,再由 TF 变换到 link_0。
遇到的驱动 Bug:
开启配准模式后,驱动仅仅将深度点云 TF 的 child_frame_id 从 depth_0 改成了 color_0,但底层使用的变换矩阵仍然是 link_0 → depth_0 的那组外参。
这就导致了一个诡异的现象:在 rviz 中观察到点云在持续地微小抖动。其本质是同一个 TF 变换(link_0 → color_0)下,RGB 点云和深度点云各自使用了不同的变换矩阵,两帧数据在空间中产生了微小的错位,随帧率交替刷新就表现为抖动。
解决思路:在驱动源码中修正配准模式下的 TF 发布逻辑,确保
child_frame_id与变换矩阵一致;或在 launch 文件中关闭驱动自带的 TF 发布,改用static_transform_publisher手动发布正确的外参。
补充:系统监控脚本
前段时间调试时又发生了一次非正常关机,可以用AI写一个更详细且偏向硬件的监控脚本,对工控机的电源轨、内核状态、串口、总线等进行持续采样并写入日志,以便崩溃后回溯。
伪代码示例:
═══════════════════════════════════════════════════════
嵌入式 Linux 系统崩溃前状态监控
目标:每秒采样一次,崩溃后通过 CSV 回溯最后时刻
═══════════════════════════════════════════════════════
// ─────────────────────────────────────────
// 初始化
// ─────────────────────────────────────────
FUNCTION 初始化():
创建日志目录 "/home/user/crash_logs"
生成时间戳 TS = 当前时间("YYYYMMDD_HHMMSS")
创建 CSV 文件,写入表头:
[时间, 12V输入, 5V_SYS, 5V_Host, 5V_OTG, USB_Hub,
3.3V, CPU小核电压, 逻辑域电压, DDR电压, DDR2电压, GPU电压,
SoC温度, 大核温度, GPU温度,
小核频率, 大核0频率, 大核1频率,
内核错误计数]
// ─────────────────────────────────────────
// 后台任务:持续保存内核日志尾部
// ─────────────────────────────────────────
FUNCTION 后台保存dmesg():
LOOP 每 2 秒:
将 dmesg 最后 20 行 → 写入 dmesg_tail.log
// 目的:崩溃后能看到内核最后在做什么
// ─────────────────────────────────────────
// 主循环:每秒采样一次
// ─────────────────────────────────────────
FUNCTION 主循环():
计数器 = 0
LOOP 每 1 秒:
计数器 += 1
当前时间 = NOW("HH:MM:SS")
// ── 第一组:电源轨电压(μV)──
V_12V ← 读取 /sys/class/regulator/regulator.1/microvolts
V_5VSYS ← 读取 /sys/class/regulator/regulator.2/microvolts
V_5VHOST ← 读取 /sys/class/regulator/regulator.6/microvolts
V_5VOTG ← 读取 /sys/class/regulator/regulator.7/microvolts
V_USBHUB ← 读取 /sys/class/regulator/regulator.8/microvolts
V_3V3 ← 读取 /sys/class/regulator/regulator.3/microvolts
// ── 第二组:SoC 核心电压(μV)──
V_CPULIT ← 读取 /sys/class/regulator/regulator.18/microvolts
V_LOG ← 读取 /sys/class/regulator/regulator.19/microvolts
V_DDR ← 读取 /sys/class/regulator/regulator.21/microvolts
V_DDR2 ← 读取 /sys/class/regulator/regulator.22/microvolts
V_GPU ← 读取 /sys/class/regulator/regulator.17/microvolts
// ── 第三组:温度(m°C)──
T_SOC ← 读取 /sys/class/thermal/thermal_zone0/temp
T_BIG ← 读取 /sys/class/thermal/thermal_zone1/temp
T_GPU ← 读取 /sys/class/thermal/thermal_zone2/temp
// ── 第四组:CPU 频率(KHz)──
F_LIT ← 读取 /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
F_BIG0 ← 读取 /sys/devices/system/cpu/cpu4/cpufreq/scaling_cur_freq
F_BIG1 ← 读取 /sys/devices/system/cpu/cpu6/cpufreq/scaling_cur_freq
// ── 第五组:内核错误计数 ──
DERR ← dmesg 中匹配 "error|fail|panic|oops|disconnect|timeout" 的行数
// ── 写入 CSV ──
追加一行到 CSV:
[当前时间, V_12V, V_5VSYS, V_5VHOST, V_5VOTG, V_USBHUB, V_3V3,
V_CPULIT, V_LOG, V_DDR, V_DDR2, V_GPU,
T_SOC, T_BIG, T_GPU,
F_LIT, F_BIG0, F_BIG1,
DERR]
// ── 定期刷盘(防掉电丢数据)──
IF 计数器 % 15 == 0:
sync()
等待 1 秒
// ─────────────────────────────────────────
// 启动
// ─────────────────────────────────────────
初始化()
启动后台线程 → 后台保存dmesg()
主循环()
后续 TODO:
- 增加串口(
/dev/ttyS*、/dev/ttyUSB*)在线状态检测- 增加 I²C / SPI 总线通信心跳检测
- 增加 USB 设备枚举状态监控(
lsusb定期快照)- 用
systemd服务托管,开机自启 + 崩溃自动重启
注意:不同的系统监控会产生大量日志数据,在使用AI写的脚本的时候要特别注意。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)