先说解决办法:

        最最直接简单的办法就是将/home/xiaoan/autoware/src/sensor_component/external/nebula中的nebula_decoders/include/nebula_decoders/nebula_decoders_robosense/decoders/robosense_decoder.hpp文件中的SensorT::packet_t::n_channels改为数字16。具体位置如图所示:(图中已改)

        另外的方法就比较繁琐需要动官方的驱动代码:
        给 Helios16 建一个“16通道”的 packet/traits,并在工厂里选择它,这样以后就不用再去手改 robosense_decoder.hpp 里的 for (channel_id < n_channels) 了;

        在robosense_packet.hpp里,给 Helios16 定义专用的 packet_t(关键是 block 的 units[16]static constexpr size_t n_channels = 16;)。

        在robosense_common.hpp里,给 Helios16 放一份16个垂直角数组(垂直角一定要是 16 项,不要 32 项)。如果手头暂时没有官方表,可以先把 32 通道表里对应 16 线的那一半挑出来暂用(后续再换成官方表)。如果原来有个 Helios(32线)专用的 kVerticalAngles[32]不要用它;Helios16 的转换时要引用这 16 项。

        robosense_scan_decoder.hpp里,做型号选择(把现在只认 “Helios / Bpearl” 的地方,扩展支持 “Helios16”)。

        让 launch/参数也能填 Helios16
你现在 --show-args 只显示 'Helios' | 'Bpearl',说明 launch 限定了 choices。把 Nebula 的 robosense_launch_all_hw.xml(或 .py)里那段 DeclareLaunchArgument('sensor_model', choices=['Helios','Bpearl']) 改成包含 'Helios16',并在 nebula_ros/config/lidar/robosense/ 目录下复制一份 Helios.param.yamlHelios16.param.yaml

        这样一来,解码循环仍旧是 for (size_t channel_id = 0; channel_id < SensorT::packet_t::n_channels; ++channel_id),但 n_channels 来自你选的 traits(16),不会再“越过 16 去读后面的块”,镜像也自然没了。

再通俗的讲一下是为什么:

  • Helios16 每个数据块只有 16 个通道(激光束)。

  • 你当前用的 nebula/robosense 解码器在模板参数里把 Helios 当成 32 通道来处理(n_channels=32)。

  • 解码循环是按 channel_id = 0 .. n_channels-1 逐通道取一组返回(Dual 模式就是两组),并用 channel_id 束的竖直角表 去还原 3D 点。

  • 当它“以为”有 32 束时,channel_id = 16..31 这半段:

    • 要么读到了不属于通道数组的内存(但结构体布局下那些数看起来仍像“合法距离/强度”,不会全是 0),

    • 要么用到了32 线竖直角表里后 16 束的角度(通常与前 16 束在上下方向大致对称)。

  • 结果:你看到的第二团点云就像把第一团沿水平面翻折上去的“镜像”。
    这也解释了为什么“把 n_channels 改为 16”后就消失了——解码器不再去处理那不存在的后 16 束,自然不会“凭空造”出一份镜像点云。

简单说:模型/通道数搞错 → 竖直角表也错 → 多解出一半“假通道” → 像镜像。

下边是Robosense的Helios32和Helios16官方文档中的Data Block数据包定义:

        

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐