49 KiB
航迹起始(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.1 在整体流程中的位置
航迹起始处于 TWS 处理链的末端:只有「当圈未被任何可靠航迹关联上」的剩余点迹才会进入起始流程。
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):
// track_process()(data_process.cpp L167 起),仅 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);
工作参数为全局对象
rdp_parameter(struct.h中extern声明、data_process.cpp定义并零初始化),由公开接口parameters_reload(配置文件路径)从 TOML 配置文件加载;各模块直接以rdp_parameter.<field>访问,不再作为函数形参逐层传递(参数来源见 README 第 10 节;改造前为宿主下发RadarPara+parameters.h宏,更早则由const RDP_parameter&形参传入)。
1.2 调用频率 = 扫描圈
data_preprocess 判为一圈完成时返回 1(data_process.cpp),宿主据此调用 track_process(model=1)。判据由配置项 [radar_params] scan_mode 运行时选择(0 相扫 / 1 机扫;替代原编译期 PHASE_SCANNING/MECHANICAL_SCANNING 分支):scan_mode=0 比较前后两帧方位波位号(当前 ≤ 上一帧即满圈,last_beam_num 参与判断,清空后/首帧即满圈);scan_mode=1 判 Data_Input[0].Beam_index_aiz == 0(详见 README 7.2 与 docs/data_process_flow_report.md 2.2 节)。
因此 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~track_index_max,默认 500)分配器 |
temp_track(std::vector<std::vector<Temp_track>>)不是Track_Init的成员,而是Data_Process::temp_track,由调用方传入并跨圈保持;track_clear_all()中清空(data_process.cppL233),Track_Init::reset()只清自己的point_process。
2. 数据结构与状态容器
2.1 Temp_track(临时航迹点,struct.h)
| 字段 | 含义 | 起始流程中的作用 |
|---|---|---|
X[4] |
4 维状态 [x, vx, y, vy] | EKF 一步预测的状态;由两点卡尔曼初始化填充 |
P[4][4] |
状态协方差 | 同上的协方差 |
r / azi / vr / height / SNR / RCS / amplitude |
该点的极坐标测量 | 初始化、输出、条件判据(azi 为弧度) |
CPI_time / 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_id / point_id / circle_id |
临时航迹 ID / 末关联点迹 ID / 处理圈 ID(c3c7e66 新增) | 数据记录链路标识;起批时透传给 Trust_Track |
quality |
航迹质量(0~1,V1.5.8 新增) | 每延长一点即重算(见 8.6);起批时取末点值作为初始质量,并参与起批质量门限判断 |
temp_track_section_idx |
临时航迹区号 | 相关赋值已被注释停用,当前不参与逻辑 |
字段更名提示(c3c7e66):
snr→SNR、Amp→amplitude、T→CPI_time、Temp_track_section_idx→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 在其后继续追加) |
全局 rdp_parameter |
读取 | 工作参数(TOML 配置加载的全局对象,struct.h 声明、data_process.cpp 定义);不再经函数形参传入,模块直接访问 |
输出行数核算:
track_asso先为当圈有更新的可靠航迹写 N 行(输出循环判Track_Update_Flag==1并清零,即只含关联到实点或成功外推的航迹);track_die随后删除 D 条(已写出的行与计数不变);起始流程每次起批前判trust_track->size() < track_index_max(配置项,默认 500),故最多再追加499 − N + D行,合计最多 499 + D 行。正常情况下 D 很小,远小于 500;但理论上当 D ≥ 2 且当圈起批数量恰好占满配额(需数百条同时起批)时,行号会超过第一维容量 500,存在越界写入风险(极端场景,见 15.14)。第二维[j](j < L ≤ 10)始终安全。代价是可靠航迹数达track_index_max时不再允许新起批。
3. 处理流程总览
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"]
要点顺序(不可颠倒):
- buff_round 先自增,再做关联 —— 这正是「同一圈内不重复关联同一条临时航迹」的实现方式(见 4.2)。
- 先关联 ≥2 点临时航迹,再关联 1 点航迹头 —— 前者优先,但两者不互斥:同一圈可同时被两边关联(点迹可以既延续长航迹,又延续航迹头)。
- 关联结果统一用
Use_Flag标记,最后一次性物理删除 —— 只有Use_Flag==0的剩余点才会变成新航迹头。 - 转可靠航迹在航迹头生成之后 —— 因此当圈新建的航迹头(1 点)不参与当圈起批。
- 消亡在最后执行 —— 且即使当圈无剩余点迹(跳过 ③~⑦)也照常执行。
4. 阶段一:输入装填与圈数计数
4.1 装填(track_init.cpp L36-38)
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已在凝聚阶段做过量程过滤(下限/上限为配置项point_cohesion_range_min/point_cohesion_range_max,默认 100 m / 100000 m)。
4.2 buff_round 自增(L40-47)
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 为起点)
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)
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):
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)
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 = rdp_parameter.track_init_velocity_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 = rdp_parameter.track_init_velocity_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)
if((*Iter).Use_Flag==1) { point_process.erase(Iter); Iter = point_process.begin(); }
物理删除所有被阶段二或阶段三消费的点(两阶段共用同一 Use_Flag)。
结果:一个点迹要么参与延续已有临时航迹/航迹头(可同时延续两者),要么成为新航迹头,二者互斥。这保证不会「用同一个点既延续又起新头」。
7.2 剩余点回写(L72-75,等效空操作)
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 / amplitude / 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 维布局) |
CPI_time、GNSS_time |
点迹时间 |
temp_track_id = temp_track_id++、point_id、circle_id |
取自该点迹(记录链路标识,c3c7e66 新增) |
asso_flag = 0、buff_round = 1 |
生命周期起点 |
d |
未赋值 → 0 |
8. 阶段五:临时航迹转可靠航迹(起批)
函数:tmp_track_to_trust_track()(L458-671),四步。
8.1 步骤 1:收集候选(L467-499)
int L = (*Iter).size();
double range = (*Iter)[L-1].r;
double azi = (*Iter)[L-1].azi/PI*180; // 转度,供屏蔽区比较
double quality = (*Iter)[L-1].quality; // V1.5.8:末点航迹质量
if( L <= 10 && L >= rdp_parameter.track_init_point_num_min
&& track_init_prohibit(range, azi) == 0
&& quality >= 按长度取的质量门限 ) // V1.5.8 新增
{ 复制到 Track_to_start; 从 temp_track 中 erase; }
else
Iter++;
入选条件:
- 长度:
track_init_point_num_min ≤ L ≤ 10(配置项[track_init] track_init_point_num_min,由 TOML 配置文件提供,加载器校验范围 3~9;改造前由宿主经track_process_parameters_initial传入); - 不在起批屏蔽区内(用末点的距离/方位判断,见 8.5);
- 航迹质量达标(V1.5.8,d9a7bd0):按长度取门限
track_init_quality_L3~L7(配置项)——L=3 →0.7、L=4 →0.6、L=5 →0.5、L=6 →0.4、L≥7 →0.3;比较对象是末点quality,不达标则本圈不起批、留在temp_track继续积累。
命中即从 temp_track 摘出(先复制后删除,Track_to_start 成为候选表)。
结果:一旦长度达到阈值、不落在屏蔽区且末点质量达标,当圈即起批(没有"连续 M 圈满足才起批"的确认期)。若因屏蔽区被拦住,航迹会继续在
temp_track中增长,直到离开屏蔽区(此时L > track_init_point_num_min,见 8.3 的副作用)或达到L=10被判消亡;若因质量门限被拦住,则继续积累直到质量回升或临时航迹消亡。
8.2 步骤 2:同源去重(L504-550)
int L = rdp_parameter.track_init_point_num_min; // 注意:此 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_init_point_num_min个点的关联统计距离),保留 d 更小者; - 标记位置:只写
[0].asso_flag = 2,最后统一擦除; - 去重仅看前三点,且无论航迹实际多长都用固定下标 0/1/2。
8.3 步骤 3:起批与构造可靠航迹(L552-667)
if (Track_to_start[i].size() < 3) continue; // 防御
if (trust_track->size() < rdp_parameter.track_index_max) { // 默认 500 条上限
int index = track_index_mangement.track_ind_get(trust_track);
if (index > 0) { ... }
}
三点卡尔曼初始化(L563-571,注意使用的是 L-3, L-2, L-1,即最后三个点):
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_init_point_num_min时两者一致;当因屏蔽区滞留使长度 > 阈值时,输出的历史点里不包含用于初始化的那三个点。
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 |
取末点的对应值(CPI_time 字段) |
Amplitude / snr_point / RCS / pitch_num / speed_dim / range_dim |
末点透传 |
track_id / point_id / circle_id |
取末点的 temp_track_id / point_id / circle_id(记录链路标识,b227ae1 新增) |
Track_fingerprint |
航迹指纹(V1.5.9,0f3da99):computeFingerprint(末点.r, 末点.azi, 末点.vr, 末点.RCS, 末点.CPI_time),16 bit(量化 0.01 m / 0.001° / 0.01 m·s⁻¹ / 0.1 dBsm / 1 ms → splitmix64 混合 → 折叠 16 bit),TAS 波束与 TAS 输入均以它定位航迹(见 README 9.12) |
point_flag = 1 |
实点 |
Track_Mode = 0 |
TWS |
Target_Type = 0 |
未确认目标(UNCONF_TARGET 宏已删除,直接写 0) |
Extrapolate_round = 0 |
外推计数清零 |
approach_flag = -1 |
接近标志复位 |
manual_delete_flag / manual_tracking_flag / associate_point_number / point_type / primary_target_flag = 0 |
各类标志复位(Trust_Track trust_track_tmp = {} 零初始化,故新航迹的重点目标标记为 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 向上找第一个未被占用的号(含 track_index_max,默认 500),找不到再从 1 回绕;全满返回 0(不起批,该候选被静默丢弃)。
8.4 输出更新航迹(L612-664)
*Trust_track_num_Output += 1,在track_asso已写的行之后追加一行;- 对
j = 0 .. L-1(L = rdp_parameter.track_init_point_num_min)写入该航迹的历史点:Track_Index、Point_Sum = L,以及每个点的距离/方位/俯仰、速度、幅度/SNR/RCS、俯仰波位、十字星数据、航向角、时间、直角坐标、原始点信息等(完整映射见第 14 节); - 之后该航迹的后续更新由
track_asso(每次Point_Sum=1)负责。
8.5 起批屏蔽区(L699-712)
for (i = 0; i < rdp_parameter.track_init_prohibite_area_num; i++)
if (r < rdp_parameter.track_init_prohibite_area_range_max[i] && r > rdp_parameter.track_init_prohibite_area_range_min[i] &&
azi < rdp_parameter.track_init_prohibite_area_azimuth_max[i] && azi > rdp_parameter.track_init_prohibite_area_azimuth_min[i])
return 1; // 位于屏蔽区,禁止起批
return 0;
- 判据是距离-方位矩形区域(
azi已转成度),最多 30 个(RDP_parameter定长数组长度;配置入口由加载器校验*_num ∈ [0,30]且 4 个数组长度等于*_num,非法配置在parameters_reload阶段即失败); - 采用严格不等号:恰好落在边界上的点不算屏蔽;
- 判断用末点极坐标,不使用高度。
8.6 临时航迹质量评估与起批门限(V1.5.8,1ae0cf2 / d9a7bd0)
在阶段二(点-临时航迹关联)每成功延长一个点后,point_temp_track_asso() 立即重算该临时航迹末点的质量:
L = temp_track_ref.size();
d_tmp = exp(-temp_track_ref[L-1].d); // 末点统计距离项(d 已是马氏距离平方)
// L == 3:取三个点 SNR 的平均;L > 3:只取末点 SNR
snr_tmp = 1 / (1 + exp(-(SNR - 16) / 1.2)); // 以 16 dB 为界的 Sigmoid
// 权重为配置项 track_quality_d_weight(0.5) / track_quality_snr_weight(0.3)
quality_tmp = (w_d * d_tmp + w_snr * snr_tmp) / (w_d + w_snr); // 只用距离 + SNR 两项(不含长度项)
if (L == 3) 三点全部写 quality_tmp; // 质量起点
else 末点 quality = 前一点 quality * c + quality_tmp * (1 - c); // 指数平滑,c = track_quality_iter_coeff(0.8)
Temp_track::quality是 0~1 的归一化值;起批时Trust_Track.Quality = 末点 quality,Point_sum = Valid_point_sum = L;- 起批门限按临时航迹长度 L 取(比较对象是末点质量):L=3 → 0.7、L=4 → 0.6、L=5 → 0.5、L=6 → 0.4、L≥7 → 0.3;
- 质量不达标时该临时航迹不进入
Track_to_start,继续留在temp_track中参与下一圈关联(受buff_round/长度 10 的消亡约束)。
注意:质量只在「点-临时航迹关联」路径更新,阶段三(点 × 1 点航迹头 → 2 点临时航迹)不写
quality;2 点航迹要到下一圈被延长成 3 点时才会首次获得质量值,这与其本来也不能起批(长度不足)是一致的。
9. 阶段六:临时航迹消亡
函数:tmp_track_die()(L673-697):
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 ≤ track_init_velocity_max·ΔT;dis ≥ track_init_velocity_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,track_init_threshold=8);α < 60°(track_init_angle);vr_p·vr_末点 > 0 |
| 4. 转可靠航迹(L484, L556) | track_init_point_num_min ≤ L ≤ 10;末点不在起批屏蔽区;末点质量 ≥ 按 L 取的门限(V1.5.8);同源去重后保留;trust_track.size() < track_index_max 且成功分配航迹号 |
| 5. 消亡(L686) | 末点.buff_round > 2(连续 2 圈无新点)或 长度 ≥ 10 |
10.2 门限汇总
| 判据 | 数值 | 来源 | 可调 |
|---|---|---|---|
最大速度 vmax |
50 m/s(样例) | 配置项 track_init.track_init_velocity_max |
✅(改配置文件) |
最小速度 vmin |
1 m/s(样例) | 配置项 track_init.track_init_velocity_min |
✅(改配置文件) |
距离差下限 abs(Δr) |
5 m(硬编码) | track_init.cpp L191 |
❌ |
起批波门 d ≤ 8 |
track_init_threshold=8 |
配置项 track_init.track_init_threshold |
✅(改配置文件) |
| 起批折角 | track_init_angle=60° |
配置项 track_init.track_init_angle |
✅(改配置文件) |
| 起批点数 | 3 |
配置项 track_init.track_init_point_num_min |
✅(加载器校验 3~9) |
| 临时航迹长度上限 | 10(硬编码) | L484 / L686 | ❌ |
| 允许丢圈数 | 1 圈(buff_round > 2 消亡) |
L686 | ❌ |
| 航迹头上限等待 | 2 圈 | L686(1 点航迹同判据) | ❌ |
| 起批屏蔽区 | ≤30 个矩形 | 配置段 [track_init_prohibite_area](数组长度 = *_num) |
✅(加载器校验 0~30) |
| 起批最低质量(V1.5.8) | L3→0.7 / L4→0.6 / L5→0.5 / L6→0.4 / L≥7→0.3 | 配置项 track_init.track_init_quality_L3~L7 |
✅(改配置文件) |
| 质量权重(V1.5.8) | 距离 0.5 / SNR 0.3 / 长度 0.2 | 配置段 [track_quality] |
✅(改配置文件) |
| 航迹数上限 | 500(默认) | 配置项 track_index.track_index_max |
✅(加载器校验 1~500) |
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)。α 越小表示越接近直线;track_init_angle(配置项,样例 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.2 等节,「README 描述」列对应的是更新前的旧表述,保留以说明改动缘由。
| 项 | README 描述(更新前) | 当前源码 |
|---|---|---|
| 点-航迹头判据 | 按距离分段:近程 r≥1000 全速 / r<1000 半速;中远程 r≥2000 全速 / r<2000 1/2~1/3 速 |
该分支已整体注释停用,改为统一 track_init_velocity_min·ΔT ≤ dis ≤ track_init_velocity_max·ΔT 外加两条多普勒一致性条件 dis ≥ abs(vr_p)·ΔT、dis ≥ abs(vr_h)·ΔT(L361-372) |
| 起批触发长度 | 长度满足 track_init_point_num_min ≤ L ≤ 10 |
一致 |
| 初始化用点 | 最近三点 | 不一致:取下标 track_init_point_num_min-3 ~ -1 的三个点,航迹长度大于起批点数时不是航迹真正的末三点(详见第 15 节第 2 条) |
| 输出历史点 | "将临时航迹的全部 L 个点写入" | 实际只写前 track_init_point_num_min 个点(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_init_point_num_min(长度可大于阈值) |
L == track_init_point_num_min(严格相等) |
| 去重 | 有同源去重 | 无 |
| 屏蔽区 | 有 | 无 |
| 航迹号 | track_ind_get() 分配 |
外部传入 track_ID |
| 消亡阈值 | buff_round > 2 |
buff_round > 1(更严格) |
| 输出模式 | Track_Mode = 0(TWS) |
Track_Mode = 1(TAS) |
13. 参数与调参
参数配置方式改造后:与起始流程相关的全部可调参数都在 TOML 配置文件里(样例
config/config_tmp.toml),由公开接口parameters_reload(配置文件路径)加载到RDP_parameter;parameters.h不再有这些宏,宿主也不再下发RadarPara。改参数 = 改配置文件后重新调用parameters_reload()(加载失败时参数保持不变)。完整参数表与严格校验规则见 README 第 10 节。
13.1 配置项(样例值,均为「配置段.键」)
| 配置项 | 样例值 | 含义 | 调大效果 |
|---|---|---|---|
track_init.track_init_threshold |
8 | 起批波门,实际生效为 d ≤ 8 |
更容易起批(虚警增多) |
track_init.track_init_angle |
60 | 起批折角(度) | 更容易起批(允许更急的转向) |
track_associate.sigma_range/azimuth/pitch/velocity |
10 / 0.02 / 0.2 / 2.0 | EKF 量测噪声 | 影响 S 与 d,进而影响关联难度 |
track_index.track_index_max |
500 | 航迹号/航迹数上限(1~500) | — |
cohesion.point_cohesion_range_min/max |
100 / 100000 | 有效量程(凝聚阶段过滤) | — |
track_init.track_init_point_num_min |
3 | 起批点数(加载器校验 3~9):调大 → 起批更慢、更抗虚警,但机动目标捕获更迟 | |
track_init.track_init_velocity_max/min |
50 / 1 | 头-点关联的速度区间;min 调大可滤除静止/慢速点 |
|
radar_params.radar_work_mode |
0 | 当前对起始流程无实际影响(近/远程分支取值相同) | |
track_init_prohibite_area.*_num + 4 个数组 |
0 + 空数组 | 起批屏蔽区(距离 m / 方位 度;≤30 组,数组长度 = *_num) |
|
track_init.track_init_quality_L3~L7 |
0.7 / 0.6 / 0.5 / 0.4 / 0.3 | 按临时航迹长度的起批最低质量(V1.5.8) | 降低 → 更容易起批 |
track_quality.* |
0.5 / 0.3 / 0.2 / 0.8 | 质量权重、平滑系数与衰减系数(V1.5.8) | 影响质量评估与消亡速度 |
旧
RadarPara中的track_start_threshold字段原本就未被实现读取;新结构体只保留实现真正使用/保留的参数(见 README 10.3 对照表)。
13.2 调参直觉
- 虚警多、起批太容易:先降
track_init_threshold(8 → 5 左右),再降track_init_angle;必要时提高track_init_point_num_min。 - 真实目标起批慢:提高
track_init_threshold/track_init_angle,或降低track_init_point_num_min(最小 3)。 - 静止/低速杂波起批:提高
track_init_velocity_min。 - 某方位扇区/距离段禁止起批(如地物、干扰区):配置起批屏蔽区,比调门限更精准。
- 注意:
config/config_tmp.toml是相扫取值(scan_mode = 0);机扫部署时需配scan_mode = 1,且extrapolate_max_tas、height_smooth_win、track_die_round_tas、tas_track_num_max按机扫取值配置(见 README 4.2、10.1)。
14. 输出字段映射
对每条新起批航迹的每个历史点 j = 0 .. track_init_point_num_min-1(L614-664):
| 输出字段 | 来源 | 备注 |
|---|---|---|
Track_Index |
新分配的航迹号 | 同一行内所有点相同 |
Point_Sum |
= track_init_point_num_min |
与 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 |
点的 amplitude / SNR / RCS |
|
pitch_num / speed_dim / range_dim |
点透传 | |
track_time |
CPI_time/1000(秒) |
|
GNSS_time |
点透传 | |
Flag_Point |
恒为 1(实点) | |
Track_Mode |
恒为 0(TWS) | |
Quality |
该历史点的临时航迹质量 × 100(V1.5.8) | 内部 quality 为 0 |
| 未赋值 | Flag_Direction、x_Predict/y_Predict/z_Predict、Range_Predict/Azimuth_Predict/Elevation_Predict、Target_Type、prf_point、v_z、amp_asv_point、prn_fftn_point |
DLL 不清零该数组,宿主读到的是其自身缓存的旧值/未初始化值。注意 Flag_Direction 只在关联输出路径赋值(track_asso.cpp / track_asso_tas.cpp),起批输出不写该字段。该字段的判据已由 f249fdc 的 vr_point > 0 ? 1 : 0(实测径向速度,受多普勒速度模糊影响符号可能取反)改为 fc49707 + 42b598e 的航向-位置夹角法:Direction_Angle = atan2(X[4], X[1])(弧度转度后同时输出到 Direction_Angle),x、y 为经配置项 radar_system_delay 补偿后的位置、r 为其模,acos((-x·cos(Direction_Angle) - y·sin(Direction_Angle))/r) < π/2 判为靠近(1)、否则远离(0),即滤波速度方向与"雷达→目标"位置方向夹角超 90° 判为接近。另 amp_asv_point / prn_fftn_point 属 e8c56f9 新增,data_preprocess() 现已把 DataRev.amp_asv / prn_fftn 搬入 PointRecv(TWS 与 TAS 分支均赋值,并随 RdpRecPoint 落库),因此 TWS 关联/输出路径的该字段已有有效来源;TAS 关联与输出路径(track_asso_tas.cpp)仍未涉及这两个字段,TAS 输出行中它们保持宿主原值 |
15. 已知问题与风险点
以下为阅读源码得到的观察,不代表已确认的缺陷,部分为有意保留的历史行为;修改前请结合实测数据评估。
- 硬编码 5 m 距离差门限(L191):
|r_p − r_末点| < 5的点永不参与关联。对切向飞行、远距离慢速目标可能造成漏关联(起批失败)。 - 初始化用点不是航迹真正的末三点(L505、L563-565 vs L614):起批流程中
L = track_init_point_num_min(L505 覆盖了前面循环里的航迹长度变量),Z0/Z1/Z2 取下标L-3 / L-2 / L-1,输出循环也只写到j = L-1。因此当航迹长度 N 大于起批点数时,参与初始化的只是前 L 个点中的最后三点,而不是航迹真正的末三点;第 L 个点之后的尾部点既未参与初始化也不出现在输出中(这些点通常来自滞留在起批屏蔽区期间的积累)。 - 去重只比较前三个点(L517-519 硬编码 0/1/2),且优度指标取
[track_init_point_num_min-1].d(长度大于阈值时非末点);若track_init_point_num_min > 3,共享前三点但后续分叉的两条航迹会被误判为同源。 - 无一对一关联约束:一个点可同时为多条临时航迹续点(阶段二/三),产生航迹分裂,虚警场景下临时航迹表可能快速膨胀(靠去重与消亡收敛)。
- ΔT ≤ 0 无显式校验(BUG-33 遗留):头-点关联靠
dis ≤ track_init_velocity_max·ΔT隐式排除负 ΔT;EKF 关联路径d_cal_track_init_EKF(ΔT<0)会得到无物理意义的结果,只是通常会被d ≤ 8挡住。 - 判据对马氏距离平方二次平方(L221):
track_init_threshold=8时实际门限为d ≤ 8(3 自由度约 95.4%)。若按字面d² ≤ 64理解会误判为d ≤ 64(极宽松)。修改track_init_threshold时务必记得这一层。 - 两点/三点初始化无
T > 0保护(BUG-18):T极小(重复/乱序时间戳)时速度、加速度与协方差会爆炸性放大。 - 死代码:L72-75 的
point_recv回写随即被 L117-118 清空;L606-608 的cart2polar结果未使用;L348-356 的近/远程分支取值相同。 acos无定义域钳位(L452):浮点越界产生NaN,表现为条件恒假(静默丢弃该关联),不报错也不崩溃。- 航迹数饱和静默丢弃:
trust_track.size() ≥ track_index_max(配置项,默认 500)或track_ind_get()返回 0 时,候选被直接跳过且该临时航迹已从temp_track摘除 → 起批机会永久丢失。 - 未赋值输出字段(第 14 节):宿主若直接使用
x_Predict、Flag_Direction、Target_Type等字段,会读到非本次写入的数据。 PI为 float 常量(3.1415926f)参与双精度运算,角度换算存在约 1e-7 量级偏差,属既有实现风格。- 精度/量纲提醒:
Temp_track::vr直接取点的Velocity(多普勒)作为径向速度,EKF 关联时用于残差折叠(盲速v_bind)与符号判据;若宿主的Velocity存在模糊,符号判据vr_p·vr_末点 > 0可能失效。 - 输出数组行号可能越界(极端场景):容量判据用
trust_track->size() < track_index_max,而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() < track_index_max。 - 起批质量门限比较的是「末点」质量而非整条航迹质量(V1.5.8):
tmp_track_to_trust_track()取(*Iter)[L-1].quality与按长度取的门限比较,而该质量在 L>3 时只是末点的指数平滑值(L=3 时三点同值),并不代表整条临时航迹的平均质量;长度越大门限越低,实际是「用更宽松的门限校验最新一点」。 - 起批质量来源依赖阶段二:
quality只在「点-临时航迹关联」成功后更新,阶段三产生的 2 点临时航迹不带质量值;长度 3 的临时航迹在第三次延长时写入三点同值,因此其起批质量有定义。若将来把起批点数放宽到 3 以下(当前加载器校验 3~9),则会出现质量恒为 0、永远无法通过质量门限的情况。
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 L22 |
data_preprocess |
一圈完成 → model=1 |
data_process.cpp L167 起 |
track_process |
起始流程调用点(L187-201 调用 track_asso/track_die/track_init) |
data_process.cpp L246-258 |
参数加载 | parameters_reload():TOML 配置 → 全局对象 rdp_parameter(原「参数初始化/修改」已删除) |