Files
Inbox/关于新版雷达前端通信协议的若干想法.md
2025-12-11 07:24:36 +08:00

7.6 KiB
Raw Permalink Blame History

tags, aliases, date created, date modified
tags aliases date created date modified
网络标准是 大端序。 但是考虑到既然大家都在 x86/ARM (Little-Endian) 环境下跑,且为了追求极致性能(减少转换指令),保持主机字节序是雷达内部私有协议的常见做法
星期四, 十二月 4日 2025, 8:34:02 晚上 星期四, 十二月 4日 2025, 10:22:01 晚上

网络标准是 大端序。 但是考虑到既然大家都在 x86/ARM (Little-Endian) 环境下跑,且为了追求极致性能(减少转换指令),保持主机字节序是雷达内部私有协议的常见做法

此处 C++ 防御性编程

// 在 protocol_v1.0.h 头部加入
#include <type_traits>

// C++20 标准检测方式 (推荐)
// static_assert(std::endian::native == std::endian::little, "CRITICAL ERROR: Platform must be Little-Endian!");

// C++17 兼容检测方式 (针对您的环境)
constexpr bool is_little_endian() {
    uint16_t x = 0x0001;
    auto p = reinterpret_cast<const uint8_t*>(&x);
    return *p == 0x01;
}
static_assert(is_little_endian(), "CRITICAL ERROR: Platform must be Little-Endian according to ICD V0.1 !");

核心议题 1.1:校验算法 (Checksum)——为了工程安全升级为 CRC

升级 (CRC-16-CCITT)

  • 2 字节 (末尾)

核心议题 1.3:帧头与对齐 (Header & Alignment)

- C++ 结构体对齐方式(`#pragma pack(1)` 还是 4 字节对齐?),以及如何统一两种链路的帧头处理。【判断我们的硬件资源倾向于去优化什么?】

巨型帧硬件可能不支持

路径 A硬件流 - 强制巨型帧 (Jumbo Frames)

  • 原理:命令网卡和交换机支持更大的包,将 MTU 设置为 9000 字节。

  • 优点

    • 极简代码C++ 端几乎不需要改动,直接发大包。

    • 极高性能CPU 中断次数减少 6 倍(发 1 个大包 vs 发 6 个小包)。

  • 缺点

    • 环境依赖:必须确保所有设备(雷达网卡、交换机、服务器网卡)都配置了 MTU 9000。如果中间经过一个不支持 Jumbo 的普通路由器,包会被丢弃。

    • 运维成本:您提到过您是运维工程师,这意味着每次部署新环境,您都必须手动配置 MTU。

路径 B软件流 - 应用层分片 (Application Layer Slicing)

  • 原理:在 C++ 代码里,手动把 16KB 数据切成 1400 字节的小块,给每个小块加一个微型包头(包含:帧 ID、分片序号、总分片数。接收端收到后再手动拼起来。

  • 优点

    • 环境适应性强:插在任何普通交换机或路由器上都能跑。

    • 抗干扰优化:如果丢了一个小片,我们可以只重传那个小片(虽然 UDP 实现这个很难,但理论上可行),或者至少我们知道丢了哪一片。

  • 缺点

    • 代码极其复杂:需要编写“分包器”和“重组缓冲区”逻辑,处理乱序到达、超时丢弃等棘手问题。这对开发进度是巨大挑战。

补充防御:预留分片能力 (The Safety Valve) 虽然我们主推巨型帧,但我建议在定义回波数据包的 C++ 结构体时,不要把所有空间都写死。 在《以太网协议格式》(表 7中 ,有一个 参数长度 (2 Bytes) 和 命令参数 (不定长)。对于回波数据(表 A虽然它没有显式的“保留字段”但我建议在设计 EchoPacket 结构体时,定义一个可选的头部结构,一旦后续需要应用层切片,直接启用即可,无需重构整个通信流程。 (此动作不改变当前文档,仅在代码层面做防御性设计。)

UDP 可靠性机制 需要在算法上增加其可靠性

决策点

  • 重发次数定多少?
  • 超时时间设为多少(建议 <5ms--> 这个根据雷达的设计指标确定。建议不同指令设置不同的时间间隔。
  • 控制指令是否需要 QoS 优先标记?必须使用这个作为标注。

综合建议

第一级:紧急指令(如"紧急停机"
  - 重发次数1次
  - 超时时间1ms
  - QoS最高优先级EF
  - 特点:宁可丢包,不可延迟

第二级:实时控制指令(如"波束指向"
  - 重发次数2次
  - 超时时间3ms
  - QoS高优先级AF41
  - 特点:平衡可靠性与实时性

第三级:配置与状态指令
  - 重发次数3次
  - 超时时间10ms
  - QoS普通优先级CS0
  - 特点:保证可靠,允许延迟

指令精度与物理现实—— DBF???

传输层:严格按照 int16_t 传输,缩放因子为 0.0025

// 0.0025 度量化 -> 2 Bytes (int16_t)
// Max value: 65.0 / 0.0025 = 26000 (fit in int16_t range ±32767)
int16_t azimuth_raw; 

// 辅助函数 (Helper)
float get_azimuth_deg() const { return azimuth_raw * 0.0025f; }
void set_azimuth_deg(float deg) { azimuth_raw = (int16_t)(deg / 0.0025f); }
  • 混合模型
class BeamSteeringSimulator:
    def __init__(self, hardware_type="DBF"):
        """
        硬件类型:
        - "DBF": 数字波束形成,完美精度
        - "HighRes": 高精度移相器(10-12位)
        - "MidRes": 中精度移相器(8位)+抖动
        - "LowRes": 低精度移相器(6位)+校准
        """
        self.hardware_type = hardware_type
        
        # 设置不同硬件的精度模型
        self.models = {
            "DBF": {"bits": 32, "has_dithering": False, "has_calibration": False},
            "HighRes": {"bits": 12, "has_dithering": True, "has_calibration": True},
            "MidRes": {"bits": 8, "has_dithering": True, "has_calibration": True},
            "LowRes": {"bits": 6, "has_dithering": True, "has_calibration": False}
        }
        
        model = self.models[hardware_type]
        self.min_step = 360.0 / (2**model["bits"])
        
        if model["has_calibration"]:
            self.effective_step = self.min_step / 10.0  # 校准提升10倍
        else:
            self.effective_step = self.min_step
        
        self.has_dithering = model["has_dithering"]
    
    def steer_beam(self, target_angle):
        # 基础量化
        base_angle = round(target_angle / self.effective_step) * self.effective_step
        
        # 相位抖动效果
        if self.has_dithering and abs(target_angle - base_angle) > 0:
            # 在两个相邻状态间抖动,获得平均精度
            next_angle = base_angle + self.effective_step
            error_to_base = target_angle - base_angle
            dither_ratio = error_to_base / self.effective_step
            
            # 实际实现中,抖动是时分的,这里模拟平均效果
            actual_angle = base_angle * (1 - dither_ratio) + next_angle * dither_ratio
        else:
            actual_angle = base_angle
        
        # 加上微小随机误差(模拟现实不完美)
        if self.hardware_type != "DBF":
            random_error = np.random.normal(0, self.effective_step * 0.1)
            actual_angle += random_error
        
        return actual_angle

# 使用示例
sim = BeamSteeringSimulator(hardware_type="HighRes")
target = 45.0025
actual = sim.steer_beam(target)
print(f"硬件类型: {sim.hardware_type}")
print(f"目标角度: {target:f}°, 实际角度: {actual:f}°")
print(f"角度误差: {abs(target-actual):f}°")