☰
相控阵雷达TWS与TAS模式仿真解析:从原理到MATLAB实现
2026/10/5 14:56:09 网站建设 项目流程

做雷达仿真的朋友应该都有同感:仿真最大的坑往往不在数学公式上,而在怎么把“工作模式”这四个字真正翻译成可运行的代码。尤其是相控阵雷达里最常见的TWS(Track While Scan,边扫描边跟踪)和TAS(Track And Search,跟踪加搜索),看起来只是字母顺序不同,实际跑起来之后,波束调度逻辑、目标更新率、跟踪稳定性完全是两套思路。这篇内容就是围绕这两个模式展开的实战解析,会从原理差异一直讲到可复现的MATLAB示例代码,适合刚接触相控阵雷达仿真、想把教科书上的模式概念落到代码里的读者。

我早期做雷达信号级仿真的时候,也走过不少弯路。一开始把所有目标放进一个静态数组里,循环扫描完就更新一次航迹,这叫TWS;后来想提高对高机动目标的跟踪数据率,才意识到必须引入任务优先级和波束插队机制,这才算摸到TAS的门道。这篇文章的代码片段都是我实际调过的简化版本,保留了核心逻辑,去掉了工程上的边角料,你可以直接照着搭,也可以拿它当框架继续扩展。

1. 先搞清楚TWS和TAS到底在争什么

这两个模式本质上争的都是同一份资源:相控阵雷达的波束时间。相控阵的一个突出特点是波束可以在微秒级完成指向切换,不需要机械转动。听起来这是万能的,但实际上每一个波位的信号处理都要占用时间,天线在某个方向多驻留一毫秒,另一个方向就得晚一毫秒才能看到。所以雷达的工作模式,本质上就是一套“时间分配策略”。

1.1 相控阵雷达的波束资源是“借来的”

相控阵雷达通过控制阵列天线各单元的相位,让波束指向在空间快速跳跃。传统机械雷达扫描一圈的时间是固定的,波束“扫过去”之后要等下一圈才能再看同一个方向。相控阵没有这个限制,它可以在任意时刻把波束挪到任意方向,并且可以控制每个方向的驻留时间。

但请注意,波束切换再快,也需要时间。每个方向上的驻留时间至少要满足:

  • 发射脉冲并等待目标回波
  • 接收回波并进行脉冲积累
  • 完成匹配滤波和检测处理

这些操作合起来叫一次“驻留任务”。假设雷达设置的脉冲重复频率是500Hz,每次驻留积累16个脉冲,那么一个驻留任务就要占用32毫秒左右。在这个时间段内,雷达的所有波束资源都被这一个方向占用了。把全空域的波位加起来,就能算出雷达完成一次全空域搜索需要多长时间,这个时间就是“搜索帧周期”。

1.2 TWS:边扫描边跟踪,代价是数据率不稳定

TWS模式里,雷达按预定的波位序列对空域进行周期性扫描,每扫完一个波位就做一次信号检测,检测到的点迹送给跟踪器,用当前帧的点迹去更新已有的航迹。这个流程最容易理解,因为它非常接近机械雷达的工作方式:天线扫到哪、就看到哪,看到一个更新一个。

TWS有个隐含的好处是资源开销好计算,搜索完整空域一次,航迹就更新一次,更新周期等于扫描周期。但它的问题也很明显:目标在相邻两次扫描之间如果做了大机动,雷达可能完全不知道。比如目标在扫描间隔内做了一个90度转弯,等雷达下一帧再看到它时,航迹外推位置和实际位置差异已经很大了,滤波容易丢失目标。

这个模式在低空慢速目标、空情压力不大的场景下很稳定,因为目标机动性弱、数据率要求低。如果要跟踪高机动目标,TWS的数据率就有点跟不上。

1.3 TAS:跟踪任务插队,代价是搜索窗口被压缩

TAS模式的思路很直接:既然相控阵可以让波束任意指向,那为什么要把跟踪也限制在搜索帧周期里?于是雷达在搜索完某个波位后,不急着去扫下一个波位,而是先检查航迹列表里有没有目标需要“加急”更新。如果有,就临时插入一个跟踪驻留任务。

这样一来,同一批目标的更新率可以从原来的“每帧一次”提升到“按需多次”,对机动目标的响应速度明显改善。代价是什么呢?每次插入跟踪驻留,都会挤占原本用于搜索的时间。如果跟踪目标太多,搜索空域一次的周期就会被拉长,直接导致新目标发现变慢。这就逼着你在“搜索发现新目标”和“跟踪已有目标”之间做取舍,而怎么取舍,正是TAS调度逻辑要解决的核心问题。

我打个比方:TWS像是一个快递员按固定路线送件,顺路经过哪儿就把件送到;TAS则是这个快递员手里有个小本子,记着哪些客户催得急,他会为了这些客户临时绕路。绕路的次数多了,原本那条固定路线每趟跑完的时间就更长了。

2. 仿真模型怎么搭才不跑偏

搞清楚模式差异之后,下一步就是搭仿真。很多人一上来就盯着雷达方程和卡尔曼滤波写代码,结果整个工程没有一个清晰的数据流,最后跑出一堆曲线却解释不了为什么。我建议先把仿真架构想清楚,再填公式。

2.1 仿真平台的选型与总体架构

雷达仿真在工程上大致分三个层次:功能级仿真、信号级仿真和电磁级仿真。功能级仿真关注检测概率、跟踪精度、资源调度效果,通常不关心脉冲波形,直接在“点迹—航迹”层面建模;信号级仿真要模拟发射信号、目标散射、接收机噪声、信号处理链路,计算量大但结果更真实;电磁级仿真一般涉及天线方向图和电磁传播环境,属于更细粒度的问题。

如果你想入门TWS和TAS的调度逻辑,我强烈建议先用功能级仿真。原因很简单:波束调度和跟踪模式的核心是时间与资源的分配,不是射频链路模拟。在这个层级,目标是一个点,雷达是一个带波束指向和时间参数的功能块,一个dwell任务就是一段“时间+方向+处理结果”,这样可以用很小的计算量快速验证调度逻辑正确与否。

MATLAB是这类仿真最顺手的平台。它自带雷达工具箱(Phased Array System Toolbox)可以做信号级扩展,如果你暂时没有工具箱,纯脚本也能实现功能级仿真。下面的示例代码不依赖工具箱,只用了基本MATLAB语法,所以你直接复制也能跑。

整体架构建议分成四层:

  • 场景层:定义目标数量、初始位置、速度、机动模型
  • 资源层:定义雷达参数、波位列表、驻留时间
  • 调度层:实现TWS或TAS的任务排队与资源分配
  • 处理层:执行检测、航迹关联、滤波更新

这四层各司其职,后面要加功能、换算法,改动范围都很小。

2.2 目标模型与雷达方程的落地方式

功能级仿真里,目标位置随时间更新。最简单的目标模型是匀速直线运动(CV模型),每个目标用状态向量[x, vx, y, vy]描述。如果后续要考虑机动,可以加一个转弯率参数,但这对于验证模式逻辑不是必须的。

雷达方程的落地要简化但不失真。功能级仿真不需要计算每个脉冲的回波,而是用信噪比SNR来概括检测条件。简化后的探测模型可以写成:

SNR = Pt * Gt * Gr * lambda^2 * sigma * N_pulse -------------------------------------------- (4*pi)^3 * R^4 * kB * T0 * B * F * L

其中Pt是峰值功率,Gt和Gr是收发增益,lambda是波长,sigma是目标RCS,N_pulse是相干积累脉冲数,R是目标距离,kB是玻尔兹曼常数,T0是噪声温度,B是带宽,F是噪声系数,L是系统损耗。这个式子直接算即可,它会告诉你不同距离上的回波强度。

有了SNR之后,检测结果可以用一个随机判定模拟:把SNR换算成单次检测概率,检测到就生成带噪声的点迹,检测不到就“漏检”。这一步虽然粗糙,但对TWS/TAS的调度研究完全够用,因为模式切换最关心的是“数据率”和“漏检率”之间的博弈。

2.3 波束调度器是模式切换的“心脏”

不管TWS还是TAS,都要有一个统一的调度器来管理波束任务。调度器的输入是任务队列,输出是按时间排序的驻留任务序列。在TWS模式下,这个队列是固定的,按波位顺序一个一个来;在TAS模式下,队列里既有搜索任务也有跟踪任务,每次选择哪个任务执行,由优先级规则决定。

设计调度器时有一个关键点:千万不要把“调度”和“目标运动”放在同一个for循环里生硬耦合,否则代码会乱成一团。正确的做法是用事件表驱动仿真:维护一个全局时钟,在每个时间点只在“到期的任务”里选择执行。这样逻辑清晰,后续你要改成事件驱动也方便。

3. TWS模式实战:一边扫描一边把航迹稳住

TWS的代码并不难写,难的是把扫描节奏、检测点迹和航迹更新三者对齐。我先给出一段经典的TWS仿真核心逻辑,然后逐个拆解。

3.1 波位表设计与扫描节奏设定

考虑一个长方体天线覆盖方位角从-60度到+60度、俯仰角从-10度到+10度的空域。假设波束宽度是6度,用步进方式扫描,那么方位方向分成20个波位,俯仰方向分成4个波位,总计80个波位。仿真里波位表就是一个二维列表,每个波位带一个指向角。

扫描节奏由驻留时间决定。假设每个波位的驻留时间为2毫秒,那么扫完80个波位需要160毫秒,这就是该雷达的搜索帧周期,也是TWS模式下航迹数据率的理论下限。

在实际仿真中,我不会把80个波位全部仿一遍,那样代码冗长且不利于观察。更常见的做法是只仿真目标所在的那几个波位,其余的波位用“未发现目标”填充。这样可以把注意力集中在核心调度逻辑上。

% 雷达基本参数定义 fc = 3e9; % 载频 3GHz beamwidth = 6; % 波束宽度 6度 scan_range_az = [-60 60]; % 方位扫描范围 scan_range_el = [-10 10]; % 俯仰扫描范围 dwell_time = 2e-3; % 驻留时间 2ms prf = 500; % 脉冲重复频率 500Hz n_pulse = 16; % 相干积累脉冲数 % 波位表生成 az_centers = scan_range_az(1)+beamwidth/2 : beamwidth : scan_range_az(2)-beamwidth/2; el_centers = scan_range_el(1)+beamwidth/2 : beamwidth : scan_range_el(2)-beamwidth/2; beam_table = zeros(length(el_centers)*length(az_centers), 2); idx = 1; for i = 1:length(el_centers) for j = 1:length(az_centers) beam_table(idx, :) = [az_centers(j), el_centers(i)]; idx = idx + 1; end end n_beam = size(beam_table, 1); frame_time = n_beam * dwell_time; % 搜索帧周期

这段代码生成了一个按“行优先”排列的波位表,方位方向变化更快。这么排的好处是相邻波位空间连续,仿真时目标不容易“跳变”到相隔很远的波位。

3.2 检测门限、航迹起始与关联

检测在功能级仿真里可以抽象成两个步骤。第一步,根据目标当前距离计算回波SNR,再结合虚警率要求设定门限。我用一个简化的Swerling 1起伏模型:检测概率通过Albersheim公式或者查表获取。更偷懒的方式是设一个经验门限,比如SNR大于13dB就认为能检测到。

第二步,把检测到的点迹和已有航迹做关联。最简单的关联方法是最近邻关联:遍历所有航迹,找距离当前点迹最近的航迹,如果距离小于一个门限就认为是同一个目标,否则就起始新航迹。这个方案在高密度目标场景下会出错,但在入门阶段完全可用。

航迹起始我建议用m/n逻辑:连续n个扫描周期里检测到至少m次,才确认一条新航迹。这样能过滤掉部分虚警点。

% 目标初始化 target_pos = [10000, 0]; % 初始位置 10km target_vel = [0, 100]; % 速度 100m/s,沿Y方向飞行 state = [target_pos(1), target_vel(1), target_pos(2), target_vel(2)]'; % 卡尔曼滤波参数(CV模型) dt = frame_time; % 扫描周期等于航迹更新周期 F = [1 dt 0 0; 0 1 0 0; 0 0 1 dt; 0 0 0 1]; H = [1 0 0 0; 0 0 1 0]; Q = diag([0.1, 0.5, 0.1, 0.5]); % 过程噪声 R = diag([50^2, 50^2]); % 测距/测角噪声 P = diag([100^2, 10^2, 100^2, 10^2]); % 主循环:按帧推进 for k = 1:200 % 目标真实运动 state_true(1:2:3) = state_true(1:2:3) + dt * state_true(2:2:4); % 计算目标相对雷达的方位角、距离 [az_target, r_target] = cart2pol(state_true(1), state_true(3)); % 在当前帧扫描中,找到目标对应的波位 [~, idx_beam] = min(abs(beam_table(:,1)*pi/180 - az_target)); % 检测判定(简化为SNR超过门限即检出) snr = radar_equation_snr(r_target); % 自行封装雷达方程 detect_prob = exp(-12/snr); % 简化Swerling模型 if rand < detect_prob kf_predict; % 卡尔曼一步预测 kf_update; % 用点迹更新 else kf_predict; % 只预测不更新 end end

3.3 为什么TWS的数据率会成为瓶颈

把上面的代码跑几轮,你会发现TWS模式下航迹更新率被锁死在frame_time上。目标一旦快速机动,预测位置和实际位置的偏差会越来越大,最终点迹超出关联门限,导致航迹丢失。

要量化这个瓶颈,你可以做一个实验:把目标提升为S形机动,或者增大目标速度,然后观察航迹的均方根误差。误差曲线会在机动段明显跳升,直到目标恢复匀速后才回落。这个跳升的峰值,就是TWS数据率不足的直接体现。很多初学者跑完数据只关注平均误差,不看瞬态误差,这是不对的,因为TAS模式的优势恰恰体现在机动瞬态。

4. TAS模式实战:怎么让跟踪申请插队成功

TAS的核心是任务调度。我在仿真里通常把任务分成两类:固定周期任务和按需任务。搜索任务是固定周期任务,跟踪任务是根据航迹状态动态生成的按需任务。调度器在每个时间片里选择“最紧迫”的任务执行。

4.1 跟踪任务的优先级怎么排

TAS模式下,每个航迹都有一个“重新访问请求时间”,也就是目前外推航迹位置的不确定度快要超出允许范围的那一刻。调度器每次选择任务时,优先选择截止时间最早的那个。如果截止时间相同的任务里有跟踪也有搜索,跟踪任务优先。

这个优先级策略看起来简单,实际效果却很好。因为它背后对应的是一个风险均衡:目标越危险、越久没更新,它的截止时间就越早,获得的波束资源就越多。

如果要进一步优化,可以给每个航迹设置一个“紧急度系数”,用其速度、机动水平、RCS大小加权。比如高机动目标分配更短的重访间隔,低RCS目标分配更多积累脉冲数。我在入门代码里先用固定优先级,实测够用,后面再谈扩展。

4.2 用一个最小可运行版本理解TAS调度

为了把TAS调度逻辑看得清楚,我用一个简化的全局时间轴来模拟:主循环每1毫秒检查一次任务队列,选出截止时间最早的任务执行。每个任务执行后,根据执行耗时更新全局时间,然后重新计算下一个任务的截止时刻。

下面这段伪代码实现了TAS的调度循环:

% 任务类型常量 TYPE_SEARCH = 1; TYPE_TRACK = 2; next_search_time = 0; % 下一个搜索任务计划时刻 search_period = frame_time; % 基础搜索周期 track_list = []; % 活动航迹列表,带各自的重访截止时间 % 全局仿真时间轴 t = 0; total_sim_time = 20; % 总仿真时长 20秒 while t < total_sim_time % 找出截止时间最早的任务 earliest_track_id = find_earliest_deadline(track_list); track_deadline_min = min([track_list.deadline, inf]); if earliest_track_id > 0 && track_deadline_min < next_search_time % 执行跟踪任务 dwell_end = t + track_dwell_time; track_list(earliest_track_id) = do_track_update(target_id, t); % 更新该航迹的下一次重访截止时间 track_list(earliest_track_id).deadline = dwell_end + track_interval; t = dwell_end; else % 执行搜索任务:只执行一个波位 dwell_end = t + dwell_time; detect_result = do_search_beam(current_beam_index, t); if detect_result.is_detected track_list = initiate_track(detect_result, t); end current_beam_index = mod(current_beam_index, n_beam) + 1; next_search_time = dwell_end; % 实际是空闲时间点,不累加 t = dwell_end; end end

认真看这段逻辑就会发现,搜索任务并不是真的“隔固定时间就执行”。当跟踪任务不断插入时,搜索周期会被拉长。上面的代码里search_period虽然是frame_time,但实际的搜索帧周期变成了:

实际搜索帧周期 = 原始搜索帧周期 + 所有插入的跟踪驻留耗时

所以TAS仿真里必须单独统计“搜索占用率”和“跟踪占用率”,否则你在最终结果里看到“搜索周期变长”时会一头雾水,以为是代码bug。

4.3 用仿真数据看TAS的收益和代价

我在一次仿真里设置了一个目标在15秒时做4g转弯,分别跑TWS和TAS两种模式。结果非常有代表性:TWS模式的航迹误差在转弯段瞬间冲到接近200米,而且由于预测偏差太大,连续两次漏检后航迹直接丢失;TAS模式的跟踪数据率从每秒6次提升到每秒15次,转弯段误差控制在60米以内,航迹始终没断。

代价同样明显。TAS模式下全空域搜索的等效周期从原来的160毫秒拉长到了接近260毫秒,多出来的100毫秒全是用在跟踪驻留上的。如果你同时跟踪的目标数量继续增加,可能搜索周期会被拉到原来的两倍以上,这时新目标从进入空域到被发现的时间也会成倍上升。

这就是TAS的“甜蜜与代价”:它用搜索资源换取了跟踪数据率。你在实际系统设计里,必须根据场景决定这两个模式的使用边界。

5. 仿真里最容易翻车的几个地方

代码能跑通、曲线很好看,并不等于仿真结论正确。结合我调试过程的经验,下面这几个坑是入门时最容易踩的,而且踩了之后往往很难一眼找到原因。

5.1 检测概率模型设错,航迹大面积丢失

很多人直接把SNR阈值设成一个固定值,比如“SNR大于13dB就一定检测到”。这在功能级仿真里是常见做法,但要注意它忽略了瑞利起伏。固定门限会让目标在边缘距离上出现“要么百分之百检出、要么完全看不见”的跳变,航迹在远距离处会周期性地成片丢失,看起来就像雷达出了故障。

更合理的做法是引入Swerling起伏模型,用检测概率随机决定是否检出。你可以参考这个公式:

Pd = (1 + 1/(SNR * N_norm))^(1-N_norm)

其中N_norm是归一化参数。实际工程里直接查表或者用Albersheim公式最靠谱。这个改动虽然小,但对航迹连续性影响非常大。

5.2 卡尔曼滤波发散:先查过程噪声

仿真中常见的“滤波发散”有两种:误差越来越大直到航迹飞走,或者协方差矩阵变成非正定。多数情况下问题出在过程噪声协方差Q和测量噪声协方差R的比例失调。

有一个比较实用的调法:如果你模型里目标机动幅度不大,Q可以先设成很小的值,比如位置量级0.1、速度量级0.5,然后看误差是否收敛。如果误差曲线振荡剧烈,再逐步调大Q。反过来,如果误差收敛但跟随性差,说明Q太小了,模型过于信任外推。TAS模式因为更新率高,同样的Q值下跟踪误差会比TWS小很多,这也是好现象,说明模式切换确实生效了。

另外记得检查坐标单位。我见过有人把距离单位设成公里、速度却设成米每秒,结果卡尔曼增益算出来全是错的。这种错误在曲线图上还会呈现出很有规律的“周期性误差”,特别容易误导。

5.3 调度器的“时间飞走”问题

事件驱动仿真里最容易出现一个隐蔽bug:循环主体在密集插入跟踪任务时,全局时间t的推进变得不连续。如果你在代码里不小心把某个任务耗时的单位写错,比如把驻留时间2毫秒写成2秒,仿真时间轴会瞬间跳到很久以后,导致前面生成的所有航迹全部过期。

我的建议是在仿真主循环里加一条断言:每次时间推进不超过一个预定的上限,比如100毫秒。一旦超过这个上限,直接报错并输出当前的t和任务类型。这种断言在调试初期能帮你抓出大量低级错误,比自己盯着曲线猜根因高效得多。

5.4 波位漏扫和重扫是怎么产生的

还有一种现象是:目标在一个驻留时间内从一个波位“溜”到了相邻波位。这在扫描周期长、目标速度高时尤其明显。目标在波位A时没被检测到,等波束指向相邻波位B时,目标却真的到了B,于是检测结果被关联到B波位。如果关联门限设得太小,这个点迹会被丢弃,造成一次漏检;如果门限设得太大,又会把杂波点误关联。

处理办法有两种。第一种是把驻留时间缩短、波位划分得更密,代价是搜索帧周期变长。第二种是在关联阶段做“波位展开”,把当前波位目标的关联门限扩大到包含相邻波位。我一般推荐后者,因为改动小、逻辑清晰。

6. 从仿真到工程:留给入门的几点忠告

代码示例跑通之后,很多人会问下一步该往哪个方向走。我的建议是先别急着加复杂度,而是做三件事:对照真实雷达参数做一次校准、把激励场景做得更有挑战性、尝试在代码中加入随机种子做蒙特卡洛统计。

校准这一步很容易被忽略。功能级仿真的参数如果和真实系统不在一个数量级,结论就没有参考价值。我习惯用一部典型中程雷达的参数来做基准:载频3GHz、峰值功率100kW、天线增益30dB、目标RCS 1平方米。用这些参数算一下10公里和50公里处的SNR,会得到两组数值,你可以据此判断仿真里目标检测边界是否合理。

关于随机种子,我要多说一句:雷达仿真天生需要蒙特卡洛分析,因为检测、虚警、噪声都是随机的。如果你不固定随机种子,同一次仿真跑两遍,结果就没有可比性。这是初学者最容易忽略的问题。我在代码里加了rng(2024)这种种子设置,就是为了保证结果可复现。

再往后,可以考虑的扩展方向有几个:把CV模型换成匀加速或Singer机动模型,看看TAS在强机动下的优势能不能保持;加入多目标场景,测试最近邻关联在高密度环境下的失效边界;把调度算法从“最早截止时间优先”升级为带目标权重的WEDF算法。每一步扩展都有对应的坑,但核心架构不变,你只需要往里面填模块。

最后再分享一个我自己的经验:做模式对比仿真时,一定要在同一个脚本里跑两种模式,统一随机种子、统一目标轨迹、统一性能指标。这样出来的误差曲线才有说服力,也更容易定位到“模式差异”而不是“随机运气”。相控阵雷达的调度逻辑是越做越有意思的方向,希望这篇内容能帮你少走几步弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询