首次使用深度相机

编译完 ROS 驱动后,成功获取了深度点云信息,遇到以下问题。

问题一:深度点云太多,打开可视化就卡死

原始深度图得到的点云数量大约有百万甚至千万级。如果逐一对这些点进行渲染显示,对于边缘计算的工控机来说简直是噩梦。

如何在减少点数量的同时保留物体特征? 这里我采用的是体素下采样(Voxel Downsampling) 的方式对深度点云进行稀疏化:将点云所在的三维空间划分为若干个边长为 5 cm(可根据需求调整)的体素(Voxel),将同一体素内所有点的坐标取均值,最终仅用一个点来代表该体素内的所有点。

问题二:深度点云坐标转换

坐标系定义:

坐标系名称 含义
color_0 RGB 点云坐标系
depth_0 深度点云坐标系
link_0 相机刚体(基座)坐标系

为什么一个深度相机会有这么多坐标系?
深度相机内部集成了多颗摄像头(RGB 摄像头、红外/深度摄像头等),每颗摄像头有自己独立的光学坐标系;同时相机本体还有一个机械基座坐标系。各坐标系之间存在固定的物理偏移(外参)。

配准模式开启前:

  • 深度点云发布在 depth_0 坐标系下
  • RGB 点云发布在 color_0 坐标系下
  • 两者通过各自的 TF 变换挂载到 link_0
    • 深度:link_0depth_0(parent = link_0, child = depth_0
    • RGB:link_0color_0(parent = link_0, child = color_0

配准模式开启后:
深度点云与 RGB 点云对齐,统一发布在 color_0 坐标系下,再由 TF 变换到 link_0

遇到的驱动 Bug:
开启配准模式后,驱动仅仅将深度点云 TF 的 child_frame_iddepth_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写的脚本的时候要特别注意。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐