更新:1、TAS航迹不关联时间戳更早的TWS点迹,但标记点迹已使用,避免生成TWS航迹;
2、调整目录结构,将过期的文档都放到archived_docs文件夹中留档; Signed-off-by: waiwaylee <waiwaylee@foxmail.com>
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
# Bug 修复报告
|
||||
|
||||
根据 `BUG_REPORT.md` 中的“是否修复”指示,本次完成了所有标记为“按建议修改/按建议修复”的项;标记为“暂不修复/暂不修改/暂不处理”的项保持原样未改动。
|
||||
|
||||
---
|
||||
|
||||
## 修复状态汇总
|
||||
|
||||
| 编号 | 标题 | 指示 | 状态 |
|
||||
|---|---|---|---|
|
||||
| BUG-01 | 基类无虚析构函数 | 暂不修复 | 未修改 |
|
||||
| BUG-02 | Hight_smooth 无限增长 | 暂不修复 | 未修改 |
|
||||
| BUG-03 | 工厂单例非线程安全 | 暂不修复 | 未修改 |
|
||||
| BUG-04 | TAS Point_Sum 未限幅 | 按建议修复 | ✅ 已修复 |
|
||||
| BUG-05 | Track_to_start.size()-1 下溢 | 按建议修复 | ✅ 已修复 |
|
||||
| BUG-06 | track_start_point_num 未校验 | 按建议修复 | ✅ 已修复 |
|
||||
| BUG-07 | 禁止区域个数未限制 | 暂不修复 | 未修改 |
|
||||
| BUG-08 | 消亡航迹输出无容量检查 | 暂不修改 | 未修改 |
|
||||
| BUG-09 | Beam_Ctrl 输出计数越界风险 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-10 | 航迹号数组下标未校验 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-11 | TAS model_filter 未初始化变量 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-12 | tas_beam_output 未初始化变量 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-13 | Work_Parameter 未初始化 | 暂不修复 | 未修改 |
|
||||
| BUG-14 | lastest_index 未初始化 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-15 | TWS delta_T<=0 仍关联 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-16 | TAS 无 delta_T>0 检查 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-17 | TAS 外推负时间差 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-18 | 卡尔曼时间差除零 | 暂不修改 | 未修改 |
|
||||
| BUG-19 | Bind_speed prt=0 除零 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-20 | 门限重复平方 | 暂不修改 | 未修改 |
|
||||
| BUG-21 | 近程模型 3 门限整数除法 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-22 | EKF/凝聚方位角未环绕 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-23 | IMM 概率零分母/奇异矩阵 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-24 | EKF 似然只取 2x2 S | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-25 | TWS 处理 TAS 航迹 | 暂不处理 | 未修改 |
|
||||
| BUG-26 | 输出航向角使用 atan | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-27 | asin(height/range) 未保护 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-28 | track_clear_all 清理不彻底 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-29 | tracking_stop 队列延迟 | 暂不修改 | 未修改 |
|
||||
| BUG-30 | work_mode 注释不一致 | 注释有误 | ✅ 已修复注释 |
|
||||
| BUG-31 | tracking_point/引导跟踪空实现 | 注释明确 | ✅ 已加注释 |
|
||||
| BUG-32 | 凝聚内层未跳过已用点 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-33 | 起批 delta_T 未校验 | 暂不修改 | 未修改 |
|
||||
| BUG-34 | tmp_track_die 空向量越界 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-35 | 航迹号 500 不复用 | 按建议修改 | ✅ 已修复 |
|
||||
| BUG-36 | TAS 波束关闭字段未清 | 暂不修改 | 未修改 |
|
||||
| BUG-37 | 局部结构体未完整初始化 | 按建议修改 | ✅ 已修复 |
|
||||
|
||||
---
|
||||
|
||||
## 已修复项明细
|
||||
|
||||
### BUG-04
|
||||
- 文件:`data_process.cpp`
|
||||
- 修改:TAS 分支 `data_num = min(max(Point_Sum,0), 150)`,避免 `Point_Sum > 150` 时越界读取输入数组。
|
||||
|
||||
### BUG-05
|
||||
- 文件:`track_init.cpp`
|
||||
- 修改:重复航迹去重循环改为 `for (size_t i = 0; i + 1 < Track_to_start.size(); ++i)`,避免空容器时 `size()-1` 下溢。
|
||||
|
||||
### BUG-06
|
||||
- 文件:`data_process.cpp`、`track_init.cpp`、`track_init_direct_tracking.cpp`
|
||||
- 修改:
|
||||
- `track_process_parameters_initial/modify` 校验 `3 <= track_start_point_num <= 9`,非法参数返回 `-1`。
|
||||
- 起批转可靠航迹前增加 `Track_to_start.empty()` 和每条航迹 `size() >= 3` 防御。
|
||||
- 直接跟踪的 `tmp_track_to_trust_track` 也增加 `L >= 3` 保护。
|
||||
|
||||
### BUG-09
|
||||
- 文件:`tas_ctrl.cpp`
|
||||
- 修改:
|
||||
- `tas_ctrl_process` 开始时校验 `Trust_track_num_Output` 非空并清零。
|
||||
- `tas_target_add` 写入输出数组前检查 `*Trust_track_num_Output < MAX_TRACK_NUM`。
|
||||
|
||||
### BUG-10
|
||||
- 文件:`track_index_mangement.cpp`
|
||||
- 修改:写入 `List[]` 前校验 `Track_Index` 在 `[1, MAX_TRACK_INDEX]`。
|
||||
|
||||
### BUG-11
|
||||
- 文件:`track_asso_tas.cpp`
|
||||
- 修改:`model_filter` 增加 `found_tas_track` 标记;找不到目标时直接返回,局部变量均初始化。
|
||||
|
||||
### BUG-12
|
||||
- 文件:`tas_ctrl.cpp`
|
||||
- 修改:`tas_beam_output` 初始化 `H_track/X_now/CPI_time`,找不到目标时 `open_flag=0` 并返回。
|
||||
|
||||
### BUG-14
|
||||
- 文件:`track_index_mangement.h`
|
||||
- 修改:`lastest_index` 声明时初始化为 `0`。
|
||||
|
||||
### BUG-15
|
||||
- 文件:`track_asso.cpp`
|
||||
- 修改:TWS 关联中 `delta_T <= 0` 时从候选列表移除该无效配对并 `continue`,不再标记点迹已使用、不刷新航迹状态。
|
||||
|
||||
### BUG-16
|
||||
- 文件:`track_asso_tas.cpp`
|
||||
- 修改:TAS 关联点循环中 `delta_T <= 0` 时跳过该点。
|
||||
|
||||
### BUG-17
|
||||
- 文件:`track_asso_tas.cpp`
|
||||
- 修改:TAS 外推时 `delta_T <= 0` 直接跳过,避免航迹时间回退和负时间预测。
|
||||
|
||||
### BUG-19
|
||||
- 文件:`kalman.cpp`、`data_process_class_dll.h`
|
||||
- 修改:`Bind_speed` 对 `prt <= 0` 或 `freq <= 0` 返回安全非零值;接口注释改为“PRI 不允许为 0”。
|
||||
|
||||
### BUG-21
|
||||
- 文件:`track_asso.cpp`
|
||||
- 修改:近程门限中 `/1000`、`/100` 改为浮点除法,避免整数除零恒不成立;保留 `d*d` 比较方式(未修改 BUG-20)。
|
||||
|
||||
### BUG-22
|
||||
- 文件:`kalman.cpp`、`dot_coh.cpp`、`dot_coh_tas.cpp`
|
||||
- 修改:
|
||||
- 新增 `wrapAnglePi()`,EKF 各残差计算后对方位角分量做 `[-π,π]` 环绕。
|
||||
- 点迹凝聚 `work_mode==0` 分支和 TAS 凝聚统一使用最小角度差 `delta_F`。
|
||||
|
||||
### BUG-23
|
||||
- 文件:`track_asso.cpp`、`track_asso_tas.cpp`、`track_asso_direct_tracking.cpp`
|
||||
- 修改:
|
||||
- IMM 交互中 `c[0..2]` 为 0/负时钳位到 `1e-12`。
|
||||
- 模型概率更新增加分母保护,分母异常时保持上一拍概率。
|
||||
- 似然计算对 `det_S <= 0` 返回 0,避免 NaN。
|
||||
|
||||
### BUG-24
|
||||
- 文件:`kalman.h`、`kalman.cpp`、`track_asso.cpp`、`track_asso_tas.cpp`、`track_asso_direct_tracking.cpp`
|
||||
- 修改:
|
||||
- `kalman_filter_EKF` 的 `S_filter` 由 `[2][2]` 改为 `[3][3]`。
|
||||
- 调用侧使用 `Matrix3f` 和 3x3 行列式,似然归一化改为 `1/sqrt(pow(2*PI,3)*detS)`。
|
||||
|
||||
### BUG-26
|
||||
- 文件:`track_asso.cpp`、`track_asso_tas.cpp`、`track_asso_direct_tracking.cpp`
|
||||
- 修改:航向角改用 `atan2(X[4], X[1])` 并归一化到 `[0,2π)`。
|
||||
|
||||
### BUG-27
|
||||
- 文件:`track_asso_tas.cpp`、`track_asso_direct_tracking.cpp`、`track_init.cpp`
|
||||
- 修改:计算 `asin` 前对 `height/range` 做定义域钳位,`range <= 0` 时按 0 处理。
|
||||
|
||||
### BUG-28
|
||||
- 文件:`data_process.cpp`、`dot_coh.h/cpp`、`track_asso.h/cpp`、`track_asso_tas.h/cpp`、`track_init.h/cpp`、`tas_ctrl.h/cpp`、`track_index_mangement.h/cpp`
|
||||
- 修改:
|
||||
- 为 `Dot_Coh`、`Track_Asso`、`Track_Asso_Tas`、`Track_Init`、`TAS_Ctrl`、`Track_Ind_Mangement` 增加 `reset()`。
|
||||
- `track_clear_all()` 调用上述 reset,并恢复 `last_beam_num = INT_MAX`。
|
||||
- 直接跟踪相关类也补充了 `reset()`。
|
||||
|
||||
### BUG-30
|
||||
- 文件:`data_process_class_dll.h`
|
||||
- 修改:`work_mode` 注释由“0进程 1中程 3远程”改为“0进程 1中程 2远程”。
|
||||
|
||||
### BUG-31
|
||||
- 文件:`data_process_class_dll.h`、`data_process.cpp`、`track_init_direct_tracking.cpp`
|
||||
- 修改:在 `direct_tracking_process`、`tracking_point`、直接跟踪入口处注释明确“当前接口未启用,保留空实现”。
|
||||
|
||||
### BUG-32
|
||||
- 文件:`dot_coh.cpp`、`dot_coh_tas.cpp`
|
||||
- 修改:内层凝聚比较增加对 `i` 点 `Use_Flag` 的检查,已使用点不再参与凝聚。
|
||||
|
||||
### BUG-34
|
||||
- 文件:`track_init.cpp`、`track_init_direct_tracking.cpp`
|
||||
- 修改:`tmp_track_die` 先判断 `n <= 0`,空向量直接删除。
|
||||
|
||||
### BUG-35
|
||||
- 文件:`track_index_mangement.cpp`
|
||||
- 修改:两处回绕循环由 `i < MAX_TRACK_INDEX` 改为 `i <= MAX_TRACK_INDEX`,使 500 号可复用。
|
||||
|
||||
### BUG-37
|
||||
- 文件:`track_init.cpp`、`track_init_direct_tracking.cpp`
|
||||
- 修改:`Temp_track`、`Trust_Track` 局部变量改为 `= {}` 值初始化,避免未初始化字段。
|
||||
|
||||
---
|
||||
|
||||
## 编译与运行验证
|
||||
|
||||
使用 **MSVC 2013 (Visual Studio 12) x86** 实际编译:
|
||||
|
||||
| 配置 | 结果 |
|
||||
|---|---|
|
||||
| X256_PS Release | ✅ 编译链接通过 |
|
||||
| X256_MS Release | ✅ 编译链接通过 |
|
||||
| X256_PS Debug | ✅ 编译链接通过 |
|
||||
| MSVC `/W4` Release | ✅ 编译通过,未再出现 C4700/C4701 未初始化变量告警 |
|
||||
|
||||
另编写临时宿主程序验证 DLL:
|
||||
- 初始化 `RadarPara`,调用 `track_process_parameters_initial` 成功。
|
||||
- 调用 `track_process`,返回 `1`,输出计数正常。
|
||||
- 工厂创建/销毁流程正常。
|
||||
|
||||
> 说明:当前构建仍会输出原有代码的 C4244 转换告警、C4018 有符号/无符号比较告警、C4819 编码告警,均非本次修复引入,不影响链接和运行。
|
||||
@@ -0,0 +1,276 @@
|
||||
# 雷达数据处理 DLL 逻辑 BUG 分析报告
|
||||
|
||||
分析范围:`data_process_class_dll/` 下全部源码(不含 `Eigen/`),以迁移后的当前代码行号为准。
|
||||
严重级别定义:
|
||||
|
||||
- **P0**:可能导致崩溃、越界读写、内存破坏或长时间运行内存泄漏,建议优先修复。
|
||||
- **P1**:在常见异常时序/边界输入下会出错,或属于明显算法逻辑错误。
|
||||
- **P2**:健壮性、数值稳定性、状态一致性、功能缺失等问题。
|
||||
- **P3**:代码质量/可维护性问题。
|
||||
|
||||
---
|
||||
|
||||
## 1. 内存与生命周期
|
||||
|
||||
### BUG-01 [P0] 基类没有虚析构函数,工厂按基类指针 delete 派生对象
|
||||
- 位置:`data_process_class_dll.h:168`、`data_process_class_dll.cpp:25-32`
|
||||
- 说明:`Data_process_class_dll` 没有声明虚析构函数,而 `Data_Process` 内部包含多个 `std::vector` 和若干成员对象。`Data_Process_Factory::Destroy()` 执行 `delete p` 时静态类型是基类指针,只会调用基类析构函数,派生类成员(`Data_buffer`、`trust_track`、`temp_track`、Eigen 相关对象等)的析构不会执行,属于未定义行为并造成内存泄漏。
|
||||
- 建议:在基类中增加 `virtual ~Data_process_class_dll() {}`;同时让工厂支持重复销毁、销毁后返回 nullptr。
|
||||
- 暂不修复
|
||||
|
||||
### BUG-02 [P1] `Hight_smooth` 高度平滑缓存只增不减,长时间运行内存持续增长
|
||||
- 位置:`track_asso.cpp:890`、`track_asso_tas.cpp:722`、`track_asso_direct_tracking.cpp:639`
|
||||
- 说明:每次高度更新都执行 `Hight_smooth.push_back(...)`,从未裁剪或清空。航迹存活时间越长,该 vector 越大;500 条航迹长时间运行时内存会持续增长。
|
||||
- 建议:仅保留最近 `height_win_length` 个高度值(如 `resize`/`erase(begin)` 后再 push),或改用固定长度 `std::deque`;航迹消亡时随结构体释放。
|
||||
- 暂不修复
|
||||
|
||||
### BUG-03 [P2] 工厂单例创建/销毁非线程安全
|
||||
- 位置:`data_process_class_dll.cpp:15-32`
|
||||
- 说明:`GetB()` 和 `Destroy()` 对静态指针 `p` 无任何同步。若宿主在多线程环境调用,可能创建两个实例(泄漏一个)或对同一对象重复销毁。
|
||||
- 建议:用 C++11 `static Data_Process instance;` 返回地址,或对工厂方法加锁;明确 DLL 接口的线程模型。
|
||||
- 暂不修复
|
||||
|
||||
---
|
||||
|
||||
## 2. 数组/向量越界
|
||||
|
||||
### BUG-04 [P0] TAS 输入点迹未限制 `Point_Sum <= 150`
|
||||
- 位置:`data_process.cpp:66`
|
||||
- 说明:TWS 分支使用 `min(Point_Sum, 150)`,但 TAS 分支直接 `data_num = Data_Input[0].Point_Sum` 并循环读取 `Data_Input[i]`。当协议传入 `Point_Sum > 150` 时,会越界读取 `Data_Input[150]`。
|
||||
- 建议:与 TWS 分支一致,使用 `data_num = min(max(Point_Sum,0), 150)`,并校验 `Point_Sum >= 0`。
|
||||
- 按建议修复
|
||||
|
||||
### BUG-05 [P0] `Track_to_start.size()-1` 在空容器时下溢导致越界
|
||||
- 位置:`track_init.cpp:534`
|
||||
- 说明:与已发现示例一致。`size()` 返回 `size_t`,空容器减 1 得到极大值,随后 `Track_to_start[i]` 越界。
|
||||
- 建议:`if (Track_to_start.empty()) return;`,或改为 `for (size_t i = 0; i + 1 < Track_to_start.size(); ++i)`。
|
||||
- 按建议修复,改为 `for (size_t i = 0; i + 1 < Track_to_start.size(); ++i)`
|
||||
|
||||
### BUG-06 [P0] `track_start_point_num` 未校验,取值 0/1/2 或大于 9 时多处越界
|
||||
- 位置:`track_init.cpp:533,544-545,588-594`、`track_init_direct_tracking.cpp:316-322`
|
||||
- 说明:重复航迹比较固定访问 `Track_to_start[i][1]`、`[2]`,三点初始化访问 `[L-3]/[L-2]/[L-1]`。该参数由外部 `RadarPara` 传入,若未初始化或配置为 0/1/2,会出现负下标或越界;若大于 9,`tmp_track_die` 会在 `n>=10` 时删除临时航迹,逻辑也无法起批。
|
||||
- 建议:在 `track_process_parameters_initial/modify` 中校验 `3 <= track_start_point_num <= 9`;使用 `Track_to_start[i].size()` 作为实际长度并在访问前检查。
|
||||
- 按建议修复
|
||||
|
||||
### BUG-07 [P0] 禁止区域个数未限制在 30 以内,外部配置过大时数组越界
|
||||
- 位置:`track_init.cpp:711`(`track_prohibite_area_num`)、`tas_ctrl.cpp:123`(`TAS_prohibite_area_num`)
|
||||
- 说明:循环上界直接使用外部传入的计数,而对应数组固定为 `[30]`。配置大于 30 时越界读。
|
||||
- 建议:循环上界改为 `min(count, 30)`,并在参数初始化/修改时拒绝非法计数或截断。
|
||||
- 暂不修复
|
||||
|
||||
### BUG-08 [P1] 消亡航迹号输出无数组容量检查
|
||||
- 位置:`track_die.cpp:24`、`track_die_tas.cpp:26`
|
||||
- 说明:`Track_die_Index_Output[*Track_die_num_Output-1] = ...` 不检查数组容量。正常流量下最多 500 条航迹,与 `MAX_TRACK_NUM` 一致,但接口没有把容量传入,一旦宿主传入较小数组、或计数被异常修改,就会越界写。
|
||||
- 建议:接口增加 `die_array_capacity` 参数,或内部保证 `*Track_die_num_Output < MAX_TRACK_NUM` 后再写。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-09 [P1] `Beam_Ctrl` 路径中输出计数未初始化/无上界,可能越界写航迹输出数组
|
||||
- 位置:`data_process.cpp:193-198`、`tas_ctrl.cpp:74-78`
|
||||
- 说明:`Beam_Ctrl()` 直接使用宿主传入的 `Trust_track_num_Output`,而 `tas_ctrl_process` 不会先清零,`tas_target_add` 会基于旧值自增并写 `Trust_Track_Output[*Trust_track_num_Output-1]`。若调用方未清零或旧值接近 `MAX_TRACK_NUM`,会越界写。
|
||||
- 建议:`tas_ctrl_process` 内部保存 `*count = 0` 或在每次写入前检查 `*count < MAX_TRACK_NUM`;同时校验指针非空。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-10 [P1] 航迹号直接作为数组下标,未校验范围
|
||||
- 位置:`track_index_mangement.cpp:29`
|
||||
- 说明:`List[(*trust_track)[i].Track_Index-1] = 1`,若航迹号不在 `[1, MAX_TRACK_INDEX]` 内(异常数据、内存损坏、外部修改),立即越界。
|
||||
- 建议:写前检查 `Track_Index >= 1 && Track_Index <= MAX_TRACK_INDEX`,异常航迹号返回错误或跳过。
|
||||
- 按建议修改
|
||||
|
||||
---
|
||||
|
||||
## 3. 未初始化变量
|
||||
|
||||
### BUG-11 [P1] `Track_Asso_Tas::model_filter` 在找不到 TAS 目标时使用未初始化变量
|
||||
- 位置:`track_asso_tas.cpp:228-232`,随后在 `271/276/280/282` 等使用
|
||||
- 说明:`X1/X2/X3/P1/P2/P3/T_track/v_track/r_track/h_track` 只在 `Track_Index == tas_track_idx` 时赋值。若 `tas_track_idx` 不存在(例如目标已被消亡、主程序传入失效批号),后续仍用这些未初始化值计算 IMM、距离门限和外推,结果不可预测。MSVC `/W4` 已报 C4701。
|
||||
- 建议:函数开头初始化这些变量,并在找不到目标时直接 return;上层也应处理“TAS 目标不存在”的返回值。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-12 [P1] `tas_beam_output` 在队列目标不在航迹表中时使用未初始化变量
|
||||
- 位置:`tas_ctrl.cpp:242-271`
|
||||
- 说明:`H_track`、`X_now[]` 只在找到匹配航迹时赋值;若 `track_clear_all()` 后队列未清空、或目标已被删除而队列未同步,循环找不到目标,随后 `asin(H_track/range)`、`X_now[...]` 使用未初始化数据。Cppcheck 和 MSVC `/W4` 均报 C4701。
|
||||
- 建议:找不到目标时立即 `open_flag=0` 并 return;变量声明时初始化。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-13 [P2] `Data_Process::Work_Parameter` 及若干成员在构造后未初始化
|
||||
- 位置:`data_process.h:28-31,78-95`
|
||||
- 说明:构造函数为空,`Work_Parameter`、`Beam_num`、`data_num`、`TAS_track_idx` 等未初始化。若宿主在调用 `track_process_parameters_initial` 前就调用 `data_preprocess/track_process/Beam_Ctrl`,`Work_Parameter.track_start_point_num`、`Sys_delay`、`V_MIN/V_MAX` 等是垃圾值,可能导致起批越界、除零或异常门限。
|
||||
- 建议:构造函数中对 `Work_Parameter` 进行 `memset`/值初始化并设置安全默认参数;在处理函数入口检查“参数是否已初始化”。
|
||||
- 暂不修复
|
||||
|
||||
### BUG-14 [P3] `Track_Ind_Mangement::lastest_index` 未初始化
|
||||
- 位置:`track_index_mangement.h:17`、`track_index_mangement.cpp:33`
|
||||
- 说明:只有空航迹表分支会赋值为 1;如果首次调用时航迹表非空,就会读取未初始化的 `lastest_index`。
|
||||
- 建议:声明为 `int lastest_index = 0;` 或增加构造函数初始化。
|
||||
- 按建议修改
|
||||
|
||||
---
|
||||
|
||||
## 4. 时间戳/时序处理
|
||||
|
||||
### BUG-15 [P1] TWS 关联在 `delta_T <= 0` 时仍把点迹标记为已关联并刷新航迹状态
|
||||
- 位置:`track_asso.cpp:610-691`
|
||||
- 说明:滤波和航迹信息更新在 `if (delta_T > 0)` 内,但 `Extrapolate_round=0`、`point_flag=1`、`associate_point_number++`、点迹 `Use_Flag=1` 都在 if 之外。重复/乱序时间戳的点仍会“占用”点迹、让航迹看起来已更新,实际状态未更新。
|
||||
- 建议:`delta_T <= 0` 时直接跳过该关联候选(或作为无效量测处理),不要标记点迹已使用、不要刷新航迹新鲜度。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-16 [P1] TAS 关联完全没有 `delta_T > 0` 检查
|
||||
- 位置:`track_asso_tas.cpp:271-335,385-452`
|
||||
- 说明:TAS 路径计算 `delta_T` 后直接进入统计距离和滤波,即使 `delta_T <= 0` 也会生成 F/Q 并更新航迹,可能把航迹时间更新到过去。
|
||||
- 建议:与 TWS 一致,只有 `delta_T > 0` 才允许关联;否则跳过该点。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-17 [P1] TAS 外推使用未校验的 `latest_timestamp - T_track`,负时间差导致反向预测
|
||||
- 位置:`track_asso_tas.cpp:483-506`
|
||||
- 说明:若 `latest_timestamp < T_track`(乱序/重复时间戳),`delta_T` 为负,`T_track += delta_T*1000` 会回退航迹时间,IMM F/Q 也按负时间生成。
|
||||
- 建议:`delta_T = max(0, latest_timestamp - T_track)/1000.0`;若为 0 则直接返回或保持原状态。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-18 [P1] 卡尔曼初始化及统计距离函数对零/负时间差没有保护
|
||||
- 位置:`kalman.cpp:13-46,126-130,158-168`;调用点 `track_init.cpp:275,450,593-594`、`track_init_direct_tracking.cpp:135,271,321-322`
|
||||
- 说明:两点/三点初始化直接除以 `T/T1/T2`。同一 CPI 重复点、时间戳相等或乱序会产生除零、inf/NaN,随后污染航迹协方差和模型概率。
|
||||
- 建议:调用前统一校验时间差大于最小阈值(如 >0 或 >1 ms);`kalman_filter_init_2dots/3dots` 内部对非法时间返回错误。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-19 [P1] `Bind_speed` 对 `prt == 0` 无保护,而接口说明 PRI 可给 0
|
||||
- 位置:`kalman.cpp:766-770`、`data_process_class_dll.h:29`
|
||||
- 说明:`return 150000.0/(freq*prt)`,当 `PRI=0` 时除零;结果传给 `Round()` 会把 inf/NaN 转换为未定义整型。
|
||||
- 建议:`prt <= 0` 时返回固定安全值或直接返回无效距离;统一约定 PRI 单位与默认值。
|
||||
- 按建议修改,同时修改接口说明:PRI不可为0
|
||||
|
||||
---
|
||||
|
||||
## 5. 关联门限与滤波算法逻辑
|
||||
|
||||
### BUG-20 [P1] 统计距离 d 已经是平方形式,门限中又平方了一次
|
||||
- 位置:`track_asso.cpp:544-546`、`track_asso_tas.cpp:335`、`track_asso_direct_tracking.cpp:286`、`track_init.cpp:221`
|
||||
- 说明:`d_cal_EKF` 返回的是 `delta_z^T S^{-1} delta_z`(马氏距离平方),后续门限却写成 `d*d < THRESHOLD*THRESHOLD`。例如阈值 3 时本意是 `d < 9`,实际变成 `d < 3`,波门明显偏小。
|
||||
- 建议:统一改为 `d < TRACK_START_THRESHOLD*TRACK_START_THRESHOLD` / `d < ASSO_THORD*ASSO_THORD`。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-21 [P1] 近程模型 3 门限因整数除法恒为 0
|
||||
- 位置:`track_asso.cpp:544-545`
|
||||
- 说明:`ASSO_THORD` 是 int 宏,`ASSO_THORD*ASSO_THORD/1000` 和 `/100` 按整数计算,结果均为 0,导致 `d3*d3 < 0` 永远不成立;近距离下模型 3 实际被禁用。
|
||||
- 建议:写为 `ASSO_THORD*ASSO_THORD/1000.0`、`/100.0`,同时按 BUG-20 修正平方关系。
|
||||
- 按建议修改,但不修改BUG-20
|
||||
|
||||
### BUG-22 [P1] EKF 方位角残差未按 0/2π 环绕处理
|
||||
- 位置:`kalman.cpp:265-298,457-492,642-680`;凝聚 `dot_coh.cpp:35,44`(`work_mode==0` 分支)、`dot_coh_tas.cpp:33,42`
|
||||
- 说明:预测方位被归一化到 `[0,2π)`,但量测方位未归一化,`delta_z = Z_mea - Z_pred` 未做 ±π 环绕。目标跨正北时残差会接近 2π,导致错误拒绝/错误滤波。凝聚中 `work_mode==0` 和 TAS 凝聚也直接 `fabs(angle)`,未处理 360° 环绕。
|
||||
- 建议:方位差统一按 `wrapToPi()` 处理;`work_mode==0` 与 TAS 凝聚复用同一环绕角差函数。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-23 [P1] IMM 模型概率计算缺少零分母/奇异矩阵保护
|
||||
- 位置:`track_asso.cpp:157-165,627-647`、`track_asso_tas.cpp:122-130,406-431`、`track_asso_direct_tracking.cpp:95-103,352-374`
|
||||
- 说明:`c[0..2]`、`Possibility1*c[0]+...`、`det_S` 都可能为 0 或负;`1/sqrt(2*PI*det_S)` 对负/零行列式产生 NaN。一旦概率变 NaN,后续 `model_output` 会把整条航迹状态污染。
|
||||
- 建议:计算前检查 `det_S > eps`、分母 > eps;异常时保持上一拍模型概率或回退为等概率 `{1/3,1/3,1/3}`。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-24 [P2] EKF 似然只取 3x3 新息协方差左上角 2x2 的行列式
|
||||
- 位置:`kalman.cpp:515-519`(S 为 3x3,但输出只保存 2x2);调用处 `track_asso.cpp:627-633`、`track_asso_tas.cpp:406-412`、`track_asso_direct_tracking.cpp:352-358`
|
||||
- 说明:EKF 量测为距离/方位/径向速度三维,新息协方差 S 是 3x3,但接口 `S_filter[2][2]` 和似然计算只使用二维子块,模型似然不完整。
|
||||
- 建议:将接口改为 3x3,并采用完整 3 维高斯归一化因子 `1/sqrt(pow(2*PI,3)*detS)`(若只比较相对大小,也至少应保持三个模型使用相同维数)。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-25 [P1] TWS 航迹关联/输出没有排除 TAS 航迹
|
||||
- 位置:`track_asso.cpp:65-133`(输出)、`141-228`(交互
|
||||
)、`414-570`(滤波)
|
||||
- 说明:原代码中有 `// if manual_tracking_flag==0` 的过滤逻辑但被注释掉。当前 TWS 处理会遍历并更新所有航迹,包括 `Track_Mode==1` 的 TAS 航迹;TWS 输出循环也会把 TAS 航迹当作 `point_type=0` 输出,造成 TAS 航迹被 TWS 点迹错误更新和重复输出。
|
||||
- 建议:TWS 的交互、关联、输出统一跳过 `Track_Mode == 1`(或 `manual_tracking_flag == 1`)的航迹;TAS 目标只在 TAS 流程中处理。
|
||||
- 暂不处理
|
||||
|
||||
### BUG-26 [P2] 输出航向角使用 `atan(y/x)` 而不是 `atan2`
|
||||
- 位置:`track_asso.cpp:100`、`track_asso_tas.cpp:66`、`track_asso_direct_tracking.cpp:59`
|
||||
- 说明:当 `vx == 0` 时除法结果接近 ±inf,现有象限修正逻辑不完整,某些象限会输出负角度或 90° 偏差。
|
||||
- 建议:统一使用 `atan2(X[4], X[1])` 并归一化到 `[0,2π)`。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-27 [P2] `asin(height/range)` 缺少定义域和零距离保护
|
||||
- 位置:`track_asso_tas.cpp:54`、`track_asso_direct_tracking.cpp:48`、`track_init.cpp:646,673`
|
||||
- 说明:`range` 为 0 或 `height > range` 时,`asin` 参数超出 `[-1,1]` 产生 NaN,并输出到 `Track.Elevation`。
|
||||
- 建议:计算前钳位 `h/r` 到 `[-1,1]`,并对 `r <= eps` 特殊处理。
|
||||
- 按建议修改
|
||||
|
||||
---
|
||||
|
||||
## 6. 状态清理与接口一致性
|
||||
|
||||
### BUG-28 [P1] `track_clear_all` 清理不彻底,重连后可能输出幽灵航迹/幽灵波束
|
||||
- 位置:`data_process.cpp:219-229`
|
||||
- 说明:只清空 6 个顶层 vector,未清理:
|
||||
- `Dot_Coh::data_input_buff`(滑窗凝聚缓存);
|
||||
- `TAS_Ctrl::tas_target_queue` 和 `tas_target_num`;
|
||||
- `last_beam_num`(扫描圈判断);
|
||||
- `Track_Ind_Mangement::lastest_index`;
|
||||
- 各关联类的 `point_process` 成员。
|
||||
清空后若立即调用 `Beam_Ctrl`,TAS 队列仍认为有目标,但 `trust_track` 已空,会触发 BUG-12 的未初始化路径并输出错误波束;下一次 TWS 处理也可能输出清空前的缓存点迹。
|
||||
- 建议:为 `Dot_Coh`、`TAS_Ctrl`、`Track_Ind_Mangement` 增加 `reset()`,`track_clear_all` 调用所有 reset,并恢复 `last_beam_num=INT_MAX`。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-29 [P2] `tracking_stop` 后 TAS 队列要到下一次 `Beam_Ctrl` 才移除
|
||||
- 位置:`data_process.cpp:260-270`、`tas_ctrl.cpp:138-162`
|
||||
- 说明:`tracking_stop` 只清标志位和 `Track_Mode`,不会立即清 `tas_target_queue`。在调用 `Beam_Ctrl` 前,队列仍会输出该目标的跟踪波束。
|
||||
- 建议:`tracking_stop` 内同步删除 TAS 队列项并更新 `tas_target_num`,或明确接口时序并文档化。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-30 [P2] 工作模式枚举与代码分支不一致
|
||||
- 位置:`data_process_class_dll.h:140`(注释:0 进程、1 中程、3 远程)、`track_asso.cpp:729-744`(按 0/1/2/else 分支)
|
||||
- 说明:注释定义远程模式为 3,但代码按 `work_mode==2` 使用远距数据率;当外部按注释传 3 时,会落入 else 使用近程数据率 `DATA_RATE_SHORT`。
|
||||
- 建议:统一枚举定义,或代码改为 `work_mode==3` 使用 `DATA_RATE_FAR`。
|
||||
- 注释有误,修改注释为:0 进程、1 中程、2 远程
|
||||
|
||||
### BUG-31 [P2] `tracking_point` 和引导跟踪处理是空实现
|
||||
- 位置:`data_process.cpp:282-286`、`data_process_class_dll.h:200-213`、`track_init_direct_tracking.cpp:11-21`
|
||||
- 说明:`tracking_point` 直接返回 0;`Data_Process` 没有重写 `direct_tracking_process`,基类默认返回 0;`Track_Init_Direct_Tracking::track_init_process_logic` 也是空函数。若接口已被主程序调用,则相关功能实际未生效。
|
||||
- 建议:确认这两个接口是否已废弃;若仍需要,补齐实现或至少在文档中明确为未实现并返回错误码。
|
||||
- 在注释中明确接口未启用,保留空实现
|
||||
|
||||
---
|
||||
|
||||
## 7. 其他逻辑与健壮性
|
||||
|
||||
### BUG-32 [P2] 凝聚内层循环没有跳过已标记使用的点
|
||||
- 位置:`dot_coh.cpp:25,148`、`dot_coh_tas.cpp:25`
|
||||
- 说明:内层只检查当前基准点 `loop_of_point` 的 `Use_Flag`,没有检查被比较点 `i` 的 `Use_Flag`。已被凝聚掉的点仍可参与后续比较,甚至反过来把高幅度基准点标记掉。
|
||||
- 建议:内层同样判断 `(*data_input)[i].Use_Flag != 1`(以及 `data_tmp[i]`)。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-33 [P2] 起批/临时航迹关联未校验 `delta_T > 0`,重复时间戳可能产生非法卡尔曼初始化
|
||||
- 位置:`track_init.cpp:189,381,450`、`track_init_direct_tracking.cpp:67,221,271`
|
||||
- 说明:点迹与临时航迹、点迹与航迹头的关联均使用 `T_point - T_track_head`,未要求正时间差。`kalman_filter_init_2dots` 遇到 0/负 T 会产生除零。
|
||||
- 建议:在关联条件中显式要求 `T_point > T_track_head`,且时间差需大于最小步长。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-34 [P2] 临时航迹消亡函数在空向量时直接取 `[n-1]`
|
||||
- 位置:`track_init.cpp:694-695`、`track_init_direct_tracking.cpp:417-418`
|
||||
- 说明:`int n = (*Iter).size();` 后立即 `(*Iter)[n-1]`。正常流程每条临时航迹至少 1 个点,但没有防御;一旦出现空内层向量,`n-1` 为负并越界。
|
||||
- 建议:先判断 `n > 0`,空向量直接删除。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-35 [P3] 航迹号复用逻辑漏掉 `MAX_TRACK_INDEX`
|
||||
- 位置:`track_index_mangement.cpp:44,56`
|
||||
- 说明:回绕查找循环写作 `i < MAX_TRACK_INDEX`,因此 500 号航迹永远不会被复用;与第一段 `i <= MAX_TRACK_INDEX` 不一致。
|
||||
- 建议:两处回绕循环改为 `i <= MAX_TRACK_INDEX`。
|
||||
- 按建议修改
|
||||
|
||||
### BUG-36 [P3] TAS 波束关闭时只清 `open_flag`,其他字段保留旧值
|
||||
- 位置:`tas_ctrl.cpp:277-284`
|
||||
- 说明:当 `tas_target_queue[0].empty_flag==0` 时,仅设置 `Tracking_beam->open_flag=0`,`Range/Azi/Elev/type/TAS_track_index` 保留上一拍内容。主程序若只按 `open_flag` 判断则无问题,但字段语义不清晰。
|
||||
- 建议:关闭时同时清零 `type/Range/Azi/Elev/TAS_track_index`。
|
||||
- 暂不修改
|
||||
|
||||
### BUG-37 [P3] 部分结构体局部变量未完整初始化
|
||||
- 位置:`track_init.cpp:80,598`、`track_init_direct_tracking.cpp:325`
|
||||
- 说明:`Temp_track temp_track_tmp`、`Trust_Track trust_track_tmp` 的 `P` 矩阵等字段未显式初始化。当前流程部分字段未被读取,但依赖调用顺序;后续维护容易读到垃圾值。
|
||||
- 建议:使用值初始化 `Temp_track tmp = {};` 或为结构体提供构造函数/`init()` 统一初始化所有字段。
|
||||
- 按建议修改
|
||||
|
||||
---
|
||||
|
||||
## 建议修复顺序
|
||||
|
||||
1. 先修 P0:BUG-01、BUG-04、BUG-05、BUG-06、BUG-07、BUG-11、BUG-12。
|
||||
2. 再修 P1 时间与关联逻辑:BUG-15~BUG-23、BUG-25、BUG-28。
|
||||
3. 最后处理数值稳定性、状态一致性和未启用功能:BUG-24、BUG-26~BUG-37。
|
||||
|
||||
> 说明:`track_asso_direct_tracking.cpp` 和 `track_init_direct_tracking.cpp` 当前未加入 CMake 构建(与旧 .pro 一致),其中问题与主流程同类问题重复,修复主流程时可同步修改或暂缓。
|
||||
@@ -0,0 +1,42 @@
|
||||
# 雷达数据处理项目修改说明
|
||||
|
||||
## 概述
|
||||
|
||||
增加日志文件输出功能,具体需求如下:
|
||||
- 将标准输出std::cout重定向到日志文件,考虑使用 rdbuf() 方法,见[参考1](#参考1)
|
||||
- 在parameters.h中添加一个日志输出开关的宏定义,开关关闭时,不重定向输出到文件
|
||||
- 日志文件输出路径为“.\\rdp_logs\\”,日志文件名按当前日期+时间命名
|
||||
- 增加宏定义,在输出日志时添加时间戳、代码文件、代码行数等关键信息再输出到标准输出
|
||||
|
||||
## 参考
|
||||
|
||||
### 参考1
|
||||
使用 rdbuf() 方法重定向标准输出,更符合C++的流式风格,通过替换 std::cout 的底层流缓冲区(streambuf),将其指向一个文件输出流(std::ofstream)。
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main() {
|
||||
std::ofstream file("output.txt");
|
||||
if (!file.is_open()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 保存原始的 cout 缓冲区,以便之后恢复
|
||||
auto original_buf = std::cout.rdbuf();
|
||||
|
||||
// 将 cout 的缓冲区替换为 file 的缓冲区
|
||||
std::cout.rdbuf(file.rdbuf());
|
||||
|
||||
// 此后的输出都会写入文件
|
||||
std::cout << "这条信息会写入文件。" << std::endl;
|
||||
|
||||
// 恢复 cout 的原始缓冲区,让输出回到控制台
|
||||
std::cout.rdbuf(original_buf);
|
||||
// file 对象会在析构时自动关闭
|
||||
|
||||
std::cout << "这条信息会回到控制台。" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user