Compare commits
15
Commits
b3e2f52262
..
V1.5.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed7d6d7902 | ||
|
|
e8c56f914b | ||
|
|
42b598e2e5 | ||
|
|
fc49707b08 | ||
|
|
50e0b5cb74 | ||
|
|
e0bf227be3 | ||
|
|
a76da34756 | ||
|
|
f249fdc50d | ||
|
|
7d5a56f3d2 | ||
|
|
604f1585f6 | ||
|
|
d6cdbc0120 | ||
|
|
15215926c5 | ||
|
|
5f820987a9 | ||
|
|
f438ac53d9 | ||
|
|
e729c5baee |
@@ -3,4 +3,6 @@ build-data_process_class_dll-Desktop_Qt_5_7_0_MSVC2013_32bit-Release/
|
|||||||
debug/
|
debug/
|
||||||
release/
|
release/
|
||||||
build/
|
build/
|
||||||
|
rdp_logs/
|
||||||
|
design_docs/
|
||||||
.mnemon/
|
.mnemon/
|
||||||
+44
-5
@@ -10,12 +10,51 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 新增 CHANGELOG.md,采用 Keep a Changelog 格式记录项目变更历史。
|
- 新增 CHANGELOG.md,采用 Keep a Changelog 格式记录项目变更历史。
|
||||||
- `RadarPara` 结构体新增 `DATA_RATE_TAS`(TAS 模式数据率)字段,由 DLL 调用者通过 `track_process_parameters_initial()` 输入。
|
- `RadarPara` 结构体新增 `DATA_RATE_TAS`(TAS 模式数据率)字段,由 DLL 调用者通过 `track_process_parameters_initial()` 输入(b3e2f52)。
|
||||||
|
- `Tracking_Target` 新增 `last_track_time` 字段,记录各 TAS 目标最近一次波束输出时间(f438ac5)。
|
||||||
|
- 新增 requirements.md,说明 TAS 波束控制逻辑的修改背景与约定(b3e2f52)。
|
||||||
|
- 更新 README.md:目录结构补充 CHANGELOG.md / requirements.md;版本历史表补充 93d3924、b3e2f52、e729c5b、f438ac5 提交记录。
|
||||||
|
- 新增日志文件输出功能:`parameters.h` 增加 `RDP_LOG_ENABLE` 开关(定义时启用;**当前源码中该宏为注释状态,即默认不重定向、日志输出到控制台**)与 `RDP_LOG_DIR` 目录宏(`.\\rdp_logs\\`);新增 `rdp_log.h/.cpp` 日志模块,首次 `Data_Process_Factory::GetB()` 时按 `RDP_LOG_ENABLE` 决定是否用 `rdbuf()` 将 `std::cout` 重定向到 `.\rdp_logs\` 下按日期+时间命名的日志文件(`rdp_YYYYMMDD_HHMMSS.log`,目录不存在自动创建),`Destroy()` 销毁实例时恢复 `std::cout` 并关闭文件;开关注释关闭时不重定向、日志仍输出到标准输出;日志文件在 `CMakeLists.txt` 的 SOURCES 中注册。
|
||||||
|
- 新增 `RDP_LOG` 日志输出宏(`rdp_log.h`):自动在每条日志前附加 `[时间戳][代码文件:行号]` 信息后再输出到标准输出(重定向开启时随之写入日志文件),供后续新增日志统一使用。
|
||||||
|
- 更新 README.md(604f158、d6cdbc0):目录结构补充 `archived_docs/` 归档目录;9.6 节改写 TWS 关联 ΔT≤0 的处理说明;功能特性、模块职责、已知问题与参考文档的文档引用路径同步指向 `archived_docs/`;版本历史表补充 604f158、d6cdbc0 提交记录。
|
||||||
|
- TWS 关联新增**高度门限**(e0bf227,`track_asso.cpp`):原实现中分距离段的高度门限代码块整体为注释状态、`d_h` 恒为 1(等于不生效),现改为独立判定 `thd_h = |h_track − h_point|` 与航迹距离分段比较后再参与关联(分段值见 Changed),与 TAS 通道的高度门限取值一致。
|
||||||
|
- 关联门限判定重构为三个显式布尔量(e0bf227):`track_asso.cpp` 与 `track_asso_tas.cpp` 的 `model_filter()` 原先把统计距离、高度、距离三类判据混写在一个长 `if` 条件里(高度门限在 TWS 侧整体被注释),现分别计算 `thd_d`(统计距离门限,按距离分段)、`thd_h`(高度门限)、`thd_r`(TWS 距离门限)后再以 `thd_d && thd_h && thd_r`(TAS 为 `thd_d && thd_h`)判定候选,逻辑等价性更易核对;TWS 侧同时移除了 `manual_tracking_flag==0` 的注释残留代码块与其缩进。
|
||||||
|
- 更新 README.md(e0bf227):目录结构(第 3 节)删除已移除的 `docs/data_process_flow_report.html` 并补充 `design_docs/` 留档目录(被 .gitignore 忽略);2、9.6、9.10、10.1、11.1、12、13 节按源码同步 `ASSO_THORD = 4`(关联波门等效 d < 4、TWS 分段比例门限 16/1000 与 16/100)、TWS/TAS 高度门限的分段取值、`thd_d/thd_h/thd_r` 三类门限判定结构、TAS 波束数据率门控与 e0bf227 提交记录;13 节参考文档表删除已不存在的 HTML 行。
|
||||||
|
- 同步 `docs/data_process_flow_report.md`(e0bf227):4.2 节波门由「统计距离 + 距离 + 恒通过的俯仰门限」改为「统计距离 thd_d + 高度 thd_h + 距离 thd_r」并给出 TWS 高度门限分段表,7 节 TAS 高度门限 2000~3000 m 段由 200 m 更正为 250 m;7.2 节判据与 9.1 节参数表按源码更新(`ASSO_THORD = 4`、`d² < 16`);8.2 节改为单条件数据率门控并在选中目标后按 CPI 时间计算外推步长。
|
||||||
|
- 输出航迹补充「靠近/远离」方向标志 `Flag_Direction`(f249fdc):TWS 关联输出(`track_asso.cpp`)与 TAS 关联输出(`track_asso_tas.cpp`)在写入 `vr_point` 后追加 `Flag_Direction = vr_point > 0 ? 1 : 0`,即径向速度为正判为靠近(1)、为零或负判为远离(0)。该字段此前已在 `data_process_class_dll.h` 的 `Track` 结构体中声明(注释「方向标志 1 靠近/0 远离」)但从未被赋值,宿主读到的是未初始化/旧值。
|
||||||
|
- 新增三份流程与专项文档(f249fdc):`docs/data_process_flow_report.md`(数据处理流程与关键逻辑说明:总体数据流、前处理与判圈、凝聚、TWS/TAS 关联与滤波、航迹起始、外推消亡与航迹号管理、TAS 波束控制、参数脉络与关键约定)、`docs/data_process_flow_report.html`(同内容的 HTML 渲染版)、`docs/track_init_readme.md`(航迹起始 Track Init 详细逻辑说明:分阶段流程、起始条件汇总、参数调参、输出字段映射、已知风险与代码索引)。
|
||||||
|
- 更新 README.md(7d5a56f、f249fdc):目录结构新增 `docs/` 目录;2、7.2、8.1 节满圈判据改为「方位波位号 == 0」并说明 `last_beam_num` 不再参与判断;8.3、9.3 节改写点-航迹头关联判据与起批输出历史点数;9.6 节补充方向标志输出与点迹消费说明;2、10.1 节 `RDP_LOG_ENABLE` 说明改为当前实际状态(注释停用、默认不重定向);11.4 节新增航迹起始未修复观察;版本历史表补充 7d5a56f、f249fdc,参考文档表补充 `docs/` 三份文档。
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- TAS 波束控制增加数据率门控:`Beam_Ctrl()` 仅在队首目标航迹时间 `T_track` 与最新时间戳 `latest_timestamp` 的差值大于 `1 / DATA_RATE_TAS` 秒时输出 TAS 跟踪波束,使 TAS 目标数据率不再随波束时间(Beam_Ctrl 调用频率)变化;队列轮转逻辑保持不变。
|
- TAS 波束控制改为按固定数据率调度:`Beam_Ctrl()` 仅当目标满足 `1 / DATA_RATE_TAS` 秒的数据率间隔(相对航迹时间 `T_track` 与上次波束输出 `last_track_time`)时才输出 TAS 跟踪波束,使 TAS 目标数据率不再随波束时间(Beam_Ctrl 调用频率)变化。
|
||||||
- 波束门控使用 `Work_Parameter.DATA_RATE_TAS`(运行时参数)而非 `parameters.h` 中的 `DATA_RATE_TAS` 宏;参数 ≤ 0 时不做门控,保持原输出行为。
|
- TAS 波束输出目标改为队列内调度:不再固定取队首,而是遍历 TAS 队列,选择满足数据率门控且 CPI 时间最早的目标输出;原每次 Beam_Ctrl 末尾的整队循环移位(队列轮转)已停用(代码注释保留)。
|
||||||
|
- 数据率门控统一使用运行时参数 `Work_Parameter.DATA_RATE_TAS`(由 DLL 调用者经 `track_process_parameters_initial()` 输入,需为 >0 的有效值);`parameters.h` 中 `DATA_RATE_TAS` 编译期宏(相扫 0.3 / 机扫 0.0625)已注释停用,引导跟踪外推同步改用运行时参数。
|
||||||
|
- 编译时以 `#pragma message` 提示当前启用的扫描体制宏(MECHANICAL_SCANNING / PHASE_SCANNING)。
|
||||||
|
- 频点宏由 `FREQ0~FREQ20`(16.8 GHz)精简为单个 `FREQ0`,取值改为 9.2 GHz(e729c5b)。
|
||||||
|
- MSVC 编译选项按编译器版本条件追加 `/utf-8`(VS2015 及以上);MSVC 2013 不支持该选项,改用源码文件带 BOM 的 UTF-8 编码解决 C4819。
|
||||||
|
- 存量调试输出收敛为告警级 `RDP_LOG` 日志(1521592):`track_asso.cpp` / `track_asso_tas.cpp` 的 `model_filter()` 在 ΔT ≤ 0(乱序/重复时间戳)分支新增告警日志(含航迹/点迹/时间差信息,其中 `track_asso.cpp` 侧后于 604f158 注释停用);`tas_ctrl.cpp` 中 TAS 波束最早目标调度的 `printf` 调试输出移除,`data_process.cpp` 手动删除与 `track_die_tas.cpp` TAS 目标消亡的 `std::cout` 调试输出注释停用。重定向开启时上述日志随 `std::cout` 一并写入日志文件。
|
||||||
|
- `RadarPara.DATA_RATE_TAS` 单位由 Hz(1/s)改为 s(秒)(1521592):`tas_beam_output()` 的 TAS 波束输出门控由 `1 / DATA_RATE_TAS` 秒改为直接按 `DATA_RATE_TAS` 秒比较,`data_process_class_dll.h` 字段注释同步更新;调用者改按「波束输出间隔(秒)」输入该参数(原 0.3 Hz 的含义不再适用,需按新单位换算后传入)。
|
||||||
|
- requirements.md 内容更新为「雷达数据处理项目修改说明」(1521592):现描述日志文件输出功能需求(rdbuf() 重定向、日志开关宏、日期+时间命名日志、前缀日志宏,附参考示例)。
|
||||||
|
- TWS 点航关联中 ΔT ≤ 0(点迹 CPI 时间不晚于航迹时间,如 TAS 航迹遇上时间戳更早的 TWS 点迹、或重复时间戳)的候选不再被剔除(604f158):此类候选仍参与最近邻最小 d 的比较与选取,但不执行 IMM/EKF 更新、不刷新航迹时间与新鲜度(`T_track`、`Extrapolate_round`、`point_flag`、`associate_point_number` 均保持原值,该航迹仍按未关联航迹外推),同时把该点迹标记为已使用(`Use_Flag=1`)消费掉,使其无法再参与航迹起始,避免由此生成虚假 TWS 航迹;`track_asso.cpp` 中 ΔT≤0 的 `RDP_LOG` 告警日志随之注释停用(`track_asso_tas.cpp` 中同名告警日志仍启用)。
|
||||||
|
- 过期文档归档(604f158):`BUG_REPORT.md`、`BUG_FIX_REPORT.md`、`requirements.md` 由仓库根目录移入 `archived_docs/` 留档,仓库内对它们的引用路径同步改为 `archived_docs/...`。
|
||||||
|
- 扫描一圈完成判据改为「方位波位号 == 0」(7d5a56f):原判据「当前方位波位号 < 上一帧波位号」在机扫模式下遇到转台反转时波位号会变小但并未扫完一圈,造成误判;现 `data_preprocess()` 仅在 `Data_Input[0].Beam_index_aiz == 0` 时返回 1(TWS 满一圈,执行航迹处理),否则返回 2(继续蓄数据,只做滑窗凝聚)。原判据代码注释保留,`last_beam_num` 仍被赋值但不再参与判断。调用方需保证点迹的方位波位号按 0~Beam_num-1 编号且每圈必然出现 0。
|
||||||
|
- 点迹-航迹头关联判据改为统一速度区间并增加多普勒-几何一致性约束(7d5a56f,`track_init.cpp`):原先按扫描体制与距离分段收紧速度门限的分支(近程 `r≥1000` 全速 / `r<1000` 半速,中远程 `r≥2000` 全速 / `r<2000` 取 1/2~1/3 速)整体注释停用,改为 `dis ≤ V_MAX·ΔT` 且 `dis ≥ V_MIN·ΔT`,同时要求 `vr_point·v_track_head > 0`,并新增 `dis ≥ |vr_point|·ΔT` 与 `dis ≥ |v_track_head|·ΔT` 两条约束——切向高速目标在 ΔT 内的实际位移远小于 `|vr|·ΔT`,据此被排除,用于限制由切向高速点迹起批出的短航迹。其中 `vmax` 的近程/中远程分支取值相同,均取 `Work_Parameter.V_MAX`。
|
||||||
|
- 同步 `docs/` 内两份专项文档(本次文档更新):`docs/data_process_flow_report.md` 附录与 `docs/track_init_readme.md` 第 12.1 节的「与 README 的差异」说明改为「差异已按结论同步到 README」并保留更新前的旧表述作为改动缘由;其中「起始输入过滤」一行更正为「上游 `track_asso_process()` 已删除 `Use_Flag==1` 的点迹 + `track_init` 入口再次剔除」,「初始化用点」一行更正为「取下标 `track_start_point_num-3 ~ -1`,航迹更长时不是真正的末三点」;`docs/track_init_readme.md` 第 15 节第 2 条相应更正(`track_init.cpp` L505 的 `L` 覆盖为 `track_start_point_num`,第 L 个点之后的尾部点既不参与初始化也不输出),第 14 节补充说明 `Flag_Direction` 仅由关联输出路径赋值、起批输出不写该字段。
|
||||||
|
- 关联波门 `ASSO_THORD` 由 3 调大至 4(e0bf227,`parameters.h` 相扫/机扫两组宏同步):判据写作 `d*d < ASSO_THORD*ASSO_THORD`,而 `d` 本身已是马氏距离平方,等效门限由 `d < 3` 放宽为 `d < 4`(TWS 分距离段的比例门限随之由 9/1000、9/100 变为 16/1000、16/100),配合高度门限判定提高机动目标的关联概率;调参时仍需注意这一层「二次方」语义(BUG-20 有意保留)。
|
||||||
|
- TWS 与 TAS 关联的高度门限统一为同一组按航迹距离分段的取值(e0bf227):`r_track ≤ 1000 m` 时 `|h_track − h_point| ≤ 150 m`、`1000~2000 m` 时 ≤ 200 m、`2000~3000 m` 时 ≤ 250 m、`3000~5000 m` 时 ≤ 300 m、`> 5000 m` 不约束。其中 TWS 侧为该门限首次生效(原代码块被注释),TAS 侧 `2000~3000 m` 段由 200 m 放宽到 250 m。
|
||||||
|
- TAS 波束输出的数据率门控条件修正(e0bf227,`tas_ctrl.cpp::tas_beam_output()`):原判据同时要求「距上次波束输出超过 DATA_RATE_TAS」与「航迹时间 T_track 与最新时间戳之差超过 DATA_RATE_TAS」,后者与「选取 CPI 时间最早目标」的语义冲突,会额外抑制本可输出的目标;现仅保留 `delta_T_last_track = (latest_timestamp − last_track_time)/1000 > DATA_RATE_TAS` 一条门控,`delta_T` 改为在选中该目标后按 `(latest_timestamp − CPI_time)/1000` 计算并用于外推,使 TAS 目标输出间隔严格跟随数据率。
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 修复 MSVC `/W3` 下全部 C4819 / C4018 / C4244 编译警告:源码文件改为带 BOM 的 UTF-8 编码;signed/unsigned 不匹配处改用 `size_t` 循环变量或显式 `static_cast<int>` 比较;double/float、__int64/double 等窄化转换改为 `static_cast` 显式转换,保持原有计算逻辑不变(涉及 `data_process.cpp`、`dot_coh.cpp`、`dot_coh_tas.cpp`、`tas_ctrl.cpp`、`track_asso.cpp`、`track_asso_tas.cpp`、`track_init.cpp`、`track_init_direct_tracking.cpp`、`track_index_mangement.cpp` 等)。
|
||||||
|
- 修复 `TAS_Ctrl::tas_beam_output()` 把航迹向量下标 `earliest_track_idx` 误赋给 `Tracking_beam->TAS_track_index` 的问题(1521592):现输出实际航迹号 `(*trust_track)[earliest_track_idx].Track_Index`,避免跟踪波束批号与目标不符。
|
||||||
|
- 修正 README.md(第 2、5.2、8.1、8.3、9.3、13 节)与 `docs/data_process_flow_report.md`(第 0、1、6.1~6.4 节、附录)中航迹起始的步骤顺序描述(纯文档勘误,无代码改动):两份文档原写作「航迹头(1 点)→ 点-航迹头关联(2 点)→ 点-临时航迹关联(≥3 点)→ 起批」,与 `track_init.cpp`(L49-126)每圈的实际执行顺序相反;现更正为「① 点迹先与 ≥2 点临时航迹关联(延长已有临时航迹)→ ② 再与 1 点航迹头关联(两点卡尔曼初始化出 2 点临时航迹)→ ③ 两个阶段都结束后统一删除被消费(`Use_Flag==1`)的点迹、剩余点迹逐条转为新航迹头 → ④ 长度达标的临时航迹经三点卡尔曼初始化转为可靠航迹」,并同步修正流程图与状态机;另补充两点此前的描述缺失:两个关联阶段互不排斥(航迹头阶段不检查临时航迹阶段留下的 `Use_Flag`,同一点迹可同时延长一条临时航迹并开启一条 2 点临时航迹)、两类关联都不做一对一分配(同一条临时航迹可被同圈多个点延长)。
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- 删除已注释停用的无用代码残留(d6cdbc0):`data_process.cpp` 中 TWS/TAS 分支的 `std::cout` 调试输出注释块,以及 `dot_coh.cpp` 中早期「1 km 以内 SNR < 20 dB 点迹过滤」的注释代码块。仅清理注释,不改变任何运行逻辑。
|
||||||
|
- 删除 `docs/data_process_flow_report.html`(e0bf227):该 HTML 渲染版与 `docs/data_process_flow_report.md` 内容重复且已明显滞后,保留价值不足;同内容的 HTML 已在 git 忽略的 `design_docs/` 内另行留档。README 目录结构、参考文档表与版本历史表中指向该文件的条目同步移除。
|
||||||
|
|
||||||
## [1.5.5] - 2026-08-27
|
## [1.5.5] - 2026-08-27
|
||||||
|
|
||||||
@@ -46,11 +85,11 @@
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- 修复若干逻辑 BUG(数组越界/下溢、局部变量未初始化、时间差无效、方位角 ±π 环绕、IMM 概率奇异、输出数组容量越界等),明细见 `BUG_FIX_REPORT.md`。
|
- 修复若干逻辑 BUG(数组越界/下溢、局部变量未初始化、时间差无效、方位角 ±π 环绕、IMM 概率奇异、输出数组容量越界等),明细见 `archived_docs/BUG_FIX_REPORT.md`。
|
||||||
- 修复 TAS 外推时间差可能为无效值的问题。
|
- 修复 TAS 外推时间差可能为无效值的问题。
|
||||||
- 修复航迹起始时未输出跟踪类型、可靠航迹手动转跟踪标志未清零的问题。
|
- 修复航迹起始时未输出跟踪类型、可靠航迹手动转跟踪标志未清零的问题。
|
||||||
- 修复量测噪声协方差矩阵 R 赋值错误、数据预处理波位号判断规则、点迹数量上限、雅可比矩阵取值、起批负索引等问题。
|
- 修复量测噪声协方差矩阵 R 赋值错误、数据预处理波位号判断规则、点迹数量上限、雅可比矩阵取值、起批负索引等问题。
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- 移除 `requirements.md`、`CLAUDE.md`、Makefile 系列、Qt 工程用户文件、内置 Eigen 3.3.7 冗余文件及「航迹点迹区分区说明」等不必要文件。
|
- 移除 `requirements.md`(93d3924 移除,后于 b3e2f52 重新加入并改为 TAS 波束控制说明)、`CLAUDE.md`、Makefile 系列、Qt 工程用户文件、内置 Eigen 3.3.7 冗余文件及「航迹点迹区分区说明」等不必要文件。
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
data_process_class_dll/rdp_log.cpp
|
||||||
data_process_class_dll/data_process_class_dll.cpp
|
data_process_class_dll/data_process_class_dll.cpp
|
||||||
data_process_class_dll/data_process.cpp
|
data_process_class_dll/data_process.cpp
|
||||||
data_process_class_dll/dot_coh.cpp
|
data_process_class_dll/dot_coh.cpp
|
||||||
@@ -80,6 +81,13 @@ if(MSVC)
|
|||||||
/FS
|
/FS
|
||||||
$<$<CONFIG:Release>:/Zc:strictStrings>
|
$<$<CONFIG:Release>:/Zc:strictStrings>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 修复 C4819(源文件含当前代码页无法表示的字符)。
|
||||||
|
# /utf-8 从 VS2015 Update 2 开始支持;本工程使用 MSVC 2013 时无该选项,
|
||||||
|
# 通过为源码文件添加 UTF-8 BOM 解决 C4819,这里仅对支持 /utf-8 的新版 MSVC 开启。
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL 1900)
|
||||||
|
target_compile_options(data_process_class_dll PRIVATE /utf-8)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# 输出目录:build/bin 下为 DLL/PDB,build/lib 下为导入库。
|
# 输出目录:build/bin 下为 DLL/PDB,build/lib 下为导入库。
|
||||||
|
|||||||
@@ -51,15 +51,16 @@
|
|||||||
|
|
||||||
## 2. 功能特性
|
## 2. 功能特性
|
||||||
|
|
||||||
- **双模式处理管线**:data_preprocess 按输入类型与扫描圈完成标志返回 0/1/2/3,track_process 据此调度 TWS 凝聚/关联/起始或 TAS 凝聚/关联。
|
- **双模式处理管线**:data_preprocess 按输入类型与扫描圈完成标志返回 0/1/2/3(TWS 以方位波位号 == 0 判为一圈完成,机扫转台反转不再误判),track_process 据此调度 TWS 凝聚/关联/起始或 TAS 凝聚/关联。
|
||||||
- **两帧滑窗点迹凝聚**:TWS 点迹先与上一帧缓存合并凝聚,再进入关联,兼顾跨波位(CPI)相邻点迹的分裂问题;近程模式增加速度维约束。
|
- **两帧滑窗点迹凝聚**:TWS 点迹先与上一帧缓存合并凝聚,再进入关联,兼顾跨波位(CPI)相邻点迹的分裂问题;近程模式增加速度维约束。
|
||||||
- **逻辑法航迹起始**:航迹头(单点)→ 点-头速度法关联(两点)→ 点-临时航迹 EKF 波门 + 折角约束关联(三点及以上)→ 三点卡尔曼初始化转可靠航迹;带起批屏蔽区与重复航迹去重。
|
- **逻辑法航迹起始**:每圈按固定顺序推进——① 未关联点迹先与 ≥2 点临时航迹做 EKF 波门 + 折角约束关联(延长临时航迹),② 再与 1 点航迹头做速度法关联(两点卡尔曼初始化出 2 点临时航迹),③ 两步都做完后删除被消费的点迹、剩余点迹转成新航迹头,④ 长度达标的临时航迹经三点卡尔曼初始化转可靠航迹;带起批屏蔽区与重复航迹去重。
|
||||||
- **3 模型 IMM 滤波**:三个 Singer 模型(低/中/高过程噪声),量测为「距离-方位-径向速度」三维的 EKF,多普勒残差按盲速折叠,似然用 3×3 新息协方差。
|
- **3 模型 IMM 滤波**:三个 Singer 模型(低/中/高过程噪声),量测为「距离-方位-径向速度」三维的 EKF,多普勒残差按盲速折叠,似然用 3×3 新息协方差。
|
||||||
- **最近邻数据关联**:TWS 按航迹距离分段收紧模型 3 波门并附加距离门限;TAS 附加按距离分段的高度门限。
|
- **最近邻数据关联**:三模型统计距离波门 `ASSO_THORD = 4`(等效 d < 4,TWS 另按航迹距离分段收紧模型 3 波门),再叠加高度门限(≤1000 m 150 m / 2000 m 200 m / 3000 m 250 m / 5000 m 300 m,更远不约束)与 TWS 弦距-位移距离门限。ΔT ≤ 0(点迹时间戳不晚于航迹时间)的候选不更新航迹状态、仅消费该点迹(标记已使用),避免其继续起批而生成虚假 TWS 航迹。关联输出的航迹同时给出**靠近/远离方向标志**:`Flag_Direction = vr_point > 0 ? 1 : 0`(1 靠近 / 0 远离),TWS、TAS 两通道一致。
|
||||||
- **高度维独立平滑**:按距离分段选择滑动平均窗长(5/6/7/9 点),抑制俯仰测量跳变。
|
- **高度维独立平滑**:按距离分段选择滑动平均窗长(5/6/7/9 点),抑制俯仰测量跳变。
|
||||||
- **TAS 波束控制**:手动转 TAS 目标入队(队列长度与容量随扫描体制切换),按最新时间戳外推输出跟踪波束(距离/方位/俯仰/批号)。
|
- **TAS 波束控制**:手动转 TAS 目标入队(队列长度与容量随扫描体制切换),按最新时间戳外推输出跟踪波束(距离/方位/俯仰/批号)。
|
||||||
- **航迹生命周期管理**:外推轮数计数、超时消亡、手动删除、全清空(含各模块 reset,防重连后幽灵航迹)。
|
- **航迹生命周期管理**:外推轮数计数、超时消亡、手动删除、全清空(含各模块 reset,防重连后幽灵航迹)。
|
||||||
- **防御性加固**:见 BUG_FIX_REPORT.md——越界防护、时间戳正序校验、方位角 ±π 环绕、asin 定义域钳位、IMM 概率奇异保护等已修复项。
|
- **防御性加固**:见 archived_docs/BUG_FIX_REPORT.md——越界防护、时间戳正序校验、方位角 ±π 环绕、asin 定义域钳位、IMM 概率奇异保护等已修复项。
|
||||||
|
- **日志文件输出**:`RDP_LOG_ENABLE` 定义时,首次 `Data_Process_Factory::GetB()` 自动用 `rdbuf()` 将 `std::cout` 重定向到 `RDP_LOG_DIR`(`.\rdp_logs\`)下按日期+时间命名的日志文件,`Destroy()` 时恢复控制台并关闭文件;`RDP_LOG` 日志宏在每条日志前附加 `[时间戳][文件:行号]`。该宏在 `parameters.h` 中**当前为注释状态(默认不启用)**,即默认不做重定向、日志输出到控制台(见 10.1)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -68,8 +69,16 @@
|
|||||||
```text
|
```text
|
||||||
.
|
.
|
||||||
├── CMakeLists.txt # CMake 构建脚本(扫描模式切换、导出宏、输出目录)
|
├── CMakeLists.txt # CMake 构建脚本(扫描模式切换、导出宏、输出目录)
|
||||||
├── BUG_REPORT.md # 全量逻辑 BUG 分析报告(P0~P3,37 项)
|
├── CHANGELOG.md # 变更日志(Keep a Changelog 格式,按 git 提交记录维护)
|
||||||
├── BUG_FIX_REPORT.md # BUG 修复报告(修复明细 + 编译验证结果)
|
├── README.md # 本文件:项目说明(架构、接口、流程、算法、参数)
|
||||||
|
├── archived_docs/ # 过期文档留档(仅作历史参考;接口与流程以本 README 与 docs/ 专项说明为准)
|
||||||
|
│ ├── BUG_REPORT.md # 全量逻辑 BUG 分析报告(P0~P3,37 项)
|
||||||
|
│ ├── BUG_FIX_REPORT.md # BUG 修复报告(修复明细 + 编译验证结果)
|
||||||
|
│ └── requirements.md # 需求说明:日志文件输出功能修改要求(含 rdbuf() 重定向参考示例)
|
||||||
|
├── docs/ # 专项说明文档(按当前源码整理,与 README 互补)
|
||||||
|
│ ├── data_process_flow_report.md # 数据处理流程与关键逻辑说明(前处理/判圈、凝聚、关联与滤波、起始、外推消亡、TAS 波束、参数脉络)
|
||||||
|
│ └── track_init_readme.md # 航迹起始(Track Init)详细逻辑说明(阶段流程、条件汇总、输出字段映射、风险点、代码索引)
|
||||||
|
├── design_docs/ # 设计与讨论资料留档(被 .gitignore 忽略、不入库;含设计讨论、产品介绍与 README/流程报告的导出、渲染版本)
|
||||||
├── .vscode/ # VS Code 工程配置
|
├── .vscode/ # VS Code 工程配置
|
||||||
│ ├── settings.json # cmake.generator=NMake、MSVC2013 x86 环境变量、compile_commands
|
│ ├── settings.json # cmake.generator=NMake、MSVC2013 x86 环境变量、compile_commands
|
||||||
│ ├── cmake-variants.yaml # X256_PS / X256_MS × Release / Debug 变体
|
│ ├── cmake-variants.yaml # X256_PS / X256_MS × Release / Debug 变体
|
||||||
@@ -83,6 +92,7 @@
|
|||||||
│ ├── data_process_class_dll.h # 对外接口:DataRev/Track/TrackingBeam/RadarPara 结构体、抽象基类、工厂类
|
│ ├── data_process_class_dll.h # 对外接口:DataRev/Track/TrackingBeam/RadarPara 结构体、抽象基类、工厂类
|
||||||
│ ├── data_process_class_dll_global.h # DLL 导入导出宏
|
│ ├── data_process_class_dll_global.h # DLL 导入导出宏
|
||||||
│ ├── data_process_class_dll.cpp # 工厂实现(GetB/Destroy 单例)
|
│ ├── data_process_class_dll.cpp # 工厂实现(GetB/Destroy 单例)
|
||||||
|
│ ├── rdp_log.h / .cpp # 日志输出模块:rdbuf() 重定向 std::cout、RDP_LOG 宏(开关宏在 parameters.h)
|
||||||
│ ├── data_process.h / .cpp # Data_Process 实现:接口分发、TWS/TAS 主流程、参数管理、清空/删除/转跟踪
|
│ ├── data_process.h / .cpp # Data_Process 实现:接口分发、TWS/TAS 主流程、参数管理、清空/删除/转跟踪
|
||||||
│ ├── struct.h # 内部结构体:PointRecv / Trust_Track / Temp_track / Tracking_Target
|
│ ├── struct.h # 内部结构体:PointRecv / Trust_Track / Temp_track / Tracking_Target
|
||||||
│ ├── parameters.h # 编译期宏参数(按 MECHANICAL_SCANNING / PHASE_SCANNING 分两组)
|
│ ├── parameters.h # 编译期宏参数(按 MECHANICAL_SCANNING / PHASE_SCANNING 分两组)
|
||||||
@@ -90,7 +100,7 @@
|
|||||||
│ ├── dot_coh_tas.h / .cpp # TAS 点迹凝聚
|
│ ├── dot_coh_tas.h / .cpp # TAS 点迹凝聚
|
||||||
│ ├── coor_trans.h / .cpp # 极坐标 ↔ 直角坐标转换
|
│ ├── coor_trans.h / .cpp # 极坐标 ↔ 直角坐标转换
|
||||||
│ ├── kalman.h / .cpp # 卡尔曼滤波:两点/三点初始化、线性 KF、EKF(含多普勒)、统计距离、盲速计算
|
│ ├── kalman.h / .cpp # 卡尔曼滤波:两点/三点初始化、线性 KF、EKF(含多普勒)、统计距离、盲速计算
|
||||||
│ ├── track_asso.h / .cpp # TWS 航迹关联:IMM 交互 → 滤波 → 输出、距离/俯仰门限、高度平滑
|
│ ├── track_asso.h / .cpp # TWS 航迹关联:IMM 交互 → 滤波 → 输出、统计距离/高度/距离门限、高度平滑
|
||||||
│ ├── track_asso_tas.h / .cpp # TAS 航迹关联(独立实现,量测门限与数据率不同)
|
│ ├── track_asso_tas.h / .cpp # TAS 航迹关联(独立实现,量测门限与数据率不同)
|
||||||
│ ├── track_init.h / .cpp # 逻辑法航迹起始:点-临时航迹关联、点-航迹头关联、转可靠航迹、屏蔽区
|
│ ├── track_init.h / .cpp # 逻辑法航迹起始:点-临时航迹关联、点-航迹头关联、转可靠航迹、屏蔽区
|
||||||
│ ├── track_init_direct_tracking.h/.cpp# 引导跟踪航迹起始(当前入口为空实现,未启用)
|
│ ├── track_init_direct_tracking.h/.cpp# 引导跟踪航迹起始(当前入口为空实现,未启用)
|
||||||
@@ -104,6 +114,7 @@
|
|||||||
│ ├── X256_PS/ # 相扫构建目录(含 bin/data_process_class_dll.dll、rdp_playback.exe 等)
|
│ ├── X256_PS/ # 相扫构建目录(含 bin/data_process_class_dll.dll、rdp_playback.exe 等)
|
||||||
│ ├── X256_MS/ # 机扫构建目录
|
│ ├── X256_MS/ # 机扫构建目录
|
||||||
│ └── output/ # 早期打包导出(其中 data_process_class_dll.h 为旧版 32 位时间戳接口,勿作为当前 API 依据)
|
│ └── output/ # 早期打包导出(其中 data_process_class_dll.h 为旧版 32 位时间戳接口,勿作为当前 API 依据)
|
||||||
|
├── rdp_logs/ # 日志输出目录(运行时自动创建于宿主进程当前工作目录下,被 .gitignore 忽略)
|
||||||
└── .gitignore
|
└── .gitignore
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -159,6 +170,12 @@ cmake --build build/X256_PS
|
|||||||
|
|
||||||
仓库 build/X256_PS/bin/ 内还带有 **rdp_playback.exe**(回放测试工具,依赖 Qt5Core.dll、sqlite3.dll,配置样例 RadarConfigParam.ini,可回放 .db 记录的点迹数据验证 DLL 输出),不在本仓库源码范围内。
|
仓库 build/X256_PS/bin/ 内还带有 **rdp_playback.exe**(回放测试工具,依赖 Qt5Core.dll、sqlite3.dll,配置样例 RadarConfigParam.ini,可回放 .db 记录的点迹数据验证 DLL 输出),不在本仓库源码范围内。
|
||||||
|
|
||||||
|
### 4.5 编译警告处理
|
||||||
|
|
||||||
|
- 源码文件统一使用 **带 BOM 的 UTF-8** 编码保存,兼容 MSVC 2013(该版本不支持 `/utf-8`),消除 C4819。
|
||||||
|
- `CMakeLists.txt` 对 MSVC 19.0 及以上版本自动追加 `/utf-8` 编译选项;使用 MSVC 2013 构建时请保持源码为 UTF-8 with BOM。
|
||||||
|
- 修复了 `/W3` 下全部 C4018(signed/unsigned 不匹配)与 C4244(类型转换可能丢失数据)警告:循环变量按需改为 `size_t`,窄化转换改为 `static_cast` 显式转换,不改变原有计算逻辑。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. 总体架构
|
## 5. 总体架构
|
||||||
@@ -234,14 +251,15 @@ classDiagram
|
|||||||
| Data_Process(data_process.cpp) | 对外接口实现与流程编排:输入缓存、按 model 分发 TWS/TAS 流水线、参数管理、航迹清空/删除、手动转/停 TAS、波束控制转发 |
|
| Data_Process(data_process.cpp) | 对外接口实现与流程编排:输入缓存、按 model 分发 TWS/TAS 流水线、参数管理、航迹清空/删除、手动转/停 TAS、波束控制转发 |
|
||||||
| Dot_Coh | TWS 点迹凝聚:两帧滑窗合并凝聚(dot_coh_process_buff) |
|
| Dot_Coh | TWS 点迹凝聚:两帧滑窗合并凝聚(dot_coh_process_buff) |
|
||||||
| Dot_Coh_TAS | TAS 点迹凝聚(单帧,距离/方位/速度三维门限) |
|
| Dot_Coh_TAS | TAS 点迹凝聚(单帧,距离/方位/速度三维门限) |
|
||||||
| Track_Asso | TWS 点航关联 + IMM 滤波:模型交互 → 门限筛选(NN)→ 各模型 EKF → 概率更新 → 模型输出;未关联航迹外推;高度平滑 |
|
| Track_Asso | TWS 点航关联 + IMM 滤波:模型交互 → 门限筛选(NN)→ 各模型 EKF → 概率更新 → 模型输出;未关联航迹外推;高度平滑;ΔT≤0(乱序/重复时间戳)的候选取出后不更新滤波、不刷新航迹,仅消费该点迹 |
|
||||||
| Track_Asso_Tas | TAS 航迹关联(只处理指定批号 tas_track_idx,门限与 TWS 略有差异) |
|
| Track_Asso_Tas | TAS 航迹关联(只处理指定批号 tas_track_idx,门限与 TWS 略有差异) |
|
||||||
| Track_Init | 逻辑法航迹起始:航迹头维护、点-头关联(两点)、点-临时航迹关联(三点及以上)、起批(三点卡尔曼初始化)、屏蔽区判断、临时航迹消亡 |
|
| Track_Init | 逻辑法航迹起始,每圈顺序固定:点-临时航迹关联(延长 ≥2 点临时航迹)→ 点-航迹头关联(两点起始)→ 剩余点转新航迹头 → 长度达标者起批(三点卡尔曼初始化);另含起批屏蔽区判断与临时航迹消亡 |
|
||||||
| Track_Die / Track_Die_Tas | 可靠航迹消亡:外推轮数超限或手动删除标志置位时输出消亡批号并删除 |
|
| Track_Die / Track_Die_Tas | 可靠航迹消亡:外推轮数超限或手动删除标志置位时输出消亡批号并删除 |
|
||||||
| TAS_Ctrl | TAS 波束控制:手动目标入队(tas_target_add)、失效目标出队(tas_target_del)、跟踪波束预测输出(tas_beam_output,含数据率门控)、队列轮转 |
|
| TAS_Ctrl | TAS 波束控制:手动目标入队(tas_target_add)、失效目标出队(tas_target_del)、跟踪波束预测输出(tas_beam_output:数据率门控 + 队内选择最早 CPI 目标)、调度时刻记录(last_track_time) |
|
||||||
| Track_Ind_Mangement | 航迹号 1~500 的顺序分配与回绕复用 |
|
| Track_Ind_Mangement | 航迹号 1~500 的顺序分配与回绕复用 |
|
||||||
| kalman | 两点/三点滤波初始化、线性卡尔曼预测/滤波、EKF(3 维量测含多普勒)、马氏统计距离 d、盲速 Bind_speed |
|
| kalman | 两点/三点滤波初始化、线性卡尔曼预测/滤波、EKF(3 维量测含多普勒)、马氏统计距离 d、盲速 Bind_speed |
|
||||||
| coor_trans | 极坐标 ↔ 直角坐标转换 |
|
| coor_trans | 极坐标 ↔ 直角坐标转换 |
|
||||||
|
| rdp_log(rdp_log.h/.cpp) | 日志输出:按 parameters.h 的 `RDP_LOG_ENABLE` 开关,在 `Init()` 中用 `rdbuf()` 将 `std::cout` 重定向到日期+时间命名的日志文件、`Shutdown()` 恢复控制台并关闭;提供 `RDP_LOG` 宏自动附加 `[时间戳][文件:行号]` 前缀 |
|
||||||
| Track_Init_Direct_Tracking / Track_Asso_Direct_Tracking | 引导跟踪(direct tracking)专用起批/关联。**当前入口为空实现、未启用**;track_asso_direct_tracking.cpp 未加入 CMake 源列表 |
|
| Track_Init_Direct_Tracking / Track_Asso_Direct_Tracking | 引导跟踪(direct tracking)专用起批/关联。**当前入口为空实现、未启用**;track_asso_direct_tracking.cpp 未加入 CMake 源列表 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -253,7 +271,7 @@ classDiagram
|
|||||||
| 结构体 | 用途 | 要点 |
|
| 结构体 | 用途 | 要点 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| DataRev | 输入点迹 | 距离(m)、方位/俯仰(°)、速度(m/s)、幅度/门限/SNR/RCS、码盘值、CPI/GNSS 时间(ms, long long)、方位波位(0-24)/俯仰波位(0-13)、PRI(µs,**不允许为 0**)、频点号、点数、点迹号、使用标记、TAS 批号、点迹类型、十字星数据 speed_dim[129]/range_dim[8] |
|
| DataRev | 输入点迹 | 距离(m)、方位/俯仰(°)、速度(m/s)、幅度/门限/SNR/RCS、码盘值、CPI/GNSS 时间(ms, long long)、方位波位(0-24)/俯仰波位(0-13)、PRI(µs,**不允许为 0**)、频点号、点数、点迹号、使用标记、TAS 批号、点迹类型、十字星数据 speed_dim[129]/range_dim[8] |
|
||||||
| Track | 输出航迹 | 位置/速度、极坐标量、航迹号、更新点数、方向/实虚点标志、一步预测、跟踪模式、航向角、目标类型、关联点信息、航迹时间(s)/GNSS、SNR/RCS、十字星数据透传 |
|
| Track | 输出航迹 | 位置/速度、极坐标量、航迹号、更新点数、方向标志 Flag_Direction(关联输出赋值:1 靠近 / 0 远离,见 9.6)、实虚点标志 Flag_Point、一步预测、跟踪模式、航向角、目标类型、关联点信息、航迹时间(s)/GNSS、SNR/RCS、十字星数据透传 |
|
||||||
| TrackingBeam | TAS 跟踪波束指令 | open_flag、type、Range、Azi、Elev、TAS_track_index |
|
| TrackingBeam | TAS 跟踪波束指令 | open_flag、type、Range、Azi、Elev、TAS_track_index |
|
||||||
| Target_direct_tracking | 引导跟踪信息 | 批号、距离/方位/俯仰、开关(接口未启用) |
|
| Target_direct_tracking | 引导跟踪信息 | 批号、距离/方位/俯仰、开关(接口未启用) |
|
||||||
| RadarPara | 工作参数 | 见 [参数说明](#10-参数说明) |
|
| RadarPara | 工作参数 | 见 [参数说明](#10-参数说明) |
|
||||||
@@ -292,16 +310,18 @@ classDiagram
|
|||||||
| tracking_point(azimuth) | 0 | 手动打跟踪波束——**未实现(保留空实现)** |
|
| tracking_point(azimuth) | 0 | 手动打跟踪波束——**未实现(保留空实现)** |
|
||||||
| direct_tracking_process(...) | 0 | 引导跟踪——**未实现(保留空实现)** |
|
| direct_tracking_process(...) | 0 | 引导跟踪——**未实现(保留空实现)** |
|
||||||
|
|
||||||
|
> 日志输出为 DLL 内部功能(不对外导出,接口见 10.1 的宏开关):首次 `GetB()` 创建实例时自动初始化(`RDP_LOG_ENABLE` 定义则将 `std::cout` 重定向到 `.\rdp_logs\` 下按日期+时间命名的日志文件,该宏当前为注释状态,见 10.1),`Destroy()` 销毁实例时恢复 `std::cout` 并关闭日志文件。
|
||||||
|
|
||||||
### 7.2 data_preprocess 返回值的含义
|
### 7.2 data_preprocess 返回值的含义
|
||||||
|
|
||||||
| 返回值 | 含义 | 触发条件 |
|
| 返回值 | 含义 | 触发条件 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 0 | 无效数据 | point_type 既非 0 也非 1 |
|
| 0 | 无效数据 | point_type 既非 0 也非 1 |
|
||||||
| 1 | **TWS 满一圈,执行航迹处理** | point_type==0 且当前方位波位号 < 上一帧波位号(波位号由大变小判为扫描一圈完成) |
|
| 1 | **TWS 满一圈,执行航迹处理** | point_type==0 且当前帧方位波位号 == 0(7d5a56f 起改用波位号为 0 判满圈:机扫转台反转时波位号会变小但并未扫完一圈,原「波位号变小」判据会误判) |
|
||||||
| 2 | **TWS 未满一圈,继续蓄数据** | point_type==0 且波位号未变小;调用 track_process(model=2) 做滑窗凝聚 |
|
| 2 | **TWS 未满一圈,继续蓄数据** | point_type==0 且方位波位号 != 0;调用 track_process(model=2) 做滑窗凝聚 |
|
||||||
| 3 | **TAS 处理** | point_type==1;同时记录 TAS_track_idx 与最新时间戳 |
|
| 3 | **TAS 处理** | point_type==1;同时记录 TAS_track_idx 与最新时间戳 |
|
||||||
|
|
||||||
> 首次调用时 last_beam_num 为 INT_MAX,因此必然返回 1;track_clear_all() 后同样复位为 INT_MAX。
|
> 7d5a56f 起满圈判据不再依赖上一帧波位号:`last_beam_num` 仍被赋值(`track_clear_all()` 复位为 INT_MAX),但不参与判断;因此首帧是否返回 1 取决于该帧方位波位号是否为 0。调用方需保证方位波位号按 0~Beam_num-1 编号且每圈均出现 0,否则 TWS 通道将持续返回 2(不满圈)。
|
||||||
|
|
||||||
### 7.3 典型调用序列
|
### 7.3 典型调用序列
|
||||||
|
|
||||||
@@ -333,12 +353,12 @@ flowchart TD
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["data_preprocess: 点迹入 Data_buffer(度→弧度、高度=Range·sin(Elev)、时间戳缓存)"] --> B["波位号变小(一圈完成)→ model=1"]
|
A["data_preprocess: 点迹入 Data_buffer(度→弧度、高度=Range·sin(Elev)、时间戳缓存)"] --> B["方位波位号 == 0(一圈完成)→ model=1"]
|
||||||
B --> C["track_process(1)"]
|
B --> C["track_process(1)"]
|
||||||
C --> D["dot_coh 两帧滑窗凝聚 → point_recv"]
|
C --> D["dot_coh 两帧滑窗凝聚 → point_recv"]
|
||||||
D --> E["track_asso: IMM 交互 → 点航波门筛选(NN)→ EKF 滤波 → 模型输出"]
|
D --> E["track_asso: IMM 交互 → 点航波门筛选(NN)→ EKF 滤波 → 模型输出"]
|
||||||
E --> F["track_die: 外推超限/手动删除 → 输出消亡批号"]
|
E --> F["track_die: 外推超限/手动删除 → 输出消亡批号"]
|
||||||
F --> G["track_init: 点-临时航迹关联 → 点-航迹头关联 → 起批转可靠航迹"]
|
F --> G["track_init: 点-临时航迹关联 → 点-航迹头关联 → 剩余点转新航迹头 → 起批转可靠航迹"]
|
||||||
G --> H["输出 Trust_Track_Output(含起批历史点)"]
|
G --> H["输出 Trust_Track_Output(含起批历史点)"]
|
||||||
H --> I["Beam_Ctrl: 手动 TAS 目标入队 / 波束输出"]
|
H --> I["Beam_Ctrl: 手动 TAS 目标入队 / 波束输出"]
|
||||||
```
|
```
|
||||||
@@ -355,27 +375,30 @@ flowchart TD
|
|||||||
D --> E["未关联 → 按 latest_timestamp 外推(ΔT≤0 跳过)"]
|
D --> E["未关联 → 按 latest_timestamp 外推(ΔT≤0 跳过)"]
|
||||||
E --> F["track_die_tas: TAS 超时/手动删除 → 消亡输出"]
|
E --> F["track_die_tas: TAS 超时/手动删除 → 消亡输出"]
|
||||||
F --> G["输出该批号航迹(point_type=1)"]
|
F --> G["输出该批号航迹(point_type=1)"]
|
||||||
G --> H["Beam_Ctrl: 队列轮转 + 预测波束输出"]
|
G --> H["Beam_Ctrl: 数据率门控 + 队内最早 CPI 目标 + 预测波束输出"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.3 航迹起始流程(逻辑法)
|
### 8.3 航迹起始流程(逻辑法)
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["未关联点迹"] --> B["转航迹头 Temp_track(1点) buff_round=1"]
|
A["本圈未关联点迹(point_recv → point_process)"] --> A1["临时航迹所有点的 buff_round +1"]
|
||||||
B --> C{"下一帧点迹"}
|
A1 --> B["① 点-临时航迹关联(≥2 点临时航迹、末点 buff_round≥2):EKF 统计距离波门 d²≤64、折角<60°、径向速度同号、|Δr|≥5m → 复制原航迹并追加新点"]
|
||||||
C --> D["点-航迹头关联:速度区间门限 + 径向速度同号 → 两点卡尔曼初始化(航迹头→2 点临时航迹)"]
|
B --> C["② 点-航迹头关联(1 点航迹头、buff_round≥2):V_MIN·ΔT ≤ dis ≤ V_MAX·ΔT、径向速度同号、dis ≥ |vr_point|·ΔT 且 dis ≥ |v_track_head|·ΔT → 两点卡尔曼初始化(航迹头 + 新点 → 2 点临时航迹)"]
|
||||||
D --> E{"后续点迹"}
|
C --> D["③ 删除 Use_Flag==1 的点迹,剩余点全部转为新航迹头 Temp_track(1 点、buff_round=1)"]
|
||||||
E --> F["点-临时航迹关联:EKF 统计距离波门 d²≤64、折角<60°、径向速度同号、|Δr|≥5m"]
|
D --> E{"④ 长度 ≥ track_start_point_num(3~9) 且 ≤10 且不在起批屏蔽区 ?"}
|
||||||
F --> G{"长度 ≥ track_start_point_num(3~9) 且 ≤10"}
|
E -- 是 --> F["重复航迹去重(保留末点 d 更小者)→ 三点卡尔曼初始化"]
|
||||||
G -- 是 --> H["屏蔽区判断 → 重复航迹去重(保留末点 d 更小者)→ 三点卡尔曼初始化"]
|
F --> G["转可靠航迹:分配航迹号 1~500,IMM 三模型同状态初始化 u=1/3"]
|
||||||
H --> I["转可靠航迹:分配航迹号 1~500,IMM 三模型同状态初始化 u=1/3"]
|
G --> H["输出前 track_start_point_num 个历史点 Trust_Track_Output[i][0..L-1]"]
|
||||||
I --> J["按历史点数输出 Trust_Track_Output[i][0..L-1]"]
|
E -- 否 --> I["留在临时航迹表,下一圈继续关联"]
|
||||||
G -- 否 --> K{"buff_round>2 或 长度≥10 ?"}
|
H --> J["⑤ 临时航迹消亡:末点 buff_round>2 或 长度≥10"]
|
||||||
K -- 是 --> L["临时航迹消亡"]
|
I --> J
|
||||||
K -- 否 --> E
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> 顺序说明:`track_init_process_logic()` 中四步的先后顺序固定、不可颠倒——先延长已有临时航迹,再与航迹头配对,两步都走完才生成新航迹头,最后才把长度达标的临时航迹转为可靠航迹(因此当圈新建的 2 点临时航迹不可能当圈起批,长度刚达标的临时航迹则可以当圈起批);临时航迹消亡在第 ⑤ 步、即全部起始动作之后执行。
|
||||||
|
>
|
||||||
|
> 第 ① ② 步**互不排斥**:两者都只把命中的点迹标记 `Use_Flag=1`,航迹头关联并不检查临时航迹关联留下的标记,因此同一点迹可能既延长一条临时航迹、又开启一条新的两点临时航迹;两类关联也都不做一对一分配(同一条临时航迹可被本圈多个点延长,同一个航迹头也可与本圈多个点配对)。只有走完两步后才统一删除 `Use_Flag==1` 的点迹,其余点迹成为新航迹头。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. 算法实现详解
|
## 9. 算法实现详解
|
||||||
@@ -427,29 +450,18 @@ $$
|
|||||||
|
|
||||||
### 9.3 航迹起始(逻辑法)
|
### 9.3 航迹起始(逻辑法)
|
||||||
|
|
||||||
#### (1) 点-航迹头关联(两点起始)
|
每圈(model=1)在 `track_init_process_logic()` 中按**固定顺序**执行下列四步,顺序不可颠倒:
|
||||||
|
|
||||||
对单点航迹头(buff_round ≥ 2),量测点需同时满足**速度区间门限**与**径向速度同号**:
|
1. **点-临时航迹关联**:本圈未关联点迹优先延长已有的 ≥2 点临时航迹(判据见 (1));
|
||||||
|
2. **点-航迹头关联**:随后点迹与 1 点航迹头配对,产生新的 2 点临时航迹(判据见 (2));
|
||||||
|
3. **剩余点迹转航迹头**:前两步只把命中的点迹标记为已使用(`Use_Flag=1`),两步都做完后才统一删除这些点迹,其余点迹逐条转为新航迹头(见 (3));
|
||||||
|
4. **转可靠航迹(起批)**:长度达标的临时航迹经三点卡尔曼初始化转为可靠航迹(见 (4));起批动作完成后才消亡不满足条件的临时航迹。
|
||||||
|
|
||||||
- 近程(work_mode==0):
|
> 两点补充:① 第 1、2 步**互不排斥**——航迹头关联不检查临时航迹关联留下的 `Use_Flag`,因此同一点迹可能既延长一条临时航迹、又开启一条新的两点临时航迹;两类关联也都不做一对一分配(同一条临时航迹可被本圈多个点延长,同一个航迹头也可与本圈多个点配对)。② 每圈入口先把**所有**临时航迹所有点的 `buff_round` 加 1 再做关联,新建点(航迹头或被关联上的新点)`buff_round = 1`,因此当圈新建的 2 点临时航迹要到下一圈末点 `buff_round` 变为 2 之后才参与第 1 步。
|
||||||
|
|
||||||
$$
|
#### (1) 点-临时航迹关联(延长 ≥2 点临时航迹)
|
||||||
r_p \ge 1000:\ V_{min}\Delta T \le d_{12} \le V_{max}\Delta T;\qquad
|
|
||||||
r_p < 1000:\ \tfrac12 V_{min}\Delta T \le d_{12} \le \tfrac12 V_{max}\Delta T
|
|
||||||
$$
|
|
||||||
|
|
||||||
- 中/远程(work_mode!=0):
|
对 ≥ 2 点的临时航迹(末点 buff_round ≥ 2),用航迹末点状态做 EKF 一步预测,计算三维(距离-方位-径向速度)马氏统计距离 d(见 9.5.3),并要求 |r_point − r_temp| ≥ 5 m,同时满足:
|
||||||
|
|
||||||
$$
|
|
||||||
r_p \ge 2000:\ V_{min}\Delta T \le d_{12} \le V_{max}\Delta T;\qquad
|
|
||||||
r_p < 2000:\ \tfrac12 V_{min}\Delta T \le d_{12} \le \tfrac13 V_{max}\Delta T
|
|
||||||
$$
|
|
||||||
|
|
||||||
其中 d12 为两点间平面距离,ΔT 为时间差(秒),并需 vr_point · vr_head > 0。关联成功用 **两点卡尔曼初始化**(见 9.5.2)。
|
|
||||||
|
|
||||||
#### (2) 点-临时航迹关联(三点及以上)
|
|
||||||
|
|
||||||
对 ≥ 2 点的临时航迹,用航迹末点状态做 EKF 一步预测,计算三维(距离-方位-径向速度)马氏统计距离 d(见 9.5.3),并要求 |r_point − r_head| ≥ 5 m,同时满足:
|
|
||||||
|
|
||||||
$$
|
$$
|
||||||
d^2 \le TRACK\_START\_THRESHOLD^2 = 64,\qquad
|
d^2 \le TRACK\_START\_THRESHOLD^2 = 64,\qquad
|
||||||
@@ -463,13 +475,37 @@ $$
|
|||||||
\alpha=\arccos\left(\frac{\vec{D_{12}}\cdot\vec{D_{23}}}{\|\vec{D_{12}}\|\,\|\vec{D_{23}}\|}\right)\cdot\frac{180}{\pi}
|
\alpha=\arccos\left(\frac{\vec{D_{12}}\cdot\vec{D_{23}}}{\|\vec{D_{12}}\|\,\|\vec{D_{23}}\|}\right)\cdot\frac{180}{\pi}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
#### (3) 转可靠航迹(起批)
|
关联成功后**复制原临时航迹并追加该点迹**,新航迹的 4 维状态用最近两点做**两点卡尔曼初始化**(见 9.5.2)重新得到。
|
||||||
|
|
||||||
临时航迹长度 L 满足 track_start_point_num ≤ L ≤ 10(起批点数由参数给定,典型 3~4,接口层校验 3~9)且不在起批屏蔽区内(屏蔽区为距离-方位矩形区域,最多 30 个)时进入起批队列;同源(共享前三点)的重复航迹只保留末点 d 最小者。起批时用 **最近三点卡尔曼初始化** 得到 6 维状态,构造 Trust_Track:
|
#### (2) 点-航迹头关联(两点起始)
|
||||||
|
|
||||||
|
对单点航迹头(buff_round ≥ 2),量测点需同时满足以下四个条件(7d5a56f 起的判据):
|
||||||
|
|
||||||
|
$$
|
||||||
|
V_{min}\Delta T \le d_{12} \le V_{max}\Delta T,\qquad
|
||||||
|
v_{r,point}\cdot v_{r,head}>0,\qquad
|
||||||
|
d_{12} \ge \left|v_{r,point}\right|\Delta T,\qquad
|
||||||
|
d_{12} \ge \left|v_{r,head}\right|\Delta T
|
||||||
|
$$
|
||||||
|
|
||||||
|
其中 d12 为两点间平面距离,ΔT 为时间差(秒),V_min/V_max 取 `RadarPara.V_MIN / V_MAX`(代码中 vmax 的近程/中远程分支取值相同,均为 V_MAX)。后两条为**多普勒-几何一致性约束**:切向飞行目标在 ΔT 内的实际位移远小于 |vr|·ΔT,据此被排除,用于限制切向高速点迹起批出的短航迹。
|
||||||
|
|
||||||
|
> 历史行为(已注释停用):原先按扫描体制与距离分段收紧速度门限——近程 r≥1000 用全速、r<1000 用半速;中远程 r≥2000 用全速、r<2000 取下限 1/2·V_min·ΔT / 上限 1/3·V_max·ΔT。
|
||||||
|
|
||||||
|
关联成功用 **两点卡尔曼初始化**(见 9.5.2)生成 2 点临时航迹:第 1 点为原航迹头,第 2 点为该点迹。
|
||||||
|
|
||||||
|
#### (3) 剩余点迹转航迹头
|
||||||
|
|
||||||
|
第 (1)(2) 步结束后统一删除 `Use_Flag==1` 的点迹;剩余点迹回写 `point_recv`(随后被整体清空),并**逐条新建 1 点临时航迹(航迹头)**:位置直接取点迹的直角坐标、速度置 0、`buff_round = 1`。新航迹头当圈不再参与任何关联,只能从下一圈开始按第 (2) 步配对。
|
||||||
|
|
||||||
|
#### (4) 转可靠航迹(起批)
|
||||||
|
|
||||||
|
临时航迹长度 N 满足 track_start_point_num ≤ N ≤ 10(起批点数由参数给定,典型 3~4,接口层校验 3~9)且不在起批屏蔽区内(屏蔽区为距离-方位矩形区域,最多 30 个)时进入起批队列;同源(前三点时间/距离相同)的重复航迹只保留 d 较小者(比较下标 `track_start_point_num-1` 处的 d)。起批时令 L = track_start_point_num,用航迹中下标 L-3、L-2、L-1 的三个点做 **三点卡尔曼初始化** 得到 6 维状态(航迹长度恰为 L 时即最近三点),构造 Trust_Track:
|
||||||
|
|
||||||
- 三个 IMM 子模型用同一状态/协方差初始化,模型概率 u = [1/3, 1/3, 1/3];
|
- 三个 IMM 子模型用同一状态/协方差初始化,模型概率 u = [1/3, 1/3, 1/3];
|
||||||
- 分配航迹号(1~500,见 9.8);
|
- 分配航迹号(1~500,见 9.8);
|
||||||
- 将临时航迹的全部 L 个点写入 Trust_Track_Output(每条航迹最多 10 个历史点)。
|
- 输出仅写入前 L 个历史点(`Trust_Track_Output[i][0..L-1]`,`Point_Sum = L`),航迹长度大于 L 时其余点不输出;
|
||||||
|
- 起批输出不写 `Flag_Direction`、`x_Predict/y_Predict/z_Predict`、`Range_Predict/Azimuth_Predict/Elevation_Predict`、`Target_Type`、`prf_point`、`v_z` 等字段,且 DLL 不清零输出数组,宿主读到的是自身缓存的旧值(详见 docs/track_init_readme.md 第 14 节)。
|
||||||
|
|
||||||
### 9.4 IMM 框架(3 个 Singer 模型)
|
### 9.4 IMM 框架(3 个 Singer 模型)
|
||||||
|
|
||||||
@@ -646,7 +682,7 @@ $$
|
|||||||
|
|
||||||
$$
|
$$
|
||||||
v_{bind}=\frac{150000}{f_{GHz}\cdot PRI_{µs}}\quad(\mathrm{m/s}),\qquad
|
v_{bind}=\frac{150000}{f_{GHz}\cdot PRI_{µs}}\quad(\mathrm{m/s}),\qquad
|
||||||
f_{GHz}=16.8+0.02\cdot f_{ind}
|
f_{GHz}=9.2+0.02\cdot f_{ind}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
(PRI ≤ 0 或 f ≤ 0 时返回安全值 1.0,接口约定 PRI 不允许为 0。)
|
(PRI ≤ 0 或 f ≤ 0 时返回安全值 1.0,接口约定 PRI 不允许为 0。)
|
||||||
@@ -657,18 +693,19 @@ $$
|
|||||||
|
|
||||||
#### TWS(track_asso.cpp)
|
#### TWS(track_asso.cpp)
|
||||||
|
|
||||||
对每条航迹 × 每个点计算三模型 d1, d2, d3,波门按航迹距离分段:
|
对每条航迹 × 每个点计算三模型 d1, d2, d3,波门按航迹距离分段(`ASSO_THORD = 4`,判据写作 `d*d < ASSO_THORD*ASSO_THORD`,而 d 本身已是马氏距离平方,故下表的等价门限为 d < 4):
|
||||||
|
|
||||||
| 航迹距离 | 模型 1/2 门限 | 模型 3 门限 |
|
| 航迹距离 | 模型 1/2 门限 | 模型 3 门限 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| r_track ≤ 500 m | d_i² < 9 | d_3² < 9/1000(≈关闭) |
|
| r_track ≤ 500 m | d_i² < 16 | d_3² < 16/1000(≈关闭) |
|
||||||
| 500 < r_track < 1000 m | d_i² < 9 | d_3² < 9/100(收紧) |
|
| 500 < r_track < 1000 m | d_i² < 16 | d_3² < 16/100(收紧) |
|
||||||
| r_track ≥ 1000 m | d_i² < 9 | d_3² < 9 |
|
| r_track ≥ 1000 m | d_i² < 16 | d_3² < 16 |
|
||||||
|
|
||||||
同时满足两个附加门限:
|
关联判据在 `model_filter()` 中拆为三个布尔量,三者同时通过才记为候选:`thd_d`(上表统计距离门限)、`thd_h`(高度门限)、`thd_r`(距离门限)。
|
||||||
|
|
||||||
- **俯仰门限 d_p**:当前恒为 true(分距离段 7°/5°/10° 的逻辑在源码中被注释停用);
|
- **高度门限 thd_h**(e0bf227 起生效):以 |h_track − h_point| 与航迹距离分段比较,取值与 TAS 通道一致——≤ 1000 m 时 ≤ 150 m、1000~2000 m 时 ≤ 200 m、2000~3000 m 时 ≤ 250 m、3000~5000 m 时 ≤ 300 m、> 5000 m 时不约束。该项原为注释停用的代码块(等价于恒通过),现正式参与关联判定,用于压制俯仰测量跳变引起的错误关联;
|
||||||
- **距离门限 d_r**:以航迹-点迹弦距 R = √(r_t² + r_p² − 2·r_t·r_p·cos Δθ)(Δθ 为环绕方位差)与航迹速度位移 VT = v_track·ΔT 判断:
|
- **俯仰门限 d_p**:分距离段 7°/5°/10° 的逻辑仍在源码中注释停用,不参与判定(其作用已由高度门限覆盖);
|
||||||
|
- **距离门限 thd_r**:以航迹-点迹弦距 R = √(r_t² + r_p² − 2·r_t·r_p·cos Δθ)(Δθ 为环绕方位差)与航迹速度位移 VT = v_track·ΔT 判断:
|
||||||
|
|
||||||
$$
|
$$
|
||||||
VT<100\ \text{且}\ R>300\ \Rightarrow 拒绝;\qquad
|
VT<100\ \text{且}\ R>300\ \Rightarrow 拒绝;\qquad
|
||||||
@@ -676,19 +713,31 @@ VT<100\ \text{且}\ R>300\ \Rightarrow 拒绝;\qquad
|
|||||||
VT>300\ \text{且}\ R>1200\ \Rightarrow 拒绝
|
VT>300\ \text{且}\ R>1200\ \Rightarrow 拒绝
|
||||||
$$
|
$$
|
||||||
|
|
||||||
候选对按 d_min = min(d1,d2,d3) 全局排序,**最近邻**原则逐个取点:每条航迹每圈最多关联一个点、每个点只属于一条航迹。关联成功后:三模型分别 EKF 更新 → 模型概率更新 → 更新航迹时间/幅度/SNR/RCS/十字星数据 → 高度平滑。ΔT ≤ 0(乱序/重复时间戳)的候选被剔除且不占用点迹、不刷新航迹状态(BUG-15 修复)。
|
候选对按 d_min = min(d1,d2,d3) 全局排序,**最近邻**原则逐个取点:每条航迹每圈最多关联一个点、每个点只属于一条航迹。关联成功后:三模型分别 EKF 更新 → 模型概率更新 → 更新航迹时间/幅度/SNR/RCS/十字星数据 → 高度平滑。关联输出的航迹同时写入**方向标志**(f249fdc):`Flag_Direction = (vr_point > 0) ? 1 : 0`,即径向速度为正判为靠近(1)、为零或负判为远离(0),取值来自航迹记录的径向速度(最近一次关联点迹的速度)。
|
||||||
|
|
||||||
|
**ΔT ≤ 0 的候选(604f158 起的行为)**:ΔT = (点迹 CPI 时间 − 航迹 T_track)/1000,ΔT ≤ 0 表示该点迹时间戳不晚于航迹时间(典型场景:航迹已按 TAS 点迹更新过,本圈 TWS 点迹的时间戳更早,或存在重复时间戳)。这种候选**不再被剔除**,仍参与最近邻最小 d 的比较与选取,但选中后:
|
||||||
|
|
||||||
|
- 不执行 IMM/EKF 更新,不写回 X1/X2/X3、P1/P2/P3 与模型概率;
|
||||||
|
- 不刷新航迹时间 T_track / GNSS_time 与点迹信息;
|
||||||
|
- 不置实点标志:`Extrapolate_round`、`point_flag`、`associate_point_number` 均保持原值,因此该航迹仍按「未关联航迹」在后续外推环节推进一帧(见 9.9);
|
||||||
|
- 该候选对连同该航迹本圈的其余候选对被一并移出候选表,因此该航迹本圈不会再关联其他点迹;由于时间戳更早的候选仍参与最小 d 比较,它可能先于有效候选(ΔT>0)被取中;
|
||||||
|
- 该点迹的 `Use_Flag` 被置 1 消费掉:`track_asso_process()` 在关联结束后会把 `Use_Flag==1` 的点迹从 `point_recv` 中删除(track_init 入口也会再剔除一次 `Use_Flag==1` 的点),因此该点迹不会进入航迹起始、不会再参与起批,避免生成虚假 TWS 航迹。
|
||||||
|
|
||||||
|
> 历史行为:604f158 之前,ΔT ≤ 0 的候选在选取时被直接剔除并 `continue`,点迹保持未被使用,可能被后续用于航迹起始。该分支原有的 `RDP_LOG` 告警日志现已注释停用;TAS 关联(track_asso_tas.cpp,见下)中同类告警日志仍启用。
|
||||||
|
|
||||||
#### TAS(track_asso_tas.cpp)
|
#### TAS(track_asso_tas.cpp)
|
||||||
|
|
||||||
只处理 tas_track_idx 指定的航迹,门限:
|
只处理 tas_track_idx 指定的航迹,只有统计距离与高度两个门限,两者同时通过(`thd_d && thd_h`)才记为候选:
|
||||||
|
|
||||||
$$
|
$$
|
||||||
d_i^2 < ASSO\_THORD^2 = 9\ \ \text{且高度门限}\ d_h=1
|
thd\_d:\ d_i^2 < ASSO\_THORD^2 = 16 \qquad\text{且}\qquad thd\_h:\ \text{高度门限通过}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
高度门限按航迹距离分段:≤1000 m:|h_t−h_p| ≤ 150 m;1000~2000 m:≤ 200 m;2000~3000 m:≤ 200 m;3000~5000 m:≤ 300 m;>5000 m:不约束。
|
高度门限按航迹距离分段:≤1000 m:|h_t−h_p| ≤ 150 m;1000~2000 m:≤ 200 m;2000~3000 m:≤ 250 m;3000~5000 m:≤ 300 m;>5000 m:不约束(与 TWS 通道 9.6 的取值相同)。
|
||||||
|
|
||||||
> ⚠ **波门语义提示**:代码中 d 本身已是马氏距离平方,但门限写作 d*d < ASSO_THORD*ASSO_THORD,等效于 d < 3(而非 √d < 3)。该行为在 BUG-20 中被识别,**有意保留未改**;ASSO_THORD/1000、/100 已改为浮点除法(BUG-21 修复)。
|
输出航迹同样写入**方向标志** `Flag_Direction`(由 `vr_point` 符号决定,f249fdc),规则与 TWS 通道一致。
|
||||||
|
|
||||||
|
> ⚠ **波门语义提示**:代码中 d 本身已是马氏距离平方,但门限写作 d*d < ASSO_THORD*ASSO_THORD,等效于 d < 4(而非 √d < 4)。该行为在 BUG-20 中被识别,**有意保留未改**;ASSO_THORD/1000、/100 已改为浮点除法(BUG-21 修复)。TAS 不区分距离段,`ASSO_THORD` 原值直接作为门限。
|
||||||
|
|
||||||
### 9.7 高度平滑
|
### 9.7 高度平滑
|
||||||
|
|
||||||
@@ -708,7 +757,7 @@ $$
|
|||||||
|
|
||||||
### 9.9 航迹外推与消亡
|
### 9.9 航迹外推与消亡
|
||||||
|
|
||||||
**外推**:未关联到实点的 TWS 航迹(manual_tracking_flag==0)按工作模式数据率 DATA_RATE_SHORT/MIDDLE/FAR 预测一帧;TAS 通道按 latest_timestamp − T_track 预测(ΔT ≤ 0 跳过);预测用各子模型 Singer F/Qj 推进,Extrapolate_round+1,point_flag=0(虚点/补点),航迹时间同步推进。
|
**外推**:未关联到实点的 TWS 航迹(manual_tracking_flag==0)按工作模式数据率 DATA_RATE_SHORT/MIDDLE/FAR 预测一帧(ΔT≤0 的候选虽被消费但未刷新航迹状态,其 `point_flag` 仍为 0,故同样在本环节外推,见 9.6);TAS 通道按 latest_timestamp − T_track 预测(ΔT ≤ 0 跳过);预测用各子模型 Singer F/Qj 推进,Extrapolate_round+1,point_flag=0(虚点/补点),航迹时间同步推进。
|
||||||
|
|
||||||
**消亡**:
|
**消亡**:
|
||||||
|
|
||||||
@@ -721,16 +770,20 @@ $$
|
|||||||
|
|
||||||
### 9.10 TAS 波束控制(tas_ctrl.cpp)
|
### 9.10 TAS 波束控制(tas_ctrl.cpp)
|
||||||
|
|
||||||
- **入队条件**(仅手动):manual_tracking_flag==1 且 Track_Mode==0 且队列未满(MAX_TAS_NUM,相扫 4 / 机扫 1)且不在 TAS 禁止区内。入队即置 Track_Mode=1 并输出一次航迹更新。
|
- **入队条件**(仅手动):manual_tracking_flag==1 且 Track_Mode==0 且队列未满(MAX_TAS_NUM,相扫 4 / 机扫 1)且不在 TAS 禁止区内。入队即置 Track_Mode=1、以航迹时间初始化 last_track_time,并输出一次航迹更新。
|
||||||
- **出队**:队列中目标在航迹表中不存在、或不再处于手动 TAS 状态时清除。(自动转 TAS / 自动退出的 tas_auto_start/tas_auto_end 逻辑全部注释停用——只支持手动。)
|
- **出队**:队列中目标在航迹表中不存在、或不再处于手动 TAS 状态时清除。(自动转 TAS / 自动退出的 tas_auto_start/tas_auto_end 逻辑全部注释停用——只支持手动。)
|
||||||
- **波束输出**:取队首目标,先用**数据率门控**:航迹时间 T_track 与当前最新时间戳 latest_timestamp 的差值必须大于 `1 / DATA_RATE_TAS` 秒才输出(保证 TAS 目标数据率不随波束时间变化;DATA_RATE_TAS ≤ 0 时不做门控,按原逻辑输出)。门控通过后,用其状态外推到 latest_timestamp:
|
- **波束输出**:在 TAS 队列内遍历,逐个目标先按**数据率门控**筛选——仅要求目标距上次波束输出(`last_track_time`)的时间 `delta_T_last_track = (latest_timestamp − last_track_time)/1000` 大于运行时参数 `Work_Parameter.DATA_RATE_TAS` 秒(单位 s,1521592 起由 Hz 改为 s,需为 >0 的有效值),保证 TAS 目标输出间隔不随波束时间(Beam_Ctrl 调用频率)变化;对通过门控的目标再比较航迹时间 `T_track`,取 CPI 时间最早者,选中后按其 CPI 时间与最新时间戳之差外推到 latest_timestamp:
|
||||||
|
|
||||||
$$
|
$$
|
||||||
|
\Delta T=(latest\_timestamp-CPI\_time)/1000,\qquad
|
||||||
x_p=x+v_x\Delta T,\quad y_p=y+v_y\Delta T,\quad
|
x_p=x+v_x\Delta T,\quad y_p=y+v_y\Delta T,\quad
|
||||||
r_p=\sqrt{x_p^2+y_p^2},\quad \theta_p=\operatorname{atan2}(y_p,x_p)
|
r_p=\sqrt{x_p^2+y_p^2},\quad \theta_p=\operatorname{atan2}(y_p,x_p)
|
||||||
$$
|
$$
|
||||||
|
|
||||||
输出 TrackingBeam{open_flag=1, type=1, Range=rp, Azi=θp(°), Elev=asin(h/rp)(°), TAS_track_index};队空、目标不在航迹表或数据率门控未通过时 open_flag=0。每次 Beam_Ctrl 末尾做队列轮转(实现 TAS_QUEUE_LENGTH 深度的循环跟踪)。
|
输出 TrackingBeam{open_flag=1, type=1, Range=rp, Azi=θp(°), Elev=asin(h/rp)(°), TAS_track_index};队空、目标不在航迹表或数据率门控未通过时 open_flag=0。输出后更新该目标队列项的 last_track_time;原每次 Beam_Ctrl 末尾的整队循环移位(队列轮转)已停用,改为按数据率门控在队列内轮换目标。
|
||||||
|
|
||||||
|
> e0bf227 修正:数据率门控原先同时要求「距上次波束输出」与「航迹时间 T_track 距最新时间戳」都超过 DATA_RATE_TAS,第二个条件与「选 CPI 最早目标」的语义冲突(航迹时间越早反倒越容易被抑制),会漏掉本应输出的波束;现已只保留前者。
|
||||||
|
|
||||||
- tas_ctrl_process 入口强制 *Trust_track_num_Output=0 并在写入前检查容量,防止输出数组越界(BUG-09 修复)。
|
- tas_ctrl_process 入口强制 *Trust_track_num_Output=0 并在写入前检查容量,防止输出数组越界(BUG-09 修复)。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -741,7 +794,9 @@ $$
|
|||||||
|
|
||||||
| 宏 | 相扫 PHASE_SCANNING | 机扫 MECHANICAL_SCANNING | 含义 |
|
| 宏 | 相扫 PHASE_SCANNING | 机扫 MECHANICAL_SCANNING | 含义 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| DATA_RATE_TAS | 0.3 | 0.0625 | TAS 数据率(1/s)。**TAS 波束输出门控已改用运行时参数 RadarPara.DATA_RATE_TAS(见 10.2),不再使用该宏**;宏目前仅被未加入 CMake 的 track_asso_direct_tracking.cpp 引用 |
|
| RDP_LOG_ENABLE | 注释停用(默认不启用) | 同左 | 日志文件输出开关:定义时将 `std::cout` 重定向到日志文件;**当前源码中该宏为注释状态**(parameters.h 的注释文字仍写「定义(默认)」,以代码实际状态为准),不重定向、日志输出到标准输出/控制台 |
|
||||||
|
| RDP_LOG_DIR | `.\rdp_logs\` | 同左 | 日志文件输出目录(相对宿主进程当前工作目录,目录不存在时自动创建) |
|
||||||
|
| DATA_RATE_TAS | 已停用(原 0.3) | 已停用(原 0.0625) | 编译期宏已注释停用;TAS 数据率统一由运行时参数 RadarPara.DATA_RATE_TAS 提供(见 10.2) |
|
||||||
| SIGMA_R / SIGMA_A / SIGMA_E / SIGMA_V | 10.0 / 0.02 / 0.2 / 2.0(两体制相同) | 同左 | 量测误差:距离 m / 方位 rad / 俯仰 rad / 速度 m/s |
|
| SIGMA_R / SIGMA_A / SIGMA_E / SIGMA_V | 10.0 / 0.02 / 0.2 / 2.0(两体制相同) | 同左 | 量测误差:距离 m / 方位 rad / 俯仰 rad / 速度 m/s |
|
||||||
| DOT_COH_RANGE / DOT_COH_V / DOT_COH_AZI | 80 / 2 / 6 | 同左 | 凝聚门限:距离 m / 速度 m/s / 方位 ° |
|
| DOT_COH_RANGE / DOT_COH_V / DOT_COH_AZI | 80 / 2 / 6 | 同左 | 凝聚门限:距离 m / 速度 m/s / 方位 ° |
|
||||||
| MAX_BEAM_NUM | 100 | 同左 | 最大波位数 |
|
| MAX_BEAM_NUM | 100 | 同左 | 最大波位数 |
|
||||||
@@ -751,10 +806,10 @@ $$
|
|||||||
| ALPHA_START | 60 | 同左 | 起批折角(°) |
|
| ALPHA_START | 60 | 同左 | 起批折角(°) |
|
||||||
| TRACK_DIE_ROUND | 4 | 4 | TWS 航迹消亡外推轮数 |
|
| TRACK_DIE_ROUND | 4 | 4 | TWS 航迹消亡外推轮数 |
|
||||||
| TRACK_DIE_ROUND_TAS | 5 | 96 | TAS 航迹消亡外推轮数 |
|
| TRACK_DIE_ROUND_TAS | 5 | 96 | TAS 航迹消亡外推轮数 |
|
||||||
| ASSO_THORD | 3 | 同左 | 关联波门 |
|
| ASSO_THORD | 4 | 同左 | 关联波门(判据 d*d < ASSO_THORD²,d 已是马氏距离平方,等效 d < 4;e0bf227 起由 3 调大至 4) |
|
||||||
| H_F_WIN_LEN | 3 | 同左 | 高度平滑窗长基数(实际 +2/+3/+4/+6) |
|
| H_F_WIN_LEN | 3 | 同左 | 高度平滑窗长基数(实际 +2/+3/+4/+6) |
|
||||||
| TAS_QUEUE_LENGTH / MAX_TAS_NUM | 4 / 4 | 1 / 1 | TAS 队列长度 / 最大 TAS 目标数 |
|
| TAS_QUEUE_LENGTH / MAX_TAS_NUM | 4 / 4 | 1 / 1 | TAS 队列长度 / 最大 TAS 目标数 |
|
||||||
| FREQ0~FREQ20 | 16.8 GHz | 同左 | 各频点频率 |
|
| FREQ0 | 9.2 GHz | 同左 | 载波频点(原 FREQ0~FREQ20 一组宏已精简为单个 FREQ0,e729c5b 起由 16.8 GHz 改为 9.2 GHz) |
|
||||||
|
|
||||||
### 10.2 运行时参数(RadarPara)
|
### 10.2 运行时参数(RadarPara)
|
||||||
|
|
||||||
@@ -771,7 +826,7 @@ $$
|
|||||||
| north_angle | 北偏角 | 保留 |
|
| north_angle | 北偏角 | 保留 |
|
||||||
| V_MAX / V_MIN | 目标速度上下限(m/s) | 航迹头关联速度区间门限 |
|
| V_MAX / V_MIN | 目标速度上下限(m/s) | 航迹头关联速度区间门限 |
|
||||||
| DATA_RATE_SHORT / MIDDLE / FAR | 三模式数据率(s) | TWS 外推步长 |
|
| DATA_RATE_SHORT / MIDDLE / FAR | 三模式数据率(s) | TWS 外推步长 |
|
||||||
| DATA_RATE_TAS | TAS 模式数据率(1/s) | 由调用者经 track_process_parameters_initial 输入;TAS 波束输出门控阈值 1/DATA_RATE_TAS 秒,≤0 时不做门控 |
|
| DATA_RATE_TAS | TAS 波束输出间隔(s) | 由调用者经 track_process_parameters_initial 输入(须为 >0 的有效值);`tas_beam_output()` 门控阈值为 DATA_RATE_TAS 秒(1521592 起单位由 Hz 改为 s),引导跟踪外推同样使用该运行时参数 |
|
||||||
| track_start_point_num | 起批点数 | 校验范围 3~9 |
|
| track_start_point_num | 起批点数 | 校验范围 3~9 |
|
||||||
| track_start_threshold / track_asso_threshold / track_asso_threshold_tas | 起批/关联波门 | **⚠ 声明但当前实现未使用**,实际门限为宏 TRACK_START_THRESHOLD / ASSO_THORD |
|
| track_start_threshold / track_asso_threshold / track_asso_threshold_tas | 起批/关联波门 | **⚠ 声明但当前实现未使用**,实际门限为宏 TRACK_START_THRESHOLD / ASSO_THORD |
|
||||||
| Model1/2/3_Q_fast/slow | 三个 Singer 模型过程噪声强度 | Model1_Q_fast 未使用;分档规则见 9.5.1 |
|
| Model1/2/3_Q_fast/slow | 三个 Singer 模型过程噪声强度 | Model1_Q_fast 未使用;分档规则见 9.5.1 |
|
||||||
@@ -780,15 +835,16 @@ $$
|
|||||||
|
|
||||||
## 11. 已知问题与限制
|
## 11. 已知问题与限制
|
||||||
|
|
||||||
详见 BUG_REPORT.md(37 项分析)与 BUG_FIX_REPORT.md(修复明细)。要点:
|
详见 archived_docs/BUG_REPORT.md(37 项分析)与 archived_docs/BUG_FIX_REPORT.md(修复明细)。要点:
|
||||||
|
|
||||||
### 11.1 已修复(BUG_FIX_REPORT.md)
|
### 11.1 已修复(archived_docs/BUG_FIX_REPORT.md)
|
||||||
|
|
||||||
- **越界/防御**:TAS Point_Sum 限幅 150(BUG-04);size()-1 下溢(BUG-05);起批点数校验(BUG-06);航迹号下标校验(BUG-10);Beam_Ctrl 输出计数清零+容量检查(BUG-09);消亡空向量保护(BUG-34);航迹号 500 可复用(BUG-35);局部结构体值初始化(BUG-37)。
|
- **越界/防御**:TAS Point_Sum 限幅 150(BUG-04);size()-1 下溢(BUG-05);起批点数校验(BUG-06);航迹号下标校验(BUG-10);Beam_Ctrl 输出计数清零+容量检查(BUG-09);消亡空向量保护(BUG-34);航迹号 500 可复用(BUG-35);局部结构体值初始化(BUG-37)。
|
||||||
- **时间戳/时序**:TWS/TAS 关联 ΔT≤0 拒绝(BUG-15/16);TAS 外推负时间差跳过(BUG-17);Bind_speed 除零保护(BUG-19)。
|
- **时间戳/时序**:TWS 关联 ΔT≤0 的候选不参与滤波更新、不刷新航迹状态并消费该点迹(604f158 起由「剔除候选、点迹保持未使用」改为当前行为,仍属 BUG-15 处置范围);TAS 关联 ΔT≤0 拒绝(BUG-16);TAS 外推负时间差跳过(BUG-17);Bind_speed 除零保护(BUG-19)。
|
||||||
- **数值稳定性**:方位残差 ±π 环绕(BUG-22);IMM 概率零分母/奇异保护(BUG-23);EKF 似然 3×3 新息协方差(BUG-24);航向角 atan2(BUG-26);asin 定义域钳位(BUG-27);近程模型 3 门限浮点除法(BUG-21);track_clear_all 全模块 reset(BUG-28);未初始化变量修复(BUG-11/12/14)。
|
- **数值稳定性**:方位残差 ±π 环绕(BUG-22);IMM 概率零分母/奇异保护(BUG-23);EKF 似然 3×3 新息协方差(BUG-24);航向角 atan2(BUG-26);asin 定义域钳位(BUG-27);近程模型 3 门限浮点除法(BUG-21);track_clear_all 全模块 reset(BUG-28);未初始化变量修复(BUG-11/12/14)。
|
||||||
|
- **后修订(e0bf227,BUG_FIX_REPORT.md 成文之后)**:TWS 关联高度门限由注释状态改为实际生效(`track_asso.cpp`),统计距离/高度/距离三类判据拆为独立布尔量,`ASSO_THORD` 由 3 调大至 4;TAS 关联高度门限 2000~3000 m 段放宽至 250 m;修复 `tas_beam_output()` 数据率门控误判(详见 CHANGELOG 的 Unreleased 与 9.6、9.10)。
|
||||||
|
|
||||||
### 11.2 有意保留 / 未修复(标注于 BUG_REPORT)
|
### 11.2 有意保留 / 未修复(标注于 archived_docs/BUG_REPORT.md)
|
||||||
|
|
||||||
- **BUG-01**:基类无虚析构,Destroy() 按基类指针 delete。
|
- **BUG-01**:基类无虚析构,Destroy() 按基类指针 delete。
|
||||||
- **BUG-02**:Hight_smooth 只增不减,长时运行内存持续增长。
|
- **BUG-02**:Hight_smooth 只增不减,长时运行内存持续增长。
|
||||||
@@ -811,6 +867,16 @@ $$
|
|||||||
- RadarPara 中的起批/关联波门字段未被实现读取(见 10.2)。
|
- RadarPara 中的起批/关联波门字段未被实现读取(见 10.2)。
|
||||||
- build/output/ 下为早期打包导出物,其 data_process_class_dll.h 时间戳仍为 32 位 int,与当前 64 位接口不一致,勿作为对接依据。
|
- build/output/ 下为早期打包导出物,其 data_process_class_dll.h 时间戳仍为 32 位 int,与当前 64 位接口不一致,勿作为对接依据。
|
||||||
|
|
||||||
|
### 11.4 航迹起始相关的未修复观察(详见 docs/track_init_readme.md 第 15 节)
|
||||||
|
|
||||||
|
以下为阅读源码得到的观察,**未在本轮文档更新中改动代码**;修改前请结合实测数据评估:
|
||||||
|
|
||||||
|
- 点-临时航迹关联硬编码 `|Δr| ≥ 5 m` 门限,切向/远距离慢速目标可能漏关联导致起批失败。
|
||||||
|
- 起批判据对马氏距离平方再次平方(`d*d ≤ TRACK_START_THRESHOLD²`),实际门限为 `d ≤ 8`,按字面 `d² ≤ 64` 理解会严重放宽;调 `TRACK_START_THRESHOLD` 时需注意这一层。
|
||||||
|
- 折角计算 `acos` 无定义域钳位,浮点越界产生 NaN 时条件恒假(静默丢弃该关联)。
|
||||||
|
- 起批输出数组行号可能越过容量:容量判据用 `trust_track->size() < MAX_TRACK_INDEX`,而输出行计数在 track_asso 阶段(track_die 删除航迹之前)已推进,极端场景(当圈消亡 ≥ 2 条且起批占满配额)可写到 `MAX_TRACK_NUM` 之外。
|
||||||
|
- 起批输出有多个字段未赋值(见 9.3(4) 与 docs/track_init_readme.md 第 14 节),宿主不应依赖这些字段。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. 版本历史
|
## 12. 版本历史
|
||||||
@@ -819,8 +885,19 @@ $$
|
|||||||
|
|
||||||
| 提交 | 内容 |
|
| 提交 | 内容 |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
| e0bf227 | 关联判定重构并加强:TWS `track_asso.cpp` 新增按航迹距离分段的高度门限(原高度门限代码块为注释状态)、统计距离/高度/距离三类判据拆为 `thd_d`/`thd_h`/`thd_r` 布尔量;`parameters.h` 的 `ASSO_THORD` 由 3 调大至 4(等效门限 d < 4,提高机动目标关联概率);TAS `track_asso_tas.cpp` 高度门限 2000~3000 m 段由 200 m 放宽至 250 m;修复 `tas_beam_output()` 的数据率门控条件(去掉与「取最早 CPI 目标」冲突的 T_track 判据);删除 `docs/data_process_flow_report.html`;`.gitignore` 增加 `design_docs/`;同步更新 README/CHANGELOG/docs |
|
||||||
|
| f249fdc | 输出航迹新增「靠近/远离」方向标志:`track_asso.cpp`(TWS)与 `track_asso_tas.cpp`(TAS)在写入 `vr_point` 后补 `Flag_Direction = vr_point > 0 ? 1 : 0`;新增 `docs/data_process_flow_report.md`、`docs/data_process_flow_report.html`、`docs/track_init_readme.md` 三份流程与专项文档(其中 HTML 版已于 e0bf227 删除) |
|
||||||
|
| 7d5a56f | 满圈判据由「波位号变小」改为「方位波位号 == 0」(避免机扫转台反转误判,`data_process.cpp`);点-航迹头关联改为统一速度区间 `V_MIN·ΔT ≤ dis ≤ V_MAX·ΔT` 并新增 `dis ≥ |vr_point|·ΔT`、`dis ≥ |v_track_head|·ΔT` 两条多普勒-几何一致性约束,限制切向高速短航迹(`track_init.cpp`);同步更新 README/CHANGELOG |
|
||||||
|
| 604f158 | TWS 关联中 ΔT≤0(点迹时间戳不晚于航迹时间)的候选不再剔除:仍参与最近邻选取但不更新 IMM/EKF、不刷新航迹时间与新鲜度,并标记该点迹已使用(`Use_Flag=1`)消费掉,避免其继续参与航迹起始生成虚假 TWS 航迹;`track_asso.cpp` 的 ΔT≤0 告警日志注释停用;过期文档(BUG_REPORT.md、BUG_FIX_REPORT.md、requirements.md)移入 archived_docs/ 留档 |
|
||||||
|
| d6cdbc0 | 删除 `data_process.cpp`、`dot_coh.cpp` 中已注释停用的调试输出与早期 1 km SNR 过滤代码残留(不改变运行逻辑);同步更新 README/CHANGELOG |
|
||||||
|
| 1521592 | 新增日志模块(`rdp_log.h/.cpp`,CMake SOURCES 注册、.gitignore 忽略 `rdp_logs/`):`RDP_LOG_ENABLE` / `RDP_LOG_DIR` 宏(parameters.h)、std::cout 经 `rdbuf()` 重定向到 `.\rdp_logs\` 下日期+时间命名日志、`RDP_LOG` 前缀宏、ΔT≤0 告警日志;`RadarPara.DATA_RATE_TAS` 单位由 Hz 改为 s;修复 `tas_beam_output()` 将向量下标误赋给 `Tracking_beam->TAS_track_index` 的问题;更新 README/CHANGELOG |
|
||||||
|
| 5f82098 | 修复 MSVC `/W3` 下全部 C4819 / C4018 / C4244 警告(UTF-8 with BOM、size_t / static_cast 等);更新项目文档 |
|
||||||
|
| f438ac5 | 优化 TAS 调度:波束输出改为在队列内选择满足数据率门控且 CPI 时间最早的目标,停用整队循环移位;DATA_RATE_TAS 编译期宏停用、统一使用运行时参数;#pragma message 提示扫描体制 |
|
||||||
|
| e729c5b | 频点宏精简为 FREQ0 = 9.2 GHz(原 FREQ0~FREQ20 均为 16.8 GHz) |
|
||||||
|
| b3e2f52 | TAS 波束控制改为按固定数据率调度,RadarPara 新增 DATA_RATE_TAS 运行时参数;新增 CHANGELOG.md、requirements.md,README 补充相应说明 |
|
||||||
|
| 93d3924 | 新增 README.md(本文档);移除 requirements.md;调整 .gitignore |
|
||||||
| 3500652 | 去掉 1 km 以内航迹起批的 20 dB 信噪比门限 |
|
| 3500652 | 去掉 1 km 以内航迹起批的 20 dB 信噪比门限 |
|
||||||
| 01d28e0 | 改用 VS Code + CMake 重新编译(编译器不变);修复若干逻辑 BUG(见 BUG_FIX_REPORT.md) |
|
| 01d28e0 | 改用 VS Code + CMake 重新编译(编译器不变);修复若干逻辑 BUG(见 archived_docs/BUG_FIX_REPORT.md) |
|
||||||
| 0cb31b4 | 删除不必要文件;输入点迹/输出航迹的 CPI 与 GNSS 时间改为 64 位整型;修复 TAS 外推时间差可能无效的问题 |
|
| 0cb31b4 | 删除不必要文件;输入点迹/输出航迹的 CPI 与 GNSS 时间改为 64 位整型;修复 TAS 外推时间差可能无效的问题 |
|
||||||
| d101fe9 | 增加航迹清空功能(解决重连乱窜);TAS 外推时间间隔按波束时间计算;增加 1 km 内 SNR<20 dB 不起批限制(后于 3500652 移除) |
|
| d101fe9 | 增加航迹清空功能(解决重连乱窜);TAS 外推时间间隔按波束时间计算;增加 1 km 内 SNR<20 dB 不起批限制(后于 3500652 移除) |
|
||||||
| 8636179 | 机扫/相扫程序合并,宏定义配置切换 |
|
| 8636179 | 机扫/相扫程序合并,宏定义配置切换 |
|
||||||
@@ -841,8 +918,12 @@ $$
|
|||||||
|
|
||||||
| 文档 | 内容 |
|
| 文档 | 内容 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| BUG_REPORT.md | 全量逻辑 BUG 分析(P0~P3 共 37 项,含位置、说明、建议、处置结论) |
|
| CHANGELOG.md | 变更日志(Keep a Changelog 格式,按 git 提交记录维护) |
|
||||||
| BUG_FIX_REPORT.md | 本次修复明细、修复状态汇总表与 MSVC 2013 x86 编译验证记录 |
|
| docs/data_process_flow_report.md | 数据处理流程与关键逻辑说明(按当前源码整理:前处理与判圈、凝聚、TWS/TAS 关联与滤波、航迹起始、外推消亡、TAS 波束控制、参数脉络;含与本文档的历史差异提示)——原同内容 HTML 渲染版(`data_process_flow_report.html`)已于 e0bf227 删除,HTML 版本在 git 忽略的 `design_docs/` 内留档 |
|
||||||
|
| docs/track_init_readme.md | 航迹起始(Track Init)专项说明:分阶段流程、起始条件汇总、调参直觉、输出字段映射(含未赋值字段)、已知风险与代码索引 |
|
||||||
|
| archived_docs/BUG_REPORT.md | 全量逻辑 BUG 分析(P0~P3 共 37 项,含位置、说明、建议、处置结论)——过期留档,仅作历史参考 |
|
||||||
|
| archived_docs/BUG_FIX_REPORT.md | 修复明细、修复状态汇总表与 MSVC 2013 x86 编译验证记录——过期留档(对应 01d28e0 时期) |
|
||||||
|
| archived_docs/requirements.md | 修改需求说明:日志文件输出功能(rdbuf() 重定向、parameters.h 日志开关宏、日期+时间命名日志、前缀日志宏,附参考示例)——已实现,留档 |
|
||||||
| backup/data_process_class_dll/data_process_class_dll.pro | 迁移前的 Qt/qmake 工程文件(源文件清单参考) |
|
| backup/data_process_class_dll/data_process_class_dll.pro | 迁移前的 Qt/qmake 工程文件(源文件清单参考) |
|
||||||
| .vscode/tasks.json、.vscode/cmake-variants.yaml | VS Code 构建任务与变体定义 |
|
| .vscode/tasks.json、.vscode/cmake-variants.yaml | VS Code 构建任务与变体定义 |
|
||||||
| build/X256_PS/bin/RadarConfigParam.ini | 回放测试工具(rdp_playback.exe)配置样例 |
|
| build/X256_PS/bin/RadarConfigParam.ini | 回放测试工具(rdp_playback.exe)配置样例 |
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef COOR_TRANS_H
|
#ifndef COOR_TRANS_H
|
||||||
#define COOR_TRANS_H
|
#define COOR_TRANS_H
|
||||||
|
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "data_process.h"
|
#include "data_process.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -45,7 +46,9 @@ int Data_Process::data_preprocess(struct DataRev Data_Input[150])
|
|||||||
|
|
||||||
Data_buffer.push_back(Data_buffer_temp);
|
Data_buffer.push_back(Data_buffer_temp);
|
||||||
}
|
}
|
||||||
if(Data_Input[0].Beam_index_aiz < last_beam_num) //TWS
|
|
||||||
|
// 修改一周扫描完成的判断条件,原来采用判断波位号变小为一周扫描完成,但机扫模式下,可能存在转台反转的情况,导致波位号变小,但并未扫描一周,因此改为判断波位号为0时,表示扫描一周完成
|
||||||
|
if(Data_Input[0].Beam_index_aiz == 0) //TWS
|
||||||
{
|
{
|
||||||
last_beam_num = Data_Input[0].Beam_index_aiz;
|
last_beam_num = Data_Input[0].Beam_index_aiz;
|
||||||
|
|
||||||
@@ -56,6 +59,17 @@ int Data_Process::data_preprocess(struct DataRev Data_Input[150])
|
|||||||
last_beam_num = Data_Input[0].Beam_index_aiz;
|
last_beam_num = Data_Input[0].Beam_index_aiz;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
// if(Data_Input[0].Beam_index_aiz < last_beam_num) //TWS
|
||||||
|
// {
|
||||||
|
// last_beam_num = Data_Input[0].Beam_index_aiz;
|
||||||
|
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// last_beam_num = Data_Input[0].Beam_index_aiz;
|
||||||
|
// return 2;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(Data_Input[0].point_type == 1) //tas数据
|
else if(Data_Input[0].point_type == 1) //tas数据
|
||||||
@@ -65,7 +79,6 @@ int Data_Process::data_preprocess(struct DataRev Data_Input[150])
|
|||||||
|
|
||||||
data_num = min(max(Data_Input[0].Point_Sum, 0), 150);
|
data_num = min(max(Data_Input[0].Point_Sum, 0), 150);
|
||||||
TAS_track_idx = Data_Input[0].TAS_track_index;
|
TAS_track_idx = Data_Input[0].TAS_track_index;
|
||||||
latest_timestamp = Data_Input[0].CPI_time;
|
|
||||||
for (int i=0; i<data_num;i++)
|
for (int i=0; i<data_num;i++)
|
||||||
{
|
{
|
||||||
PointRecv Data_buffer_temp;
|
PointRecv Data_buffer_temp;
|
||||||
@@ -144,11 +157,6 @@ int model)
|
|||||||
Trust_Track_Output,
|
Trust_Track_Output,
|
||||||
Trust_track_num_Output,
|
Trust_track_num_Output,
|
||||||
Work_Parameter);
|
Work_Parameter);
|
||||||
// std::cout << "point_recv: " <<point_recv.size();
|
|
||||||
// std::cout << "trust_track: " <<trust_track.size();
|
|
||||||
// std::cout << "temp_track: " <<temp_track.size();
|
|
||||||
// std::cout << "Trust_track_num_Output: " <<*Trust_track_num_Output;
|
|
||||||
// std::cout << "Track_die_num_Output: " <<*Track_die_num_Output;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,12 +168,6 @@ int model)
|
|||||||
|
|
||||||
dot_coh_tas.dot_coh_tas_process(&Data_buffer_tas,&point_recv_tas); //点迹凝聚
|
dot_coh_tas.dot_coh_tas_process(&Data_buffer_tas,&point_recv_tas); //点迹凝聚
|
||||||
|
|
||||||
// if(point_recv_tas.size()>0)
|
|
||||||
// {
|
|
||||||
// std::cout << "point_recv_tas :" <<point_recv_tas[0].Azimuth/PI*180<<" "<<point_recv_tas[0].Range;
|
|
||||||
// }
|
|
||||||
//std::cout << "TAS process :" << TAS_track_idx << "p a r:"<<point_recv_tas[0].Point_Sum<<" " <<point_recv_tas[0].Azimuth/PI*180<<" "<<point_recv_tas[0].Range;
|
|
||||||
|
|
||||||
std::vector<PointRecv>().swap(Data_buffer_tas);//凝聚完毕 清除Data_buffer
|
std::vector<PointRecv>().swap(Data_buffer_tas);//凝聚完毕 清除Data_buffer
|
||||||
|
|
||||||
track_asso_tas.track_asso_process_tas(&point_recv_tas, //点迹文件
|
track_asso_tas.track_asso_process_tas(&point_recv_tas, //点迹文件
|
||||||
@@ -247,13 +249,13 @@ int Data_Process:: track_delete(int delete_track_num, //手动
|
|||||||
{
|
{
|
||||||
for (int i=0;i<delete_track_num ;i++)
|
for (int i=0;i<delete_track_num ;i++)
|
||||||
{
|
{
|
||||||
for (int j=0;j<trust_track.size();j++)
|
for (size_t j=0;j<trust_track.size();j++)
|
||||||
{
|
{
|
||||||
if(trust_track[j].Track_Index == delete_track_index[i])
|
if(trust_track[j].Track_Index == delete_track_index[i])
|
||||||
{
|
{
|
||||||
|
|
||||||
trust_track[j].manual_delete_flag=1;
|
trust_track[j].manual_delete_flag=1;
|
||||||
std::cout << "Delete :" << trust_track[j].Track_Index << std::endl;
|
// RDP_LOG << "Delete :" << trust_track[j].Track_Index << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,14 +264,48 @@ int Data_Process:: track_delete(int delete_track_num, //手动
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//手动添加重点目标
|
||||||
|
int Data_Process::primary_target_add(int track_index)
|
||||||
|
{
|
||||||
|
|
||||||
|
for ( size_t i=0; i<trust_track.size();i++){
|
||||||
|
if(trust_track[i].Track_Index==track_index)
|
||||||
|
{
|
||||||
|
trust_track[i].primary_target_flag = 1;
|
||||||
|
//std::cout<< "Add primary target :" << trust_track[i].Track_Index << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//手动取消重点目标
|
||||||
|
int Data_Process::primary_target_cancel(int track_index)
|
||||||
|
{
|
||||||
|
|
||||||
|
for ( size_t i=0; i<trust_track.size();i++){
|
||||||
|
if(trust_track[i].Track_Index==track_index)
|
||||||
|
{
|
||||||
|
trust_track[i].primary_target_flag = 0;
|
||||||
|
//std::cout<< "Cancel primary target :" << trust_track[i].Track_Index << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//手动转TAS跟踪函数
|
//手动转TAS跟踪函数
|
||||||
int Data_Process:: tracking_start(int track_index) //需要手动转入TAS跟踪的航迹号
|
int Data_Process:: tracking_start(int track_index) //需要手动转入TAS跟踪的航迹号
|
||||||
{
|
{
|
||||||
|
|
||||||
for ( int i=0; i<trust_track.size();i++)
|
for ( size_t i=0; i<trust_track.size();i++){
|
||||||
if(trust_track[i].Track_Index==track_index)
|
if(trust_track[i].Track_Index==track_index)
|
||||||
{
|
{
|
||||||
trust_track[i].manual_tracking_flag = 1;
|
trust_track[i].manual_tracking_flag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -279,11 +315,12 @@ int Data_Process:: tracking_start(int track_index) //需要手动
|
|||||||
int Data_Process:: tracking_stop(int track_index) //需要手动转入TAS跟踪的航迹号
|
int Data_Process:: tracking_stop(int track_index) //需要手动转入TAS跟踪的航迹号
|
||||||
{
|
{
|
||||||
|
|
||||||
for ( int i=0; i<trust_track.size();i++){
|
for ( size_t i=0; i<trust_track.size();i++){
|
||||||
if(trust_track[i].Track_Index==track_index)
|
if(trust_track[i].Track_Index==track_index)
|
||||||
{
|
{
|
||||||
trust_track[i].manual_tracking_flag = 0;
|
trust_track[i].manual_tracking_flag = 0;
|
||||||
trust_track[i].Track_Mode = 0;
|
trust_track[i].Track_Mode = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef DATA_PROCESS_H
|
#ifndef DATA_PROCESS_H
|
||||||
#define DATA_PROCESS_H
|
#define DATA_PROCESS_H
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
@@ -59,6 +59,12 @@ public:
|
|||||||
//手动取消TAS跟踪函数
|
//手动取消TAS跟踪函数
|
||||||
int tracking_stop(int track_index); //需要取消TAS跟踪的航迹号
|
int tracking_stop(int track_index); //需要取消TAS跟踪的航迹号
|
||||||
|
|
||||||
|
//手动添加重点目标
|
||||||
|
int primary_target_add(int track_index); //将指定目标转为重点目标
|
||||||
|
|
||||||
|
//手动取消重点目标
|
||||||
|
int primary_target_cancel(int track_index); //将指定重点目标取消
|
||||||
|
|
||||||
//手动打跟踪波束
|
//手动打跟踪波束
|
||||||
int tracking_point(float Azimuth); //方位角
|
int tracking_point(float Azimuth); //方位角
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#ifndef DATA_PROCESS_CLASS_DLL_LIBRARY
|
#ifndef DATA_PROCESS_CLASS_DLL_LIBRARY
|
||||||
#define DATA_PROCESS_CLASS_DLL_LIBRARY
|
#define DATA_PROCESS_CLASS_DLL_LIBRARY
|
||||||
#endif
|
#endif
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "data_process.h"
|
#include "data_process.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Data_process_class_dll::Data_process_class_dll()
|
Data_process_class_dll::Data_process_class_dll()
|
||||||
@@ -16,6 +17,8 @@ Data_process_class_dll *Data_Process_Factory::GetB()
|
|||||||
{
|
{
|
||||||
if(!p)
|
if(!p)
|
||||||
{
|
{
|
||||||
|
//初始化日志输出:RDP_LOG_ENABLE 开启时重定向 std::cout 到日志文件
|
||||||
|
//rdp_log::Init();
|
||||||
p=new Data_Process();
|
p=new Data_Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,5 +33,8 @@ void Data_Process_Factory::Destroy()
|
|||||||
if (p) {
|
if (p) {
|
||||||
delete p;
|
delete p;
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
|
|
||||||
|
//恢复 std::cout 到控制台并关闭日志文件
|
||||||
|
//rdp_log::Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef DATA_PROCESS_CLASS_DLL_H
|
#ifndef DATA_PROCESS_CLASS_DLL_H
|
||||||
#define DATA_PROCESS_CLASS_DLL_H
|
#define DATA_PROCESS_CLASS_DLL_H
|
||||||
|
|
||||||
@@ -30,6 +30,8 @@ struct DATA_PROCESS_CLASS_DLLSHARED_EXPORT DataRev
|
|||||||
int TAS_track_index; //TAS的航迹号
|
int TAS_track_index; //TAS的航迹号
|
||||||
int point_type; //点迹类型 TAS 1/TWS 0
|
int point_type; //点迹类型 TAS 1/TWS 0
|
||||||
int pitch_num; // 俯仰波位号
|
int pitch_num; // 俯仰波位号
|
||||||
|
float amp_asv; //目标归一化幅度(dB)
|
||||||
|
float prn_fftn; //速度维FFT点数
|
||||||
float speed_dim[129]; // 目标的十字星数据,目标点速度维129个点
|
float speed_dim[129]; // 目标的十字星数据,目标点速度维129个点
|
||||||
float range_dim[8]; // 目标的十字星数据,目标点距离维8个点
|
float range_dim[8]; // 目标的十字星数据,目标点距离维8个点
|
||||||
};
|
};
|
||||||
@@ -69,6 +71,8 @@ struct DATA_PROCESS_CLASS_DLLSHARED_EXPORT Track
|
|||||||
float elev_point;
|
float elev_point;
|
||||||
float vr_point;
|
float vr_point;
|
||||||
float prf_point;
|
float prf_point;
|
||||||
|
float amp_asv_point; //关联上的点迹信息(归一化幅度)
|
||||||
|
float prn_fftn_point; //点迹速度维FFT点数
|
||||||
|
|
||||||
float track_time; //航迹时间 (单位 s)
|
float track_time; //航迹时间 (单位 s)
|
||||||
float track_snr; //信噪比
|
float track_snr; //信噪比
|
||||||
@@ -147,7 +151,7 @@ struct DATA_PROCESS_CLASS_DLLSHARED_EXPORT RadarPara
|
|||||||
float DATA_RATE_MIDDLE;
|
float DATA_RATE_MIDDLE;
|
||||||
float DATA_RATE_FAR;
|
float DATA_RATE_FAR;
|
||||||
|
|
||||||
float DATA_RATE_TAS; //TAS模式数据率,由dll调用者输入;TAS波束输出间隔阈值为 1/DATA_RATE_TAS 秒
|
float DATA_RATE_TAS; //TAS模式数据率,由dll调用者输入;TAS波束输出间隔阈值为 DATA_RATE_TAS 秒
|
||||||
|
|
||||||
//数据关联参数
|
//数据关联参数
|
||||||
int track_start_point_num; //起批点数(典型值 3或4)
|
int track_start_point_num; //起批点数(典型值 3或4)
|
||||||
@@ -236,6 +240,18 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//手动添加重点目标
|
||||||
|
virtual int primary_target_add(int track_index) //将指定目标转为重点目标
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//手动取消重点目标
|
||||||
|
virtual int primary_target_cancel(int track_index) //将指定重点目标取消
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//手动打跟踪波束
|
//手动打跟踪波束
|
||||||
virtual int tracking_point(float Azimuth) //方位角(当前接口未启用,保留空实现)
|
virtual int tracking_point(float Azimuth) //方位角(当前接口未启用,保留空实现)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef DATA_PROCESS_CLASS_DLL_GLOBAL_H
|
#ifndef DATA_PROCESS_CLASS_DLL_GLOBAL_H
|
||||||
#define DATA_PROCESS_CLASS_DLL_GLOBAL_H
|
#define DATA_PROCESS_CLASS_DLL_GLOBAL_H
|
||||||
|
|
||||||
#if defined(DATA_PROCESS_CLASS_DLL_LIBRARY)
|
#if defined(DATA_PROCESS_CLASS_DLL_LIBRARY)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "dot_coh.h"
|
#include "dot_coh.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -16,18 +16,18 @@ int Dot_Coh::dot_coh_process(std::vector <PointRecv> *data_input,
|
|||||||
{
|
{
|
||||||
if( (*data_input)[loop_of_point].Use_Flag!=1)
|
if( (*data_input)[loop_of_point].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_0_R=(*data_input)[loop_of_point].Range;
|
float point_0_R=static_cast<float>((*data_input)[loop_of_point].Range);
|
||||||
float point_0_V=(*data_input)[loop_of_point].Velocity;
|
float point_0_V=static_cast<float>((*data_input)[loop_of_point].Velocity);
|
||||||
float point_0_F=(*data_input)[loop_of_point].Azimuth;
|
float point_0_F=static_cast<float>((*data_input)[loop_of_point].Azimuth);
|
||||||
float point_0_A=(*data_input)[loop_of_point].Amplitude;
|
float point_0_A=static_cast<float>((*data_input)[loop_of_point].Amplitude);
|
||||||
for (unsigned int i=loop_of_point+1;i<data_input->size();i++)
|
for (unsigned int i=loop_of_point+1;i<data_input->size();i++)
|
||||||
{
|
{
|
||||||
if((*data_input)[loop_of_point].Use_Flag!=1 && (*data_input)[i].Use_Flag!=1)
|
if((*data_input)[loop_of_point].Use_Flag!=1 && (*data_input)[i].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_1_R=(*data_input)[i].Range;
|
float point_1_R=static_cast<float>((*data_input)[i].Range);
|
||||||
float point_1_V=(*data_input)[i].Velocity;
|
float point_1_V=static_cast<float>((*data_input)[i].Velocity);
|
||||||
float point_1_F=(*data_input)[i].Azimuth;
|
float point_1_F=static_cast<float>((*data_input)[i].Azimuth);
|
||||||
float point_1_A=(*data_input)[i].Amplitude;
|
float point_1_A=static_cast<float>((*data_input)[i].Amplitude);
|
||||||
|
|
||||||
//凝聚条件: 距离、方位接近
|
//凝聚条件: 距离、方位接近
|
||||||
if(Work_Parameter.work_mode == 0)
|
if(Work_Parameter.work_mode == 0)
|
||||||
@@ -36,10 +36,10 @@ int Dot_Coh::dot_coh_process(std::vector <PointRecv> *data_input,
|
|||||||
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
||||||
&& point_0_A <point_1_A )//
|
&& point_0_A <point_1_A )//
|
||||||
{
|
{
|
||||||
point_0_R=(*data_input)[i].Range;
|
point_0_R=static_cast<float>((*data_input)[i].Range);
|
||||||
point_0_V=(*data_input)[i].Velocity;
|
point_0_V=static_cast<float>((*data_input)[i].Velocity);
|
||||||
point_0_A=(*data_input)[i].Amplitude;
|
point_0_A=static_cast<float>((*data_input)[i].Amplitude);
|
||||||
point_0_F=(*data_input)[i].Azimuth;
|
point_0_F=static_cast<float>((*data_input)[i].Azimuth);
|
||||||
(*data_input)[loop_of_point].Use_Flag=1;
|
(*data_input)[loop_of_point].Use_Flag=1;
|
||||||
}
|
}
|
||||||
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
||||||
@@ -54,10 +54,10 @@ int Dot_Coh::dot_coh_process(std::vector <PointRecv> *data_input,
|
|||||||
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
||||||
&& point_0_A <point_1_A )//
|
&& point_0_A <point_1_A )//
|
||||||
{
|
{
|
||||||
point_0_R=(*data_input)[i].Range;
|
point_0_R=static_cast<float>((*data_input)[i].Range);
|
||||||
point_0_V=(*data_input)[i].Velocity;
|
point_0_V=static_cast<float>((*data_input)[i].Velocity);
|
||||||
point_0_A=(*data_input)[i].Amplitude;
|
point_0_A=static_cast<float>((*data_input)[i].Amplitude);
|
||||||
point_0_F=(*data_input)[i].Azimuth;
|
point_0_F=static_cast<float>((*data_input)[i].Azimuth);
|
||||||
(*data_input)[loop_of_point].Use_Flag=1;
|
(*data_input)[loop_of_point].Use_Flag=1;
|
||||||
}
|
}
|
||||||
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
||||||
@@ -88,7 +88,7 @@ int Dot_Coh::dot_coh_process(std::vector <PointRecv> *data_input,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<data_input->size();i++) //data_buffer_2 ---> point_recv
|
for (size_t i=0;i<data_input->size();i++) //data_buffer_2 ---> point_recv
|
||||||
{
|
{
|
||||||
(*point_recv).push_back((*data_input)[i]);
|
(*point_recv).push_back((*data_input)[i]);
|
||||||
}
|
}
|
||||||
@@ -106,26 +106,18 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
|
|
||||||
//1.1 data_input、data_input_buff中的数据放在一起
|
//1.1 data_input、data_input_buff中的数据放在一起
|
||||||
std::vector <PointRecv> data_tmp;
|
std::vector <PointRecv> data_tmp;
|
||||||
for (int i=0;i<data_input_buff.size();i++)
|
for (size_t i=0;i<data_input_buff.size();i++)
|
||||||
{
|
{
|
||||||
data_tmp.push_back(data_input_buff[i]);
|
data_tmp.push_back(data_input_buff[i]);
|
||||||
data_tmp[data_tmp.size()-1].point_section_asso = 1;
|
data_tmp[data_tmp.size()-1].point_section_asso = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<data_input->size();i++)
|
for (size_t i=0;i<data_input->size();i++)
|
||||||
{
|
{
|
||||||
data_tmp.push_back((*data_input)[i]);
|
data_tmp.push_back((*data_input)[i]);
|
||||||
data_tmp[data_tmp.size()-1].point_section_asso = 2;
|
data_tmp[data_tmp.size()-1].point_section_asso = 2;
|
||||||
}
|
}
|
||||||
// //去除点迹中,1km以内,SNR小于20dB的点
|
|
||||||
// for (int i=0;i<data_input->size();i++)
|
|
||||||
// {
|
|
||||||
// if((*data_input)[i].Range > 1000 || (*data_input)[i].snr >= 20){
|
|
||||||
// data_tmp.push_back((*data_input)[i]);
|
|
||||||
// data_tmp[data_tmp.size()-1].point_section_asso = 2;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//1.2 把data_input、data_input_buff清空
|
//1.2 把data_input、data_input_buff清空
|
||||||
|
|
||||||
@@ -140,18 +132,18 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
{
|
{
|
||||||
if( data_tmp[loop_of_point].Use_Flag!=1)
|
if( data_tmp[loop_of_point].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_0_R=data_tmp[loop_of_point].Range;
|
float point_0_R=static_cast<float>(data_tmp[loop_of_point].Range);
|
||||||
float point_0_V=data_tmp[loop_of_point].Velocity;
|
float point_0_V=static_cast<float>(data_tmp[loop_of_point].Velocity);
|
||||||
float point_0_F=data_tmp[loop_of_point].Azimuth;
|
float point_0_F=static_cast<float>(data_tmp[loop_of_point].Azimuth);
|
||||||
float point_0_A=data_tmp[loop_of_point].Amplitude;
|
float point_0_A=static_cast<float>(data_tmp[loop_of_point].Amplitude);
|
||||||
for (unsigned int i=loop_of_point+1;i<data_tmp.size();i++)
|
for (unsigned int i=loop_of_point+1;i<data_tmp.size();i++)
|
||||||
{
|
{
|
||||||
if(data_tmp[loop_of_point].Use_Flag!=1 && data_tmp[i].Use_Flag!=1)
|
if(data_tmp[loop_of_point].Use_Flag!=1 && data_tmp[i].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_1_R=data_tmp[i].Range;
|
float point_1_R=static_cast<float>(data_tmp[i].Range);
|
||||||
float point_1_V=data_tmp[i].Velocity;
|
float point_1_V=static_cast<float>(data_tmp[i].Velocity);
|
||||||
float point_1_F=data_tmp[i].Azimuth;
|
float point_1_F=static_cast<float>(data_tmp[i].Azimuth);
|
||||||
float point_1_A=data_tmp[i].Amplitude;
|
float point_1_A=static_cast<float>(data_tmp[i].Amplitude);
|
||||||
|
|
||||||
//凝聚条件: 距离、方位接近
|
//凝聚条件: 距离、方位接近
|
||||||
if(Work_Parameter.work_mode == 0)
|
if(Work_Parameter.work_mode == 0)
|
||||||
@@ -160,10 +152,10 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
||||||
&& point_0_A <point_1_A )//
|
&& point_0_A <point_1_A )//
|
||||||
{
|
{
|
||||||
point_0_R=data_tmp[i].Range;
|
point_0_R=static_cast<float>(data_tmp[i].Range);
|
||||||
point_0_V=data_tmp[i].Velocity;
|
point_0_V=static_cast<float>(data_tmp[i].Velocity);
|
||||||
point_0_A=data_tmp[i].Amplitude;
|
point_0_A=static_cast<float>(data_tmp[i].Amplitude);
|
||||||
point_0_F=data_tmp[i].Azimuth;
|
point_0_F=static_cast<float>(data_tmp[i].Azimuth);
|
||||||
data_tmp[loop_of_point].Use_Flag=1;
|
data_tmp[loop_of_point].Use_Flag=1;
|
||||||
}
|
}
|
||||||
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)//
|
||||||
@@ -178,10 +170,10 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
||||||
&& point_0_A <point_1_A )//
|
&& point_0_A <point_1_A )//
|
||||||
{
|
{
|
||||||
point_0_R=data_tmp[i].Range;
|
point_0_R=static_cast<float>(data_tmp[i].Range);
|
||||||
point_0_V=data_tmp[i].Velocity;
|
point_0_V=static_cast<float>(data_tmp[i].Velocity);
|
||||||
point_0_A=data_tmp[i].Amplitude;
|
point_0_A=static_cast<float>(data_tmp[i].Amplitude);
|
||||||
point_0_F=data_tmp[i].Azimuth;
|
point_0_F=static_cast<float>(data_tmp[i].Azimuth);
|
||||||
data_tmp[loop_of_point].Use_Flag=1;
|
data_tmp[loop_of_point].Use_Flag=1;
|
||||||
}
|
}
|
||||||
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI )//
|
||||||
@@ -213,7 +205,7 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//1.5 将data_tmp中凝聚后的点再分到 data_input_buff和data_input中
|
//1.5 将data_tmp中凝聚后的点再分到 data_input_buff和data_input中
|
||||||
for (int i=0;i<data_tmp.size();i++)
|
for (size_t i=0;i<data_tmp.size();i++)
|
||||||
{
|
{
|
||||||
if(data_tmp[i].point_section_asso==1)
|
if(data_tmp[i].point_section_asso==1)
|
||||||
{
|
{
|
||||||
@@ -229,7 +221,7 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
|
|
||||||
//2.data_input_buff数据输出给point_recv
|
//2.data_input_buff数据输出给point_recv
|
||||||
|
|
||||||
for (int i=0;i<data_input_buff.size();i++)
|
for (size_t i=0;i<data_input_buff.size();i++)
|
||||||
{
|
{
|
||||||
(*point_recv).push_back(data_input_buff[i]);
|
(*point_recv).push_back(data_input_buff[i]);
|
||||||
}
|
}
|
||||||
@@ -237,7 +229,7 @@ int Dot_Coh::dot_coh_process_buff( std::vector <PointRecv> *data_input,
|
|||||||
std::vector<PointRecv>().swap(data_input_buff);
|
std::vector<PointRecv>().swap(data_input_buff);
|
||||||
|
|
||||||
//3.data_input数据输出给data_input_buff
|
//3.data_input数据输出给data_input_buff
|
||||||
for (int i=0;i<data_input->size();i++)
|
for (size_t i=0;i<data_input->size();i++)
|
||||||
{
|
{
|
||||||
data_input_buff.push_back((*data_input)[i]);
|
data_input_buff.push_back((*data_input)[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef DOT_COH_H
|
#ifndef DOT_COH_H
|
||||||
#define DOT_COH_H
|
#define DOT_COH_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "dot_coh_tas.h"
|
#include "dot_coh_tas.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -12,32 +12,32 @@ int Dot_Coh_TAS::dot_coh_tas_process(std::vector <PointRecv> *dat
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int loop_of_point=0; loop_of_point<data_input->size()-1;loop_of_point++ )
|
for (size_t loop_of_point=0; loop_of_point<data_input->size()-1;loop_of_point++ )
|
||||||
{
|
{
|
||||||
if( (*data_input)[loop_of_point].Use_Flag!=1)
|
if( (*data_input)[loop_of_point].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_0_R=(*data_input)[loop_of_point].Range;
|
float point_0_R=static_cast<float>((*data_input)[loop_of_point].Range);
|
||||||
float point_0_V=(*data_input)[loop_of_point].Velocity;
|
float point_0_V=static_cast<float>((*data_input)[loop_of_point].Velocity);
|
||||||
float point_0_F=(*data_input)[loop_of_point].Azimuth;
|
float point_0_F=static_cast<float>((*data_input)[loop_of_point].Azimuth);
|
||||||
float point_0_A=(*data_input)[loop_of_point].Amplitude;
|
float point_0_A=static_cast<float>((*data_input)[loop_of_point].Amplitude);
|
||||||
for ( int i=loop_of_point+1;i<(*data_input).size();i++)
|
for ( size_t i=loop_of_point+1;i<(*data_input).size();i++)
|
||||||
{
|
{
|
||||||
if((*data_input)[loop_of_point].Use_Flag!=1 && (*data_input)[i].Use_Flag!=1)
|
if((*data_input)[loop_of_point].Use_Flag!=1 && (*data_input)[i].Use_Flag!=1)
|
||||||
{
|
{
|
||||||
float point_1_R=(*data_input)[i].Range;
|
float point_1_R=static_cast<float>((*data_input)[i].Range);
|
||||||
float point_1_V=(*data_input)[i].Velocity;
|
float point_1_V=static_cast<float>((*data_input)[i].Velocity);
|
||||||
float point_1_F=(*data_input)[i].Azimuth;
|
float point_1_F=static_cast<float>((*data_input)[i].Azimuth);
|
||||||
float point_1_A=(*data_input)[i].Amplitude;
|
float point_1_A=static_cast<float>((*data_input)[i].Amplitude);
|
||||||
|
|
||||||
//凝聚条件: 距离、方位接近
|
//凝聚条件: 距离、方位接近
|
||||||
float delta_F = fabs(point_0_F-point_1_F)<2*PI-fabs(point_0_F-point_1_F) ? fabs(point_0_F-point_1_F) :2*PI-fabs(point_0_F-point_1_F);
|
float delta_F = fabs(point_0_F-point_1_F)<2*PI-fabs(point_0_F-point_1_F) ? fabs(point_0_F-point_1_F) :2*PI-fabs(point_0_F-point_1_F);
|
||||||
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)
|
if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)
|
||||||
&& point_0_A <point_1_A )
|
&& point_0_A <point_1_A )
|
||||||
{
|
{
|
||||||
point_0_R=(*data_input)[i].Range;
|
point_0_R=static_cast<float>((*data_input)[i].Range);
|
||||||
point_0_V=(*data_input)[i].Velocity;
|
point_0_V=static_cast<float>((*data_input)[i].Velocity);
|
||||||
point_0_A=(*data_input)[i].Amplitude;
|
point_0_A=static_cast<float>((*data_input)[i].Amplitude);
|
||||||
point_0_F=(*data_input)[i].Azimuth;
|
point_0_F=static_cast<float>((*data_input)[i].Azimuth);
|
||||||
(*data_input)[loop_of_point].Use_Flag=1;
|
(*data_input)[loop_of_point].Use_Flag=1;
|
||||||
}
|
}
|
||||||
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)
|
else if( (fabs(point_0_R-point_1_R)<=DOT_COH_RANGE && delta_F <=DOT_COH_AZI/180.0*PI && fabs(point_0_V-point_1_V)<=DOT_COH_V)
|
||||||
@@ -65,7 +65,7 @@ int Dot_Coh_TAS::dot_coh_tas_process(std::vector <PointRecv> *dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<data_input->size();i++)
|
for (size_t i=0;i<data_input->size();i++)
|
||||||
{
|
{
|
||||||
(*point_recv_tas).push_back((*data_input)[i]);
|
(*point_recv_tas).push_back((*data_input)[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef DOT_COH_TAS_H
|
#ifndef DOT_COH_TAS_H
|
||||||
#define DOT_COH_TAS_H
|
#define DOT_COH_TAS_H
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include "struct.h"
|
#include "struct.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef KALMAN_H
|
#ifndef KALMAN_H
|
||||||
#define KALMAN_H
|
#define KALMAN_H
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include "struct.h"
|
#include "struct.h"
|
||||||
|
|||||||
@@ -1,38 +1,29 @@
|
|||||||
#ifndef PARAMETERS_H
|
#ifndef PARAMETERS_H
|
||||||
#define PARAMETERS_H
|
#define PARAMETERS_H
|
||||||
#pragma once
|
#pragma once
|
||||||
/**********************************雷达参数*************************************************/
|
/**********************************雷达参数*************************************************/
|
||||||
#define PI 3.1415926f
|
#define PI 3.1415926f
|
||||||
|
|
||||||
//频点(GHz)
|
//频点(GHz)
|
||||||
#define FREQ0 16.8
|
#define FREQ0 9.2
|
||||||
#define FREQ1 16.8
|
|
||||||
#define FREQ2 16.8
|
/**********************************日志输出开关**********************************************/
|
||||||
#define FREQ3 16.8
|
// 日志文件输出功能开关:
|
||||||
#define FREQ4 16.8
|
// 1) 定义(默认)RDP_LOG_ENABLE:启用日志文件输出 —— 调用 Data_Process_Factory::GetB()
|
||||||
#define FREQ5 16.8
|
// 时自动将 std::cout 重定向到日志文件,日志文件存放于 RDP_LOG_DIR 目录,
|
||||||
#define FREQ6 16.8
|
// 文件名按当前日期+时间自动命名(如 rdp_20240826_153000.log);
|
||||||
#define FREQ7 16.8
|
// 2) 注释掉 RDP_LOG_ENABLE:关闭 —— 不做重定向,日志仍输出到标准输出(控制台)。
|
||||||
#define FREQ8 16.8
|
//#define RDP_LOG_ENABLE
|
||||||
#define FREQ9 16.8
|
|
||||||
#define FREQ10 16.8
|
//日志文件输出目录(相对当前工作目录的路径,目录不存在时自动创建)
|
||||||
#define FREQ11 16.8
|
#define RDP_LOG_DIR ".\\rdp_logs\\"
|
||||||
#define FREQ12 16.8
|
|
||||||
#define FREQ13 16.8
|
|
||||||
#define FREQ14 16.8
|
|
||||||
#define FREQ15 16.8
|
|
||||||
#define FREQ16 16.8
|
|
||||||
#define FREQ17 16.8
|
|
||||||
#define FREQ18 16.8
|
|
||||||
#define FREQ19 16.8
|
|
||||||
#define FREQ20 16.8
|
|
||||||
|
|
||||||
//#define MECHANICAL_SCANNING
|
//#define MECHANICAL_SCANNING
|
||||||
//#define PHASE_SCANNING
|
//#define PHASE_SCANNING
|
||||||
|
|
||||||
#ifdef MECHANICAL_SCANNING
|
#ifdef MECHANICAL_SCANNING
|
||||||
/******************************数据处理参数**************************************/
|
/******************************数据处理参数**************************************/
|
||||||
#define DATA_RATE_TAS 0.0625
|
// #define DATA_RATE_TAS 0.0625
|
||||||
|
|
||||||
#define SIGMA_R 10.0 //测量误差
|
#define SIGMA_R 10.0 //测量误差
|
||||||
#define SIGMA_A 0.02
|
#define SIGMA_A 0.02
|
||||||
@@ -58,10 +49,14 @@
|
|||||||
#define TRACK_START_THRESHOLD 8 //起航波门 3 越大越容易起批
|
#define TRACK_START_THRESHOLD 8 //起航波门 3 越大越容易起批
|
||||||
#define ALPHA_START 60 //起航夹角 120 越大越容易起批
|
#define ALPHA_START 60 //起航夹角 120 越大越容易起批
|
||||||
|
|
||||||
#define TRACK_DIE_ROUND 4 // 航迹消亡时间
|
#define MAX_EXTRAPOLATE_NUM 3 //最大外推点数
|
||||||
#define TRACK_DIE_ROUND_TAS 96 //
|
#define MAX_EXTRAPOLATE_NUM_TAS 48 //TAS最大外推点数
|
||||||
|
|
||||||
#define ASSO_THORD 3
|
#define TRACK_DIE_ROUND 6 // 航迹消亡圈数
|
||||||
|
#define TRACK_DIE_ROUND_PRIMARY 10 // 重点航迹消亡圈数
|
||||||
|
#define TRACK_DIE_ROUND_TAS 96 //TAS航迹消亡圈数
|
||||||
|
|
||||||
|
#define ASSO_THORD 4
|
||||||
|
|
||||||
#define H_F_WIN_LEN 3
|
#define H_F_WIN_LEN 3
|
||||||
|
|
||||||
@@ -72,12 +67,14 @@
|
|||||||
|
|
||||||
#define DIRECT_TRACKING_QUEUE_LENGTH 10
|
#define DIRECT_TRACKING_QUEUE_LENGTH 10
|
||||||
|
|
||||||
|
#pragma message("MECHANICAL_SCANNING")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PHASE_SCANNING
|
#ifdef PHASE_SCANNING
|
||||||
|
|
||||||
/******************************数据处理参数**************************************/
|
/******************************数据处理参数**************************************/
|
||||||
#define DATA_RATE_TAS 0.3
|
// #define DATA_RATE_TAS 0.3
|
||||||
|
|
||||||
#define SIGMA_R 10.0 //测量误差
|
#define SIGMA_R 10.0 //测量误差
|
||||||
#define SIGMA_A 0.02
|
#define SIGMA_A 0.02
|
||||||
@@ -105,10 +102,14 @@
|
|||||||
#define TRACK_START_THRESHOLD 8 //起航波门 3 越大越容易起批
|
#define TRACK_START_THRESHOLD 8 //起航波门 3 越大越容易起批
|
||||||
#define ALPHA_START 60 //起航夹角 120 越大越容易起批
|
#define ALPHA_START 60 //起航夹角 120 越大越容易起批
|
||||||
|
|
||||||
#define TRACK_DIE_ROUND 4 // 航迹消亡时间
|
#define MAX_EXTRAPOLATE_NUM 3 //最大外推点数
|
||||||
#define TRACK_DIE_ROUND_TAS 5
|
#define MAX_EXTRAPOLATE_NUM_TAS 5 //TAS最大外推点数
|
||||||
|
|
||||||
#define ASSO_THORD 3
|
#define TRACK_DIE_ROUND 6 // 航迹消亡圈数
|
||||||
|
#define TRACK_DIE_ROUND_PRIMARY 10 // 重点航迹消亡圈数
|
||||||
|
#define TRACK_DIE_ROUND_TAS 10 //TAS航迹消亡圈数
|
||||||
|
|
||||||
|
#define ASSO_THORD 4
|
||||||
|
|
||||||
#define H_F_WIN_LEN 3
|
#define H_F_WIN_LEN 3
|
||||||
|
|
||||||
@@ -119,6 +120,8 @@
|
|||||||
|
|
||||||
#define DIRECT_TRACKING_QUEUE_LENGTH 10
|
#define DIRECT_TRACKING_QUEUE_LENGTH 10
|
||||||
|
|
||||||
|
#pragma message("PHASE_SCANNING")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define Round(x) (((x) > 0) \
|
#define Round(x) (((x) > 0) \
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#include "rdp_log.h"
|
||||||
|
#include "parameters.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <time.h>
|
||||||
|
#include <direct.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//日志模块内部状态:日志文件流 + 重定向前 std::cout 的原始缓冲区
|
||||||
|
struct RdpLogState
|
||||||
|
{
|
||||||
|
std::ofstream file; //日志文件输出流
|
||||||
|
std::streambuf *original_buf; //重定向前 std::cout 的原始缓冲区
|
||||||
|
bool enabled; //是否已成功重定向到日志文件
|
||||||
|
|
||||||
|
RdpLogState() : original_buf(0), enabled(false) {}
|
||||||
|
|
||||||
|
~RdpLogState()
|
||||||
|
{
|
||||||
|
//进程退出兜底:若宿主进程未调用 Data_Process_Factory::Destroy(),
|
||||||
|
//此处恢复 std::cout,避免其仍指向即将析构的日志文件流缓冲区。
|
||||||
|
if (enabled && original_buf)
|
||||||
|
{
|
||||||
|
std::cout.rdbuf(original_buf);
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RdpLogState &State()
|
||||||
|
{
|
||||||
|
static RdpLogState s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//当前本地时间字符串,格式 "YYYY-MM-DD HH:MM:SS"
|
||||||
|
std::string CurrentTime()
|
||||||
|
{
|
||||||
|
char buf[32] = {0};
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm local;
|
||||||
|
if (localtime_s(&local, &now) != 0)
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &local);
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//提取纯文件名(去掉路径前缀),日志前缀中只显示 文件名:行号
|
||||||
|
const char *FileName(const char *path)
|
||||||
|
{
|
||||||
|
if (path == 0)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const char *base = path;
|
||||||
|
for (const char *p = path; *p != '\0'; ++p)
|
||||||
|
{
|
||||||
|
if (*p == '\\' || *p == '/')
|
||||||
|
{
|
||||||
|
base = p + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace rdp_log
|
||||||
|
{
|
||||||
|
bool Init()
|
||||||
|
{
|
||||||
|
RdpLogState &st = State();
|
||||||
|
if (st.enabled)
|
||||||
|
{
|
||||||
|
return true; //已经重定向,避免重复初始化
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RDP_LOG_ENABLE
|
||||||
|
//创建日志目录(目录已存在时 _mkdir 返回 EEXIST,忽略)
|
||||||
|
std::string log_dir = RDP_LOG_DIR;
|
||||||
|
while (log_dir.size() > 0 &&
|
||||||
|
(log_dir[log_dir.size() - 1] == '\\' || log_dir[log_dir.size() - 1] == '/'))
|
||||||
|
{
|
||||||
|
log_dir.erase(log_dir.size() - 1);
|
||||||
|
}
|
||||||
|
if (log_dir.size() > 0)
|
||||||
|
{
|
||||||
|
_mkdir(log_dir.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//按当前日期+时间生成日志文件名:rdp_YYYYMMDD_HHMMSS.log
|
||||||
|
char time_buf[32] = {0};
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm local;
|
||||||
|
if (localtime_s(&local, &now) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strftime(time_buf, sizeof(time_buf), "%Y%m%d_%H%M%S", &local);
|
||||||
|
|
||||||
|
std::string log_path = RDP_LOG_DIR;
|
||||||
|
log_path += "rdp_";
|
||||||
|
log_path += time_buf;
|
||||||
|
log_path += ".log";
|
||||||
|
|
||||||
|
st.file.open(log_path.c_str(), std::ios::out | std::ios::trunc);
|
||||||
|
if (!st.file.is_open())
|
||||||
|
{
|
||||||
|
//日志文件打开失败(目录不可写等):保持控制台输出,不做重定向
|
||||||
|
std::cout << "[rdp_log] cannot open log file: " << log_path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//用 rdbuf() 将 std::cout 的流缓冲区替换为日志文件输出流
|
||||||
|
st.original_buf = std::cout.rdbuf();
|
||||||
|
std::cout.rdbuf(st.file.rdbuf());
|
||||||
|
st.enabled = true;
|
||||||
|
|
||||||
|
//重定向成功后写入起始标记(该行已写入日志文件)
|
||||||
|
std::cout << prefix(__FILE__, __LINE__)
|
||||||
|
<< "rdp_log enabled, log file: " << log_path << std::endl;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
//日志开关关闭:不重定向,日志仍输出到标准输出
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
RdpLogState &st = State();
|
||||||
|
if (!st.enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//写入结束标记后刷新、恢复 std::cout 并关闭日志文件
|
||||||
|
std::cout << prefix(__FILE__, __LINE__) << "rdp_log shutdown" << std::endl;
|
||||||
|
st.file.flush();
|
||||||
|
std::cout.rdbuf(st.original_buf);
|
||||||
|
st.enabled = false;
|
||||||
|
st.file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string prefix(const char *file, int line)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << CurrentTime() << "][" << FileName(file) << ":" << line << "] ";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef RDP_LOG_H
|
||||||
|
#define RDP_LOG_H
|
||||||
|
#pragma once
|
||||||
|
/*************************************日志输出模块*******************************************/
|
||||||
|
// 功能:
|
||||||
|
// 1) rdp_log::Init():按 parameters.h 中 RDP_LOG_ENABLE 宏开关决定是否将 std::cout
|
||||||
|
// 重定向到日志文件(RDP_LOG_DIR 目录,文件名按当前日期+时间自动生成)。
|
||||||
|
// 开关关闭(注释掉 RDP_LOG_ENABLE)时不做重定向,日志仍输出到标准输出。
|
||||||
|
// 2) rdp_log::Shutdown():恢复 std::cout 原始缓冲区(回到控制台)并关闭日志文件。
|
||||||
|
// 3) RDP_LOG 宏:日志输出宏,在每条日志前自动附加 [时间戳][代码文件:行号] 信息,
|
||||||
|
// 随后输出到 std::cout(若开关开启则随 cout 一并写入日志文件)。
|
||||||
|
// 用法示例:
|
||||||
|
// RDP_LOG << "目标批号:" << track_index << std::endl;
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace rdp_log
|
||||||
|
{
|
||||||
|
bool Init(); //初始化日志输出(由 Data_Process_Factory::GetB() 调用)
|
||||||
|
void Shutdown(); //恢复 std::cout 并关闭日志文件(由 Data_Process_Factory::Destroy() 调用)
|
||||||
|
std::string prefix(const char *file, int line); //生成 "[时间戳][文件名:行号] " 前缀字符串
|
||||||
|
}
|
||||||
|
|
||||||
|
//日志输出宏:自动附加 时间戳、代码文件、代码行号 后输出到标准输出(std::cout)
|
||||||
|
#define RDP_LOG std::cout << rdp_log::prefix(__FILE__, __LINE__)
|
||||||
|
|
||||||
|
#endif // RDP_LOG_H
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef STRUCT_H
|
#ifndef STRUCT_H
|
||||||
#define STRUCT_H
|
#define STRUCT_H
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -16,6 +16,8 @@ struct PointRecv
|
|||||||
double Height; //高度
|
double Height; //高度
|
||||||
double snr; //信噪比
|
double snr; //信噪比
|
||||||
double RCS; //目标RCS
|
double RCS; //目标RCS
|
||||||
|
float amp_asv_point; //归一化幅度dB
|
||||||
|
float prn_fftn_point; //点迹速度维FFT点数
|
||||||
long long CPI_Time; //CPI时间
|
long long CPI_Time; //CPI时间
|
||||||
long long GNSS_time; //GNSS时间
|
long long GNSS_time; //GNSS时间
|
||||||
int Point_index; //点迹号 1~50
|
int Point_index; //点迹号 1~50
|
||||||
@@ -57,6 +59,8 @@ struct Trust_Track
|
|||||||
int manual_tracking_flag; //手动TAS
|
int manual_tracking_flag; //手动TAS
|
||||||
int associate_point_number; //关联的点数
|
int associate_point_number; //关联的点数
|
||||||
|
|
||||||
|
int primary_target_flag; //重点目标标记
|
||||||
|
|
||||||
int Target_Type; //目标类型 搜索目标 低空目标 地面目标
|
int Target_Type; //目标类型 搜索目标 低空目标 地面目标
|
||||||
|
|
||||||
int Track_section_idx; //航迹区号
|
int Track_section_idx; //航迹区号
|
||||||
@@ -70,6 +74,8 @@ struct Trust_Track
|
|||||||
double prf_point;
|
double prf_point;
|
||||||
int point_type; //TWS TAS
|
int point_type; //TWS TAS
|
||||||
double snr_point; //信噪比
|
double snr_point; //信噪比
|
||||||
|
float amp_asv_point; //关联上的点迹信息(归一化幅度)
|
||||||
|
float prn_fftn_point; //点迹速度维FFT点数
|
||||||
|
|
||||||
double RCS;
|
double RCS;
|
||||||
|
|
||||||
@@ -125,7 +131,7 @@ struct Tracking_Target
|
|||||||
{
|
{
|
||||||
int Index; //目标批号
|
int Index; //目标批号
|
||||||
int empty_flag; //是否为空标志位 1非空 0空
|
int empty_flag; //是否为空标志位 1非空 0空
|
||||||
|
long long last_track_time; //最新跟踪时间
|
||||||
};
|
};
|
||||||
|
|
||||||
//引导跟踪目标结构体
|
//引导跟踪目标结构体
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "tas_ctrl.h"
|
#include "tas_ctrl.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -39,14 +42,14 @@ void TAS_Ctrl::tas_ctrl_process(std::vector<Trust_Track> *trust_track
|
|||||||
tas_target_del(trust_track, Trust_Track_Output, Trust_track_num_Output,Work_Parameter);
|
tas_target_del(trust_track, Trust_Track_Output, Trust_track_num_Output,Work_Parameter);
|
||||||
tas_beam_output(trust_track,Tracking_beam,Work_Parameter,latest_timestamp);
|
tas_beam_output(trust_track,Tracking_beam,Work_Parameter,latest_timestamp);
|
||||||
|
|
||||||
//跟踪队列移位
|
// //跟踪队列移位
|
||||||
struct Tracking_Target tas_target_tmp;
|
// struct Tracking_Target tas_target_tmp;
|
||||||
memcpy(&tas_target_tmp, &tas_target_queue[TAS_QUEUE_LENGTH-1], sizeof(Tracking_Target));
|
// memcpy(&tas_target_tmp, &tas_target_queue[TAS_QUEUE_LENGTH-1], sizeof(Tracking_Target));
|
||||||
for (int i=TAS_QUEUE_LENGTH-1;i>0;i--)
|
// for (int i=TAS_QUEUE_LENGTH-1;i>0;i--)
|
||||||
{
|
// {
|
||||||
memcpy(&tas_target_queue[i],&tas_target_queue[i-1],sizeof(Tracking_Target));
|
// memcpy(&tas_target_queue[i],&tas_target_queue[i-1],sizeof(Tracking_Target));
|
||||||
}
|
// }
|
||||||
memcpy(&tas_target_queue[0], &tas_target_tmp, sizeof(Tracking_Target));
|
// memcpy(&tas_target_queue[0], &tas_target_tmp, sizeof(Tracking_Target));
|
||||||
};
|
};
|
||||||
|
|
||||||
void TAS_Ctrl::tas_target_add(std::vector<Trust_Track> *trust_track,
|
void TAS_Ctrl::tas_target_add(std::vector<Trust_Track> *trust_track,
|
||||||
@@ -55,7 +58,7 @@ void TAS_Ctrl::tas_target_add(std::vector<Trust_Track> *trust_track,
|
|||||||
struct RadarPara Work_Parameter)
|
struct RadarPara Work_Parameter)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i=0;i<trust_track->size();i++)
|
for (size_t i=0;i<trust_track->size();i++)
|
||||||
{
|
{
|
||||||
double r=sqrt(pow((*trust_track)[i].X[0],2)+pow((*trust_track)[i].X[3],2));
|
double r=sqrt(pow((*trust_track)[i].X[0],2)+pow((*trust_track)[i].X[3],2));
|
||||||
double v=sqrt(pow((*trust_track)[i].X[1],2)+pow((*trust_track)[i].X[4],2));
|
double v=sqrt(pow((*trust_track)[i].X[1],2)+pow((*trust_track)[i].X[4],2));
|
||||||
@@ -81,6 +84,7 @@ void TAS_Ctrl::tas_target_add(std::vector<Trust_Track> *trust_track,
|
|||||||
//插入跟踪队列
|
//插入跟踪队列
|
||||||
tas_target_queue[j].Index=(*trust_track)[i].Track_Index;
|
tas_target_queue[j].Index=(*trust_track)[i].Track_Index;
|
||||||
tas_target_queue[j].empty_flag=1;
|
tas_target_queue[j].empty_flag=1;
|
||||||
|
tas_target_queue[j].last_track_time=(*trust_track)[i].T_track;
|
||||||
|
|
||||||
//跟踪目标数目加一
|
//跟踪目标数目加一
|
||||||
tas_target_num=tas_target_num+1;
|
tas_target_num=tas_target_num+1;
|
||||||
@@ -94,18 +98,18 @@ void TAS_Ctrl::tas_target_add(std::vector<Trust_Track> *trust_track,
|
|||||||
coor_trans Coor_trans;
|
coor_trans Coor_trans;
|
||||||
Coor_trans.cart2polar((*trust_track)[i].X[0],(*trust_track)[i].X[3],&r_output,&azmi_output);
|
Coor_trans.cart2polar((*trust_track)[i].X[0],(*trust_track)[i].X[3],&r_output,&azmi_output);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=r_output;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=static_cast<float>(r_output);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=azmi_output/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=static_cast<float>(azmi_output/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index; //航迹号
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index; //航迹号
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V=
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V=
|
||||||
sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]);
|
static_cast<float>(sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]));
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude=(*trust_track)[i].Amplitude;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude=static_cast<float>((*trust_track)[i].Amplitude);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point=(*trust_track)[i].point_flag;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point=(*trust_track)[i].point_flag;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation=asin((*trust_track)[i].Height/r_output)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation=static_cast<float>(asin((*trust_track)[i].Height/r_output)/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].z=(*trust_track)[i].Height+Work_Parameter.Height;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].z=static_cast<float>((*trust_track)[i].Height+Work_Parameter.Height);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Target_Type=(*trust_track)[i].Target_Type;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Target_Type=(*trust_track)[i].Target_Type;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = (*trust_track)[i].snr_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = static_cast<float>((*trust_track)[i].snr_point);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -163,7 +167,7 @@ void TAS_Ctrl::tas_target_del(std::vector<Trust_Track> *trust_track,
|
|||||||
{
|
{
|
||||||
//查找TAS队列里的目标是否存在
|
//查找TAS队列里的目标是否存在
|
||||||
int flag=0;
|
int flag=0;
|
||||||
for (int j=0;j<trust_track->size();j++){
|
for (size_t j=0;j<trust_track->size();j++){
|
||||||
{
|
{
|
||||||
if(tas_target_queue[i].Index==(*trust_track)[j].Track_Index && (*trust_track)[j].Track_Mode == 1 && (*trust_track)[j].manual_tracking_flag == 1)
|
if(tas_target_queue[i].Index==(*trust_track)[j].Track_Index && (*trust_track)[j].Track_Mode == 1 && (*trust_track)[j].manual_tracking_flag == 1)
|
||||||
{
|
{
|
||||||
@@ -212,17 +216,17 @@ void TAS_Ctrl::tas_target_del(std::vector<Trust_Track> *trust_track,
|
|||||||
// coor_trans Coor_trans;
|
// coor_trans Coor_trans;
|
||||||
// Coor_trans.cart2polar((*trust_track)[i].X[0],(*trust_track)[i].X[3],&r_output,&azmi_output);
|
// Coor_trans.cart2polar((*trust_track)[i].X[0],(*trust_track)[i].X[3],&r_output,&azmi_output);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Range=r_output;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Range=static_cast<float>(r_output);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=azmi_output/PI*180;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=static_cast<float>(azmi_output/PI*180);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index; //航迹号
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index; //航迹号
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V=sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]);
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V=static_cast<float>(sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]));
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude=(*trust_track)[i].Amplitude;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude=static_cast<float>((*trust_track)[i].Amplitude);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point=(*trust_track)[i].point_flag;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point=(*trust_track)[i].point_flag;
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation=asin((*trust_track)[i].Height/r_output)/PI*180;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation=static_cast<float>(asin((*trust_track)[i].Height/r_output)/PI*180);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].z=(*trust_track)[i].Height+Work_Parameter.Height;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].z=static_cast<float>((*trust_track)[i].Height+Work_Parameter.Height);
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].Target_Type=(*trust_track)[i].Target_Type;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Target_Type=(*trust_track)[i].Target_Type;
|
||||||
// Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = (*trust_track)[i].snr_point;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = static_cast<float>((*trust_track)[i].snr_point);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@@ -255,46 +259,60 @@ void TAS_Ctrl::tas_beam_output(std::vector<Trust_Track> *trust_track
|
|||||||
struct RadarPara Work_Parameter,
|
struct RadarPara Work_Parameter,
|
||||||
long long latest_timestamp)
|
long long latest_timestamp)
|
||||||
{
|
{
|
||||||
if(tas_target_queue[0].empty_flag==1)
|
|
||||||
{
|
|
||||||
|
|
||||||
double H_track = 0;
|
|
||||||
double X_now[6] = {0};
|
|
||||||
long long CPI_time = 0;
|
long long CPI_time = 0;
|
||||||
bool found_track = false;
|
long long earliest_CPI_time = LLONG_MAX;
|
||||||
for (int i=0;i<trust_track->size();i++ )
|
float delta_T = 0;
|
||||||
|
float delta_T_last_track = 0;
|
||||||
|
double H_track = 0;
|
||||||
|
int earliest_track_idx=-1;
|
||||||
|
int earliest_tas_queue_idx=-1;
|
||||||
|
double X_now[6] = {0};
|
||||||
|
|
||||||
|
//查找TAS队列中CPI时间最早的目标且满足TAS数据率的目标
|
||||||
|
for(int tas_idx=0;tas_idx<TAS_QUEUE_LENGTH;tas_idx++)
|
||||||
{
|
{
|
||||||
if((*trust_track)[i].Track_Index == tas_target_queue[0].Index)
|
if(tas_target_queue[tas_idx].empty_flag==0)
|
||||||
{
|
{
|
||||||
H_track = (*trust_track)[i].Height;
|
continue;
|
||||||
CPI_time = (*trust_track)[i].T_track;
|
}
|
||||||
for(int ii=0;ii<6;ii++)
|
|
||||||
X_now[ii]=(*trust_track)[i].X[ii];
|
for (size_t track_idx=0;track_idx<trust_track->size();track_idx++ )
|
||||||
found_track = true;
|
{
|
||||||
|
if((*trust_track)[track_idx].Track_Index == tas_target_queue[tas_idx].Index)
|
||||||
|
{
|
||||||
|
CPI_time = (*trust_track)[track_idx].T_track;
|
||||||
|
delta_T_last_track = (latest_timestamp - tas_target_queue[tas_idx].last_track_time) / 1000.0f;
|
||||||
|
|
||||||
|
//查找CPI时间最早,且满足TAS数据率的目标
|
||||||
|
if(CPI_time < earliest_CPI_time && (delta_T_last_track > Work_Parameter.DATA_RATE_TAS))
|
||||||
|
{
|
||||||
|
earliest_CPI_time = CPI_time;
|
||||||
|
H_track = (*trust_track)[track_idx].Height;
|
||||||
|
delta_T = (latest_timestamp - CPI_time) / 1000.0f;
|
||||||
|
|
||||||
|
earliest_track_idx = track_idx;
|
||||||
|
earliest_tas_queue_idx = tas_idx;
|
||||||
|
|
||||||
|
for(int ii=0;ii<6;ii++){
|
||||||
|
X_now[ii]=(*trust_track)[track_idx].X[ii];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_track)
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//没有满足条件的TAS目标,关闭跟踪波束
|
||||||
|
if(earliest_track_idx == -1)
|
||||||
{
|
{
|
||||||
Tracking_beam->open_flag = 0;
|
Tracking_beam->open_flag = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//数据率门控:航迹时间与当前最新时间戳的差值大于 1/DATA_RATE_TAS 时才输出TAS跟踪波束,
|
//更新目标最后跟踪时间
|
||||||
//保证TAS目标数据率不随波束时间变化(使用Work_Parameter中的DATA_RATE_TAS参数值)。
|
tas_target_queue[earliest_tas_queue_idx].last_track_time = latest_timestamp;
|
||||||
//DATA_RATE_TAS<=0 时不做门控,按原逻辑每次输出(避免除零,兼容未配置该参数的调用者)。
|
|
||||||
if (Work_Parameter.DATA_RATE_TAS > 0)
|
|
||||||
{
|
|
||||||
double delta_T_track = (double)(latest_timestamp - CPI_time) / 1000.0;
|
|
||||||
if (delta_T_track <= 1.0 / Work_Parameter.DATA_RATE_TAS)
|
|
||||||
{
|
|
||||||
//更新间隔未到 不输出跟踪波束
|
|
||||||
Tracking_beam->open_flag = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float delta_T = (latest_timestamp - CPI_time) / 1000.0f;
|
|
||||||
|
|
||||||
//预测目标位置 计算跟踪波束波位号 俯仰角
|
//预测目标位置 计算跟踪波束波位号 俯仰角
|
||||||
double x_track=X_now[0]+X_now[1]*delta_T;
|
double x_track=X_now[0]+X_now[1]*delta_T;
|
||||||
@@ -304,9 +322,9 @@ void TAS_Ctrl::tas_beam_output(std::vector<Trust_Track> *trust_track
|
|||||||
Coor_trans.cart2polar(x_track,y_track,&range,&amzi);
|
Coor_trans.cart2polar(x_track,y_track,&range,&amzi);
|
||||||
|
|
||||||
//目标距离
|
//目标距离
|
||||||
Tracking_beam->Range=range;
|
Tracking_beam->Range=(float)range;
|
||||||
//目标方位
|
//目标方位
|
||||||
Tracking_beam->Azi=amzi/PI*180;
|
Tracking_beam->Azi=(float)amzi/PI*180;
|
||||||
// Tracking_beam->Azi+=6;
|
// Tracking_beam->Azi+=6;
|
||||||
//目标俯仰角
|
//目标俯仰角
|
||||||
double elev=asin(H_track/range)/PI*180;
|
double elev=asin(H_track/range)/PI*180;
|
||||||
@@ -318,23 +336,16 @@ void TAS_Ctrl::tas_beam_output(std::vector<Trust_Track> *trust_track
|
|||||||
// else
|
// else
|
||||||
// elev=elev;
|
// elev=elev;
|
||||||
|
|
||||||
Tracking_beam->Elev=elev;
|
Tracking_beam->Elev=(float)elev;
|
||||||
|
|
||||||
//跟踪波束类型
|
//跟踪波束类型
|
||||||
Tracking_beam->type=1;
|
Tracking_beam->type=1;
|
||||||
|
|
||||||
//跟踪目标批号
|
//跟踪目标批号
|
||||||
Tracking_beam->TAS_track_index = tas_target_queue[0].Index;
|
Tracking_beam->TAS_track_index = (*trust_track)[earliest_track_idx].Track_Index;
|
||||||
|
|
||||||
//跟踪波束开关开启
|
//跟踪波束开关开启
|
||||||
Tracking_beam->open_flag=1;
|
Tracking_beam->open_flag=1;
|
||||||
|
|
||||||
//std::cout << "TAS: range: " <<Tracking_beam->Range << "azi: " <<Tracking_beam->Azi <<"pit: " <<Tracking_beam->Elev;
|
//RDP_LOG << "TAS <" << (*trust_track)[earliest_track_idx].Track_Index << "> output: range: " <<Tracking_beam->Range << "azi: " <<Tracking_beam->Azi <<"pit: " <<Tracking_beam->Elev << std::endl;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//跟踪波束开关关闭
|
|
||||||
Tracking_beam->open_flag=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TAS_CTRL_H
|
#ifndef TAS_CTRL_H
|
||||||
#define TAS_CTRL_H
|
#define TAS_CTRL_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "track_asso.h"
|
#include "track_asso.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -20,7 +21,7 @@ int Track_Asso:: track_asso_process(std::vector<PointRecv> *point_
|
|||||||
{
|
{
|
||||||
|
|
||||||
//取出对应点迹区的点
|
//取出对应点迹区的点
|
||||||
for (int i=0;i< point_recv->size();i++)
|
for (size_t i=0;i< point_recv->size();i++)
|
||||||
{
|
{
|
||||||
point_process.push_back((*point_recv)[i]);
|
point_process.push_back((*point_recv)[i]);
|
||||||
int n=point_process.size();
|
int n=point_process.size();
|
||||||
@@ -51,7 +52,7 @@ int Track_Asso:: track_asso_process(std::vector<PointRecv> *point_
|
|||||||
|
|
||||||
//剩余点重新存入点迹
|
//剩余点重新存入点迹
|
||||||
std::vector<PointRecv>().swap((*point_recv));
|
std::vector<PointRecv>().swap((*point_recv));
|
||||||
for (int i=0;i<point_process.size();i++)
|
for (size_t i=0;i<point_process.size();i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
(*point_recv).push_back(point_process[i]);
|
(*point_recv).push_back(point_process[i]);
|
||||||
@@ -62,11 +63,10 @@ int Track_Asso:: track_asso_process(std::vector<PointRecv> *point_
|
|||||||
std::vector<PointRecv>().swap(point_process);
|
std::vector<PointRecv>().swap(point_process);
|
||||||
|
|
||||||
//输出航迹
|
//输出航迹
|
||||||
for (int i=0;i<trust_track->size();i++)
|
for (size_t i=0;i<trust_track->size();i++)
|
||||||
{ // 输出更新航迹条件:
|
{ // 输出更新航迹条件:
|
||||||
// if((*trust_track)[i].manual_tracking_flag==0)
|
if((*trust_track)[i].Track_Update_Flag==1){
|
||||||
// {
|
(*trust_track)[i].Track_Update_Flag=0;
|
||||||
|
|
||||||
*Trust_track_num_Output= *Trust_track_num_Output+1;
|
*Trust_track_num_Output= *Trust_track_num_Output+1;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
||||||
@@ -76,58 +76,80 @@ int Track_Asso:: track_asso_process(std::vector<PointRecv> *point_
|
|||||||
coor_trans Coor_trans;
|
coor_trans Coor_trans;
|
||||||
double r, azi;
|
double r, azi;
|
||||||
Coor_trans.cart2polar(x, y, &r, &azi);
|
Coor_trans.cart2polar(x, y, &r, &azi);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=r;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=static_cast<float>(r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=static_cast<float>(azi/PI*180);
|
||||||
|
|
||||||
if((*trust_track)[i].Height<r)
|
if((*trust_track)[i].Height<r)
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = asin((*trust_track)[i].Height/r)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = static_cast<float>(asin((*trust_track)[i].Height/r)/PI*180);
|
||||||
else
|
else
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = (*trust_track)[i].elev_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = static_cast<float>((*trust_track)[i].elev_point);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V =
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V =
|
||||||
sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]);
|
static_cast<float>(sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]));
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude = (*trust_track)[i].Amplitude;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude = static_cast<float>((*trust_track)[i].Amplitude);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_time=(*trust_track)[i].T_track/1000.0;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_time=static_cast<float>((*trust_track)[i].T_track/1000.0);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].GNSS_time=(*trust_track)[i].GNSS_time;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].GNSS_time=(*trust_track)[i].GNSS_time;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point = (*trust_track)[i].point_flag;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point = (*trust_track)[i].point_flag;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].z=(*trust_track)[i].Height+Work_Parameter.Height;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].z=static_cast<float>((*trust_track)[i].Height+Work_Parameter.Height);
|
||||||
|
|
||||||
double Direction_Angle;
|
double Direction_Angle;
|
||||||
Direction_Angle=atan2((*trust_track)[i].X[4], (*trust_track)[i].X[1]);
|
Direction_Angle=atan2((*trust_track)[i].X[4], (*trust_track)[i].X[1]);
|
||||||
if(Direction_Angle<0){Direction_Angle=Direction_Angle+2*PI;}
|
if(Direction_Angle<0){Direction_Angle=Direction_Angle+2*PI;}
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Direction_Angle=Direction_Angle/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Direction_Angle=static_cast<float>(Direction_Angle/PI*180);
|
||||||
|
|
||||||
//关联点信息
|
//关联点信息
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].range_point=(*trust_track)[i].range_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].range_point=static_cast<float>((*trust_track)[i].range_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].azi_point=(*trust_track)[i].azi_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].azi_point=static_cast<float>((*trust_track)[i].azi_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].elev_point=(*trust_track)[i].elev_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].elev_point=static_cast<float>((*trust_track)[i].elev_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point=(*trust_track)[i].vr_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point=static_cast<float>((*trust_track)[i].vr_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].point_type=0;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].point_type=0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].prf_point = (*trust_track)[i].prf_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].prf_point = static_cast<float>((*trust_track)[i].prf_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = (*trust_track)[i].snr_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = static_cast<float>((*trust_track)[i].snr_point);
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].amp_asv_point = static_cast<float>((*trust_track)[i].amp_asv_point);
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].prn_fftn_point = static_cast<float>((*trust_track)[i].prn_fftn_point);
|
||||||
|
|
||||||
//直接输出点迹高度-20260605
|
//直接输出点迹高度-20260605
|
||||||
//Trust_Track_Output[*Trust_track_num_Output-1][0].z = (*trust_track)[i].range_point * sin((*trust_track)[i].elev_point/180.0*PI);
|
//Trust_Track_Output[*Trust_track_num_Output-1][0].z = (*trust_track)[i].range_point * sin((*trust_track)[i].elev_point/180.0*PI);
|
||||||
//输出平滑后的高度
|
//输出平滑后的高度
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].z = (*trust_track)[i].Height+Work_Parameter.Height;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].z = static_cast<float>((*trust_track)[i].Height+Work_Parameter.Height);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = (*trust_track)[i].elev_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = static_cast<float>((*trust_track)[i].elev_point);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].x=(*trust_track)[i].X[0];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].x=static_cast<float>((*trust_track)[i].X[0]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].y=(*trust_track)[i].X[3];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].y=static_cast<float>((*trust_track)[i].X[3]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].v_x=(*trust_track)[i].X[1];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].v_x=static_cast<float>((*trust_track)[i].X[1]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].v_y=(*trust_track)[i].X[4];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].v_y=static_cast<float>((*trust_track)[i].X[4]);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_rcs = (*trust_track)[i].RCS;
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point>0?1:0;
|
||||||
|
|
||||||
|
if(acos((-x * cos(Direction_Angle) - y * sin(Direction_Angle)) / r ) < PI / 2)
|
||||||
|
{
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=1;
|
||||||
|
// if(r*abs(sin(azi - Direction_Angle))<500)
|
||||||
|
// {
|
||||||
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=1;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_rcs = static_cast<float>((*trust_track)[i].RCS);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].pitch_num = (*trust_track)[i].pitch_num;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].pitch_num = (*trust_track)[i].pitch_num;
|
||||||
|
|
||||||
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim, (*trust_track)[i].speed_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim));
|
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim, (*trust_track)[i].speed_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim));
|
||||||
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim, (*trust_track)[i].range_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim));
|
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim, (*trust_track)[i].range_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim));
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -137,7 +159,7 @@ int Track_Asso:: track_asso_process(std::vector<PointRecv> *point_
|
|||||||
void Track_Asso:: model_interaction(std::vector <Trust_Track> *trust_track)
|
void Track_Asso:: model_interaction(std::vector <Trust_Track> *trust_track)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
for (size_t loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
||||||
{
|
{
|
||||||
|
|
||||||
// if((*trust_track)[loop_of_track].manual_tracking_flag == 0)
|
// if((*trust_track)[loop_of_track].manual_tracking_flag == 0)
|
||||||
@@ -413,13 +435,11 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
std::vector <asso_info> associated_info;
|
std::vector <asso_info> associated_info;
|
||||||
|
|
||||||
//遍历所有点迹航迹 计算点迹和航迹的统计距离
|
//遍历所有点迹航迹 计算点迹和航迹的统计距离
|
||||||
for (int loop_of_track = 0; loop_of_track<trust_track->size();loop_of_track++)
|
for (size_t loop_of_track = 0; loop_of_track<trust_track->size();loop_of_track++)
|
||||||
{
|
{
|
||||||
// if((*trust_track)[loop_of_track].manual_tracking_flag==0)
|
|
||||||
// {
|
|
||||||
(*trust_track)[loop_of_track].point_flag = 0; //航迹的point_flag置为0 关联上点后再置为1
|
(*trust_track)[loop_of_track].point_flag = 0; //航迹的point_flag置为0 关联上点后再置为1
|
||||||
|
|
||||||
for (int loop_of_point = 0; loop_of_point<point_process.size();loop_of_point++)
|
for (size_t loop_of_point = 0; loop_of_point<point_process.size();loop_of_point++)
|
||||||
{
|
{
|
||||||
|
|
||||||
//时间差
|
//时间差
|
||||||
@@ -448,76 +468,33 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
double d1,d2,d3;
|
double d1,d2,d3;
|
||||||
IMM_d_cal(v_track,X1,P1,X2,P2, X3,P3,Z,prt,freq_ind,delta_T,&d1,&d2,&d3,Work_Parameter);
|
IMM_d_cal(v_track,X1,P1,X2,P2, X3,P3,Z,prt,freq_ind,delta_T,&d1,&d2,&d3,Work_Parameter);
|
||||||
|
|
||||||
//计算高度门限
|
//判定统计距离门限,thd_d
|
||||||
// double d_h;
|
bool thd_d = false;
|
||||||
// if (r_track<1000)
|
|
||||||
// {
|
|
||||||
// if(abs(h_track-h_point)<=150)
|
|
||||||
// {
|
|
||||||
// d_h = 1;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// d_h = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
if( (r_track <= 500 && \
|
||||||
// else if (r_track<2000 && r_track>=1000)
|
(d1*d1 < ASSO_THORD*ASSO_THORD || d2*d2 < ASSO_THORD*ASSO_THORD || d3*d3 < ASSO_THORD*ASSO_THORD / 1000.0)) || \
|
||||||
// {
|
((r_track > 500 && r_track < 1000) && \
|
||||||
// if(abs(h_track-h_point)<=200)
|
(d1*d1 < ASSO_THORD*ASSO_THORD || d2*d2 < ASSO_THORD*ASSO_THORD || d3*d3 < ASSO_THORD*ASSO_THORD / 100.0)) || \
|
||||||
// {
|
(r_track >= 1000 && \
|
||||||
// d_h = 1;
|
(d1*d1 < ASSO_THORD*ASSO_THORD || d2*d2 < ASSO_THORD*ASSO_THORD || d3*d3 < ASSO_THORD*ASSO_THORD))\
|
||||||
// }
|
){
|
||||||
// else
|
thd_d = true;
|
||||||
// {
|
}
|
||||||
// d_h = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
//判定高度门限,thd_h
|
||||||
// else if(r_track>=2000 && r_track<3000 )
|
bool thd_h = false;
|
||||||
// {
|
double delta_h = abs(h_track-h_point);
|
||||||
// if(abs(h_track-h_point)<=200)
|
|
||||||
// {
|
|
||||||
// d_h = 1;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// d_h = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if(r_track>=3000 && r_track<5000)
|
|
||||||
// {
|
|
||||||
// if(abs(h_track-h_point)<=300)
|
|
||||||
// {
|
|
||||||
// d_h = 1;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// d_h = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// d_h = 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// std::cout << delta_T<<" "<<d1<<" "<<d2<<" "<<d3;
|
if( (r_track <= 1000 && delta_h <= 150) || \
|
||||||
// std::cout << h_track<<" "<<h_point<<" "<<d_h;
|
((r_track > 1000 && r_track <= 2000) && delta_h <= 200) || \
|
||||||
// d_h = 1;
|
((r_track > 2000 && r_track <= 3000) && delta_h <= 250) || \
|
||||||
|
((r_track > 3000 && r_track <= 5000) && delta_h <= 300) || \
|
||||||
|
r_track > 5000
|
||||||
|
){
|
||||||
|
thd_h = true;
|
||||||
|
}
|
||||||
|
|
||||||
//计算俯仰门限
|
//判定距离门限,R=航迹点与量测点的距离,VT=航向速度乘以扫描时间差
|
||||||
bool d_p = true;
|
|
||||||
|
|
||||||
// double p_track = atan2(h_track, r_track); //航迹俯仰
|
|
||||||
// double p_point = asin(h_point/point_process[loop_of_point].Range); //点迹俯仰
|
|
||||||
|
|
||||||
// if( (r_track > 3000 && abs(p_track - p_point)*180/PI <= 7) || \
|
|
||||||
// (r_track > 1000 && r_track <= 3000 && abs(p_track - p_point)*180/PI <= 5) || \
|
|
||||||
// (r_track <= 1000 && abs(p_track - p_point)*180/PI <= 10)){
|
|
||||||
// d_p = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//计算距离门限,R=航迹点与量测点的距离,VT=航向速度乘以扫描时间差
|
|
||||||
double& t_x0 = (*trust_track)[loop_of_track].X[0];
|
double& t_x0 = (*trust_track)[loop_of_track].X[0];
|
||||||
double& t_y0 = (*trust_track)[loop_of_track].X[3];
|
double& t_y0 = (*trust_track)[loop_of_track].X[3];
|
||||||
double a_track = atan2(t_y0, t_x0); //航迹方位角
|
double a_track = atan2(t_y0, t_x0); //航迹方位角
|
||||||
@@ -530,23 +507,19 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
double R = sqrt(r_track * r_track + r_point*r_point - 2*r_track*r_point*cos(a_delta));
|
double R = sqrt(r_track * r_track + r_point*r_point - 2*r_track*r_point*cos(a_delta));
|
||||||
double VT = v_track*delta_T;
|
double VT = v_track*delta_T;
|
||||||
|
|
||||||
bool d_r = true;
|
bool thd_r = true;
|
||||||
|
|
||||||
if(VT < 100 && R > 300){
|
if(VT < 100 && R > 300){
|
||||||
//VT<100m,使用固定门限300m
|
//VT<100m,使用固定门限300m
|
||||||
d_r = false;
|
thd_r = false;
|
||||||
}else if((VT>=100 && VT<=300 && R/VT>3)){
|
}else if((VT>=100 && VT<=300 && R/VT>3)){
|
||||||
d_r = false;
|
thd_r = false;
|
||||||
}else if(VT>300 && R > 1200){
|
}else if(VT>300 && R > 1200){
|
||||||
d_r = false;
|
thd_r = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//小于关联门限 保存关联信息
|
//小于关联门限 保存关联信息
|
||||||
if(
|
if(thd_d && thd_h && thd_r)
|
||||||
( r_track<=500 && (d1*d1<ASSO_THORD*ASSO_THORD || d2*d2<ASSO_THORD*ASSO_THORD || d3*d3<ASSO_THORD*ASSO_THORD/1000.0) && d_p && d_r)//
|
|
||||||
||( (r_track>500&&r_track<1000) && (d1*d1<ASSO_THORD*ASSO_THORD || d2*d2<ASSO_THORD*ASSO_THORD || d3*d3<ASSO_THORD*ASSO_THORD/100.0) && d_p && d_r)//
|
|
||||||
||( r_track>=1000 && (d1*d1<ASSO_THORD*ASSO_THORD || d2*d2<ASSO_THORD*ASSO_THORD || d3*d3<ASSO_THORD*ASSO_THORD) && d_p && d_r)//
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
//std::cout << "asooooooooooo";
|
//std::cout << "asooooooooooo";
|
||||||
|
|
||||||
@@ -554,8 +527,8 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
associated_info_tmp.d1=d1;
|
associated_info_tmp.d1=d1;
|
||||||
associated_info_tmp.d2=d2;
|
associated_info_tmp.d2=d2;
|
||||||
associated_info_tmp.d3=d3;
|
associated_info_tmp.d3=d3;
|
||||||
associated_info_tmp.point_index=loop_of_point+1;
|
associated_info_tmp.point_index=static_cast<int>(loop_of_point)+1;
|
||||||
associated_info_tmp.track_index=loop_of_track+1;
|
associated_info_tmp.track_index=static_cast<int>(loop_of_track)+1;
|
||||||
if(d1<=d2&&d1<=d3)
|
if(d1<=d2&&d1<=d3)
|
||||||
associated_info_tmp.d_min=d1;
|
associated_info_tmp.d_min=d1;
|
||||||
else if(d2<=d1&& d2<=d3)
|
else if(d2<=d1&& d2<=d3)
|
||||||
@@ -571,7 +544,7 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
|
|
||||||
//最近邻法关联
|
//最近邻法关联
|
||||||
int associated_num=associated_info.size();
|
int associated_num=associated_info.size();
|
||||||
for (int i=0;i<trust_track->size();i++)
|
for (size_t i=0;i<trust_track->size();i++)
|
||||||
{
|
{
|
||||||
//寻找最小d
|
//寻找最小d
|
||||||
if(associated_num>0)
|
if(associated_num>0)
|
||||||
@@ -611,34 +584,9 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
|
|
||||||
if (delta_T <= 0)
|
if (delta_T <= 0)
|
||||||
{
|
{
|
||||||
|
// RDP_LOG<<"delta_T <= 0, track_index: "<<track_index<<", point_index: "<<point_index<<", delta_T: "<<delta_T<<std::endl;
|
||||||
// 乱序/重复时间戳:不作为有效关联,不标记点迹已使用、不刷新航迹新鲜度
|
// 乱序/重复时间戳:不作为有效关联,不标记点迹已使用、不刷新航迹新鲜度
|
||||||
for (int ii=0;ii<associated_num;)
|
}else{
|
||||||
{
|
|
||||||
if(associated_info[ii].track_index==track_index)
|
|
||||||
{
|
|
||||||
associated_info.erase(associated_info.begin()+ii);
|
|
||||||
associated_num=associated_info.size();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ii++;
|
|
||||||
}
|
|
||||||
associated_num=associated_info.size();
|
|
||||||
for (int ii=0;ii<associated_num;)
|
|
||||||
{
|
|
||||||
if(associated_info[ii].point_index==point_index)
|
|
||||||
{
|
|
||||||
associated_info.erase(associated_info.begin()+ii);
|
|
||||||
associated_num=associated_info.size();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ii++;
|
|
||||||
}
|
|
||||||
associated_num=associated_info.size();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(delta_T>0)
|
|
||||||
{
|
|
||||||
double X1_filter[6],X2_filter[6],X3_filter[6],P1_filter[6][6],P2_filter[6][6],P3_filter[6][6];
|
double X1_filter[6],X2_filter[6],X3_filter[6],P1_filter[6][6],P2_filter[6][6],P3_filter[6][6];
|
||||||
double S1[3][3] = {{0}},S2[3][3] = {{0}},S3[3][3] = {{0}};
|
double S1[3][3] = {{0}},S2[3][3] = {{0}},S3[3][3] = {{0}};
|
||||||
kalman Kalman;
|
kalman Kalman;
|
||||||
@@ -650,9 +598,9 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
for (int ii=0;ii<3;ii++)
|
for (int ii=0;ii<3;ii++)
|
||||||
for (int jj=0;jj<3;jj++)
|
for (int jj=0;jj<3;jj++)
|
||||||
{
|
{
|
||||||
S1_out(ii,jj)=S1[ii][jj];
|
S1_out(ii,jj)=static_cast<float>(S1[ii][jj]);
|
||||||
S2_out(ii,jj)=S2[ii][jj];
|
S2_out(ii,jj)=static_cast<float>(S2[ii][jj]);
|
||||||
S3_out(ii,jj)=S3[ii][jj];
|
S3_out(ii,jj)=static_cast<float>(S3[ii][jj]);
|
||||||
}
|
}
|
||||||
double det_S1=S1_out.determinant();
|
double det_S1=S1_out.determinant();
|
||||||
double Possibility1=(det_S1>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S1)*exp(-0.5*d1)):0.0;
|
double Possibility1=(det_S1>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S1)*exp(-0.5*d1)):0.0;
|
||||||
@@ -711,6 +659,8 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
(*trust_track)[track_index-1].Amplitude= point_process[point_index-1].Amplitude; //幅度
|
(*trust_track)[track_index-1].Amplitude= point_process[point_index-1].Amplitude; //幅度
|
||||||
|
|
||||||
(*trust_track)[track_index-1].RCS = point_process[point_index-1].RCS;
|
(*trust_track)[track_index-1].RCS = point_process[point_index-1].RCS;
|
||||||
|
(*trust_track)[track_index-1].amp_asv_point = point_process[point_index-1].amp_asv_point;
|
||||||
|
(*trust_track)[track_index-1].prn_fftn_point = point_process[point_index-1].prn_fftn_point;
|
||||||
|
|
||||||
(*trust_track)[track_index-1].pitch_num = point_process[point_index-1].pitch_num;
|
(*trust_track)[track_index-1].pitch_num = point_process[point_index-1].pitch_num;
|
||||||
|
|
||||||
@@ -720,10 +670,11 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
//更新高度
|
//更新高度
|
||||||
track_hight_update(track_index,point_index,trust_track);
|
track_hight_update(track_index,point_index,trust_track);
|
||||||
|
|
||||||
}
|
|
||||||
(*trust_track)[track_index-1].Extrapolate_round = 0; //连续未用实点更新时间
|
(*trust_track)[track_index-1].Extrapolate_round = 0; //连续未用实点更新时间
|
||||||
(*trust_track)[track_index-1].point_flag=1; //实点
|
(*trust_track)[track_index-1].point_flag=1; //实点
|
||||||
(*trust_track)[track_index-1].associate_point_number = (*trust_track)[track_index-1].associate_point_number+1; //关联点数+1
|
(*trust_track)[track_index-1].associate_point_number = (*trust_track)[track_index-1].associate_point_number+1; //关联点数+1
|
||||||
|
(*trust_track)[track_index-1].Track_Update_Flag = 1; //航迹更新标志
|
||||||
|
}
|
||||||
|
|
||||||
//删除associated_info中关联上的航迹 点迹信息
|
//删除associated_info中关联上的航迹 点迹信息
|
||||||
for (int ii=0;ii<associated_num;)
|
for (int ii=0;ii<associated_num;)
|
||||||
@@ -755,9 +706,12 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
}
|
}
|
||||||
|
|
||||||
//未关联上的航迹 进行外推 tws
|
//未关联上的航迹 进行外推 tws
|
||||||
for (int i =0; i<(*trust_track).size();i++ )
|
for (size_t i =0; i<(*trust_track).size();i++ )
|
||||||
{
|
{
|
||||||
if((*trust_track)[i].point_flag == 0 && (*trust_track)[i].manual_tracking_flag == 0)
|
if((*trust_track)[i].point_flag == 0 && (*trust_track)[i].manual_tracking_flag == 0) //未关联上点迹的航迹进行外推
|
||||||
|
{
|
||||||
|
//外推点数未到上限,则继续外推,否则不外推
|
||||||
|
if((*trust_track)[i].Extrapolate_round <= MAX_EXTRAPOLATE_NUM)
|
||||||
{
|
{
|
||||||
double v_track = sqrt(pow((*trust_track)[i].X[1],2)+pow((*trust_track)[i].X[4],2));
|
double v_track = sqrt(pow((*trust_track)[i].X[1],2)+pow((*trust_track)[i].X[4],2));
|
||||||
double delta_T;
|
double delta_T;
|
||||||
@@ -804,10 +758,16 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
memcpy((*trust_track)[i].P2,P2_pred,6*6*sizeof(double));
|
memcpy((*trust_track)[i].P2,P2_pred,6*6*sizeof(double));
|
||||||
memcpy((*trust_track)[i].P3,P3_pred,6*6*sizeof(double));
|
memcpy((*trust_track)[i].P3,P3_pred,6*6*sizeof(double));
|
||||||
|
|
||||||
(*trust_track)[i].T_track = (*trust_track)[i].T_track+delta_T*1000.0; //更新航迹时间
|
(*trust_track)[i].T_track = static_cast<long long>((*trust_track)[i].T_track+delta_T*1000.0); //更新航迹时间
|
||||||
(*trust_track)[i].GNSS_time = (*trust_track)[i].GNSS_time+delta_T*1000.0; //更新航迹时间
|
(*trust_track)[i].GNSS_time = static_cast<long long>((*trust_track)[i].GNSS_time+delta_T*1000.0); //更新航迹时间
|
||||||
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1; //连续未用实点更新时间
|
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1; //连续未用实点更新时间
|
||||||
(*trust_track)[i].point_flag=0; //虚点
|
(*trust_track)[i].point_flag=0; //虚点
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 1; //航迹更新标志
|
||||||
|
}else{
|
||||||
|
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1; //连续未用实点更新时间
|
||||||
|
(*trust_track)[i].point_flag=0; //虚点
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 0; //航迹更新标志
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +775,7 @@ void Track_Asso:: model_filter(std::vector <Trust_Track> *trust_track,struct Ra
|
|||||||
|
|
||||||
void Track_Asso:: model_output(std::vector <Trust_Track> *trust_track)
|
void Track_Asso:: model_output(std::vector <Trust_Track> *trust_track)
|
||||||
{
|
{
|
||||||
for(int loop_of_track=0; loop_of_track<trust_track->size(); loop_of_track++)
|
for(size_t loop_of_track=0; loop_of_track<trust_track->size(); loop_of_track++)
|
||||||
{
|
{
|
||||||
|
|
||||||
// if((*trust_track)[loop_of_track].manual_tracking_flag==0)
|
// if((*trust_track)[loop_of_track].manual_tracking_flag==0)
|
||||||
@@ -919,7 +879,7 @@ void Track_Asso:: track_hight_update(int updata_
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(updata_track_index<=trust_track->size() && asso_point_index<=point_process.size())
|
if(updata_track_index<=static_cast<int>(trust_track->size()) && asso_point_index<=static_cast<int>(point_process.size()))
|
||||||
{
|
{
|
||||||
|
|
||||||
(*trust_track)[updata_track_index-1].Hight_smooth.push_back(point_process[asso_point_index-1].Height);
|
(*trust_track)[updata_track_index-1].Hight_smooth.push_back(point_process[asso_point_index-1].Height);
|
||||||
@@ -944,10 +904,10 @@ void Track_Asso:: track_hight_update(int updata_
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sum=0;
|
double sum=0;
|
||||||
if((*trust_track)[updata_track_index-1].Hight_smooth.size()<height_win_length)
|
if((*trust_track)[updata_track_index-1].Hight_smooth.size()<static_cast<size_t>(height_win_length))
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i=0;i<(*trust_track)[updata_track_index-1].Hight_smooth.size();i++)
|
for (size_t i=0;i<(*trust_track)[updata_track_index-1].Hight_smooth.size();i++)
|
||||||
{
|
{
|
||||||
sum=sum+(*trust_track)[updata_track_index-1].Hight_smooth[i];
|
sum=sum+(*trust_track)[updata_track_index-1].Hight_smooth[i];
|
||||||
|
|
||||||
@@ -956,7 +916,7 @@ void Track_Asso:: track_hight_update(int updata_
|
|||||||
(*trust_track)[updata_track_index-1].Height=sum/(*trust_track)[updata_track_index-1].Hight_smooth.size();
|
(*trust_track)[updata_track_index-1].Height=sum/(*trust_track)[updata_track_index-1].Hight_smooth.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if((*trust_track)[updata_track_index-1].Hight_smooth.size()>=height_win_length)
|
else if((*trust_track)[updata_track_index-1].Hight_smooth.size()>=static_cast<size_t>(height_win_length))
|
||||||
{
|
{
|
||||||
|
|
||||||
int N=(*trust_track)[updata_track_index-1].Hight_smooth.size();
|
int N=(*trust_track)[updata_track_index-1].Hight_smooth.size();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_ASSO_H
|
#ifndef TRACK_ASSO_H
|
||||||
#define TRACK_ASSO_H
|
#define TRACK_ASSO_H
|
||||||
|
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "track_asso_direct_tracking.h"
|
#include "track_asso_direct_tracking.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -424,7 +424,7 @@ void Track_Asso_Direct_Tracking::model_filter(Trust_Track *trust_track,
|
|||||||
//未关联上,航迹外推
|
//未关联上,航迹外推
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double delta_T = DATA_RATE_TAS;
|
double delta_T = Work_Parameter.DATA_RATE_TAS/1000.0;
|
||||||
double F[6][6], Q1[6][6], Q2[6][6], Q3[6][6];
|
double F[6][6], Q1[6][6], Q2[6][6], Q3[6][6];
|
||||||
IMM_F_Q_gen( v_track, delta_T, F, Q1, Q2, Q3,Work_Parameter);
|
IMM_F_Q_gen( v_track, delta_T, F, Q1, Q2, Q3,Work_Parameter);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_ASSO_DIRECT_TRACKING_H
|
#ifndef TRACK_ASSO_DIRECT_TRACKING_H
|
||||||
#define TRACK_ASSO_DIRECT_TRACKING_H
|
#define TRACK_ASSO_DIRECT_TRACKING_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "track_asso_tas.h"
|
#include "track_asso_tas.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -20,7 +21,7 @@ long long latest_timestamp //最新时间戳
|
|||||||
{
|
{
|
||||||
|
|
||||||
//取出点迹
|
//取出点迹
|
||||||
for (int i=0;i< point_recv_tas->size();i++)
|
for (size_t i=0;i< point_recv_tas->size();i++)
|
||||||
{
|
{
|
||||||
point_process.push_back((*point_recv_tas)[i]);
|
point_process.push_back((*point_recv_tas)[i]);
|
||||||
}
|
}
|
||||||
@@ -36,10 +37,11 @@ long long latest_timestamp //最新时间戳
|
|||||||
std::vector<PointRecv>().swap(point_process);
|
std::vector<PointRecv>().swap(point_process);
|
||||||
|
|
||||||
//输出航迹
|
//输出航迹
|
||||||
for (int i=0;i<trust_track->size();i++)
|
for (size_t i=0;i<trust_track->size();i++)
|
||||||
{ // 输出更新航迹条件:
|
{ // 输出更新航迹条件:
|
||||||
if((*trust_track)[i].Track_Index == tas_track_idx)
|
if((*trust_track)[i].Track_Index == tas_track_idx && (*trust_track)[i].Track_Update_Flag == 1)
|
||||||
{
|
{
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 0; //航迹更新标志
|
||||||
*Trust_track_num_Output= *Trust_track_num_Output+1;
|
*Trust_track_num_Output= *Trust_track_num_Output+1;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Point_Sum=1;
|
||||||
@@ -49,43 +51,61 @@ long long latest_timestamp //最新时间戳
|
|||||||
coor_trans Coor_trans;
|
coor_trans Coor_trans;
|
||||||
double r, azi;
|
double r, azi;
|
||||||
Coor_trans.cart2polar(x, y, &r, &azi);
|
Coor_trans.cart2polar(x, y, &r, &azi);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=r;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range=static_cast<float>(r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Azimuth=static_cast<float>(azi/PI*180);
|
||||||
{
|
{
|
||||||
double elev_ratio = (r > 0.0) ? (*trust_track)[i].Height / r : 0.0;
|
double elev_ratio = (r > 0.0) ? (*trust_track)[i].Height / r : 0.0;
|
||||||
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
||||||
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = asin(elev_ratio)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Elevation = static_cast<float>(asin(elev_ratio)/PI*180);
|
||||||
}
|
}
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Index=(*trust_track)[i].Track_Index;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V =
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Range_V =
|
||||||
sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]);
|
static_cast<float>(sqrt((*trust_track)[i].X[1]*(*trust_track)[i].X[1]+(*trust_track)[i].X[4]*(*trust_track)[i].X[4]));
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude = (*trust_track)[i].Amplitude;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Amplitude = static_cast<float>((*trust_track)[i].Amplitude);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Track_Mode=(*trust_track)[i].Track_Mode;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_time=(*trust_track)[i].T_track/1000.0;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_time=static_cast<float>((*trust_track)[i].T_track/1000.0);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].GNSS_time=(*trust_track)[i].GNSS_time;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].GNSS_time=(*trust_track)[i].GNSS_time;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point = (*trust_track)[i].point_flag;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Point = (*trust_track)[i].point_flag;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].z=(*trust_track)[i].Height+Work_Parameter.Height;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].z=static_cast<float>((*trust_track)[i].Height+Work_Parameter.Height);
|
||||||
|
|
||||||
double Direction_Angle;
|
double Direction_Angle;
|
||||||
Direction_Angle=atan2((*trust_track)[i].X[4], (*trust_track)[i].X[1]);
|
Direction_Angle=atan2((*trust_track)[i].X[4], (*trust_track)[i].X[1]);
|
||||||
if(Direction_Angle<0){Direction_Angle=Direction_Angle+2*PI;}
|
if(Direction_Angle<0){Direction_Angle=Direction_Angle+2*PI;}
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].Direction_Angle=Direction_Angle/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Direction_Angle=static_cast<float>(Direction_Angle/PI*180);
|
||||||
|
|
||||||
//关联点信息
|
//关联点信息
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].range_point=(*trust_track)[i].range_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].range_point=static_cast<float>((*trust_track)[i].range_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].azi_point=(*trust_track)[i].azi_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].azi_point=static_cast<float>((*trust_track)[i].azi_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].elev_point=(*trust_track)[i].elev_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].elev_point=static_cast<float>((*trust_track)[i].elev_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point=(*trust_track)[i].vr_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point=static_cast<float>((*trust_track)[i].vr_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].point_type=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].point_type=1;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].prf_point = (*trust_track)[i].prf_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].prf_point = static_cast<float>((*trust_track)[i].prf_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = (*trust_track)[i].snr_point;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_snr = static_cast<float>((*trust_track)[i].snr_point);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].x=(*trust_track)[i].X[0];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].x=static_cast<float>((*trust_track)[i].X[0]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].y=(*trust_track)[i].X[3];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].y=static_cast<float>((*trust_track)[i].X[3]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].v_x=(*trust_track)[i].X[1];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].v_x=static_cast<float>((*trust_track)[i].X[1]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].v_y=(*trust_track)[i].X[4];
|
Trust_Track_Output[*Trust_track_num_Output-1][0].v_y=static_cast<float>((*trust_track)[i].X[4]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].track_rcs = (*trust_track)[i].RCS;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].track_rcs = static_cast<float>((*trust_track)[i].RCS);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][0].pitch_num = (*trust_track)[i].pitch_num;
|
Trust_Track_Output[*Trust_track_num_Output-1][0].pitch_num = (*trust_track)[i].pitch_num;
|
||||||
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=Trust_Track_Output[*Trust_track_num_Output-1][0].vr_point>0?1:0;
|
||||||
|
|
||||||
|
if(acos((-x * cos(Direction_Angle) - y * sin(Direction_Angle)) / r ) < PI / 2)
|
||||||
|
{
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=1;
|
||||||
|
// if(r*abs(sin(azi - Direction_Angle))<500)
|
||||||
|
// {
|
||||||
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=1;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trust_Track_Output[*Trust_track_num_Output-1][0].Flag_Direction=0;
|
||||||
|
}
|
||||||
|
|
||||||
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim, (*trust_track)[i].speed_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim));
|
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim, (*trust_track)[i].speed_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].speed_dim));
|
||||||
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim, (*trust_track)[i].range_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim));
|
std::memcpy(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim, (*trust_track)[i].range_dim, sizeof(Trust_Track_Output[*Trust_track_num_Output-1][0].range_dim));
|
||||||
@@ -101,7 +121,7 @@ long long latest_timestamp //最新时间戳
|
|||||||
void Track_Asso_Tas:: model_interaction( std::vector<Trust_Track> *trust_track, int tas_track_idx)
|
void Track_Asso_Tas:: model_interaction( std::vector<Trust_Track> *trust_track, int tas_track_idx)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
for (size_t loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if((*trust_track)[loop_of_track].Track_Index == tas_track_idx)
|
if((*trust_track)[loop_of_track].Track_Index == tas_track_idx)
|
||||||
@@ -238,17 +258,12 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
double r_track = 0;
|
double r_track = 0;
|
||||||
double h_track = 0;
|
double h_track = 0;
|
||||||
bool found_tas_track = false;
|
bool found_tas_track = false;
|
||||||
for (int loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
for (size_t loop_of_track=0;loop_of_track<trust_track->size();loop_of_track++)
|
||||||
{
|
{
|
||||||
if((*trust_track)[loop_of_track].Track_Index == tas_track_idx)
|
if((*trust_track)[loop_of_track].Track_Index == tas_track_idx)
|
||||||
{
|
{
|
||||||
found_tas_track = true;
|
found_tas_track = true;
|
||||||
|
|
||||||
// if(point_process.size()>0)
|
|
||||||
// {
|
|
||||||
// std::cout << "model_filter point_process :" <<point_process[0].Azimuth/PI*180<<" "<<point_process[0].Range;
|
|
||||||
// }
|
|
||||||
|
|
||||||
(*trust_track)[loop_of_track].point_flag = 0; //航迹的point_flag置为0 关联上点后再置为1
|
(*trust_track)[loop_of_track].point_flag = 0; //航迹的point_flag置为0 关联上点后再置为1
|
||||||
memcpy(X1,(*trust_track)[loop_of_track].X1,6*sizeof(double));
|
memcpy(X1,(*trust_track)[loop_of_track].X1,6*sizeof(double));
|
||||||
memcpy(X2,(*trust_track)[loop_of_track].X2,6*sizeof(double));
|
memcpy(X2,(*trust_track)[loop_of_track].X2,6*sizeof(double));
|
||||||
@@ -257,7 +272,7 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
memcpy(P2,(*trust_track)[loop_of_track].P2,6*6*sizeof(double));
|
memcpy(P2,(*trust_track)[loop_of_track].P2,6*6*sizeof(double));
|
||||||
memcpy(P3,(*trust_track)[loop_of_track].P3,6*6*sizeof(double));
|
memcpy(P3,(*trust_track)[loop_of_track].P3,6*6*sizeof(double));
|
||||||
|
|
||||||
T_track = (*trust_track)[loop_of_track].T_track;
|
T_track = static_cast<double>((*trust_track)[loop_of_track].T_track);
|
||||||
v_track = sqrt(pow((*trust_track)[loop_of_track].X[1],2)+pow((*trust_track)[loop_of_track].X[4],2));
|
v_track = sqrt(pow((*trust_track)[loop_of_track].X[1],2)+pow((*trust_track)[loop_of_track].X[4],2));
|
||||||
r_track = sqrt(pow((*trust_track)[loop_of_track].X[0],2)+pow((*trust_track)[loop_of_track].X[3],2));
|
r_track = sqrt(pow((*trust_track)[loop_of_track].X[0],2)+pow((*trust_track)[loop_of_track].X[3],2));
|
||||||
h_track = (*trust_track)[loop_of_track].Height;
|
h_track = (*trust_track)[loop_of_track].Height;
|
||||||
@@ -269,7 +284,7 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// 计算量测和航迹统计距离
|
// 计算量测和航迹统计距离
|
||||||
for (int loop_of_point = 0; loop_of_point<point_process.size();loop_of_point++)
|
for (size_t loop_of_point = 0; loop_of_point<point_process.size();loop_of_point++)
|
||||||
{
|
{
|
||||||
//量测信息
|
//量测信息
|
||||||
// double Z[2]={point_process[loop_of_point].Range*cos(point_process[loop_of_point].Azimuth),
|
// double Z[2]={point_process[loop_of_point].Range*cos(point_process[loop_of_point].Azimuth),
|
||||||
@@ -281,73 +296,39 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
double prt = point_process[loop_of_point].PRF_index;
|
double prt = point_process[loop_of_point].PRF_index;
|
||||||
double freq_ind = point_process[loop_of_point].Freq_index;
|
double freq_ind = point_process[loop_of_point].Freq_index;
|
||||||
double delta_T = (point_process[loop_of_point].CPI_Time - T_track)/1000.0;
|
double delta_T = (point_process[loop_of_point].CPI_Time - T_track)/1000.0;
|
||||||
if (delta_T <= 0)
|
if (delta_T <= 0){
|
||||||
|
RDP_LOG << "Warning: delta_T <= 0, skipping point association for point index " << point_process[loop_of_point].CPI_Time << " " << T_track << std::endl;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
double h_point = point_process[loop_of_point].Height;
|
double h_point = point_process[loop_of_point].Height;
|
||||||
|
|
||||||
//计算统计距离d
|
//计算统计距离d
|
||||||
double d1,d2,d3;
|
double d1,d2,d3;
|
||||||
IMM_d_cal(v_track,X1,P1,X2,P2, X3,P3,Z,prt,freq_ind,delta_T,&d1,&d2,&d3,Work_Parameter);
|
IMM_d_cal(v_track,X1,P1,X2,P2, X3,P3,Z,prt,freq_ind,delta_T,&d1,&d2,&d3,Work_Parameter);
|
||||||
|
|
||||||
//计算高度门限
|
//判定统计距离门限,thd_d
|
||||||
double d_h;
|
bool thd_d = false;
|
||||||
if (r_track<1000)
|
|
||||||
{
|
if(d1*d1<ASSO_THORD*ASSO_THORD || d2*d2<ASSO_THORD*ASSO_THORD || d3*d3<ASSO_THORD*ASSO_THORD){
|
||||||
if(abs(h_track-h_point)<=150)
|
thd_d = true;
|
||||||
{
|
|
||||||
d_h = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_h = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//判定高度门限,thd_h
|
||||||
else if (r_track<2000 && r_track>=1000)
|
bool thd_h = false;
|
||||||
{
|
double delta_h = abs(h_track-h_point);
|
||||||
if(abs(h_track-h_point)<=200)
|
|
||||||
{
|
|
||||||
d_h = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_h = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if( (r_track <= 1000 && delta_h <= 150) || \
|
||||||
|
((r_track > 1000 && r_track <= 2000) && delta_h <= 200) || \
|
||||||
|
((r_track > 2000 && r_track <= 3000) && delta_h <= 250) || \
|
||||||
|
((r_track > 3000 && r_track <= 5000) && delta_h <= 300) || \
|
||||||
|
r_track > 5000
|
||||||
|
){
|
||||||
|
thd_h = true;
|
||||||
}
|
}
|
||||||
else if(r_track>=2000 && r_track<3000 )
|
|
||||||
{
|
|
||||||
if(abs(h_track-h_point)<=200)
|
|
||||||
{
|
|
||||||
d_h = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_h = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(r_track>=3000 && r_track<5000)
|
|
||||||
{
|
|
||||||
if(abs(h_track-h_point)<=300)
|
|
||||||
{
|
|
||||||
d_h = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_h = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_h = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::cout << "T d" <<point_process[loop_of_point].CPI_Time/1000<<" "<<T_track/1000<<" "<<delta_T<<" "<<d1<<" "<<d2<<" "<<d3;
|
|
||||||
// std::cout << "h_track" <<h_track<<" h_point"<<h_point<<" d_h"<<d_h;
|
|
||||||
|
|
||||||
//小于关联门限 保存关联信息
|
//小于关联门限 保存关联信息
|
||||||
if((d1*d1<ASSO_THORD*ASSO_THORD || d2*d2<ASSO_THORD*ASSO_THORD || d3*d3<ASSO_THORD*ASSO_THORD)
|
if(thd_d && thd_h)
|
||||||
&& d_h == 1)//
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// std::cout << "TAS asoooooo111" ;
|
// std::cout << "TAS asoooooo111" ;
|
||||||
@@ -355,7 +336,7 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
associated_info_tmp.d1=d1;
|
associated_info_tmp.d1=d1;
|
||||||
associated_info_tmp.d2=d2;
|
associated_info_tmp.d2=d2;
|
||||||
associated_info_tmp.d3=d3;
|
associated_info_tmp.d3=d3;
|
||||||
associated_info_tmp.point_index=loop_of_point+1;
|
associated_info_tmp.point_index=static_cast<int>(loop_of_point)+1;
|
||||||
if(d1<=d2&&d1<=d3)
|
if(d1<=d2&&d1<=d3)
|
||||||
associated_info_tmp.d_min=d1;
|
associated_info_tmp.d_min=d1;
|
||||||
else if(d2<=d1&& d2<=d3)
|
else if(d2<=d1&& d2<=d3)
|
||||||
@@ -370,18 +351,18 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
//有关联 滤波
|
//有关联 滤波
|
||||||
if (associated_info.size()>0)
|
if (associated_info.size()>0)
|
||||||
{
|
{
|
||||||
|
//RDP_LOG << "associated point for track index " << tas_track_idx << std::endl;
|
||||||
// std::cout << "TAS asoooooo222" ;
|
// std::cout << "TAS asoooooo222" ;
|
||||||
|
|
||||||
//找最近点
|
//找最近点
|
||||||
int min_index=1;
|
int min_index=1;
|
||||||
double min_d=associated_info[0].d_min;
|
double min_d=associated_info[0].d_min;
|
||||||
for (int ii=0;ii<associated_info.size();ii++)
|
for (size_t ii=0;ii<associated_info.size();ii++)
|
||||||
{
|
{
|
||||||
if(associated_info[ii].d_min<min_d)
|
if(associated_info[ii].d_min<min_d)
|
||||||
{
|
{
|
||||||
min_d=associated_info[ii].d_min;
|
min_d=associated_info[ii].d_min;
|
||||||
min_index=ii+1;
|
min_index=static_cast<int>(ii)+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int point_index=associated_info[min_index-1].point_index;
|
int point_index=associated_info[min_index-1].point_index;
|
||||||
@@ -413,9 +394,9 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
for (int ii=0;ii<3;ii++)
|
for (int ii=0;ii<3;ii++)
|
||||||
for (int jj=0;jj<3;jj++)
|
for (int jj=0;jj<3;jj++)
|
||||||
{
|
{
|
||||||
S1_out(ii,jj)=S1[ii][jj];
|
S1_out(ii,jj)=static_cast<float>(S1[ii][jj]);
|
||||||
S2_out(ii,jj)=S2[ii][jj];
|
S2_out(ii,jj)=static_cast<float>(S2[ii][jj]);
|
||||||
S3_out(ii,jj)=S3[ii][jj];
|
S3_out(ii,jj)=static_cast<float>(S3[ii][jj]);
|
||||||
}
|
}
|
||||||
double det_S1=S1_out.determinant();
|
double det_S1=S1_out.determinant();
|
||||||
double Possibility1=(det_S1>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S1)*exp(-0.5*d1)):0.0;
|
double Possibility1=(det_S1>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S1)*exp(-0.5*d1)):0.0;
|
||||||
@@ -425,7 +406,7 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
double Possibility3=(det_S3>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S3)*exp(-0.5*d3)):0.0;
|
double Possibility3=(det_S3>1e-12)?(1.0/sqrt(pow(2*PI,3)*det_S3)*exp(-0.5*d3)):0.0;
|
||||||
|
|
||||||
//更新航迹
|
//更新航迹
|
||||||
for(int i=0;i<trust_track->size();i++)
|
for(size_t i=0;i<trust_track->size();i++)
|
||||||
|
|
||||||
if((*trust_track)[i].Track_Index == tas_track_idx)
|
if((*trust_track)[i].Track_Index == tas_track_idx)
|
||||||
{
|
{
|
||||||
@@ -481,6 +462,7 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
(*trust_track)[i].Amplitude= point_process[point_index-1].Amplitude; //幅度
|
(*trust_track)[i].Amplitude= point_process[point_index-1].Amplitude; //幅度
|
||||||
(*trust_track)[i].associate_point_number = (*trust_track)[i].associate_point_number+1; //关联点数+1
|
(*trust_track)[i].associate_point_number = (*trust_track)[i].associate_point_number+1; //关联点数+1
|
||||||
(*trust_track)[i].RCS = point_process[point_index-1].RCS;
|
(*trust_track)[i].RCS = point_process[point_index-1].RCS;
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 1; //航迹更新标志
|
||||||
|
|
||||||
(*trust_track)[i].pitch_num = point_process[point_index-1].pitch_num;
|
(*trust_track)[i].pitch_num = point_process[point_index-1].pitch_num;
|
||||||
|
|
||||||
@@ -495,9 +477,11 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
//未关联上,航迹外推
|
//未关联上,航迹外推
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//RDP_LOG << "unassociated point for track index " << tas_track_idx << std::endl;
|
||||||
for(int i=0;i<trust_track->size();i++)
|
for(size_t i=0;i<trust_track->size();i++){
|
||||||
if((*trust_track)[i].Track_Index == tas_track_idx)
|
if((*trust_track)[i].Track_Index == tas_track_idx)
|
||||||
|
{
|
||||||
|
if((*trust_track)[i].Extrapolate_round >= MAX_EXTRAPOLATE_NUM_TAS)
|
||||||
{
|
{
|
||||||
double delta_T = (latest_timestamp - T_track)/1000.0;
|
double delta_T = (latest_timestamp - T_track)/1000.0;
|
||||||
if (delta_T <= 0)
|
if (delta_T <= 0)
|
||||||
@@ -517,19 +501,25 @@ void Track_Asso_Tas::model_filter( std::vector<Trust_Track> *t
|
|||||||
memcpy((*trust_track)[i].P2,P2_pred,6*6*sizeof(double));
|
memcpy((*trust_track)[i].P2,P2_pred,6*6*sizeof(double));
|
||||||
memcpy((*trust_track)[i].P3,P3_pred,6*6*sizeof(double));
|
memcpy((*trust_track)[i].P3,P3_pred,6*6*sizeof(double));
|
||||||
|
|
||||||
(*trust_track)[i].T_track = (*trust_track)[i].T_track+delta_T*1000.0; //更新航迹时间
|
(*trust_track)[i].T_track = static_cast<long long>((*trust_track)[i].T_track+delta_T*1000.0); //更新航迹时间
|
||||||
(*trust_track)[i].GNSS_time = (*trust_track)[i].GNSS_time+delta_T*1000.0; //更新航迹时间
|
(*trust_track)[i].GNSS_time = static_cast<long long>((*trust_track)[i].GNSS_time+delta_T*1000.0); //更新航迹时间
|
||||||
(*trust_track)[i].point_flag=0; //虚点
|
(*trust_track)[i].point_flag=0; //虚点
|
||||||
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1;
|
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1;
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 1; //航迹更新标志
|
||||||
|
}else{
|
||||||
|
(*trust_track)[i].point_flag=0; //虚点
|
||||||
|
(*trust_track)[i].Extrapolate_round =(*trust_track)[i].Extrapolate_round+1;
|
||||||
|
(*trust_track)[i].Track_Update_Flag = 0; //航迹更新标志
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Track_Asso_Tas::model_output(std::vector<Trust_Track> *trust_track, int tas_track_idx )
|
void Track_Asso_Tas::model_output(std::vector<Trust_Track> *trust_track, int tas_track_idx )
|
||||||
{
|
{
|
||||||
for(int i=0; i<trust_track->size(); i++)
|
for(size_t i=0; i<trust_track->size(); i++)
|
||||||
if((*trust_track)[i].Track_Index==tas_track_idx)
|
if((*trust_track)[i].Track_Index==tas_track_idx)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -737,7 +727,7 @@ void Track_Asso_Tas::track_hight_update(int tas_
|
|||||||
std::vector<Trust_Track> *trust_track //航迹
|
std::vector<Trust_Track> *trust_track //航迹
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for(int i=0; i<trust_track->size(); i++)
|
for(size_t i=0; i<trust_track->size(); i++)
|
||||||
if((*trust_track)[i].Track_Index==tas_track_idx)
|
if((*trust_track)[i].Track_Index==tas_track_idx)
|
||||||
{
|
{
|
||||||
(*trust_track)[i].Hight_smooth.push_back(point_process[asso_point_index-1].Height);
|
(*trust_track)[i].Hight_smooth.push_back(point_process[asso_point_index-1].Height);
|
||||||
@@ -761,10 +751,10 @@ void Track_Asso_Tas::track_hight_update(int tas_
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sum=0;
|
double sum=0;
|
||||||
if((*trust_track)[i].Hight_smooth.size()<height_win_length)
|
if((*trust_track)[i].Hight_smooth.size()<static_cast<size_t>(height_win_length))
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int ii=0;ii<(*trust_track)[i].Hight_smooth.size();ii++)
|
for (size_t ii=0;ii<(*trust_track)[i].Hight_smooth.size();ii++)
|
||||||
{
|
{
|
||||||
sum=sum+(*trust_track)[i].Hight_smooth[ii];
|
sum=sum+(*trust_track)[i].Hight_smooth[ii];
|
||||||
|
|
||||||
@@ -773,7 +763,7 @@ void Track_Asso_Tas::track_hight_update(int tas_
|
|||||||
(*trust_track)[i].Height=sum/(*trust_track)[i].Hight_smooth.size();
|
(*trust_track)[i].Height=sum/(*trust_track)[i].Hight_smooth.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if((*trust_track)[i].Hight_smooth.size()>=height_win_length)
|
else if((*trust_track)[i].Hight_smooth.size()>=static_cast<size_t>(height_win_length))
|
||||||
{
|
{
|
||||||
|
|
||||||
int N=(*trust_track)[i].Hight_smooth.size();
|
int N=(*trust_track)[i].Hight_smooth.size();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_ASSO_TAS_H
|
#ifndef TRACK_ASSO_TAS_H
|
||||||
#define TRACK_ASSO_TAS_H
|
#define TRACK_ASSO_TAS_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "track_die.h"
|
#include "track_die.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -14,10 +14,24 @@ void Track_Die::track_die_process( std::vector <Trust_Track> *trust_track,
|
|||||||
std::vector <Trust_Track>::iterator Iter;
|
std::vector <Trust_Track>::iterator Iter;
|
||||||
for (Iter=trust_track->begin(); Iter!=trust_track->end();)
|
for (Iter=trust_track->begin(); Iter!=trust_track->end();)
|
||||||
{
|
{
|
||||||
if( ((*Iter).Track_Mode == 0 && (*Iter).Extrapolate_round >= TRACK_DIE_ROUND)
|
bool die_flag = false;
|
||||||
// ||((*Iter).Track_Mode == 1 && (*Iter).Extrapolate_round >= TRACK_DIE_ROUND_TAS)
|
|
||||||
||(*Iter).manual_delete_flag == 1)
|
|
||||||
|
|
||||||
|
if((*Iter).manual_delete_flag == 1)
|
||||||
|
{
|
||||||
|
die_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*Iter).Track_Mode == 0 && (*Iter).primary_target_flag == 0 && (*Iter).Extrapolate_round > TRACK_DIE_ROUND)
|
||||||
|
{
|
||||||
|
die_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*Iter).Track_Mode == 0 && (*Iter).primary_target_flag == 1 && (*Iter).Extrapolate_round > TRACK_DIE_ROUND_PRIMARY)
|
||||||
|
{
|
||||||
|
die_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(die_flag)
|
||||||
{
|
{
|
||||||
//输出消亡信息
|
//输出消亡信息
|
||||||
*Track_die_num_Output=*Track_die_num_Output+1;
|
*Track_die_num_Output=*Track_die_num_Output+1;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_DIE_H
|
#ifndef TRACK_DIE_H
|
||||||
#define TRACK_DIE_H
|
#define TRACK_DIE_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "track_die_tas.h"
|
#include "track_die_tas.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
|
#include "rdp_log.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -16,11 +17,21 @@ void Track_Die_Tas::track_die_process_tas( std::vector <Trust_Track> *trust_trac
|
|||||||
std::vector <Trust_Track>::iterator Iter;
|
std::vector <Trust_Track>::iterator Iter;
|
||||||
for (Iter=trust_track->begin(); Iter!=trust_track->end();)
|
for (Iter=trust_track->begin(); Iter!=trust_track->end();)
|
||||||
{
|
{
|
||||||
if( ((*Iter).Track_Mode == 1 && (*Iter).Extrapolate_round >= TRACK_DIE_ROUND_TAS)
|
bool die_flag = false;
|
||||||
||(*Iter).manual_delete_flag == 1)
|
|
||||||
|
|
||||||
|
if((*Iter).manual_delete_flag == 1)
|
||||||
{
|
{
|
||||||
std::cout << "remove tas target :" << (*Iter).Track_Index << std::endl;
|
die_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*Iter).Track_Mode == 1 && (*Iter).Extrapolate_round > TRACK_DIE_ROUND_TAS)
|
||||||
|
{
|
||||||
|
die_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(die_flag)
|
||||||
|
{
|
||||||
|
// RDP_LOG << "remove tas target :" << (*Iter).Track_Index << std::endl;
|
||||||
//输出消亡信息
|
//输出消亡信息
|
||||||
*Track_die_num_Output=*Track_die_num_Output+1;
|
*Track_die_num_Output=*Track_die_num_Output+1;
|
||||||
Track_die_Index_Output[*Track_die_num_Output-1]=(*Iter).Track_Index;
|
Track_die_Index_Output[*Track_die_num_Output-1]=(*Iter).Track_Index;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_DIE_TAS_H
|
#ifndef TRACK_DIE_TAS_H
|
||||||
#define TRACK_DIE_TAS_H
|
#define TRACK_DIE_TAS_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "track_index_mangement.h"
|
#include "track_index_mangement.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -30,7 +30,7 @@ int Track_Ind_Mangement ::track_ind_get( std::vector<Trust_Track> *trust_track
|
|||||||
{
|
{
|
||||||
//建立航迹号列表
|
//建立航迹号列表
|
||||||
int List[MAX_TRACK_INDEX]={0};
|
int List[MAX_TRACK_INDEX]={0};
|
||||||
for (int i=0;i<trust_track->size();i++)
|
for (size_t i=0;i<trust_track->size();i++)
|
||||||
{
|
{
|
||||||
int ti = (*trust_track)[i].Track_Index;
|
int ti = (*trust_track)[i].Track_Index;
|
||||||
if (ti >= 1 && ti <= MAX_TRACK_INDEX)
|
if (ti >= 1 && ti <= MAX_TRACK_INDEX)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_INDEX_MANGEMENT_H
|
#ifndef TRACK_INDEX_MANGEMENT_H
|
||||||
#define TRACK_INDEX_MANGEMENT_H
|
#define TRACK_INDEX_MANGEMENT_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "track_init.h"
|
#include "track_init.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -34,13 +34,13 @@ int Track_Init::track_init_process_logic( std::vector <PointRecv>
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
//取出待起航的点迹数据
|
//取出待起航的点迹数据
|
||||||
for (int i=0;i<(*point_recv).size();i++)
|
for (size_t i=0;i<(*point_recv).size();i++)
|
||||||
point_process.push_back((*point_recv)[i]);
|
point_process.push_back((*point_recv)[i]);
|
||||||
|
|
||||||
//临时航迹的buff_round+1
|
//临时航迹的buff_round+1
|
||||||
for (int i=0;i<temp_track->size();i++)
|
for (size_t i=0;i<temp_track->size();i++)
|
||||||
{
|
{
|
||||||
for (int j=0;j<(*temp_track)[i].size();j++)
|
for (size_t j=0;j<(*temp_track)[i].size();j++)
|
||||||
{
|
{
|
||||||
(*temp_track)[i][j].buff_round = (*temp_track)[i][j].buff_round+1;
|
(*temp_track)[i][j].buff_round = (*temp_track)[i][j].buff_round+1;
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ int Track_Init::track_init_process_logic( std::vector <PointRecv>
|
|||||||
|
|
||||||
//剩余点重新存入点迹
|
//剩余点重新存入点迹
|
||||||
std::vector<PointRecv>().swap((*point_recv));
|
std::vector<PointRecv>().swap((*point_recv));
|
||||||
for (int i=0;i<point_process.size();i++)
|
for (size_t i=0;i<point_process.size();i++)
|
||||||
(*point_recv).push_back(point_process[i]);
|
(*point_recv).push_back(point_process[i]);
|
||||||
|
|
||||||
//剩余点转为航迹头
|
//剩余点转为航迹头
|
||||||
@@ -155,9 +155,9 @@ void Track_Init::point_temp_track_asso(std::vector <std::vector<Temp_track>>
|
|||||||
};
|
};
|
||||||
std::vector <Asso_info> asso_info;
|
std::vector <Asso_info> asso_info;
|
||||||
|
|
||||||
for ( int i=0;i<point_process.size();i++)
|
for ( size_t i=0;i<point_process.size();i++)
|
||||||
{
|
{
|
||||||
for ( int j=0;j<(*temp_track).size();j++)
|
for ( size_t j=0;j<(*temp_track).size();j++)
|
||||||
{
|
{
|
||||||
int L = (*temp_track)[j].size();
|
int L = (*temp_track)[j].size();
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ void Track_Init::point_temp_track_asso(std::vector <std::vector<Temp_track>>
|
|||||||
double prt = point_process[i].PRF_index;
|
double prt = point_process[i].PRF_index;
|
||||||
double freq_ind = point_process[i].Freq_index;
|
double freq_ind = point_process[i].Freq_index;
|
||||||
double h_point = point_process[i].Height;
|
double h_point = point_process[i].Height;
|
||||||
double T_point = point_process[i].CPI_Time;
|
double T_point = static_cast<double>(point_process[i].CPI_Time);
|
||||||
|
|
||||||
//航迹信息
|
//航迹信息
|
||||||
double X[4];
|
double X[4];
|
||||||
@@ -184,7 +184,7 @@ void Track_Init::point_temp_track_asso(std::vector <std::vector<Temp_track>>
|
|||||||
double v_temp_track=(*temp_track)[j][L-1].vr;
|
double v_temp_track=(*temp_track)[j][L-1].vr;
|
||||||
double r_temp_track=(*temp_track)[j][L-1].r;
|
double r_temp_track=(*temp_track)[j][L-1].r;
|
||||||
double h_temp_track=(*temp_track)[j][L-1].height;
|
double h_temp_track=(*temp_track)[j][L-1].height;
|
||||||
double T_track_head = (*temp_track)[j][L-1].T;
|
double T_track_head = static_cast<double>((*temp_track)[j][L-1].T);
|
||||||
|
|
||||||
double delta_T = (T_point - T_track_head)/1000.0;
|
double delta_T = (T_point - T_track_head)/1000.0;
|
||||||
|
|
||||||
@@ -221,8 +221,8 @@ void Track_Init::point_temp_track_asso(std::vector <std::vector<Temp_track>>
|
|||||||
if(d*d<=TRACK_START_THRESHOLD*TRACK_START_THRESHOLD && alpha<ALPHA_START && vr_point*v_temp_track>0)// && fabs(h_point-h_temp_track )<= r_point*SIGMA_E&& abs(vr_point-v_temp_track)/abs(v_temp_track)<0.8
|
if(d*d<=TRACK_START_THRESHOLD*TRACK_START_THRESHOLD && alpha<ALPHA_START && vr_point*v_temp_track>0)// && fabs(h_point-h_temp_track )<= r_point*SIGMA_E&& abs(vr_point-v_temp_track)/abs(v_temp_track)<0.8
|
||||||
{
|
{
|
||||||
struct Asso_info asso_info_tmp;
|
struct Asso_info asso_info_tmp;
|
||||||
asso_info_tmp.point_idx = i+1;
|
asso_info_tmp.point_idx = static_cast<int>(i)+1;
|
||||||
asso_info_tmp.track_idx = j+1;
|
asso_info_tmp.track_idx = static_cast<int>(j)+1;
|
||||||
asso_info_tmp.d = d;
|
asso_info_tmp.d = d;
|
||||||
asso_info.push_back(asso_info_tmp);
|
asso_info.push_back(asso_info_tmp);
|
||||||
(*temp_track)[j][L-1].asso_flag = 1;
|
(*temp_track)[j][L-1].asso_flag = 1;
|
||||||
@@ -235,7 +235,7 @@ void Track_Init::point_temp_track_asso(std::vector <std::vector<Temp_track>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// temp_track中加入新关联上的临时航迹
|
// temp_track中加入新关联上的临时航迹
|
||||||
for (int i = 0 ; i<asso_info.size();i++ )
|
for (size_t i = 0 ; i<asso_info.size();i++ )
|
||||||
{
|
{
|
||||||
(*temp_track).push_back(std::vector <Temp_track> ());
|
(*temp_track).push_back(std::vector <Temp_track> ());
|
||||||
|
|
||||||
@@ -316,10 +316,10 @@ void Track_Init::point_track_head_asso( std::vector <std::vector<Temp_track>>
|
|||||||
std::vector <Asso_info> asso_info;
|
std::vector <Asso_info> asso_info;
|
||||||
|
|
||||||
//关联
|
//关联
|
||||||
for ( int i=0;i<point_process.size();i++)
|
for ( size_t i=0;i<point_process.size();i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
for ( int j=0;j<temp_track->size();j++)
|
for ( size_t j=0;j<temp_track->size();j++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if((*temp_track)[j].size()==1 && (*temp_track)[j][0].buff_round >= 2)
|
if((*temp_track)[j].size()==1 && (*temp_track)[j][0].buff_round >= 2)
|
||||||
@@ -332,7 +332,7 @@ void Track_Init::point_track_head_asso( std::vector <std::vector<Temp_track>>
|
|||||||
vr_point=point_process[i].Velocity;
|
vr_point=point_process[i].Velocity;
|
||||||
double r_point=point_process[i].Range;
|
double r_point=point_process[i].Range;
|
||||||
double h_point = point_process[i].Height;
|
double h_point = point_process[i].Height;
|
||||||
double T_point = point_process[i].CPI_Time;
|
double T_point = static_cast<double>(point_process[i].CPI_Time);
|
||||||
|
|
||||||
//航迹信息
|
//航迹信息
|
||||||
double x_track_head, y_track_head;
|
double x_track_head, y_track_head;
|
||||||
@@ -340,30 +340,7 @@ void Track_Init::point_track_head_asso( std::vector <std::vector<Temp_track>>
|
|||||||
y_track_head=(*temp_track)[j][0].X[2];
|
y_track_head=(*temp_track)[j][0].X[2];
|
||||||
double v_track_head=(*temp_track)[j][0].vr;
|
double v_track_head=(*temp_track)[j][0].vr;
|
||||||
double h_track_head = (*temp_track)[j][0].height;
|
double h_track_head = (*temp_track)[j][0].height;
|
||||||
double T_track_head = (*temp_track)[j][0].T;
|
double T_track_head = static_cast<double>((*temp_track)[j][0].T);
|
||||||
|
|
||||||
// if(T_track_head == 30675948)
|
|
||||||
// {
|
|
||||||
// std::cout << "r_point=" << r_point
|
|
||||||
// << "h_point=" << h_point
|
|
||||||
// << "T_point=" << T_point
|
|
||||||
// << "x_track_head=" << x_track_head
|
|
||||||
// << "y_track_head=" << y_track_head
|
|
||||||
// << "v_track_head=" << v_track_head
|
|
||||||
// << "T_track_head=" << T_track_head;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(T_point == 30682320)
|
|
||||||
// {
|
|
||||||
// std::cout <<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
|
||||||
// std::cout << "r_point=" << r_point
|
|
||||||
// << "h_point=" << h_point
|
|
||||||
// << "T_point=" << T_point
|
|
||||||
// << "x_track_head=" << x_track_head
|
|
||||||
// << "y_track_head=" << y_track_head
|
|
||||||
// << "v_track_head=" << v_track_head
|
|
||||||
// << "T_track_head=" << T_track_head;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//距离差
|
//距离差
|
||||||
double dis = sqrt(pow(x_point-x_track_head,2)+pow(y_point-y_track_head,2));
|
double dis = sqrt(pow(x_point-x_track_head,2)+pow(y_point-y_track_head,2));
|
||||||
@@ -380,30 +357,23 @@ void Track_Init::point_track_head_asso( std::vector <std::vector<Temp_track>>
|
|||||||
|
|
||||||
double delta_T = (T_point - T_track_head)/1000.0;
|
double delta_T = (T_point - T_track_head)/1000.0;
|
||||||
|
|
||||||
//满足关联条件的点航
|
|
||||||
// if( ( (r_point>=1000 && dis<=vmax*delta_T && dis>=V_MIN*delta_T) || (r_point<1000 && dis<=vmax*delta_T/2.0 && dis>=V_MIN*delta_T/2.0) )
|
// if(
|
||||||
// && vr_point*v_track_head>0 )//&& fabs(vr_point-v_track_head)/fabs(v_track_head)<0.2 && fabs(h_point-h_track_head)<=r_point*SIGMA_E
|
// ( (Work_Parameter.work_mode == 0&&( (r_point>=1000 && dis<=vmax*delta_T && dis>=Work_Parameter.V_MIN*delta_T) || (r_point<1000 && dis<=vmax*delta_T/2.0 && dis>=Work_Parameter.V_MIN*delta_T/2.0) ))
|
||||||
if(
|
// || (Work_Parameter.work_mode != 0&&( (r_point>=2000 && dis<=vmax*delta_T && dis>=Work_Parameter.V_MIN*delta_T) || (r_point<2000 && dis<=vmax*delta_T/3.0 && dis>=Work_Parameter.V_MIN*delta_T/2.0) ))
|
||||||
( (Work_Parameter.work_mode == 0&&( (r_point>=1000 && dis<=vmax*delta_T && dis>=Work_Parameter.V_MIN*delta_T) || (r_point<1000 && dis<=vmax*delta_T/2.0 && dis>=Work_Parameter.V_MIN*delta_T/2.0) ))
|
// )
|
||||||
|| (Work_Parameter.work_mode != 0&&( (r_point>=2000 && dis<=vmax*delta_T && dis>=Work_Parameter.V_MIN*delta_T) || (r_point<2000 && dis<=vmax*delta_T/3.0 && dis>=Work_Parameter.V_MIN*delta_T/2.0) ))
|
// && vr_point*v_track_head>0 )
|
||||||
|
|
||||||
|
//点航关联条件
|
||||||
|
if( dis <= vmax* delta_T && dis >= Work_Parameter.V_MIN * delta_T && \
|
||||||
|
vr_point*v_track_head>0 && \
|
||||||
|
dis >= abs(vr_point) * delta_T && \
|
||||||
|
dis >= abs(v_track_head) * delta_T
|
||||||
)
|
)
|
||||||
&& vr_point*v_track_head>0 )
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// if(T_track_head == 30675948)
|
|
||||||
// {
|
|
||||||
// std::cout << "r_point=" << r_point
|
|
||||||
// << "h_point=" << h_point
|
|
||||||
// << "T_point=" << T_point
|
|
||||||
// << "x_track_head=" << x_track_head
|
|
||||||
// << "y_track_head=" << y_track_head
|
|
||||||
// << "v_track_head=" << v_track_head
|
|
||||||
// << "T_track_head=" << T_track_head;
|
|
||||||
// }
|
|
||||||
|
|
||||||
struct Asso_info asso_info_tmp;
|
struct Asso_info asso_info_tmp;
|
||||||
asso_info_tmp.point_idx = i+1;
|
asso_info_tmp.point_idx = static_cast<int>(i)+1;
|
||||||
asso_info_tmp.track_idx = j+1;
|
asso_info_tmp.track_idx = static_cast<int>(j)+1;
|
||||||
asso_info.push_back(asso_info_tmp);
|
asso_info.push_back(asso_info_tmp);
|
||||||
(*temp_track)[j][0].asso_flag = 1;
|
(*temp_track)[j][0].asso_flag = 1;
|
||||||
point_process[i].Use_Flag = 1;
|
point_process[i].Use_Flag = 1;
|
||||||
@@ -415,7 +385,7 @@ void Track_Init::point_track_head_asso( std::vector <std::vector<Temp_track>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// temp_track中加入新关联上的临时航迹
|
// temp_track中加入新关联上的临时航迹
|
||||||
for (int i = 0 ; i<asso_info.size();i++ )
|
for (size_t i = 0 ; i<asso_info.size();i++ )
|
||||||
{
|
{
|
||||||
(*temp_track).push_back(std::vector <Temp_track> ());
|
(*temp_track).push_back(std::vector <Temp_track> ());
|
||||||
|
|
||||||
@@ -646,19 +616,19 @@ void Track_Init::tmp_track_to_trust_track(std::vector<Trust_Track> *trust_tra
|
|||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Index=index;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Index=index;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Point_Sum=L;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Point_Sum=L;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Range=Track_to_start[i][j].r;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Range=static_cast<float>(Track_to_start[i][j].r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Azimuth=Track_to_start[i][j].azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Azimuth=static_cast<float>(Track_to_start[i][j].azi/PI*180);
|
||||||
{
|
{
|
||||||
double elev_ratio = (Track_to_start[i][j].r > 0.0) ? Track_to_start[i][j].height / Track_to_start[i][j].r : 0.0;
|
double elev_ratio = (Track_to_start[i][j].r > 0.0) ? Track_to_start[i][j].height / Track_to_start[i][j].r : 0.0;
|
||||||
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
||||||
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Elevation=asin(elev_ratio)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Elevation=static_cast<float>(asin(elev_ratio)/PI*180);
|
||||||
}
|
}
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Range_V=sqrt(pow(Track_to_start[i][j].X[1],2)+pow(Track_to_start[i][j].X[3],2));
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Range_V=static_cast<float>(sqrt(pow(Track_to_start[i][j].X[1],2)+pow(Track_to_start[i][j].X[3],2)));
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].z=Track_to_start[i][j].height;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].z=static_cast<float>(Track_to_start[i][j].height);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Amplitude=Track_to_start[i][j].Amp;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Amplitude=static_cast<float>(Track_to_start[i][j].Amp);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_snr = Track_to_start[i][j].snr;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_snr = static_cast<float>(Track_to_start[i][j].snr);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_rcs = Track_to_start[i][j].RCS;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_rcs = static_cast<float>(Track_to_start[i][j].RCS);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].pitch_num = Track_to_start[i][j].pitch_num;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].pitch_num = Track_to_start[i][j].pitch_num;
|
||||||
|
|
||||||
@@ -668,25 +638,25 @@ void Track_Init::tmp_track_to_trust_track(std::vector<Trust_Track> *trust_tra
|
|||||||
Direction_Angle=atan2(Track_to_start[i][j].X[3],Track_to_start[i][j].X[1]);
|
Direction_Angle=atan2(Track_to_start[i][j].X[3],Track_to_start[i][j].X[1]);
|
||||||
if(Direction_Angle<0)
|
if(Direction_Angle<0)
|
||||||
Direction_Angle=Direction_Angle+2*PI;
|
Direction_Angle=Direction_Angle+2*PI;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Direction_Angle=Direction_Angle/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Direction_Angle=static_cast<float>(Direction_Angle/PI*180);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_time=(Track_to_start[i][j].T)/1000.0;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_time=static_cast<float>((Track_to_start[i][j].T)/1000.0);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].GNSS_time=Track_to_start[i][j].GNSS_time;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].GNSS_time=Track_to_start[i][j].GNSS_time;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].x=Track_to_start[i][j].X[0];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].x=static_cast<float>(Track_to_start[i][j].X[0]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].v_x=Track_to_start[i][j].X[1];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].v_x=static_cast<float>(Track_to_start[i][j].X[1]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].y=Track_to_start[i][j].X[2];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].y=static_cast<float>(Track_to_start[i][j].X[2]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].v_y=Track_to_start[i][j].X[3];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].v_y=static_cast<float>(Track_to_start[i][j].X[3]);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].range_point=Track_to_start[i][j].r;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].range_point=static_cast<float>(Track_to_start[i][j].r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].azi_point=Track_to_start[i][j].azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].azi_point=static_cast<float>(Track_to_start[i][j].azi/PI*180);
|
||||||
{
|
{
|
||||||
double elev_ratio = (Track_to_start[i][j].r > 0.0) ? Track_to_start[i][j].height / Track_to_start[i][j].r : 0.0;
|
double elev_ratio = (Track_to_start[i][j].r > 0.0) ? Track_to_start[i][j].height / Track_to_start[i][j].r : 0.0;
|
||||||
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
if (elev_ratio > 1.0) elev_ratio = 1.0;
|
||||||
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
if (elev_ratio < -1.0) elev_ratio = -1.0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].elev_point=asin(elev_ratio)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].elev_point=static_cast<float>(asin(elev_ratio)/PI*180);
|
||||||
}
|
}
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].vr_point=Track_to_start[i][j].vr;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].vr_point=static_cast<float>(Track_to_start[i][j].vr);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].point_type=0;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].point_type=0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Flag_Point=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Flag_Point=1;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Mode=0;//跟踪模式 TWS 0
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Mode=0;//跟踪模式 TWS 0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_INIT_H
|
#ifndef TRACK_INIT_H
|
||||||
#define TRACK_INIT_H
|
#define TRACK_INIT_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "track_index_mangement.h"
|
#include "track_index_mangement.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "track_init_direct_tracking.h"
|
#include "track_init_direct_tracking.h"
|
||||||
#include "kalman.h"
|
#include "kalman.h"
|
||||||
#include "coor_trans.h"
|
#include "coor_trans.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -33,9 +33,9 @@ void Track_Init_Direct_Tracking::point_temp_track_asso(std::vector <std::vector<
|
|||||||
};
|
};
|
||||||
std::vector <Asso_info> asso_info;
|
std::vector <Asso_info> asso_info;
|
||||||
|
|
||||||
for ( int i=0;i<point_process.size();i++)
|
for ( size_t i=0;i<point_process.size();i++)
|
||||||
{
|
{
|
||||||
for ( int j=0;j<(*temp_track).size();j++)
|
for ( size_t j=0;j<(*temp_track).size();j++)
|
||||||
{
|
{
|
||||||
int L = (*temp_track)[j].size();
|
int L = (*temp_track)[j].size();
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ void Track_Init_Direct_Tracking::point_temp_track_asso(std::vector <std::vector<
|
|||||||
double prt = point_process[i].PRF_index;
|
double prt = point_process[i].PRF_index;
|
||||||
double freq_ind = point_process[i].Freq_index;
|
double freq_ind = point_process[i].Freq_index;
|
||||||
double h_point = point_process[i].Height;
|
double h_point = point_process[i].Height;
|
||||||
double T_point = point_process[i].CPI_Time;
|
double T_point = static_cast<double>(point_process[i].CPI_Time);
|
||||||
|
|
||||||
//航迹信息
|
//航迹信息
|
||||||
double X[4];
|
double X[4];
|
||||||
@@ -62,7 +62,7 @@ void Track_Init_Direct_Tracking::point_temp_track_asso(std::vector <std::vector<
|
|||||||
double v_temp_track=(*temp_track)[j][L-1].vr;
|
double v_temp_track=(*temp_track)[j][L-1].vr;
|
||||||
double r_temp_track=(*temp_track)[j][L-1].r;
|
double r_temp_track=(*temp_track)[j][L-1].r;
|
||||||
double h_temp_track=(*temp_track)[j][L-1].height;
|
double h_temp_track=(*temp_track)[j][L-1].height;
|
||||||
double T_track_head = (*temp_track)[j][L-1].T;
|
double T_track_head = static_cast<double>((*temp_track)[j][L-1].T);
|
||||||
|
|
||||||
double delta_T = (T_point - T_track_head)/1000.0;
|
double delta_T = (T_point - T_track_head)/1000.0;
|
||||||
|
|
||||||
@@ -85,8 +85,8 @@ void Track_Init_Direct_Tracking::point_temp_track_asso(std::vector <std::vector<
|
|||||||
if(d*d<=TRACK_START_THRESHOLD*TRACK_START_THRESHOLD && alpha<ALPHA_START && vr_point*v_temp_track>0)// && fabs(h_point-h_temp_track )<= r_point*SIGMA_E&& abs(vr_point-v_temp_track)/abs(v_temp_track)<0.8
|
if(d*d<=TRACK_START_THRESHOLD*TRACK_START_THRESHOLD && alpha<ALPHA_START && vr_point*v_temp_track>0)// && fabs(h_point-h_temp_track )<= r_point*SIGMA_E&& abs(vr_point-v_temp_track)/abs(v_temp_track)<0.8
|
||||||
{
|
{
|
||||||
struct Asso_info asso_info_tmp;
|
struct Asso_info asso_info_tmp;
|
||||||
asso_info_tmp.point_idx = i+1;
|
asso_info_tmp.point_idx = static_cast<int>(i)+1;
|
||||||
asso_info_tmp.track_idx = j+1;
|
asso_info_tmp.track_idx = static_cast<int>(j)+1;
|
||||||
asso_info.push_back(asso_info_tmp);
|
asso_info.push_back(asso_info_tmp);
|
||||||
(*temp_track)[j][L-1].asso_flag = 1;
|
(*temp_track)[j][L-1].asso_flag = 1;
|
||||||
point_process[i].Use_Flag = 1;
|
point_process[i].Use_Flag = 1;
|
||||||
@@ -97,7 +97,7 @@ void Track_Init_Direct_Tracking::point_temp_track_asso(std::vector <std::vector<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// temp_track中加入新关联上的临时航迹
|
// temp_track中加入新关联上的临时航迹
|
||||||
for (int i = 0 ; i<asso_info.size();i++ )
|
for (size_t i = 0 ; i<asso_info.size();i++ )
|
||||||
{
|
{
|
||||||
(*temp_track).push_back(std::vector <Temp_track> ());
|
(*temp_track).push_back(std::vector <Temp_track> ());
|
||||||
|
|
||||||
@@ -175,10 +175,10 @@ void Track_Init_Direct_Tracking::point_track_head_asso( std::vector <std::vector
|
|||||||
std::vector <Asso_info> asso_info;
|
std::vector <Asso_info> asso_info;
|
||||||
|
|
||||||
//关联
|
//关联
|
||||||
for ( int i=0;i<point_process.size();i++)
|
for ( size_t i=0;i<point_process.size();i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
for ( int j=0;j<temp_track->size();j++)
|
for ( size_t j=0;j<temp_track->size();j++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if((*temp_track)[j].size()==1 && (*temp_track)[j][0].buff_round >= 2)
|
if((*temp_track)[j].size()==1 && (*temp_track)[j][0].buff_round >= 2)
|
||||||
@@ -191,7 +191,7 @@ void Track_Init_Direct_Tracking::point_track_head_asso( std::vector <std::vector
|
|||||||
vr_point=point_process[i].Velocity;
|
vr_point=point_process[i].Velocity;
|
||||||
double r_point=point_process[i].Range;
|
double r_point=point_process[i].Range;
|
||||||
double h_point = point_process[i].Height;
|
double h_point = point_process[i].Height;
|
||||||
double T_point = point_process[i].CPI_Time;
|
double T_point = static_cast<double>(point_process[i].CPI_Time);
|
||||||
|
|
||||||
//航迹信息
|
//航迹信息
|
||||||
double x_track_head, y_track_head;
|
double x_track_head, y_track_head;
|
||||||
@@ -199,7 +199,7 @@ void Track_Init_Direct_Tracking::point_track_head_asso( std::vector <std::vector
|
|||||||
y_track_head=(*temp_track)[j][0].X[2];
|
y_track_head=(*temp_track)[j][0].X[2];
|
||||||
double v_track_head=(*temp_track)[j][0].vr;
|
double v_track_head=(*temp_track)[j][0].vr;
|
||||||
double h_track_head = (*temp_track)[j][0].height;
|
double h_track_head = (*temp_track)[j][0].height;
|
||||||
double T_track_head = (*temp_track)[j][0].T;
|
double T_track_head = static_cast<double>((*temp_track)[j][0].T);
|
||||||
|
|
||||||
//距离差
|
//距离差
|
||||||
double dis = sqrt(pow(x_point-x_track_head,2)+pow(y_point-y_track_head,2));
|
double dis = sqrt(pow(x_point-x_track_head,2)+pow(y_point-y_track_head,2));
|
||||||
@@ -225,8 +225,8 @@ void Track_Init_Direct_Tracking::point_track_head_asso( std::vector <std::vector
|
|||||||
&& vr_point*v_track_head>0 )//&& fabs(vr_point-v_track_head)/fabs(v_track_head)<0.2 && fabs(h_point-h_track_head)<=r_point*SIGMA_E
|
&& vr_point*v_track_head>0 )//&& fabs(vr_point-v_track_head)/fabs(v_track_head)<0.2 && fabs(h_point-h_track_head)<=r_point*SIGMA_E
|
||||||
{
|
{
|
||||||
struct Asso_info asso_info_tmp;
|
struct Asso_info asso_info_tmp;
|
||||||
asso_info_tmp.point_idx = i+1;
|
asso_info_tmp.point_idx = static_cast<int>(i)+1;
|
||||||
asso_info_tmp.track_idx = j+1;
|
asso_info_tmp.track_idx = static_cast<int>(j)+1;
|
||||||
asso_info.push_back(asso_info_tmp);
|
asso_info.push_back(asso_info_tmp);
|
||||||
(*temp_track)[j][0].asso_flag = 1;
|
(*temp_track)[j][0].asso_flag = 1;
|
||||||
point_process[i].Use_Flag = 1;
|
point_process[i].Use_Flag = 1;
|
||||||
@@ -237,7 +237,7 @@ void Track_Init_Direct_Tracking::point_track_head_asso( std::vector <std::vector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// temp_track中加入新关联上的临时航迹
|
// temp_track中加入新关联上的临时航迹
|
||||||
for (int i = 0 ; i<asso_info.size();i++ )
|
for (size_t i = 0 ; i<asso_info.size();i++ )
|
||||||
{
|
{
|
||||||
(*temp_track).push_back(std::vector <Temp_track> ());
|
(*temp_track).push_back(std::vector <Temp_track> ());
|
||||||
|
|
||||||
@@ -370,29 +370,29 @@ void Track_Init_Direct_Tracking::tmp_track_to_trust_track( std::vector<Trust_Tr
|
|||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Index=track_ID;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Index=track_ID;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Point_Sum=L;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Point_Sum=L;
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Range=(*Iter)[j].r;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Range=static_cast<float>((*Iter)[j].r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Azimuth=(*Iter)[j].azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Azimuth=static_cast<float>((*Iter)[j].azi/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Elevation=asin((*Iter)[j].height/(*Iter)[j].r)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Elevation=static_cast<float>(asin((*Iter)[j].height/(*Iter)[j].r)/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Range_V=sqrt(pow((*Iter)[j].X[1],2)+pow((*Iter)[j].X[3],2));
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Range_V=static_cast<float>(sqrt(pow((*Iter)[j].X[1],2)+pow((*Iter)[j].X[3],2)));
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].z=(*Iter)[j].height;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].z=static_cast<float>((*Iter)[j].height);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Amplitude=(*Iter)[j].Amp;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Amplitude=static_cast<float>((*Iter)[j].Amp);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_snr = (*Iter)[j].snr;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_snr = static_cast<float>((*Iter)[j].snr);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_rcs = (*Iter)[j].RCS;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_rcs = static_cast<float>((*Iter)[j].RCS);
|
||||||
double Direction_Angle;
|
double Direction_Angle;
|
||||||
Direction_Angle=atan2((*Iter)[j].X[3],(*Iter)[j].X[1]);
|
Direction_Angle=atan2((*Iter)[j].X[3],(*Iter)[j].X[1]);
|
||||||
if(Direction_Angle<0)
|
if(Direction_Angle<0)
|
||||||
Direction_Angle=Direction_Angle+2*PI;
|
Direction_Angle=Direction_Angle+2*PI;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Direction_Angle=Direction_Angle/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Direction_Angle=static_cast<float>(Direction_Angle/PI*180);
|
||||||
|
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].track_time=((*Iter)[j].T)/1000.0;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].track_time=static_cast<float>(((*Iter)[j].T)/1000.0);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].x=(*Iter)[j].X[0];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].x=static_cast<float>((*Iter)[j].X[0]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].v_x=(*Iter)[j].X[1];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].v_x=static_cast<float>((*Iter)[j].X[1]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].y=(*Iter)[j].X[2];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].y=static_cast<float>((*Iter)[j].X[2]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].v_y=(*Iter)[j].X[3];
|
Trust_Track_Output[*Trust_track_num_Output-1][j].v_y=static_cast<float>((*Iter)[j].X[3]);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].range_point=(*Iter)[j].r;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].range_point=static_cast<float>((*Iter)[j].r);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].azi_point=(*Iter)[j].azi/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].azi_point=static_cast<float>((*Iter)[j].azi/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].elev_point=asin((*Iter)[j].height/(*Iter)[j].r)/PI*180;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].elev_point=static_cast<float>(asin((*Iter)[j].height/(*Iter)[j].r)/PI*180);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].vr_point=(*Iter)[j].vr;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].vr_point=static_cast<float>((*Iter)[j].vr);
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].point_type=0;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].point_type=0;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Flag_Point=1;
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Flag_Point=1;
|
||||||
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Mode=1;//跟踪模式 TWS 0
|
Trust_Track_Output[*Trust_track_num_Output-1][j].Track_Mode=1;//跟踪模式 TWS 0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef TRACK_INIT_DIRECT_TRACKING_H
|
#ifndef TRACK_INIT_DIRECT_TRACKING_H
|
||||||
#define TRACK_INIT_DIRECT_TRACKING_H
|
#define TRACK_INIT_DIRECT_TRACKING_H
|
||||||
#include "data_process_class_dll.h"
|
#include "data_process_class_dll.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|||||||
@@ -0,0 +1,590 @@
|
|||||||
|
# 雷达数据处理流程与关键逻辑说明
|
||||||
|
|
||||||
|
> 适用对象:本仓库 `data_process_class_dll`(X256 雷达数据处理动态链接库)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. 一页速览
|
||||||
|
|
||||||
|
| 环节 | 输入 | 处理 | 输出 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| ① 前处理 | 一帧原始点迹(TWS 或 TAS) | 单位换算、缓存、判圈 | 处理模式码 0/1/2/3 |
|
||||||
|
| ② 调度 | 模式码 | 分流到 TWS / TAS 通道 | — |
|
||||||
|
| ③ 凝聚 | 单 CPI 或相邻两 CPI 点迹 | 同类点合并(保幅度大者) | 凝聚点迹表 |
|
||||||
|
| ④ 关联 | 凝聚点迹 + 已有航迹 | IMM 交互 → 波门筛选 → 最近邻一对一 → EKF 更新 | 更新航迹 + 剩余点迹 |
|
||||||
|
| ⑤ 起始 | 剩余(未关联)点迹 | 逻辑法(每圈顺序固定):点 × ≥2 点临时航迹关联 → 点 × 1 点航迹头关联 → 剩余点转新航迹头 → 达标临时航迹起批 | 新可靠航迹 + 更新后的临时航迹表 |
|
||||||
|
| ⑥ 外推/消亡 | 未关联航迹 | 按数据率预测一帧;超限则消亡 | 补点航迹 / 消亡批号 |
|
||||||
|
| ⑦ 波束控制 | TAS 队列 + 航迹 | 数据率门控 + 队列调度 → 位置外推 | 跟踪波束指令 |
|
||||||
|
|
||||||
|
**贯穿全流程的三条主线**
|
||||||
|
|
||||||
|
1. **时间主线**:所有时间戳为 64 位毫秒(CPI/GNSS),参与运算时除 1000 转秒;ΔT = 点迹时间 − 航迹时间,ΔT 的正负决定"有效更新 / 只消费不更新 / 跳过"。
|
||||||
|
2. **状态主线**:每条可靠航迹维护一套 IMM(3 个 Singer 模型)状态 [x, vx, ax, y, vy, ay],x/y 两轴解耦,量测为「距离-方位-径向速度」三维 EKF。
|
||||||
|
3. **生命周期主线**:可靠航迹靠"外推轮数"消亡;临时航迹靠"缓存圈数 buff_round"消亡。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 总体数据流
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
IN["宿主逐波位/逐CPI送入 DataRev[150]"] --> DP["data_preprocess 前处理与判圈"]
|
||||||
|
DP -->|"model=2 TWS未满圈"| M2["滑窗凝聚(只凝聚,不关联)"]
|
||||||
|
DP -->|"model=1 TWS满一圈"| M1["TWS 通道"]
|
||||||
|
DP -->|"model=3 TAS数据"| M3["TAS 通道"]
|
||||||
|
|
||||||
|
M2 --> BUF["本帧凝聚结果留作下一圈缓存"]
|
||||||
|
M2 --> PR["上一帧凝聚点 → point_recv(参与下一圈关联)"]
|
||||||
|
|
||||||
|
M1 --> A1["IMM 交互 + 波门筛选 + 最近邻关联 + EKF 更新"]
|
||||||
|
A1 --> A2["未关联航迹外推 / 超限消亡"]
|
||||||
|
A2 --> A3["剩余点迹 → 逻辑法起始:点×临时航迹 → 点×航迹头 → 剩余点转航迹头 → 起批"]
|
||||||
|
A3 --> OUT1["输出更新航迹 + 起批航迹历史点 + 消亡批号"]
|
||||||
|
|
||||||
|
M3 --> B1["TAS 凝聚(单帧)"]
|
||||||
|
B1 --> B2["仅对指定批号航迹做关联/EKF 或外推"]
|
||||||
|
B2 --> B3["TAS 超时消亡"]
|
||||||
|
B3 --> OUT2["输出该批号航迹"]
|
||||||
|
|
||||||
|
OUT1 --> BC["Beam_Ctrl 波束控制"]
|
||||||
|
OUT2 --> BC
|
||||||
|
BC --> OUT3["TrackingBeam:距离/方位/俯仰/批号"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 入口前处理与"判圈"
|
||||||
|
|
||||||
|
### 2.1 前处理动作
|
||||||
|
|
||||||
|
对每一个输入点迹统一做下面几件事(TWS 与 TAS 相同):
|
||||||
|
|
||||||
|
| 动作 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| 单位换算 | 方位 度 → 弧度(内部统一弧度,输出再转度) |
|
||||||
|
| 高度折算 | `Height = Range · sin(Elevation)`(由量测俯仰直接折算,不经坐标滤波) |
|
||||||
|
| 字段搬运 | 幅度、SNR、RCS、时间戳、频点号、PRI、俯仰波位、十字星数据(`speed_dim[129]`/`range_dim[8]`)全部透传 |
|
||||||
|
| 使用标记 | 全部置 0(未使用) |
|
||||||
|
| 数量保护 | TWS:`min(Point_Sum, 150)`;TAS:`clamp(Point_Sum, 0, 150)` |
|
||||||
|
| 全局时间 | 每次调用都用本帧首点的 CPI 时间刷新"最新时间戳",供 TAS 外推/波束使用 |
|
||||||
|
|
||||||
|
### 2.2 判圈逻辑(决定走哪条通道)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["收到一帧点迹"] --> B{"point_type ?"}
|
||||||
|
B -->|"0 = TWS"| C["写入 TWS 缓存"]
|
||||||
|
C --> D{"方位波位号 Beam_index_aiz == 0 ?"}
|
||||||
|
D -->|"是"| E["return 1:满一圈,执行 TWS 航迹处理"]
|
||||||
|
D -->|"否"| F["return 2:未满圈,仅做滑窗凝聚"]
|
||||||
|
B -->|"1 = TAS"| G["写入 TAS 缓存<br/>记录 TAS 批号与本帧时间戳"]
|
||||||
|
G --> H["return 3:TAS 处理"]
|
||||||
|
B -->|"其它"| I["return 0:无效数据,丢弃"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**要点**
|
||||||
|
|
||||||
|
- 判圈条件由"波位号由大变小"改为 **波位号为 0**(7d5a56f),避免机扫转台反转时误判一圈完成(代码中保留了旧判断的注释)。
|
||||||
|
- 波位号 0 是每圈的起始波位,因此**每圈恰好触发一次 model=1**。
|
||||||
|
- 清空(`track_clear_all`)后圈状态复位,下一次调用必然判为"满一圈"。
|
||||||
|
- TAS 数据不参与判圈,**每来一帧就处理一次**(TAS 是调度的跟踪波位,本身就是单目标 CPI)。
|
||||||
|
|
||||||
|
### 2.3 调度:model 与动作的对应
|
||||||
|
|
||||||
|
| model | 触发 | 实际执行的动作(顺序固定) |
|
||||||
|
|---|---|---|
|
||||||
|
| 2 | TWS 未满圈 | 两帧滑窗凝聚;缓存本帧点迹 |
|
||||||
|
| 1 | TWS 满一圈 | ① 关联/滤波/外推 ② 航迹消亡 ③ 航迹起始 |
|
||||||
|
| 3 | TAS 帧 | ① TAS 凝聚 ② TAS 关联/外推 ③ TAS 消亡 |
|
||||||
|
| 0 | 非法类型 | 无 |
|
||||||
|
|
||||||
|
> 顺序很关键:**消散在起始之前**,消亡腾出的资源不会与本圈更新冲突;**起始在最后**,只有"没被任何可靠航迹用掉"的点迹才有资格起批。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 点迹凝聚
|
||||||
|
|
||||||
|
### 3.1 目的与判据
|
||||||
|
|
||||||
|
同一目标在相邻波位/相邻 CPI 上会分裂成多个点,需先合并(保留幅度最大者,其余标记删除)。
|
||||||
|
|
||||||
|
| 模式 | 距离门限 | 方位门限 | 速度门限 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 近程 `work_mode==0` | ≤ 80 m | ≤ 6°(按环绕最小角差) | ≤ 2 m/s |
|
||||||
|
| 中/远程 `work_mode!=0` | ≤ 80 m | ≤ 6° | 不约束 |
|
||||||
|
|
||||||
|
方位差按环绕处理:
|
||||||
|
|
||||||
|
```
|
||||||
|
Δθ = min( |θ0 − θ1| , 2π − |θ0 − θ1| )
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 合并规则(链式比较)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["两两比较点迹 (0, i)"] --> B{"距离/方位/速度<br/>均在门限内?"}
|
||||||
|
B -- 否 --> Z["跳过"]
|
||||||
|
B -- 是 --> C{"幅度:点0 < 点i ?"}
|
||||||
|
C -- 是 --> D["点0 标记删除<br/>并把点i 的 R/方位/V/幅度<br/>接管为当前基准值"]
|
||||||
|
C -- 否 --> E["点i 标记删除"]
|
||||||
|
D --> F["后续比较以幅度更大者为基准(链式凝聚)"]
|
||||||
|
E --> F
|
||||||
|
F --> G["统一删除:被标记点 + 量程外点<br/>r < 100 m 或 r > 100000 m"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 TWS 两帧滑窗(关键机制)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["上一帧缓存点(区号=1)"] --> C["合并成同一张表"]
|
||||||
|
B["本帧新点(区号=2)"] --> C
|
||||||
|
C --> D["整表凝聚 + 量程过滤"]
|
||||||
|
D --> E{"点的区号"}
|
||||||
|
E -->|"1(较早的点)"| F["输出到 point_recv<br/>→ 本圈参与关联/起始"]
|
||||||
|
E -->|"2(本帧的点)"| G["留在缓存中<br/>→ 与下一帧合并后再输出"]
|
||||||
|
F --> H["缓存清空,本帧剩余点成为新缓存"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**为什么这样设计**
|
||||||
|
|
||||||
|
- 相邻两个 CPI 的同一目标点会落在不同帧里,单帧凝聚无法合并 → 延迟一帧输出,换取跨 CPI 的分裂点合并;
|
||||||
|
- 代价是关联/起始用的是"上一帧"的点,时间上滞后一圈,但由于后续所有 ΔT 都按真实 CPI 时间戳计算,滤波本身不受影响;
|
||||||
|
- 因此 TWS 通道的正常节奏是:**未满圈 model=2 只做凝聚 + 缓存;满圈 model=1 用上一帧凝聚结果做关联与起始**。
|
||||||
|
|
||||||
|
> TAS 凝聚为**单帧**不缓存,门限恒为「距离 ≤ 80 m、方位 ≤ 6°、速度 ≤ 2 m/s」,之后同样做量程过滤。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. TWS 点航关联与滤波(model=1 的核心)
|
||||||
|
|
||||||
|
### 4.1 处理骨架
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["全部可靠航迹"] --> A1["IMM 交互(mix)"]
|
||||||
|
A1 --> B["滤波前先统一置 point_flag=0(本圈默认未关联实点)"]
|
||||||
|
B --> C["逐航迹 × 逐点:算 ΔT、三个模型马氏距离 d1/d2/d3"]
|
||||||
|
C --> D{"波门判定<br/>统计距离波门 thd_d + 高度门限 thd_h + 距离门限 thd_r"}
|
||||||
|
D -- 通过 --> E["记入候选表(含 d_min = min(d1,d2,d3))"]
|
||||||
|
D -- 不通过 --> F["丢弃该候选对"]
|
||||||
|
E --> G["最近邻:反复取全表 d_min 最小者"]
|
||||||
|
G --> H["该航迹本圈候选全部移除<br/>该点迹候选全部移除<br/>(一对一)"]
|
||||||
|
H --> I{"ΔT > 0 ?"}
|
||||||
|
I -- 是 --> J["三模型 EKF 更新 → 模型概率更新 → 融合输出<br/>更新航迹时间/点信息/高度平滑<br/>Extrapolate_round=0, point_flag=1"]
|
||||||
|
I -- 否 --> K["不更新状态、不刷新航迹时间<br/>但把该点迹标记为已使用(消费掉)"]
|
||||||
|
J --> L{"还有候选?"}
|
||||||
|
K --> L
|
||||||
|
L -- 有 --> G
|
||||||
|
L -- 无 --> M["未关联航迹(point_flag==0 且非手动TAS)按数据率外推"]
|
||||||
|
M --> N["输出全部航迹(更新行 + 补点行)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 波门(统计距离、高度、距离三类都通过才算候选)
|
||||||
|
|
||||||
|
**(1)统计距离波门 thd_d**——按航迹距离分段收紧高机动模型(`ASSO_THORD = 4`):
|
||||||
|
|
||||||
|
| 航迹距离 r_track | 模型 1 / 2 | 模型 3 |
|
||||||
|
|---|---|---|
|
||||||
|
| ≤ 500 m | d² < 16 | d² < 16/1000(≈ 关闭,抑制近程高机动模型的乱关联) |
|
||||||
|
| 500 ~ 1000 m | d² < 16 | d² < 16/100(收紧) |
|
||||||
|
| ≥ 1000 m | d² < 16 | d² < 16 |
|
||||||
|
|
||||||
|
> ⚠ **门限语义**:代码里 d 已经是马氏距离平方,判据又写作 `d*d < ASSO_THORD*ASSO_THORD`,`ASSO_THORD = 4` 时等效于 **d < 4**(而非 √d < 4)。调整 ASSO_THORD 时务必记住这一层"二次方"(该行为在 BUG-20 中被识别,有意保留)。
|
||||||
|
|
||||||
|
**(2)高度门限 thd_h**(e0bf227 起在 TWS 侧生效)——|h_track − h_point| 按航迹距离分段:
|
||||||
|
|
||||||
|
| 航迹距离 r_track | 高度差门限 |
|
||||||
|
|---|---|
|
||||||
|
| ≤ 1000 m | 150 m |
|
||||||
|
| 1000 ~ 2000 m | 200 m |
|
||||||
|
| 2000 ~ 3000 m | 250 m |
|
||||||
|
| 3000 ~ 5000 m | 300 m |
|
||||||
|
| > 5000 m | 不约束 |
|
||||||
|
|
||||||
|
> 该门限此前在 `track_asso.cpp` 中整块被注释、`d_h` 恒为 1(等于不生效),现改为独立布尔量 `thd_h` 参与判定,取值与 TAS 通道一致,用于压制俯仰测量跳变引起的错误关联。
|
||||||
|
|
||||||
|
**(3)距离门限 thd_r**——抑制远距离突跳。用航迹-点迹弦距 R 与航迹位移 VT = v_track·ΔT 判断:
|
||||||
|
|
||||||
|
```
|
||||||
|
VT < 100 且 R > 300 → 拒绝(慢速目标不允许 300 m 以上的跳变)
|
||||||
|
100 ≤ VT ≤ 300 且 R/VT > 3 → 拒绝(允许的跳变与速度位移成比例)
|
||||||
|
VT > 300 且 R > 1200 → 拒绝(高速目标给固定 1200 m 上限)
|
||||||
|
```
|
||||||
|
|
||||||
|
**(4)俯仰门限 d_p**:分距离段 7°/5°/10° 的逻辑仍被注释停用,不参与判定(其作用已由高度门限覆盖)。
|
||||||
|
|
||||||
|
> 实现要点:三类判据分别算成 `thd_d` / `thd_h` / `thd_r` 三个布尔量,最后以 `thd_d && thd_h && thd_r` 决定是否记入候选表(e0bf227 起;此前三者混写在一个长 `if` 条件里)。
|
||||||
|
|
||||||
|
### 4.3 最近邻(NN)选取规则
|
||||||
|
|
||||||
|
- 候选对按 `d_min = min(d1, d2, d3)` 排序,**每轮取全表最小值**;
|
||||||
|
- 选中后,候选表中"该航迹的全部候选"和"该点迹的全部候选"一并删除 → **每条航迹每圈最多关联一个点,每个点最多被一条航迹使用**;
|
||||||
|
- 直到候选表为空或遍历完航迹数。
|
||||||
|
|
||||||
|
### 4.4 ΔT ≤ 0 的特殊处理(当前行为)
|
||||||
|
|
||||||
|
ΔT = (点迹 CPI 时间 − 航迹 T_track)/1000 ≤ 0,典型场景是"航迹刚被 TAS 点迹更新过,本圈 TWS 点迹时间更早"或"重复时间戳"。
|
||||||
|
|
||||||
|
| 环节 | 行为 |
|
||||||
|
|---|---|
|
||||||
|
| 是否参与最近邻比较 | **参与**(仍可能与最小 d 一起被选中) |
|
||||||
|
| IMM/EKF 更新 | **不执行**,X1/X2/X3、P1/P2/P3、模型概率均保持原值 |
|
||||||
|
| 航迹时间/点信息 | **不刷新**(T_track、GNSS_time、关联点信息、幅度/SNR/RCS 都不变) |
|
||||||
|
| 新鲜度标志 | `point_flag` 保持 0、`Extrapolate_round` 不归零、`associate_point_number` 不递增 |
|
||||||
|
| 本圈后续 | 该航迹本圈不再关联其它点迹;由于 point_flag 仍为 0,**在随后的外推环节被推进一帧** |
|
||||||
|
| 点迹归属 | 该点迹被标记"已使用"消费掉 → **不会再进入航迹起始**,避免生成虚假 TWS 航迹 |
|
||||||
|
|
||||||
|
### 4.5 关联成功后的更新内容
|
||||||
|
|
||||||
|
1. 三个模型的 EKF 状态/协方差更新;
|
||||||
|
2. 模型概率按新息协方差似然更新(见第 5 节);
|
||||||
|
3. 航迹时间 T_track / GNSS 时间跟进到该点迹;
|
||||||
|
4. 关联点信息(距离/方位/俯仰/径向速度/PRI)、幅度、SNR、RCS、俯仰波位、十字星数据刷新;
|
||||||
|
5. **高度维平滑**(见 4.6);
|
||||||
|
6. `Extrapolate_round = 0`、`point_flag = 1`、`associate_point_number += 1`。
|
||||||
|
|
||||||
|
### 4.6 高度平滑
|
||||||
|
|
||||||
|
关联实点后把点迹高度压入滑窗,输出高度取最近 w 个点的均值(不足 w 个则全平均):
|
||||||
|
|
||||||
|
| 点迹距离 | 窗口长度 w |
|
||||||
|
|---|---|
|
||||||
|
| ≤ 1000 m | 5 |
|
||||||
|
| 1000 ~ 2000 m | 6 |
|
||||||
|
| 2000 ~ 4000 m | 7 |
|
||||||
|
| > 4000 m | 9 |
|
||||||
|
|
||||||
|
> 距离越远俯仰测量跳变越大,窗口随之放长;仅 TWS/TAS 关联到实点时才刷新,外推补点不改变高度。
|
||||||
|
|
||||||
|
### 4.7 未关联航迹的外推
|
||||||
|
|
||||||
|
对 `point_flag == 0` 且 `manual_tracking_flag == 0` 的航迹(含 ΔT≤0 被消费的情形):
|
||||||
|
|
||||||
|
- 推算步长取运行时数据率:`work_mode` 0/1/2 → `DATA_RATE_SHORT / MIDDLE / FAR`(秒);
|
||||||
|
- 用各子模型的 Singer F、Q 推进一帧(**不做量测更新**);
|
||||||
|
- `T_track`、`GNSS_time` 各推进 ΔT×1000 毫秒;
|
||||||
|
- `Extrapolate_round += 1`,`point_flag = 0`(输出为补点/虚点)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 航迹起始(逻辑法)
|
||||||
|
|
||||||
|
### 5.1 状态机(每圈按 ①→⑤ 的固定顺序执行)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["本圈未被可靠航迹关联的点迹"] --> A0["临时航迹所有点的 buff_round +1"]
|
||||||
|
A0 --> B["① 点 × ≥2 点临时航迹关联(三点及以上)<br/>EKF 统计距离 + 折角 + 多普勒同号<br/>命中 → 复制原航迹 + 追加新点"]
|
||||||
|
B --> C["② 点 × 1 点航迹头关联(两点起始)<br/>速度区间 + 多普勒一致性<br/>命中 → 两点卡尔曼初始化 → 2 点临时航迹"]
|
||||||
|
C --> D["③ 删除 Use_Flag==1 的点迹<br/>剩余点全部转成新航迹头(1 点,buff_round=1)<br/>当圈不再参与关联"]
|
||||||
|
D --> E{"④ 长度 ≥ 起批点数<br/>且 ≤10 且不在起批屏蔽区?"}
|
||||||
|
E -- 是 --> F["同源去重(保留末点 d 更小者)"]
|
||||||
|
F --> G["三点卡尔曼初始化 → 分配航迹号 1~500<br/>IMM 三模型同状态,u=1/3"]
|
||||||
|
G --> H["输出该航迹的历史点(前 N 个点)"]
|
||||||
|
E -- 否 --> I["留在临时航迹表,下一圈继续关联"]
|
||||||
|
H --> J["⑤ 临时航迹消亡(不对外输出)<br/>末点 buff_round > 2 或 长度 ≥ 10"]
|
||||||
|
I --> J
|
||||||
|
```
|
||||||
|
|
||||||
|
**每圈顺序不可颠倒(`track_init.cpp` L49-126)**:点迹**先**做点-临时航迹关联(延长已有 ≥2 点临时航迹),**再**做点-航迹头关联(产生新的 2 点临时航迹),两阶段都结束后才把未被消费的点迹转成新航迹头,最后才把长度达标的临时航迹转可靠航迹,消亡放在最末。由此可得:
|
||||||
|
|
||||||
|
- 当圈新建的 2 点临时航迹**不可能当圈起批**——长度不足,且新点 `buff_round=1` 要到下一圈才具备关联资格;
|
||||||
|
- 当圈刚被延长到达标长度的临时航迹**可以当圈起批**(第 ④ 步在第 ① 步之后执行);
|
||||||
|
- 两个关联阶段**互不排斥**:都只把命中的点迹标记 `Use_Flag=1`,航迹头阶段不检查临时航迹阶段留下的标记,因此同一点迹可同时延长一条临时航迹、又开启一条 2 点临时航迹,只有走完两阶段后才统一删除被标记的点迹。
|
||||||
|
|
||||||
|
> 第 ⑤ 步的消亡判据对**未起批**的临时航迹生效;已起批的航迹在第 ④ 步中已从临时航迹表移除。
|
||||||
|
|
||||||
|
### 5.2 关联判据汇总
|
||||||
|
|
||||||
|
每圈按 **① 点-临时航迹关联 → ② 点-航迹头关联** 的顺序依次执行,两阶段的关联判据如下。
|
||||||
|
|
||||||
|
**阶段①:点 ↔ ≥2 点临时航迹(三点及以上)**
|
||||||
|
|
||||||
|
```
|
||||||
|
|r_point − r_末点| ≥ 5 m 距离差硬门限(近距点不参与)
|
||||||
|
d ≤ 8(代码写作 d² ≤ TRACK_START_THRESHOLD²=64) 3 维 EKF 统计距离波门
|
||||||
|
α < ALPHA_START = 60° 折角:最近三点连线夹角
|
||||||
|
v_r,point · v_r,末点 > 0 多普勒同号
|
||||||
|
```
|
||||||
|
|
||||||
|
- d 由 4 维 CV 状态一步预测 + 「距离-方位-径向速度」EKF 得到(过程噪声 0.03²、同样做方位环绕与盲速折叠);
|
||||||
|
- 折角 α 为向量 D12(前一点→末点)与 D23(末点→新点)的夹角;α 越小越接近直线;
|
||||||
|
- 门限同样写作 `d² ≤ TRACK_START_THRESHOLD²`,而 d 本身已是马氏距离平方,实际生效为 d ≤ 8(与可靠航迹关联门限的语义一致)。
|
||||||
|
|
||||||
|
**阶段②:点 ↔ 航迹头(两点起始)**
|
||||||
|
|
||||||
|
用航迹头位置与点迹的平面距离 `dis` 与 ΔT(秒):
|
||||||
|
|
||||||
|
```
|
||||||
|
dis ≤ V_MAX · ΔT 平均速度不超上限
|
||||||
|
dis ≥ V_MIN · ΔT 平均速度不低于下限(滤除静止/慢速杂波)
|
||||||
|
v_r,point · v_r,head > 0 两点多普勒同号(同接近/同远离)
|
||||||
|
dis ≥ |v_r,point| · ΔT 几何位移不小于"点迹自身多普勒"位移
|
||||||
|
dis ≥ |v_r,head| · ΔT 同上,用航迹头的多普勒约束
|
||||||
|
```
|
||||||
|
|
||||||
|
- 后两条是**多普勒-几何一致性**约束,用于剔除"切向高速短航迹"(7d5a56f 新增):切向飞行时真实几何位移大而多普勒径向速度小,纯速度区间门限会放进虚假航迹;
|
||||||
|
- 判据隐含要求 ΔT > 0(ΔT ≤ 0 时 `dis ≤ V_MAX·ΔT` 必然不成立);
|
||||||
|
- 近程/中远程分支当前取值相同(都是 V_MAX),**实际不做距离分段**。
|
||||||
|
|
||||||
|
### 5.3 临时航迹的"圈数"生命周期
|
||||||
|
|
||||||
|
`buff_round` 只在起始流程里自增,并且**每次调用(= 每圈)先把所有临时航迹所有点的 buff_round +1,再做关联**;因此关联判据看到的是自增后的圈数,当圈刚建立/刚追加的点(buff_round=1)当圈不可能再被关联:
|
||||||
|
|
||||||
|
| 动作 | 效果 |
|
||||||
|
|---|---|
|
||||||
|
| 新点加入 | buff_round = 1 |
|
||||||
|
| 关联资格 | 只看**末点**,要求 buff_round ≥ 2 → **上一圈加入的点本圈才能被延续**;同一圈内一条临时航迹可被多个点同时延续(每个点各复制出一条新航迹,见 6.4),并非一对一 |
|
||||||
|
| 消亡条件 | 末点 buff_round > 2(连续 2 圈无新点)或长度 ≥ 10 |
|
||||||
|
|
||||||
|
**时间轴示例(以第 k 圈加入新点为起点)**
|
||||||
|
|
||||||
|
```
|
||||||
|
第 k 圈:新点加入 → 末点 buff_round=1(本圈不再关联)
|
||||||
|
第 k+1 圈:+1 → 2 → 允许关联;成功则新点 1,失败则 2(不 >2,存活)
|
||||||
|
第 k+2 圈:+1 → 3 → 仍允许关联;成功则新点 1,失败则 3>2 → 消亡
|
||||||
|
```
|
||||||
|
|
||||||
|
即:**允许中间空 1 圈**,最大关联间隔 2 圈;生命周期完全由"圈数"驱动,与绝对时间无关。
|
||||||
|
|
||||||
|
### 5.4 航迹分裂与去重
|
||||||
|
|
||||||
|
- 关联阶段**不做一对一分配**:一个点满足多条临时航迹条件时,每条都各自复制出一条新航迹;多个点命中同一条临时航迹时也各自复制;点-航迹头阶段同理(一个航迹头可与多个点各生成一条 2 点临时航迹)→ 同一圈会产生大量同源临时航迹;
|
||||||
|
- 两个关联阶段也**互不排斥**:点-航迹头阶段不检查点-临时航迹阶段留下的 `Use_Flag`,同一点迹可同时参与两边的分裂试探;
|
||||||
|
- 起批前做**同源去重**:比较两条候选航迹的**前三个点**,只要有任一点的"时间 T + 距离 r"完全相同即判为同源,保留末点统计距离 d 更小者;
|
||||||
|
- 这样既保证不漏关联(允许分裂试探),又不会让同一批点重复起批。
|
||||||
|
|
||||||
|
### 5.5 起批与输出
|
||||||
|
|
||||||
|
| 条件 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| 长度 | `track_start_point_num ≤ L ≤ 10`(接口层校验 3~9,典型 3 或 4) |
|
||||||
|
| 位置 | 末点不落在**起批屏蔽区**(距离-方位矩形,最多 30 个,用严格不等号判断) |
|
||||||
|
| 容量 | 可靠航迹数 < 500 且能分配到一个未占用航迹号 |
|
||||||
|
| 初始化 | 用**最后三个点**做三点卡尔曼初始化 → 6 维状态;三模型同状态、u=1/3 |
|
||||||
|
| 输出 | 该航迹的**前 N 个点**(N = 起批点数)作为历史点一次性输出,每条航迹最多 10 个历史点 |
|
||||||
|
|
||||||
|
> 达到长度即当圈起批,没有"连续 M 圈确认"的环节;若被屏蔽区拦住,航迹会继续在临时航迹表里增长,直到离开屏蔽区(此时长度已大于起批点数)或长度达到 10 被判消亡。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 外推、消亡与航迹号管理
|
||||||
|
|
||||||
|
### 6.1 消亡条件
|
||||||
|
|
||||||
|
| 通道 | 条件(满足其一即消亡) |
|
||||||
|
|---|---|
|
||||||
|
| TWS 航迹 | `Track_Mode==0` 且 `Extrapolate_round ≥ 4` |
|
||||||
|
| TAS 航迹 | `Track_Mode==1` 且 `Extrapolate_round ≥ TRACK_DIE_ROUND_TAS`(相扫 5 / 机扫 96) |
|
||||||
|
| 手动删除 | `manual_delete_flag == 1`(两种通道通用,由外部删除接口置位) |
|
||||||
|
|
||||||
|
消亡时把批号写入消亡输出数组并从航迹表删除;**临时航迹消亡不对外输出**(起批失败的中间态对宿主不可见)。
|
||||||
|
|
||||||
|
### 6.2 航迹号分配
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["需要起批"] --> B{"航迹表为空?"}
|
||||||
|
B -- 是 --> C["分配 1"]
|
||||||
|
B -- 否 --> D["用航迹表建立 1~500 占用位图"]
|
||||||
|
D --> E["从 lastest_index+1 向上找第一个空闲号(含 500)"]
|
||||||
|
E --> F{"找到?"}
|
||||||
|
F -- 是 --> G["分配并更新 lastest_index"]
|
||||||
|
F -- 否 --> H["从 1 回绕扫一遍找空闲号"]
|
||||||
|
H --> I{"找到?"}
|
||||||
|
I -- 是 --> G
|
||||||
|
I -- 否 --> J["返回 0:全满,本候选不起批"]
|
||||||
|
```
|
||||||
|
|
||||||
|
特点:**优先顺序递增分配**(便于人工按批号识别新老),只有走到表尾才回绕复用早期空号。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. TAS 通道(model=3)
|
||||||
|
|
||||||
|
### 7.1 与 TWS 通道的差异
|
||||||
|
|
||||||
|
| 项 | TWS | TAS |
|
||||||
|
|---|---|---|
|
||||||
|
| 凝聚 | 相邻两帧滑窗,近程多速度维约束 | 单帧,恒有速度维约束 |
|
||||||
|
| 处理对象 | 全部可靠航迹 × 全部点 | **仅指定批号**的这一条航迹 × 全部点 |
|
||||||
|
| 俯仰/高度门限 | 俯仰门限已注释停用;**高度门限生效**(按距离分段,e0bf227 起) | **高度门限生效**(按距离分段,取值与 TWS 相同) |
|
||||||
|
| ΔT ≤ 0 | 参与选取但只消费点迹、不更新 | **直接跳过该点**(并记告警日志) |
|
||||||
|
| 外推时间 | 按 work_mode 数据率固定步长 | 按 `最新时间戳 − 航迹时间` |
|
||||||
|
| 输出 | 全部航迹 | 仅该批号航迹 |
|
||||||
|
|
||||||
|
### 7.2 TAS 关联与更新
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["TAS 本帧点迹 + 指定批号航迹"] --> B{"该批号航迹存在?"}
|
||||||
|
B -- 否 --> Z["直接返回(不做任何处理)"]
|
||||||
|
B -- 是 --> C["IMM 交互;航迹 point_flag 置 0"]
|
||||||
|
C --> D["逐点:ΔT ≤ 0 → 记告警并跳过"]
|
||||||
|
D --> E["逐点:三模型统计距离 d1/d2/d3 + 高度门限"]
|
||||||
|
E --> F{"d² < 16(任一模型)且高度门限通过?"}
|
||||||
|
F -- 是 --> G["记入候选表"]
|
||||||
|
F -- 否 --> H["丢弃"]
|
||||||
|
G --> I["取 d_min 最小的一点"]
|
||||||
|
I --> J["三模型 EKF 更新 → 概率更新 → 融合<br/>刷新时间/点信息/高度平滑"]
|
||||||
|
J --> K["输出该批号航迹"]
|
||||||
|
E --> L{"候选表为空?"}
|
||||||
|
L -- 是 --> M["按 ΔT = 最新时间戳 − 航迹时间 外推一帧<br/>(ΔT ≤ 0 则跳过)"]
|
||||||
|
M --> K
|
||||||
|
```
|
||||||
|
|
||||||
|
**高度门限**(|h_航迹 − h_点迹| 上限,按航迹距离分段):
|
||||||
|
|
||||||
|
| 航迹距离 | 门限 |
|
||||||
|
|---|---|
|
||||||
|
| ≤ 1000 m | 150 m |
|
||||||
|
| 1000 ~ 2000 m | 200 m |
|
||||||
|
| 2000 ~ 3000 m | 250 m |
|
||||||
|
| 3000 ~ 5000 m | 300 m |
|
||||||
|
| > 5000 m | 不约束 |
|
||||||
|
|
||||||
|
**TAS 后续处理**:外推不受 work_mode 数据率约束,而是直接推进到"本帧最新时间戳",保证 TAS 航迹时间与波束调度时刻同步。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. TAS 波束控制(外部接口 Beam_Ctrl)
|
||||||
|
|
||||||
|
### 8.1 队列管理
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["Beam_Ctrl 调用"] --> B["输出航迹计数清零"]
|
||||||
|
B --> C["入队 tas_target_add"]
|
||||||
|
C --> D["出队 tas_target_del"]
|
||||||
|
D --> E["波束输出 tas_beam_output"]
|
||||||
|
E --> F["输出 TrackingBeam"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**入队条件**(只支持手动转 TAS):
|
||||||
|
|
||||||
|
- 该航迹 `manual_tracking_flag == 1`(由外部 `tracking_start` 置位);
|
||||||
|
- 航迹当前 `Track_Mode == 0`(还不是 TAS);
|
||||||
|
- 队列未满(相扫最多 4 个 / 机扫最多 1 个);
|
||||||
|
- 不在 TAS 禁止区(距离-方位矩形)。
|
||||||
|
|
||||||
|
入队动作:写批号、标记非空、`last_track_time = T_track`、**航迹 Track_Mode 置 1**,并**立即输出一次该航迹更新**(通知宿主跟踪状态变化)。
|
||||||
|
|
||||||
|
**出队条件**:队列中的批号在航迹表中已不存在,或不再处于"手动 + TAS"状态 → 清空该队列项。
|
||||||
|
|
||||||
|
> 自动开启/退出 TAS 的逻辑(按距离/速度/高度阈值)已全部注释停用,**只支持手动**。
|
||||||
|
|
||||||
|
### 8.2 波束输出调度(关键)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["遍历 TAS 队列"] --> B["按批号在航迹表中找到该航迹"]
|
||||||
|
B --> C{"距上次波束输出 > DATA_RATE_TAS 秒<br/>且 CPI 时间早于已选中的最早 CPI?"}
|
||||||
|
C -- 否 --> A
|
||||||
|
C -- 是 --> D["选中该目标(CPI 时间最早者)"]
|
||||||
|
D --> E["位置外推:ΔT = (最新时间戳 − CPI 时间)/1000<br/>x + vx·ΔT, y + vy·ΔT"]
|
||||||
|
E --> F["Range = √(xp²+yp²),Azi = atan2(yp,xp)<br/>Elev = asin(Height / Range)"]
|
||||||
|
F --> G["open_flag=1, type=1, 批号=真实航迹号<br/>更新该目标 last_track_time = 最新时间戳"]
|
||||||
|
C -.->|"无任何合格目标"| H["open_flag = 0(其余字段保持旧值)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**要点**
|
||||||
|
|
||||||
|
- 门控只用一个条件(e0bf227 修正):目标「距上次波束输出的时间」(`latest_timestamp − last_track_time`)要大于 `DATA_RATE_TAS` 秒(单位是秒,由宿主经参数初始化传入,须为 > 0 的有效值)→ 保证 TAS 目标的数据率**不随 Beam_Ctrl 的调用频率变化**;修正前还要求「航迹时间与最新时间戳之差」也大于该门限,与"取最早 CPI 目标"的语义冲突,会漏掉本应输出的波束;
|
||||||
|
- 多目标时选**队列中 CPI 时间最早**的目标(同时要求其 CPI 时间早于当前已选者),等价于"按最久未更新者优先"的轮转;
|
||||||
|
- 选中后才按该目标的 CPI 时间算外推步长 `ΔT = (最新时间戳 − CPI 时间)/1000`;
|
||||||
|
- 原来的"每次调用整队循环移位"已停用;
|
||||||
|
- 俯仰用航迹高度直接算(叠加雷达平台高度的处理只影响对外输出的 z,不参与波束俯仰)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 参数脉络(决定行为的旋钮)
|
||||||
|
|
||||||
|
### 9.1 编译期宏(随扫描体制切换)
|
||||||
|
|
||||||
|
| 宏 | 相扫 | 机扫 | 作用点 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `SIGMA_R / A / E / V` | 10 / 0.02 / 0.2 / 2.0 | 同左 | 量测噪声、EKF 的 R、转换量测协方差 |
|
||||||
|
| `DOT_COH_RANGE / V / AZI` | 80 / 2 / 6 | 同左 | 凝聚门限(距离 m / 速度 m/s / 方位 °) |
|
||||||
|
| `R_MIN / R_MAX` | 100 / 100000 | 同左 | 有效量程(凝聚后过滤) |
|
||||||
|
| `TRACK_START_THRESHOLD` | 8 | 同左 | 起始统计距离波门(d ≤ 8) |
|
||||||
|
| `ALPHA_START` | 60 | 同左 | 起始折角上限(°) |
|
||||||
|
| `ASSO_THORD` | 4 | 同左 | 关联波门(判据 d*d < ASSO_THORD²,d 已是马氏距离平方,等效 d < 4) |
|
||||||
|
| `TRACK_DIE_ROUND` | 4 | 4 | TWS 消亡外推轮数 |
|
||||||
|
| `TRACK_DIE_ROUND_TAS` | 5 | 96 | TAS 消亡外推轮数 |
|
||||||
|
| `MAX_TRACK_NUM / MAX_TRACK_INDEX` | 500 / 500 | 同左 | 航迹数上限 / 航迹号上限 |
|
||||||
|
| `TAS_QUEUE_LENGTH / MAX_TAS_NUM` | 4 / 4 | 1 / 1 | TAS 队列长度 / 最大 TAS 目标数 |
|
||||||
|
| `H_F_WIN_LEN` | 3 | 同左 | 高度平滑窗长基数(实际 +2/+3/+4/+6) |
|
||||||
|
| `FREQ0` | 9.2 GHz | 同左 | 盲速计算的基准频率 |
|
||||||
|
| `RDP_LOG_ENABLE / RDP_LOG_DIR` | — | — | 日志落盘开关与目录 |
|
||||||
|
|
||||||
|
### 9.2 运行时参数(宿主传入,随任务变化)
|
||||||
|
|
||||||
|
| 参数 | 影响环节 |
|
||||||
|
|---|---|
|
||||||
|
| `work_mode`(0 近程/1 中程/2 远程) | 凝聚是否带速度维约束;TWS 外推步长;关联距离门限分支 |
|
||||||
|
| `track_start_point_num`(校验 3~9) | 起批所需点数 |
|
||||||
|
| `V_MAX / V_MIN` | 航迹头-点关联的速度区间 |
|
||||||
|
| `DATA_RATE_SHORT / MIDDLE / FAR` | TWS 未关联航迹外推步长(秒) |
|
||||||
|
| `DATA_RATE_TAS`(秒,须 > 0) | TAS 波束输出间隔门控 |
|
||||||
|
| `Height` | 输出 z = 航迹高度 + 平台高度 |
|
||||||
|
| `Sys_delay` | 输出位置做 x + vx·Sys_delay 的系统延迟补偿 |
|
||||||
|
| `Model1/2/3_Q_slow/fast` | 三个 Singer 模型的过程噪声强度(分档见 5.2) |
|
||||||
|
| `track_prohibite_area_*`(≤30 组) | 起批屏蔽区(距离 m + 方位 °) |
|
||||||
|
| `TAS_prohibite_area_*`(≤30 组) | TAS 禁止区 |
|
||||||
|
|
||||||
|
> `track_start_threshold / track_asso_threshold / track_asso_threshold_tas` 三个字段**当前未被实现读取**,实际门限来自编译期宏。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 关键约定与注意事项
|
||||||
|
|
||||||
|
**时序与时间戳**
|
||||||
|
|
||||||
|
- 时间戳为 64 位毫秒;`T_track` 输出为秒(`/1000`);所有 ΔT 用秒参与运算;
|
||||||
|
- TWS 关联中 ΔT ≤ 0 的候选"只消费点迹、不更新航迹"(点迹不会再去起批);
|
||||||
|
- TAS 关联中 ΔT ≤ 0 直接跳过该点;TAS 外推 ΔT ≤ 0 跳过本轮;
|
||||||
|
- 两点/三点卡尔曼初始化对 T 无除零保护 → **起批路径的时间戳必须严格递增**。
|
||||||
|
|
||||||
|
**量纲与坐标**
|
||||||
|
|
||||||
|
- 外部接口角度为度,内部统一弧度,输出再度;
|
||||||
|
- 平面坐标为水平投影,z = 目标高度 + 雷达平台高度;
|
||||||
|
- 点高度由 `R·sin(俯仰)` 直接折算,不参与滤波状态(由高度平滑单独维护)。
|
||||||
|
|
||||||
|
**门限语义**
|
||||||
|
|
||||||
|
- 关联与起始的波门写作 `d² < 门限²`,而 d 已是马氏距离平方 → 实际等效 **d < 门限**;
|
||||||
|
- 起始的"距离差 ≥ 5 m"为硬编码,对切向远距离慢速目标可能造成漏关联;
|
||||||
|
- 起批去重只比较**前三个点**,若起批点数 > 3,共享前三点后分叉的两条航迹会被判为同源。
|
||||||
|
|
||||||
|
**容量与边界**
|
||||||
|
|
||||||
|
- 点迹数上限 150(前处理已限幅);航迹数/航迹号上限 500,全满时新目标不再起批;
|
||||||
|
- 屏蔽区/禁止区的组数按 30 组数组定义,配置数量未做上限校验;
|
||||||
|
- 高度平滑缓存只增不减,长时运行下每条航迹的内存占用会持续增长。
|
||||||
|
|
||||||
|
**未启用**
|
||||||
|
|
||||||
|
- 引导跟踪(direct tracking)、手动打跟踪波束接口为空实现;
|
||||||
|
- TAS 自动开启/退出逻辑停用,只支持手动转/停 TAS;
|
||||||
|
- `tracking_stop` 后,队列项要等到下一次 `Beam_Ctrl` 才真正移除。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:与现有 `README.md` 的差异提示
|
||||||
|
|
||||||
|
> 说明:下表是本文档成文时(README 尚未同步 7d5a56f 改动)发现的差异,保留以说明改动缘由;随后已按下表结论更新 README 第 2、7.2、8.1、8.3、9.3、9.6、10.1 等节,「README 描述」列对应更新前的旧表述,现以本文档与 README 的描述为准。
|
||||||
|
|
||||||
|
| 项 | README 描述(更新前) | 当前源码 |
|
||||||
|
|---|---|---|
|
||||||
|
| 满圈判据 | 当前方位波位号 < 上一帧波位号 | **方位波位号 == 0**(7d5a56f,适应机扫转台反转) |
|
||||||
|
| 点-航迹头判据 | 按距离分段收紧速度门限(半速、1/2~1/3 速) | 该分支注释停用;改为统一速度区间 **+ 两条多普勒-几何一致性约束**(7d5a56f) |
|
||||||
|
| 起始输出历史点 | "临时航迹的全部 L 个点" | 实际输出**前 `track_start_point_num` 个点** |
|
||||||
|
| 起始输入过滤 | "track_init 跳过 Use_Flag==1 的点" | 上游 `track_asso_process()` 结束前已把 `Use_Flag==1` 的点迹从 `point_recv` 删除;`track_init` 入口(L59-70)也会再剔除一次 `Use_Flag==1` 的点,两道处理叠加,效果一致 |
|
||||||
|
| 日志开关 | "RDP_LOG_ENABLE 默认开启" | `parameters.h` 中该宏当前为**注释状态**(不落盘,日志进控制台) |
|
||||||
|
| 起始步骤顺序 | "航迹头(1 点)→ 点-航迹头关联(2 点)→ 点-临时航迹关联(≥3 点)→ 起批" | 每圈实际顺序为**点 × ≥2 点临时航迹关联 → 点 × 1 点航迹头关联 → 剩余点转新航迹头 → 长度达标的临时航迹起批**,消亡最后执行(`track_init.cpp` L49-126,见第 6 节) |
|
||||||
|
|
||||||
|
> 后续:README 与 `track_init_readme.md`(航迹起始专项说明)已按上表结论同步(见 CHANGELOG 的 Unreleased 记录);流程落地实现仍以本文为准。
|
||||||
|
>
|
||||||
|
> 补充修订(本次):起始流程的**步骤顺序**原先在本文档(第 0、6 节)与 README(第 2、5.2、8.3、9.3 节)中都写作「航迹头 → 2 点 → ≥3 点 → 起批」,与源码每圈「点 × 临时航迹关联 → 点 × 航迹头关联 → 剩余点转航迹头 → 达标者起批」的顺序相反,现已按源码修正,并补充说明两个关联阶段互不排斥、均不做一对一分配。
|
||||||
@@ -0,0 +1,752 @@
|
|||||||
|
# 航迹起始(Track Init)详细逻辑说明
|
||||||
|
|
||||||
|
> 适用范围:`data_process_class_dll/track_init.cpp` / `track_init.h`(类 `Track_Init`),TWS 通道逻辑法航迹起始。
|
||||||
|
> 关联文件:`kalman.cpp`(滤波与统计距离)、`coor_trans.cpp`(坐标转换)、`track_index_mangement.cpp`(航迹号分配)、`data_process.cpp`(调用与参数)。
|
||||||
|
> 本文按**当前源码实际行为**梳理,行号均指当前版本文件行号;与 `README.md` 第 8.3 / 9.3 节存在差异之处,见第 12 节。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
1. [模块定位与调用时机](#1-模块定位与调用时机)
|
||||||
|
2. [数据结构与状态容器](#2-数据结构与状态容器)
|
||||||
|
3. [处理流程总览](#3-处理流程总览)
|
||||||
|
4. [阶段一:输入装填与圈数计数](#4-阶段一输入装填与圈数计数)
|
||||||
|
5. [阶段二:点迹与临时航迹关联](#5-阶段二点迹与临时航迹关联)
|
||||||
|
6. [阶段三:点迹与航迹头关联](#6-阶段三点迹与航迹头关联)
|
||||||
|
7. [阶段四:点迹消费与航迹头生成](#7-阶段四点迹消费与航迹头生成)
|
||||||
|
8. [阶段五:临时航迹转可靠航迹(起批)](#8-阶段五临时航迹转可靠航迹起批)
|
||||||
|
9. [阶段六:临时航迹消亡](#9-阶段六临时航迹消亡)
|
||||||
|
10. [起始条件汇总表](#10-起始条件汇总表)
|
||||||
|
11. [关键算法细节](#11-关键算法细节)
|
||||||
|
12. [与其他文档/实现的差异](#12-与其他文档实现的差异)
|
||||||
|
13. [参数与调参](#13-参数与调参)
|
||||||
|
14. [输出字段映射](#14-输出字段映射)
|
||||||
|
15. [已知问题与风险点](#15-已知问题与风险点)
|
||||||
|
16. [代码索引](#16-代码索引)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 模块定位与调用时机
|
||||||
|
|
||||||
|
### 1.1 在整体流程中的位置
|
||||||
|
|
||||||
|
航迹起始处于 TWS 处理链的**末端**:只有「当圈未被任何可靠航迹关联上」的剩余点迹才会进入起始流程。
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A["data_preprocess<br/>点迹入 Data_buffer"] --> B["dot_coh(model=2)<br/>两帧滑窗凝聚"]
|
||||||
|
B --> C["track_asso(model=1)<br/>IMM + EKF 点航关联<br/>已用点从 point_recv 删除"]
|
||||||
|
C --> D["track_die<br/>可靠航迹消亡"]
|
||||||
|
D --> E["<b>track_init</b><br/>逻辑法航迹起始"]
|
||||||
|
E --> F["Trust_Track_Output<br/>(起批航迹 + 历史点)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
调用点(`data_process.cpp`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// L130-161,仅 model==1(TWS 满一圈)时执行
|
||||||
|
track_asso.track_asso_process(&point_recv, &trust_track, ...); // 入口删除 Use_Flag==1 的点
|
||||||
|
track_die.track_die_process(&trust_track, ...);
|
||||||
|
track_init.track_init_process_logic(&point_recv, &trust_track, &temp_track,
|
||||||
|
Trust_Track_Output, Trust_track_num_Output, Work_Parameter);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 调用频率 = 扫描圈
|
||||||
|
|
||||||
|
`data_preprocess` 在 `Data_Input[0].Beam_index_aiz == 0` 时返回 1(`data_process.cpp` L51),宿主据此调用 `track_process(model=1)`。
|
||||||
|
因此 **`track_init_process_logic()` 每次调用对应 TWS 一圈**,`Temp_track::buff_round`(已缓存圈数)正是以「调用次数」为单位累加的。
|
||||||
|
|
||||||
|
### 1.3 类接口
|
||||||
|
|
||||||
|
| 成员 | 可见性 | 作用 |
|
||||||
|
|---|---|---|
|
||||||
|
| `track_init_process_logic(...)` | public | 起始主流程(唯一入口) |
|
||||||
|
| `reset()` | public | 清空内部点迹缓存 + 复位航迹号分配器 |
|
||||||
|
| `point_temp_track_asso(...)` | private | 点迹 ↔ ≥2 点临时航迹关联 |
|
||||||
|
| `point_track_head_asso(...)` | private | 点迹 ↔ 1 点航迹头关联 |
|
||||||
|
| `tmp_track_to_trust_track(...)` | private | 收集 → 去重 → 起批 → 输出 |
|
||||||
|
| `tmp_track_die(...)` | private | 临时航迹消亡 |
|
||||||
|
| `alpha_cal_track_init(...)` | private | 三点折角(度) |
|
||||||
|
| `track_init_prohibit(...)` | private | 起批屏蔽区判断 |
|
||||||
|
| `track_index_mangement` | private | 航迹号(1~500)分配器 |
|
||||||
|
|
||||||
|
> `temp_track`(`std::vector<std::vector<Temp_track>>`)**不是** `Track_Init` 的成员,而是 `Data_Process::temp_track`,由调用方传入并跨圈保持;`track_clear_all()` 中清空(`data_process.cpp` L233),`Track_Init::reset()` 只清自己的 `point_process`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 数据结构与状态容器
|
||||||
|
|
||||||
|
### 2.1 Temp_track(临时航迹点,`struct.h` L94-121)
|
||||||
|
|
||||||
|
| 字段 | 含义 | 起始流程中的作用 |
|
||||||
|
|---|---|---|
|
||||||
|
| `X[4]` | 4 维状态 **[x, vx, y, vy]** | EKF 一步预测的状态;由两点卡尔曼初始化填充 |
|
||||||
|
| `P[4][4]` | 状态协方差 | 同上的协方差 |
|
||||||
|
| `r / azi / vr / height / snr / RCS / Amp` | 该点的极坐标测量 | 初始化、输出、条件判据(`azi` 为**弧度**) |
|
||||||
|
| `T` / `GNSS_time` | CPI 时间 / GNSS 时间(ms) | ΔT 计算(除 1000 转秒) |
|
||||||
|
| `d` | 该点关联时的马氏统计距离 | 去重阶段用于「保留更优者」 |
|
||||||
|
| `buff_round` | **已缓存圈数** | 生命周期与关联时机控制(见 4.2) |
|
||||||
|
| `asso_flag` | 0 未关联 / 1 已关联(待删除)/ 2 去重淘汰 | 临时状态标记 |
|
||||||
|
| `pitch_num`、`speed_dim[129]`、`range_dim[8]` | 俯仰波位、十字星数据 | 纯透传 |
|
||||||
|
| `Temp_track_section_idx` | 临时航迹区号 | 相关赋值已被注释停用,当前不参与逻辑 |
|
||||||
|
|
||||||
|
> ⚠ **下标陷阱**:`Temp_track::X` 是 4 维 `[x, vx, y, vy]`(y 在 index 2),而 `Trust_Track::X` 是 6 维 `[x, vx, ax, y, vy, ay]`(y 在 index 3)。两套结构混用下标必错。
|
||||||
|
|
||||||
|
### 2.2 容器语义
|
||||||
|
|
||||||
|
| 容器 | 语义 |
|
||||||
|
|---|---|
|
||||||
|
| `temp_track`(外层 vector) | 「临时航迹表」:外层每一项 = 一条临时航迹,**下标是不稳定的位置号**(擦除后会重排);内层 vector = 该航迹按时间正序的点序列 |
|
||||||
|
| `point_process`(`Track_Init` 成员) | 本次调用待处理的点迹工作副本 |
|
||||||
|
| `point_recv`(`Data_Process` 成员) | TWS 点迹文件:凝聚输出 → 被 `track_asso` 消费 → 剩余点进入 `track_init` → 被清空 |
|
||||||
|
|
||||||
|
### 2.3 输入与输出
|
||||||
|
|
||||||
|
| 参数 | 方向 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `point_recv` | 输入/输出 | 输入:当圈未被可靠航迹关联的点迹;**输出:被清空**(`track_init.cpp` L118) |
|
||||||
|
| `trust_track` | 输入/输出 | 可靠航迹表;起批成功的临时航迹 `push_back` 到此 |
|
||||||
|
| `temp_track` | 输入/输出 | 临时航迹表(跨圈状态) |
|
||||||
|
| `Trust_Track_Output[MAX_TRACK_NUM][10]` | 输出 | 与 `track_asso` **共用同一数组与同一计数**;起始流程在 `track_asso` 已写入的行之后追加新航迹的历史点 |
|
||||||
|
| `Trust_track_num_Output` | 输出 | 累计行数(track_asso 输出 N 行后,track_init 在其后继续追加) |
|
||||||
|
| `Work_Parameter` | 输入 | 运行时雷达参数(`RadarPara`) |
|
||||||
|
|
||||||
|
> **输出行数核算**:`track_asso` 先为当圈全部可靠航迹写 N 行;`track_die` 随后删除 D 条(已写出的行与计数不变);起始流程每次起批前判 `trust_track->size() < MAX_TRACK_INDEX(500)`,故最多再追加 `499 − N + D` 行,**合计最多 499 + D 行**。正常情况下 D 很小,远小于 500;但理论上当 D ≥ 2 且当圈起批数量恰好占满配额(需数百条同时起批)时,行号会超过第一维容量 500,存在越界写入风险(极端场景,见 15.14)。第二维 `[j]`(j < L ≤ 10)始终安全。代价是可靠航迹数达 500 时不再允许新起批。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 处理流程总览
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
S["track_init_process_logic 入口"] --> A1["① 取出 point_recv → point_process"]
|
||||||
|
A1 --> A2["② temp_track 全部点的 buff_round += 1"]
|
||||||
|
A2 --> Q{"point_process 空?"}
|
||||||
|
Q -- 是 --> DIE["⑥ tmp_track_die"]
|
||||||
|
Q -- 否 --> B["③ point_temp_track_asso<br/>点 ×(≥2 点临时航迹)"]
|
||||||
|
B --> C["④ point_track_head_asso<br/>点 ×(1 点航迹头)"]
|
||||||
|
C --> E["⑤ 删除 Use_Flag==1 的点<br/>剩余点 → 新建航迹头(buff_round=1)"]
|
||||||
|
E --> F["⑦ tmp_track_to_trust_track<br/>收集 → 去重 → 起批 → 输出"]
|
||||||
|
F --> G["清空 point_process / point_recv"]
|
||||||
|
G --> DIE
|
||||||
|
DIE --> R["return 0"]
|
||||||
|
```
|
||||||
|
|
||||||
|
要点顺序(不可颠倒):
|
||||||
|
|
||||||
|
1. **buff_round 先自增,再做关联** —— 这正是「同一圈内不重复关联同一条临时航迹」的实现方式(见 4.2)。
|
||||||
|
2. **先关联 ≥2 点临时航迹,再关联 1 点航迹头** —— 前者优先,但两者**不互斥**:同一圈可同时被两边关联(点迹可以既延续长航迹,又延续航迹头)。
|
||||||
|
3. **关联结果统一用 `Use_Flag` 标记,最后一次性物理删除** —— 只有 `Use_Flag==0` 的剩余点才会变成新航迹头。
|
||||||
|
4. **转可靠航迹在航迹头生成之后** —— 因此当圈新建的航迹头(1 点)不参与当圈起批。
|
||||||
|
5. **消亡在最后执行** —— 且即使当圈无剩余点迹(跳过 ③~⑦)也照常执行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 阶段一:输入装填与圈数计数
|
||||||
|
|
||||||
|
### 4.1 装填(`track_init.cpp` L36-38)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
for (size_t i=0;i<(*point_recv).size();i++)
|
||||||
|
point_process.push_back((*point_recv)[i]); // 全量拷贝,不检查 Use_Flag
|
||||||
|
```
|
||||||
|
|
||||||
|
- 上游 `track_asso` 已把关联上的点从 `point_recv` 中删除,所以这里进来的都是「未关联点」;函数内部**不再**用 `Use_Flag` 过滤输入(`Use_Flag` 只用于本次调用内部两阶段关联的标记)。
|
||||||
|
- 点迹的 `Range` 已在凝聚阶段做过 `[R_MIN=100, R_MAX=100000] m` 量程过滤。
|
||||||
|
|
||||||
|
### 4.2 buff_round 自增(L40-47)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
for (每一条临时航迹 j) (*temp_track)[i][j].buff_round += 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
含义与后果(关键机制):
|
||||||
|
|
||||||
|
| 动作 | 效果 |
|
||||||
|
|---|---|
|
||||||
|
| 新建点(航迹头 / 新关联点) | `buff_round = 1` |
|
||||||
|
| 每经过一次 `track_init` 调用(一圈) | 该航迹内**所有**点的 `buff_round` +1;关联判据只看**末点** |
|
||||||
|
| 关联判据要求 `末点.buff_round >= 2` | 等价于:**上一圈加入的点才能被本圈延续** ⇒ 同一条临时航迹每圈最多吸收一个点(除分裂,见 5.5) |
|
||||||
|
| 消亡判据 `末点.buff_round > 2` | 等价于:**连续 2 圈没有新点**就消亡(允许中间空 1 圈,最大关联间隔 2 圈) |
|
||||||
|
|
||||||
|
> 时间戳只在关联时用 `ΔT = (T_point − T_末点)/1000` 秒表示,**不参与生命周期判断**;生命周期完全由「圈数」驱动。这也意味着临时航迹的存活时间与扫描周期成正比,与航迹的绝对时间无关。
|
||||||
|
|
||||||
|
**生命周期时间轴(以 scan k 为起点)**
|
||||||
|
|
||||||
|
```text
|
||||||
|
scan k : 新点加入 → 末点 buff_round = 1 (本圈不能再关联)
|
||||||
|
scan k+1 : 自增 → 2 → 允许关联;若关联成功 → 新点 1;若失败 → 2 > 2 不成立,存活
|
||||||
|
scan k+2 : 自增 → 3 → 仍然允许关联;若成功 → 新点 1;若失败 → 3 > 2 成立,消亡
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 阶段二:点迹与临时航迹关联
|
||||||
|
|
||||||
|
函数:`point_temp_track_asso()`(L145-304)。双重循环:外层点迹、内层临时航迹,**无一对一竞争约束**。
|
||||||
|
|
||||||
|
### 5.1 参与资格(L164)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if( (*temp_track)[j].size() > 1 && (*temp_track)[j][L-1].buff_round >= 2 )
|
||||||
|
```
|
||||||
|
|
||||||
|
- 只处理 **≥2 点** 的临时航迹(1 点的是航迹头,留给阶段三);
|
||||||
|
- 末点必须来自历史圈次。
|
||||||
|
|
||||||
|
### 5.2 关联判据(L167-221)
|
||||||
|
|
||||||
|
设点迹量测(`Z[3]`):
|
||||||
|
|
||||||
|
$$
|
||||||
|
Z=\begin{bmatrix} r_p \\ \theta_p \\ v_{r,p}\end{bmatrix},\qquad
|
||||||
|
\mathbf{X}_{k-1}=\text{末点状态}[x,v_x,y,v_y],\qquad
|
||||||
|
\Delta T=\frac{T_p-T_{\text{末点}}}{1000}\ \text{(s)}
|
||||||
|
$$
|
||||||
|
|
||||||
|
**前置硬门限(L191)**:`|r_p − r_末点| >= 5` —— 距离差小于 5 m 的点直接不参与(连 d 都不算)。
|
||||||
|
|
||||||
|
**统计距离(L194-195)**:调用 `kalman::d_cal_track_init_EKF(Z, X, P, ΔT, prt, freq_ind)` 得到 3 维量测的马氏距离平方 `d`(详见 11.2)。
|
||||||
|
|
||||||
|
**折角(L199-205)**:取末点前一点 → 末点 → 新点,计算折角 `α`(度,详见 11.3)。
|
||||||
|
|
||||||
|
**三条件同时成立(L221)**:
|
||||||
|
|
||||||
|
$$
|
||||||
|
\boxed{\;d^2 \le \text{TRACK\_START\_THRESHOLD}^2=64
|
||||||
|
\quad\wedge\quad
|
||||||
|
\alpha < \text{ALPHA\_START}=60^\circ
|
||||||
|
\quad\wedge\quad
|
||||||
|
v_{r,p}\cdot v_{r,\text{末点}} > 0\;}
|
||||||
|
$$
|
||||||
|
|
||||||
|
> ⚠ 由于 `d_cal_track_init_EKF` 返回的 `d` **本身就是马氏距离平方**,而判据又写作 `d*d <= 64`(即 `d <= 8`),实际生效的门限是「马氏距离平方 ≤ 8」。3 自由度卡方分布 95% 分位为 7.815,因此该写法恰好给出约 95.4% 的置信门限(详见 11.2 与 15.6)。
|
||||||
|
|
||||||
|
### 5.3 记录关联(L223-231)
|
||||||
|
|
||||||
|
命中后向 `asso_info` 记录 `(point_idx=i+1, track_idx=j+1, d)`,同时:
|
||||||
|
|
||||||
|
- `末点.asso_flag = 1` → 标记**原航迹**待删除;
|
||||||
|
- `point_process[i].Use_Flag = 1` → 标记该点已被消费。
|
||||||
|
|
||||||
|
索引在整个扫描循环中保持稳定(循环期间不修改两个容器),因此后面的 1-based 索引回查是安全的。
|
||||||
|
|
||||||
|
### 5.4 生成新临时航迹(L237-281)
|
||||||
|
|
||||||
|
对每一条关联记录:**复制原航迹的全部 L 个点**(并把各点 `asso_flag` 清 0)、再**追加关联上的新点**,作为一条**新的临时航迹** push 到 `temp_track` 末尾。
|
||||||
|
|
||||||
|
新点字段:极坐标测量、幅度、SNR、RCS、时间、俯仰波位、十字星数据全套透传;`asso_flag=0`、`buff_round=1`、`d = asso_info[i].d`;
|
||||||
|
状态与协方差由 **两点卡尔曼初始化** 得到(L268-279):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Z0 = (末点.r·cos(末点.azi), 末点.r·sin(末点.azi)); // 原航迹末点
|
||||||
|
Z1 = (点.Range·cos(点.Azimuth), 点.Range·sin(点.Azimuth));
|
||||||
|
T = (点.CPI_Time − 末点.T)/1000.0;
|
||||||
|
Kalman.kalman_filter_init_2dots(Z0, Z1, T, X, P); // 4 维 CV 初始化
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.5 航迹分裂(重要特性)
|
||||||
|
|
||||||
|
关联循环**不做一对一分配**:
|
||||||
|
|
||||||
|
- 一个点若满足多条临时航迹的判据,会为**每一条**各自复制出一条新航迹 —— 一条母航迹可以派生多条子航迹;
|
||||||
|
- 一条临时航迹若被多个点同时命中,也会**各自复制**成多条子航迹(每个子航迹只带一个点);
|
||||||
|
- 因此同一圈内可能产生大量同源临时航迹,靠第 8.3 节的**去重**收敛。
|
||||||
|
|
||||||
|
### 5.6 删除被关联的原航迹(L283-303)
|
||||||
|
|
||||||
|
遍历 `temp_track`,凡 `size()>=2` 且 **末点 `asso_flag==1`** 者整体 `erase`(每次擦除后 `Iter = begin()` 重扫,O(n²) 但结果正确;1 点航迹不在此处理)。新生成的子航迹末点 `asso_flag==0`,不会被误删。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 阶段三:点迹与航迹头关联
|
||||||
|
|
||||||
|
函数:`point_track_head_asso()`(L306-445)。这是**两点起始**:航迹头 + 1 个点 → 2 点临时航迹。
|
||||||
|
|
||||||
|
### 6.1 参与资格(L325)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if((*temp_track)[j].size()==1 && (*temp_track)[j][0].buff_round >= 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
只处理 **1 点**且该点来自历史圈次的航迹头。
|
||||||
|
|
||||||
|
### 6.2 关联判据(L328-372)
|
||||||
|
|
||||||
|
点迹与航迹头都转直角坐标后取**平面距离**:
|
||||||
|
|
||||||
|
$$
|
||||||
|
x_p = r_p\cos\theta_p,\quad y_p=r_p\sin\theta_p;\qquad
|
||||||
|
x_h=\text{头.X}[0],\quad y_h=\text{头.X}[2]
|
||||||
|
$$
|
||||||
|
|
||||||
|
$$
|
||||||
|
dis=\sqrt{(x_p-x_h)^2+(y_p-y_h)^2},\qquad \Delta T=\frac{T_p-T_h}{1000}\ \text{(s)}
|
||||||
|
$$
|
||||||
|
|
||||||
|
**当前生效的判据(L368-372)**:
|
||||||
|
|
||||||
|
$$
|
||||||
|
\boxed{\;
|
||||||
|
dis \le V_{max}\Delta T
|
||||||
|
\;\wedge\;
|
||||||
|
dis \ge V_{min}\Delta T
|
||||||
|
\;\wedge\;
|
||||||
|
v_{r,p}\cdot v_{r,h} > 0
|
||||||
|
\;\wedge\;
|
||||||
|
dis \ge |v_{r,p}|\,\Delta T
|
||||||
|
\;\wedge\;
|
||||||
|
dis \ge |v_{r,h}|\,\Delta T\;}
|
||||||
|
$$
|
||||||
|
|
||||||
|
各条件的物理含义:
|
||||||
|
|
||||||
|
| 条件 | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| `dis ≤ V_max·ΔT` | 平均速度不超过最大速度(`V_max = Work_Parameter.V_MAX`) |
|
||||||
|
| `dis ≥ V_min·ΔT` | 平均速度不低于最小速度(滤除静止/慢速点) |
|
||||||
|
| `v_r,p · v_r,h > 0` | 两点多普勒径向速度**同号**(同接近/同远离) |
|
||||||
|
| `dis ≥ abs(v_r,p)·ΔT` | 位置变化不小于**点迹自身多普勒**在这段时间内的径向位移(多普勒-几何一致性) |
|
||||||
|
| `dis ≥ abs(v_r,h)·ΔT` | 同上,用航迹头的多普勒约束 |
|
||||||
|
|
||||||
|
**近/远程分支(L348-356)当前是死分支**:`work_mode==0` 与 `else` 都取 `vmax = Work_Parameter.V_MAX`(注释"近程模式最大速度减小一点"未生效;原 `V_MAX/5` 写法仅保留在未启用的 `track_init_direct_tracking.cpp` 注释里)。
|
||||||
|
|
||||||
|
**ΔT 语义**:判据隐含要求 `ΔT > 0`(若 `ΔT < 0`,则 `dis ≤ 负数` 必假)。`ΔT == 0` 时仅在 `dis == 0`(同时间同位置的点)才可能成立,属退化情形。
|
||||||
|
|
||||||
|
**与文档差异**:源码中被注释停用的旧判据按距离分段收紧门限(`r<1000` 时半速、中远程 `r<2000` 时 1/2~1/3 速),见第 12 节。
|
||||||
|
|
||||||
|
### 6.3 命中后的处理(L374-427)
|
||||||
|
|
||||||
|
- 记录 `(point_idx, track_idx)`,标记 `头.asso_flag=1`、`point_process[i].Use_Flag=1`;
|
||||||
|
- 逐条生成 2 点临时航迹:**第 1 点 = 原航迹头**(`asso_flag` 清 0),**第 2 点 = 新点**(全套测量透传,`buff_round=1`,`asso_flag=0`,**`d` 未赋值,保持 0**);
|
||||||
|
- 同样调用 `kalman_filter_init_2dots` 得到 4 维状态/协方差(`Z0` = 头点、`Z1` = 新点,`T = (点.CPI_Time − 头.T)/1000`)。
|
||||||
|
|
||||||
|
### 6.4 删除被关联的航迹头(L429-443)
|
||||||
|
|
||||||
|
凡 `[0].asso_flag==1` 的 1 点航迹头整条 `erase`(同样每次重扫)。
|
||||||
|
注意:本阶段遍历的是**全部** `temp_track`,其中由阶段二新建的 ≥2 点航迹因 `size()!=1` 不会被误处理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 阶段四:点迹消费与航迹头生成
|
||||||
|
|
||||||
|
### 7.1 删除已消费点迹(L57-70)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if((*Iter).Use_Flag==1) { point_process.erase(Iter); Iter = point_process.begin(); }
|
||||||
|
```
|
||||||
|
|
||||||
|
物理删除所有被阶段二或阶段三消费的点(两阶段共用同一 `Use_Flag`)。
|
||||||
|
|
||||||
|
> 结果:一个点迹**要么**参与延续已有临时航迹/航迹头(可同时延续两者),**要么**成为新航迹头,二者互斥。这保证不会「用同一个点既延续又起新头」。
|
||||||
|
|
||||||
|
### 7.2 剩余点回写(L72-75,等效空操作)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::vector<PointRecv>().swap((*point_recv));
|
||||||
|
for (...) (*point_recv).push_back(point_process[i]); // 回写未被使用的点
|
||||||
|
```
|
||||||
|
|
||||||
|
紧接着 L117-118 又把 `point_process` 与 `point_recv` 双双清空,因此这段回写**不产生任何对外效果**(`point_recv` 最终必然为空),属历史残留代码。
|
||||||
|
|
||||||
|
### 7.3 剩余点转航迹头(L77-114)
|
||||||
|
|
||||||
|
对每个剩余点构造 1 点 `Temp_track`:
|
||||||
|
|
||||||
|
| 字段 | 取值 |
|
||||||
|
|---|---|
|
||||||
|
| `r / azi / height / Amp / vr / snr / RCS` | 点迹对应量(`azi` 为弧度) |
|
||||||
|
| `pitch_num / speed_dim / range_dim` | 透传 |
|
||||||
|
| `X[0] = Range·cos(Azimuth)`、`X[1]=0`、`X[2] = Range·sin(Azimuth)`、`X[3]=0` | 位置赋值,速度置 0(**注意 4 维布局**) |
|
||||||
|
| `T`、`GNSS_time` | 点迹时间 |
|
||||||
|
| `asso_flag = 0`、`buff_round = 1` | 生命周期起点 |
|
||||||
|
| `d` | 未赋值 → 0 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 阶段五:临时航迹转可靠航迹(起批)
|
||||||
|
|
||||||
|
函数:`tmp_track_to_trust_track()`(L458-671),四步。
|
||||||
|
|
||||||
|
### 8.1 步骤 1:收集候选(L467-499)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int L = (*Iter).size();
|
||||||
|
double range = (*Iter)[L-1].r;
|
||||||
|
double azi = (*Iter)[L-1].azi/PI*180; // 转度,供屏蔽区比较
|
||||||
|
|
||||||
|
if( (L <= 10 && L >= Work_Parameter.track_start_point_num) && track_init_prohibit(range, azi, Work_Parameter)==0 )
|
||||||
|
{ 复制到 Track_to_start; 从 temp_track 中 erase; }
|
||||||
|
else
|
||||||
|
Iter++;
|
||||||
|
```
|
||||||
|
|
||||||
|
**入选条件**:
|
||||||
|
|
||||||
|
1. **长度**:`track_start_point_num ≤ L ≤ 10`(`track_start_point_num` 由宿主经 `track_process_parameters_initial` 传入,接口层校验范围 **3~9**,`data_process.cpp` L208);
|
||||||
|
2. **不在起批屏蔽区**内(用**末点**的距离/方位判断,见 8.5)。
|
||||||
|
|
||||||
|
命中即从 `temp_track` 摘出(先复制后删除,`Track_to_start` 成为候选表)。
|
||||||
|
|
||||||
|
> 结果:**一旦长度达到阈值且不落在屏蔽区,当圈即起批**(没有"连续 M 圈满足才起批"的确认期)。若因屏蔽区被拦住,航迹会继续在 `temp_track` 中增长,直到离开屏蔽区(此时 `L > track_start_point_num`,见 8.3 的副作用)或达到 `L=10` 被判消亡。
|
||||||
|
|
||||||
|
### 8.2 步骤 2:同源去重(L504-550)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int L = Work_Parameter.track_start_point_num; // 注意:此 L 是"起批点数",不是航迹长度
|
||||||
|
for (i: 0 .. size-2) for (j: i+1 .. size-1) {
|
||||||
|
if (两者都未被标记 asso_flag==2) {
|
||||||
|
if (某条长度 < 3) continue; // 防御性判断(实际不会触发)
|
||||||
|
if (前三点中存在一点 "T 与 r 完全相同") { // 硬编码比较点 0/1/2
|
||||||
|
if (Track_to_start[i][L-1].d < Track_to_start[j][L-1].d) j 标记 asso_flag=2;
|
||||||
|
else i 标记 asso_flag=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 然后统一删除 [0].asso_flag==2 的航迹
|
||||||
|
```
|
||||||
|
|
||||||
|
- **同源判定**:两条候选航迹的前三个点中,只要有一个点的 `T` 与 `r` 完全相等(同一点迹被复制而来),就视为同源重复;
|
||||||
|
- **择优准则**:比较 `[L-1].d`(第 `track_start_point_num` 个点的关联统计距离),**保留 d 更小者**;
|
||||||
|
- **标记位置**:只写 `[0].asso_flag = 2`,最后统一擦除;
|
||||||
|
- 去重仅看**前三点**,且无论航迹实际多长都用固定下标 0/1/2。
|
||||||
|
|
||||||
|
### 8.3 步骤 3:起批与构造可靠航迹(L552-667)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (Track_to_start[i].size() < 3) continue; // 防御
|
||||||
|
if (trust_track->size() < MAX_TRACK_INDEX) { // 500 条上限
|
||||||
|
int index = track_index_mangement.track_ind_get(trust_track);
|
||||||
|
if (index > 0) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**三点卡尔曼初始化**(L563-571,注意使用的是 `L-3, L-2, L-1`,即**最后三个点**):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Z0 = 极坐标→直角(点[L-3]); Z1 = (点[L-2]); Z2 = (点[L-1]);
|
||||||
|
T1 = (点[L-2].T − 点[L-3].T)/1000.0; T2 = (点[L-1].T − 点[L-2].T)/1000.0;
|
||||||
|
Kalman.kalman_filter_init_3dots(Z0, Z1, Z2, T1, T2, X, P); // 6 维 [x,vx,ax,y,vy,ay]
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠ **不一致点**:初始化用「最后三点」,而输出历史点(8.4)只写「前 `L` 个点」。当航迹长度 = `track_start_point_num` 时两者一致;当因屏蔽区滞留使长度 > 阈值时,输出的历史点里**不包含**用于初始化的那三个点。
|
||||||
|
|
||||||
|
**Trust_Track 字段构造(L573-608)**:
|
||||||
|
|
||||||
|
| 字段 | 赋值 |
|
||||||
|
|---|---|
|
||||||
|
| `X[6] / P[6][6]` | 三点初始化结果 |
|
||||||
|
| `X1/X2/X3 = X`、`P1/P2/P3 = P` | 三个 IMM 子模型同状态、同协方差初始化 |
|
||||||
|
| `u[0..2] = 0.3333` | 模型概率均分 |
|
||||||
|
| `Track_Index` | `track_ind_get()` 分配的航迹号 |
|
||||||
|
| `T_track` / `GNSS_time` / `Height` | 取**末点**的对应值 |
|
||||||
|
| `Amplitude / snr_point / RCS / pitch_num / speed_dim / range_dim` | 末点透传 |
|
||||||
|
| `point_flag = 1` | 实点 |
|
||||||
|
| `Track_Mode = 0` | TWS |
|
||||||
|
| `Target_Type = UNCONF_TARGET(0)` | 未确认目标 |
|
||||||
|
| `Extrapolate_round = 0` | 外推计数清零 |
|
||||||
|
| `approach_flag = -1` | 接近标志复位 |
|
||||||
|
| `manual_delete_flag / manual_tracking_flag / associate_point_number / point_type = 0` | 各类标志复位 |
|
||||||
|
|
||||||
|
> L606-608 有一处**死代码**:`coor_trans::cart2polar(X[0], X[3], &r, &azi)`(把 `X[3]=vy` 当 y 用),计算结果 `r/azi` 从未被使用。
|
||||||
|
|
||||||
|
**航迹号分配**(`track_index_mangement.cpp`):空表返回 1;否则从 `lastest_index+1` 向上找第一个未被占用的号(含 500),找不到再从 1 回绕;全满返回 0(**不起批**,该候选被静默丢弃)。
|
||||||
|
|
||||||
|
### 8.4 输出更新航迹(L612-664)
|
||||||
|
|
||||||
|
- `*Trust_track_num_Output += 1`,在 `track_asso` 已写的行之后追加一行;
|
||||||
|
- 对 `j = 0 .. L-1`(`L = track_start_point_num`)写入该航迹的**历史点**:`Track_Index`、`Point_Sum = L`,以及每个点的距离/方位/俯仰、速度、幅度/SNR/RCS、俯仰波位、十字星数据、航向角、时间、直角坐标、原始点信息等(完整映射见第 14 节);
|
||||||
|
- 之后该航迹的后续更新由 `track_asso`(每次 `Point_Sum=1`)负责。
|
||||||
|
|
||||||
|
### 8.5 起批屏蔽区(L699-712)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
for (i = 0; i < Work_Parameter.track_prohibite_area_num; i++)
|
||||||
|
if (r < R_max_track_prohibited[i] && r > R_min_track_prohibited[i] &&
|
||||||
|
azi < Azimuth_max_track_prohibited[i] && azi > Azimuth_min_track_prohibited[i])
|
||||||
|
return 1; // 位于屏蔽区,禁止起批
|
||||||
|
return 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
- 判据是**距离-方位矩形区域**(`azi` 已转成度),最多 30 个(`RadarPara` 数组长度;数量未做上限校验);
|
||||||
|
- 采用**严格不等号**:恰好落在边界上的点不算屏蔽;
|
||||||
|
- 判断用**末点**极坐标,不使用高度。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 阶段六:临时航迹消亡
|
||||||
|
|
||||||
|
函数:`tmp_track_die()`(L673-697):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (n <= 0) erase; // 空航迹
|
||||||
|
if ((*Iter)[n-1].buff_round > 2 || n >= 10) erase;
|
||||||
|
```
|
||||||
|
|
||||||
|
| 消亡条件 | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| 序列为空 | 防御性清理 |
|
||||||
|
| 末点 `buff_round > 2` | 连续 2 圈没有新点(允许空 1 圈) |
|
||||||
|
| 长度 `n >= 10` | 达到上限仍未完成起批(例如长期滞留屏蔽区) |
|
||||||
|
|
||||||
|
消亡**不输出任何信息**(与可靠航迹消亡不同,起批失败的临时航迹对宿主不可见)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 起始条件汇总表
|
||||||
|
|
||||||
|
### 10.1 条件链(一条 3 点起批航迹的完整判据)
|
||||||
|
|
||||||
|
| 阶段 | 判据(源码位置) |
|
||||||
|
|---|---|
|
||||||
|
| **0. 输入资格** | 该点未被 `track_asso` 关联(已从 `point_recv` 删除);凝聚后 `100 m ≤ r ≤ 100000 m` |
|
||||||
|
| **1. 生成航迹头** | 未被阶段二/三消费(`Use_Flag==0`);创建时 `buff_round=1`(L77-114) |
|
||||||
|
| **2. 航迹头 → 2 点**(L325, L368-372) | 航迹头 `size==1` 且 `buff_round ≥ 2`;`dis ≤ V_MAX·ΔT`;`dis ≥ V_MIN·ΔT`;`dis ≥ abs(vr_p)·ΔT`;`dis ≥ abs(vr_h)·ΔT`;`vr_p·vr_h > 0`(隐含 `ΔT > 0`) |
|
||||||
|
| **3. 2 点 → 3 点及以上**(L164, L191, L221) | 临时航迹 `size > 1` 且末点 `buff_round ≥ 2`;`abs(r_p − r_末点) ≥ 5 m`;`d ≤ 8`(代码写 `d² ≤ 64`);`α < 60°`;`vr_p·vr_末点 > 0` |
|
||||||
|
| **4. 转可靠航迹**(L484, L556) | `track_start_point_num ≤ L ≤ 10`;末点不在起批屏蔽区;同源去重后保留;`trust_track.size() < 500` 且成功分配航迹号 |
|
||||||
|
| **5. 消亡**(L686) | `末点.buff_round > 2`(连续 2 圈无新点)或 `长度 ≥ 10` |
|
||||||
|
|
||||||
|
### 10.2 门限汇总
|
||||||
|
|
||||||
|
| 判据 | 数值 | 来源 | 可调 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 最大速度 `V_MAX` | 运行时 | `RadarPara.V_MAX` | ✅ |
|
||||||
|
| 最小速度 `V_MIN` | 运行时 | `RadarPara.V_MIN` | ✅ |
|
||||||
|
| 距离差下限 `abs(Δr)` | **5 m(硬编码)** | `track_init.cpp` L191 | ❌ |
|
||||||
|
| 起批波门 `d ≤ 8` | `TRACK_START_THRESHOLD=8` | `parameters.h` L49/L98 | 编译期 |
|
||||||
|
| 起批折角 | `ALPHA_START=60°` | `parameters.h` L50/L99 | 编译期 |
|
||||||
|
| 起批点数 | 3~9(典型 3~4) | `RadarPara.track_start_point_num` | ✅ |
|
||||||
|
| 临时航迹长度上限 | 10(硬编码) | L484 / L686 | ❌ |
|
||||||
|
| 允许丢圈数 | 1 圈(`buff_round > 2` 消亡) | L686 | ❌ |
|
||||||
|
| 航迹头上限等待 | 2 圈 | L686(1 点航迹同判据) | ❌ |
|
||||||
|
| 起批屏蔽区 | ≤30 个矩形 | `RadarPara.track_prohibite_area_*` | ✅ |
|
||||||
|
| 航迹数上限 | 500 | `MAX_TRACK_INDEX` | 编译期 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 关键算法细节
|
||||||
|
|
||||||
|
### 11.1 两点卡尔曼初始化(`kalman.cpp` L18-58)
|
||||||
|
|
||||||
|
输入两个直角坐标量测 `Z0, Z1` 与时间差 `T`(秒):
|
||||||
|
|
||||||
|
$$
|
||||||
|
X=\begin{bmatrix}x_1\\ (x_1-x_0)/T\\ y_1\\ (y_1-y_0)/T\end{bmatrix},
|
||||||
|
\qquad
|
||||||
|
P_{axis}=\begin{bmatrix}R & R/T\\ R/T & 2R/T^2\end{bmatrix}
|
||||||
|
$$
|
||||||
|
|
||||||
|
其中 `R` 取 `Z1` 处的**转换量测协方差**(极坐标→直角坐标,见 `README.md` 9.1 节),x/y 两轴独立填充 `P[4][4]`。
|
||||||
|
|
||||||
|
> 风险:`T → 0` 时速度与协方差同时发散,函数无除零保护(对应 BUG-18);临时航迹的两点初始化 `T` 来自相邻两圈,实际由时间戳决定,若宿主给出重复时间戳会异常。
|
||||||
|
|
||||||
|
### 11.2 EKF 统计距离(`kalman.cpp` L615-693)
|
||||||
|
|
||||||
|
对 4 维状态做 CV 一步预测(`F = [[1,T,0,0],[0,1,0,0],[0,0,1,T],[0,0,0,1]]`,过程噪声 `Q = 0.03²·I`,`G=[T²/2, T]ᵀ`):
|
||||||
|
|
||||||
|
$$
|
||||||
|
\hat X_{k|k-1}=F X,\qquad P_{k|k-1}=FPF^{T}+GQG^{T}
|
||||||
|
$$
|
||||||
|
|
||||||
|
非线性量测函数(距离-方位-径向速度):
|
||||||
|
|
||||||
|
$$
|
||||||
|
h(\hat X)=\begin{bmatrix}\sqrt{x^2+y^2}\\ \operatorname{atan2}(y,x)\bmod 2\pi\\ -\dfrac{x v_x+y v_y}{\sqrt{x^2+y^2}}\end{bmatrix},
|
||||||
|
\qquad H=\left.\frac{\partial h}{\partial X}\right|_{\hat X_{k|k-1}}
|
||||||
|
$$
|
||||||
|
|
||||||
|
量测噪声 `R = diag(σ_r², σ_a², σ_v²) = diag(10², 0.02², 2²)`,新息协方差 `S = H P Hᵀ + R`,残差做两项修正:
|
||||||
|
|
||||||
|
- **方位环绕**:`ν_θ = wrapToPi(θ_p − θ_pred)`,归一化到 `[−π, π)`;
|
||||||
|
- **多普勒盲速折叠**:`ν_v ← ν_v − round(ν_v / v_bind)·v_bind`,其中
|
||||||
|
|
||||||
|
$$
|
||||||
|
v_{bind}=\frac{150000}{f_{GHz}\cdot PRI_{\mu s}}\ \text{(m/s)},
|
||||||
|
\qquad f_{GHz}=9.2+0.02\cdot f_{ind}
|
||||||
|
$$
|
||||||
|
|
||||||
|
(`PRI ≤ 0` 或 `f ≤ 0` 时返回安全值 1.0;调用方约定 PRI 单位 µs,不允许为 0。)
|
||||||
|
|
||||||
|
返回马氏距离平方:
|
||||||
|
|
||||||
|
$$
|
||||||
|
d=\nu^{T}S^{-1}\nu,\qquad \nu=Z-h(\hat X_{k|k-1})
|
||||||
|
$$
|
||||||
|
|
||||||
|
**调用参数来源**:`prt = point.PRF_index`(实际存的是 `DataRev.PRI`,单位 µs);`freq_ind = point.Freq_index`。
|
||||||
|
|
||||||
|
### 11.3 折角计算(L448-456)
|
||||||
|
|
||||||
|
$$
|
||||||
|
\alpha=\arccos\!\left(\frac{\vec D_{12}\cdot\vec D_{23}}{\|\vec D_{12}\|\,\|\vec D_{23}\|}\right)\cdot\frac{180}{\pi}
|
||||||
|
$$
|
||||||
|
|
||||||
|
其中 `D12 = (末点 − 前一点)`、`D23 = (新点 − 末点)`,三点均取 **Temp_track 的直角坐标**(`X[0]` 为 x、`X[2]` 为 y)。`α` 越小表示越接近直线;`ALPHA_START=60°` 表示允许的航向偏折。
|
||||||
|
|
||||||
|
> 无 `acos` 定义域钳位:当两点重合(分母为 0)或浮点误差使比值略超 ±1 时结果为 `NaN`,`NaN < 60` 恒为 false → 表现为「该点无法关联」,不崩溃。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 与其他文档/实现的差异
|
||||||
|
|
||||||
|
### 12.1 与 `README.md` 第 8.3 / 9.3 节的差异(README 已同步本节结论)
|
||||||
|
|
||||||
|
> 说明:下表为本文档成文时发现的差异,当时 README 尚未同步 7d5a56f 的改动;随后已按本节结论更新 README 第 2、7.2、8.1、8.3、9.3、9.6、10.1 等节,「README 描述」列对应的是更新前的旧表述,保留以说明改动缘由。
|
||||||
|
|
||||||
|
| 项 | README 描述(更新前) | 当前源码 |
|
||||||
|
|---|---|---|
|
||||||
|
| 点-航迹头判据 | 按距离分段:近程 `r≥1000` 全速 / `r<1000` 半速;中远程 `r≥2000` 全速 / `r<2000` 1/2~1/3 速 | 该分支已**整体注释停用**,改为统一 `V_MIN·ΔT ≤ dis ≤ V_MAX·ΔT` **外加两条多普勒一致性条件** `dis ≥ abs(vr_p)·ΔT`、`dis ≥ abs(vr_h)·ΔT`(L361-372) |
|
||||||
|
| 起批触发长度 | 长度满足 `track_start_point_num ≤ L ≤ 10` | 一致 |
|
||||||
|
| 初始化用点 | 最近三点 | 不一致:取下标 `track_start_point_num-3 ~ -1` 的三个点,航迹长度大于起批点数时**不是**航迹真正的末三点(详见第 15 节第 2 条) |
|
||||||
|
| 输出历史点 | "将临时航迹的全部 L 个点写入" | 实际只写**前 `track_start_point_num` 个点**(L614 的 `L` 是起批点数,不是航迹长度) |
|
||||||
|
| use_flag 过滤 | "track_init 跳过 Use_Flag==1 的点" | 上游 `track_asso_process()` 已删除 `Use_Flag==1` 的点迹,`track_init` 入口(L59-70)也会再剔除一次,两道处理叠加,描述成立 |
|
||||||
|
|
||||||
|
### 12.2 与 `track_init_direct_tracking.cpp`(引导跟踪版,未启用)的差异
|
||||||
|
|
||||||
|
| 项 | `track_init.cpp`(TWS,启用) | `track_init_direct_tracking.cpp`(未启用) |
|
||||||
|
|---|---|---|
|
||||||
|
| 入口 | 完整实现 | `track_init_process_logic` 空实现(L11-23) |
|
||||||
|
| 点-航迹头判据 | 统一门限 + 两条多普勒一致性条件 | 仍为分距离段门限(`V_MAX/5` 亦在其注释中) |
|
||||||
|
| 起批长度 | `L ≥ track_start_point_num`(长度可大于阈值) | `L == track_start_point_num`(严格相等) |
|
||||||
|
| 去重 | 有同源去重 | 无 |
|
||||||
|
| 屏蔽区 | 有 | 无 |
|
||||||
|
| 航迹号 | `track_ind_get()` 分配 | 外部传入 `track_ID` |
|
||||||
|
| 消亡阈值 | `buff_round > 2` | `buff_round > 1`(更严格) |
|
||||||
|
| 输出模式 | `Track_Mode = 0`(TWS) | `Track_Mode = 1`(TAS) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. 参数与调参
|
||||||
|
|
||||||
|
### 13.1 编译期宏(`parameters.h`)
|
||||||
|
|
||||||
|
| 宏 | 相扫/机扫 | 含义 | 调大效果 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `TRACK_START_THRESHOLD` | 8 / 8 | 起批波门,实际生效为 `d ≤ 8` | **更容易起批**(虚警增多) |
|
||||||
|
| `ALPHA_START` | 60 / 60 | 起批折角(度) | 更容易起批(允许更急的转向) |
|
||||||
|
| `SIGMA_R / SIGMA_A / SIGMA_V` | 10 / 0.02 / 2.0 | EKF 量测噪声 | 影响 `S` 与 `d`,进而影响关联难度 |
|
||||||
|
| `MAX_TRACK_INDEX` | 500 | 航迹号/航迹数上限 | — |
|
||||||
|
| `R_MIN / R_MAX` | 100 / 100000 | 有效量程(凝聚阶段过滤) | — |
|
||||||
|
| `PI` | 3.1415926**f** | 角度换算(float 精度) | — |
|
||||||
|
|
||||||
|
### 13.2 运行期参数(`RadarPara`)
|
||||||
|
|
||||||
|
| 字段 | 影响 |
|
||||||
|
|---|---|
|
||||||
|
| `track_start_point_num` | 起批点数(接口校验 3~9):调大 → 起批更慢、更抗虚警,但机动目标捕获更迟 |
|
||||||
|
| `V_MAX` / `V_MIN` | 头-点关联的速度区间;`V_MIN` 调大可滤除静止/慢速点 |
|
||||||
|
| `work_mode` | 当前对起始流程**无实际影响**(近/远程分支取值相同) |
|
||||||
|
| `track_prohibite_area_num` + 4×30 数组 | 起批屏蔽区(距离 m / 方位 度) |
|
||||||
|
| `track_start_threshold` | **声明但未被实现读取**(实际用宏 `TRACK_START_THRESHOLD`) |
|
||||||
|
|
||||||
|
### 13.3 调参直觉
|
||||||
|
|
||||||
|
- **虚警多、起批太容易**:先降 `TRACK_START_THRESHOLD`(8 → 5 左右),再降 `ALPHA_START`;必要时提高 `track_start_point_num`。
|
||||||
|
- **真实目标起批慢**:提高 `TRACK_START_THRESHOLD` / `ALPHA_START`,或降低 `track_start_point_num`(最小 3)。
|
||||||
|
- **静止/低速杂波起批**:提高 `V_MIN`。
|
||||||
|
- **某方位扇区/距离段禁止起批**(如地物、干扰区):配置起批屏蔽区,比调门限更精准。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. 输出字段映射
|
||||||
|
|
||||||
|
对每条新起批航迹的每个历史点 `j = 0 .. track_start_point_num-1`(L614-664):
|
||||||
|
|
||||||
|
| 输出字段 | 来源 | 备注 |
|
||||||
|
|---|---|---|
|
||||||
|
| `Track_Index` | 新分配的航迹号 | 同一行内所有点相同 |
|
||||||
|
| `Point_Sum` | `= track_start_point_num` | 与 `track_asso` 输出的 `Point_Sum=1` 可作区分 |
|
||||||
|
| `Range` / `Azimuth` | 点的 `r` / `azi`(→度) | 极坐标 |
|
||||||
|
| `Elevation` | `asin(h/r)`(度,钳位 ±1) | BUG-27 修复后的定义域钳位 |
|
||||||
|
| `z` | 点的 `height` | |
|
||||||
|
| `Range_V` | `sqrt(X[1]² + X[3]²)` = `sqrt(vx²+vy²)` | 速度**模值**(非径向速度) |
|
||||||
|
| `Direction_Angle` | `atan2(vy, vx)`(→度, `[0,360)`) | 航向角 |
|
||||||
|
| `x / v_x / y / v_y` | 点的 `X[0..3]` | 注意 4 维布局 |
|
||||||
|
| `range_point / azi_point / elev_point / vr_point` | 点的原始测量 | `point_type=0` |
|
||||||
|
| `Amplitude / track_snr / track_rcs` | 点的 `Amp / snr / RCS` | |
|
||||||
|
| `pitch_num / speed_dim / range_dim` | 点透传 | |
|
||||||
|
| `track_time` | `T/1000`(秒) | |
|
||||||
|
| `GNSS_time` | 点透传 | |
|
||||||
|
| `Flag_Point` | 恒为 **1**(实点) | |
|
||||||
|
| `Track_Mode` | 恒为 **0**(TWS) | |
|
||||||
|
| **未赋值** | `Flag_Direction`、`x_Predict/y_Predict/z_Predict`、`Range_Predict/Azimuth_Predict/Elevation_Predict`、`Target_Type`、`prf_point`、`v_z` | DLL 不清零该数组,宿主读到的是其自身缓存的旧值/未初始化值。注意 `Flag_Direction` 只在关联输出路径赋值(`track_asso.cpp` / `track_asso_tas.cpp`,f249fdc:`vr_point > 0 ? 1 : 0`),起批输出不写该字段 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. 已知问题与风险点
|
||||||
|
|
||||||
|
> 以下为阅读源码得到的观察,**不代表已确认的缺陷**,部分为有意保留的历史行为;修改前请结合实测数据评估。
|
||||||
|
|
||||||
|
1. **硬编码 5 m 距离差门限**(L191):`|r_p − r_末点| < 5` 的点永不参与关联。对切向飞行、远距离慢速目标可能造成漏关联(起批失败)。
|
||||||
|
2. **初始化用点不是航迹真正的末三点**(L505、L563-565 vs L614):起批流程中 `L = track_start_point_num`(L505 覆盖了前面循环里的航迹长度变量),Z0/Z1/Z2 取下标 `L-3 / L-2 / L-1`,输出循环也只写到 `j = L-1`。因此当航迹长度 N 大于起批点数时,参与初始化的只是**前 L 个点中的最后三点**,而不是航迹真正的末三点;第 L 个点之后的尾部点既未参与初始化也不出现在输出中(这些点通常来自滞留在起批屏蔽区期间的积累)。
|
||||||
|
3. **去重只比较前三个点**(L517-519 硬编码 0/1/2),且优度指标取 `[track_start_point_num-1].d`(长度大于阈值时非末点);若 `track_start_point_num > 3`,共享前三点但后续分叉的两条航迹会被误判为同源。
|
||||||
|
4. **无一对一关联约束**:一个点可同时为多条临时航迹续点(阶段二/三),产生航迹分裂,虚警场景下临时航迹表可能快速膨胀(靠去重与消亡收敛)。
|
||||||
|
5. **ΔT ≤ 0 无显式校验**(BUG-33 遗留):头-点关联靠 `dis ≤ V_MAX·ΔT` 隐式排除负 ΔT;EKF 关联路径 `d_cal_track_init_EKF(ΔT<0)` 会得到无物理意义的结果,只是通常会被 `d ≤ 8` 挡住。
|
||||||
|
6. **判据对马氏距离平方二次平方**(L221):实际门限为 `d ≤ 8`(3 自由度约 95.4%)。若按字面 `d² ≤ 64` 理解会误判为 `d ≤ 64`(极宽松)。修改 `TRACK_START_THRESHOLD` 时务必记得这一层。
|
||||||
|
7. **两点/三点初始化无 `T > 0` 保护**(BUG-18):`T` 极小(重复/乱序时间戳)时速度、加速度与协方差会爆炸性放大。
|
||||||
|
8. **死代码**:L72-75 的 `point_recv` 回写随即被 L117-118 清空;L606-608 的 `cart2polar` 结果未使用;L348-356 的近/远程分支取值相同。
|
||||||
|
9. **`acos` 无定义域钳位**(L452):浮点越界产生 `NaN`,表现为条件恒假(静默丢弃该关联),不报错也不崩溃。
|
||||||
|
10. **航迹数饱和静默丢弃**:`trust_track.size() ≥ 500` 或 `track_ind_get()` 返回 0 时,候选被直接跳过且该临时航迹已从 `temp_track` 摘除 → 起批机会永久丢失。
|
||||||
|
11. **未赋值输出字段**(第 14 节):宿主若直接使用 `x_Predict`、`Flag_Direction`、`Target_Type` 等字段,会读到非本次写入的数据。
|
||||||
|
12. **`PI` 为 float 常量**(3.1415926f)参与双精度运算,角度换算存在约 1e-7 量级偏差,属既有实现风格。
|
||||||
|
13. **精度/量纲提醒**:`Temp_track::vr` 直接取点的 `Velocity`(多普勒)作为径向速度,EKF 关联时用于残差折叠(盲速 `v_bind`)与符号判据;若宿主的 `Velocity` 存在模糊,符号判据 `vr_p·vr_末点 > 0` 可能失效。
|
||||||
|
14. **输出数组行号可能越界(极端场景)**:容量判据用 `trust_track->size() < 500`,而 `Trust_Track_Output` 的行计数已在 `track_asso` 阶段按「消亡前」的航迹数推进,中间的 `track_die` 删除 D 条后腾出的配额会让起始流程多写 D 行;当 D ≥ 2 且当圈起批数占满配额时,写入行号可超过 `MAX_TRACK_NUM=500`(详见 2.3)。建议把判据改为同时校验 `*Trust_track_num_Output < MAX_TRACK_NUM` 与 `trust_track->size() < MAX_TRACK_INDEX`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. 代码索引
|
||||||
|
|
||||||
|
### 16.1 `track_init.cpp`
|
||||||
|
|
||||||
|
| 行号 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| L11-143 | `track_init_process_logic` 主流程 |
|
||||||
|
| L36-38 | 装填点迹 |
|
||||||
|
| L40-47 | `buff_round` 自增 |
|
||||||
|
| L49 | `if(point_process.size()>0)` 主分支 |
|
||||||
|
| L52 / L55 | 两阶段关联调用 |
|
||||||
|
| L57-70 | 删除已消费点迹 |
|
||||||
|
| L72-75 | 点迹回写(等效空操作) |
|
||||||
|
| L77-114 | 剩余点 → 航迹头 |
|
||||||
|
| L117-118 | 清空 `point_process` / `point_recv` |
|
||||||
|
| L121 | 转可靠航迹调用 |
|
||||||
|
| L126 | 临时航迹消亡调用 |
|
||||||
|
| L145-304 | `point_temp_track_asso` |
|
||||||
|
| L164 | ≥2 点 + `buff_round≥2` 资格 |
|
||||||
|
| L191 | `abs(Δr) ≥ 5 m` 门限 |
|
||||||
|
| L194-195 | EKF 统计距离 `d` |
|
||||||
|
| L199-205 | 折角 `α` |
|
||||||
|
| L221 | 三条件判据 |
|
||||||
|
| L237-281 | 生成新临时航迹(两点初始化) |
|
||||||
|
| L283-303 | 删除被关联的原航迹 |
|
||||||
|
| L306-445 | `point_track_head_asso` |
|
||||||
|
| L325 | 1 点 + `buff_round≥2` 资格 |
|
||||||
|
| L361-372 | 门限判据(含停用的旧分支注释) |
|
||||||
|
| L388-427 | 生成 2 点临时航迹 |
|
||||||
|
| L429-443 | 删除被关联的航迹头 |
|
||||||
|
| L448-456 | `alpha_cal_track_init` |
|
||||||
|
| L458-671 | `tmp_track_to_trust_track` |
|
||||||
|
| L484 | 起批长度 + 屏蔽区条件 |
|
||||||
|
| L504-550 | 同源去重 |
|
||||||
|
| L552-667 | 起批与输出 |
|
||||||
|
| L563-571 | 三点卡尔曼初始化 |
|
||||||
|
| L573-604 | `Trust_Track` 构造 |
|
||||||
|
| L612-664 | 输出历史点 |
|
||||||
|
| L673-697 | `tmp_track_die` |
|
||||||
|
| L699-712 | `track_init_prohibit` |
|
||||||
|
| L714-723 | 构造 / `reset()` |
|
||||||
|
|
||||||
|
### 16.2 依赖
|
||||||
|
|
||||||
|
| 文件 | 函数 | 用途 |
|
||||||
|
|---|---|---|
|
||||||
|
| `kalman.cpp` L18-58 | `kalman_filter_init_2dots` | 两点(4 维)初始化 |
|
||||||
|
| `kalman.cpp` L125-194 | `kalman_filter_init_3dots` | 三点(6 维)初始化 |
|
||||||
|
| `kalman.cpp` L615-693 | `d_cal_track_init_EKF` | 起始关联统计距离 |
|
||||||
|
| `kalman.cpp` L780-789 | `Bind_speed` | 盲速计算 |
|
||||||
|
| `coor_trans.cpp` L8-20 | `polar2cart` / `cart2polar` | 坐标转换 |
|
||||||
|
| `track_index_mangement.cpp` L14-77 | `track_ind_get` | 航迹号分配 |
|
||||||
|
| `data_process.cpp` L51 | `data_preprocess` | 一圈完成 → `model=1` |
|
||||||
|
| `data_process.cpp` L154-159 | `track_process` | 起始流程调用点 |
|
||||||
|
| `data_process.cpp` L204-222 | 参数初始化/修改 | 校验 `track_start_point_num ∈ [3,9]` |
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# 雷达数据处理项目修改说明
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
本次主要修改TAS波束控制逻辑,
|
|
||||||
原有逻辑为:
|
|
||||||
- 维护一个tas_target_queue队列,队列中每个元素可以保存一个TAS跟踪目标
|
|
||||||
- 每次调用Beam_Ctrl()函数时,判断队列首个元素是否为空(empty_flag),若不为空,则输出TAS跟踪波束信息,否则不输出
|
|
||||||
- 将队列进行循环移位,队列第一个目标移动至队尾,下一次Beam_Ctrl()调用将会跟踪下一个目标
|
|
||||||
|
|
||||||
原有逻辑的问题:
|
|
||||||
- 原有逻辑下,TAS跟踪目标的数据率(目标信息更新频率)与波束时间相关,波束时间越短,则调用Beam_Ctrl()的频率越高,TAS目标的数据率也越高
|
|
||||||
|
|
||||||
新的逻辑为保证TAS目标的数据率不变:
|
|
||||||
- 维护一个tas_target_queue队列,队列中每个元素可以保存一个TAS跟踪目标
|
|
||||||
- 每次调用Beam_Ctrl()函数时,判断队列首个元素是否为空(empty_flag),若不为空,则再判断目标的航迹时间(T_track)和当前最新时间戳(latest_timestamp)的差值,若差值大于1 / DATA_RATE_TAS,则输出TAS跟踪波束信息,否则不输出
|
|
||||||
- 将队列进行循环移位,队列第一个目标移动至队尾,下一次Beam_Ctrl()调用将会跟踪下一个目标
|
|
||||||
|
|
||||||
注意:在RadarPara结构体中新增一项:DATA_RATE_TAS(TAS模式数据率),由dll调用者输入该参数的值(track_process_parameters_initial()),上述逻辑中DATA_RATE_TAS使用Work_Parameter中的DATA_RATE_TAS参数值,而不是使用parameters.h中的DATA_RATE_TAS宏定义值。
|
|
||||||
Reference in New Issue
Block a user