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

178 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
tags: []
aliases:
- 网络标准是 大端序。 但是考虑到既然大家都在 x86/ARM (Little-Endian) 环境下跑,且为了追求极致性能(减少转换指令),保持主机字节序是雷达内部私有协议的常见做法
date created: 星期四, 十二月 4日 2025, 8:34:02 晚上
date modified: 星期四, 十二月 4日 2025, 10:22:01 晚上
---
# 网络标准是 大端序。 但是考虑到既然大家都在 x86/ARM (Little-Endian) 环境下跑,且为了追求极致性能(减少转换指令),保持主机字节序是雷达内部私有协议的常见做法
> 此处 C++ 防御性编程
> ```cpp
> // 在 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 优先标记?必须使用这个作为标注。
> 综合建议
> ```text
> 第一级:紧急指令(如"紧急停机"
> - 重发次数1次
> - 超时时间1ms
> - QoS最高优先级EF
> - 特点:宁可丢包,不可延迟
>
> 第二级:实时控制指令(如"波束指向"
> - 重发次数2次
> - 超时时间3ms
> - QoS高优先级AF41
> - 特点:平衡可靠性与实时性
>
> 第三级:配置与状态指令
> - 重发次数3次
> - 超时时间10ms
> - QoS普通优先级CS0
> - 特点:保证可靠,允许延迟
> ```
# 指令精度与物理现实—— **DBF???**
> **传输层**:严格按照 `int16_t` 传输,缩放因子为 `0.0025`。
> ```cpp
> // 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); }
> ```
- **混合模型**
```python
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}°")
```