本文以一个完整的作战场景为例,手把手教你用 MATLAB 二次开发 STK Aviator,实现飞机航线自动建模、巡逻航线设计、轨迹传播和数据提取。全文约 230 行代码,4 架飞机,覆盖 Aviator 二次开发的核心流程和常见陷阱。
一、故事从一个凌晨开始
假设你是一名作战规划参谋。凌晨 3 点,雷达捕捉到一架不明飞机从西北方向逼近我国沿海。你需要紧急规划以下任务:
- 预警机(AWACS E-3):立即从基地起飞,前往指定空域建立预警巡逻航线,持续监视目标
- 战斗机(Fighter ×2):梯次起飞,前往预警机前方的战斗空中巡逻(CAP)站,准备拦截
- 威胁目标(Threat):模拟不明飞机的入侵航线,用于评估防御方案是否有效
如果用 STK 的图形界面(GUI)一步步点,一架飞机的航线可能就要 10 分钟,改个参数又要重来。而你需要在 30 分钟内给出 3 套不同巡逻半径的对比方案。
这就是二次开发的意义:用代码把 GUI 操作变成可重复、可批量、可参数化的自动化流程。改一个数字就能生成一套新方案。
下面,我们就从零开始,用大约 230 行 MATLAB 代码完成这个完整场景。
二、环境准备:让 MATLAB 和 STK 对话
2.1 你需要什么
- STK 12(Systems Tool Kit)--- 已安装并激活
- MATLAB --- 任意较新版本(R2020b 及以上推荐)
- 无需额外工具箱,MATLAB 自带的 COM 自动化接口即可
2.2 两行代码连接 STK
STK 提供了两种连接方式:
| 模式 | 连接代码 | 特点 |
|---|---|---|
| STKX Engine(推荐调试用) | actxserver('STKX12.Application') |
无 GUI,启动快,省内存 |
| STK GUI(最终交付用) | actxserver('STK12.Application') |
有完整界面,可保存可视化场景 |
在开发调试阶段,我们用 STKX Engine------它不弹出窗口,运行速度快,非常适合反复迭代:
matlab
% 启动 STKX Engine(无界面模式)
app = actxserver('STKX12.Application');
app.NoGraphics = true;
pause(1); % 等待引擎初始化
root = actxserver('AgStkObjects12.AgStkObjectRoot');
为什么需要 pause(1)? STKX 引擎启动需要一点时间,如果不等待,后续操作可能报错。1 秒足够了。
2.3 创建场景
连接成功后,第一步是创建场景(Scenario),相当于建一个空白的"沙盘":
matlab
try root.CloseScenario(); catch; end % 关闭已有场景
root.NewScenario('AWACS_v2_ZigZag');
scenario = root.CurrentScenario;
% 设置场景时间窗口(3 小时足够这次任务)
scenario.SetTimePeriod('30 Apr 2026 00:00:00.000', '30 Apr 2026 03:00:00.000');
scenario.Epoch = '30 Apr 2026 00:00:00.000';
为什么场景设 3 小时? 因为预警机巡逻约 108 分钟,加上起降和航渡时间,3 小时窗口足够覆盖整个任务。
到这里,MATLAB 和 STK 的连接就完成了。接下来进入核心部分------Aviator 的航线建模。
三、理解 Aviator 的架构:从飞机到航段
在写代码之前,必须理解 Aviator 的数据结构。它是一个层层嵌套的架构:
Aircraft(飞机)
└── Route(航线容器,需设置为 Aviator 传播器)
└── AvtrPropagator(Aviator 传播器)
└── AvtrMission(任务)
└── Phase(阶段)× N
└── Procedure(航段)× N
打个比方:
- Aircraft 是演员
- AvtrMission 是剧本
- Phase 是一幕戏(可以有多幕)
- Procedure 是每一场戏的具体动作
对于我们的场景,每架飞机只需要 1 个 Phase,里面包含多个 Procedure(起飞、巡航、巡逻、返航等)。
3.1 创建飞机的固定套路
每架飞机的创建遵循相同的模式:
matlab
ac = scenario.Children.New('eAircraft', 'AWACS_E3'); % 创建飞机对象
ac.SetRouteType('ePropagatorAviator'); % 告诉 STK 用 Aviator 传播器
prop = ac.Route.AvtrPropagator; % 获取传播器
m = prop.AvtrMission; % 获取任务对象
phase = m.Phases.Add(); % 添加一个阶段
phase.SetDefaultPerfModels(); % 加载默认性能模型(重要!)
SetDefaultPerfModels() 是什么? Aviator 需要飞机的性能参数(速度、爬升率、油耗等)才能计算轨迹。这行代码加载一套内置的默认性能模型,让我们无需手动配置就能开始飞行。
3.2 最基本的飞行单元:Waypoint + Enroute
Aviator 中最基本的飞行段是 eSiteWaypoint(航点)+ eProcEnroute(航段类型),含义是"飞到这个坐标点":
matlab
p = phase.Procedures.Add('eSiteWaypoint', 'eProcEnroute');
p.Site.Latitude = 47.5; % 纬度
p.Site.Longitude = -126.5; % 经度
p.AltitudeMSLOptions.UseDefaultCruiseAltitude = false;
p.AltitudeMSLOptions.MSLAltitude = 9000; % 高度(英尺!)
注意高度单位! Aviator 的 MSLAltitude 使用英尺 ,不是米。9000 英尺 ≈ 2743 米。后续从 DataProvider 读取的高度数据则是千米------这个单位不一致是初学者最容易掉进去的坑之一。
为了简化重复代码,我们写一个辅助函数:
matlab
function addWP(phase, lat, lon, alt)
p = phase.Procedures.Add('eSiteWaypoint', 'eProcEnroute');
p.Site.Latitude = lat;
p.Site.Longitude = lon;
p.AltitudeMSLOptions.UseDefaultCruiseAltitude = false;
p.AltitudeMSLOptions.MSLAltitude = alt; % 英尺
end
有了这个函数,添加航点只需要一行:addWP(phase, 47.5, -126.5, 9000)。
关键概念:"首相语义" :在同一个 Phase 中,第一个 eSiteWaypoint 只定义飞机的起始位置------飞机"瞬间"出现在那里,不消耗飞行时间。实际的飞行从第二个 Procedure 开始。这意味着如果你设计一条航线 "A→B→C→D",第一个点 A 不会产生飞行轨迹,B→C→D 才是实际飞行路径。
理解了架构和基本单元后,我们开始构建完整场景。
四、逐步构建:从一架飞机到完整场景
4.1 战术布局总览
先看全局布局,理解各架飞机的空间关系:
西北 ← 威胁目标 (52.0°N / 137.0°W,从远海入侵)
|
| 入侵方向 (向东南)
↓
战斗机 CAP 站 (48.0~48.5°N / 127.5~128.0°W,前出截击)
↑ |
| ↓ (zigzag 巡逻)
预警机巡逻区 (47.3~47.8°N / 127.0~128.0°W)
|
↓
KHQM 基地 (47.1°N / 124.1°W)
预警机在后方巡逻,战斗机前出到预警机和威胁之间,形成纵深防御。
4.2 第一架飞机:Threat Target(最简单的纯航点飞行)
威胁目标最简单------一条直线从西北飞过来,没有巡逻、没有盘旋。
matlab
threatProp = threat.Route.AvtrPropagator;
threatM = threatProp.AvtrMission;
thPh = threatM.Phases.Add(); thPh.SetDefaultPerfModels();
% 起点 (52.0N/137.0W) --- 瞬间出现在这里
addWP(thPh, 52.0, -137.0, 26247);
% 逐步向东南入侵
addWP(thPh, 50.5, -132.0, 26247); % 第 1 段巡航
addWP(thPh, 49.0, -129.0, 26247); % 第 2 段巡航
addWP(thPh, 48.2, -127.5, 26247); % 第 3 段,接近战斗机 CAP 区
addWP(thPh, 47.5, -126.5, 22966); % 最终逼近预警机巡逻区
为什么高度是 26247 和 22966 这种奇怪数字?因为单位是英尺:
| 实际高度 | 英尺 | 代码中的值 |
|---|---|---|
| 8000 m | 26247 ft | 26247 |
| 7000 m | 22966 ft | 22966 |
转换公式:feet = meters × 3.28084
这条航线总共约 1100 km,Aviator 会根据默认性能模型自动计算飞行时间(约 73 分钟)。
4.3 第二架飞机:AWACS 预警机(引入巡逻需求)
预警机是场景的核心。它需要飞到指定空域后持续巡逻------在目标区域来回飞行,保持雷达覆盖。
理想方案 vs 现实方案
理想情况下,我们希望预警机绕一个圆形航线盘旋(Stationkeeping):
matlab
% 理想方案(但需要 Aviator Pro 许可证!)
p2 = phase.Procedures.Add('eSiteEndOfPrevProcedure', 'eProcBasicManeuver');
p2.NavigationStrategyType = 'Stationkeeping';
但这里有个大坑:Stationkeeping 是 Aviator Pro 的付费功能。如果你只有基础版 Aviator 许可证:
- 设置参数不会报错(
DesiredRadius、StopCondition等都可以写入) - 但传播时静默失败,只返回 1 个数据点------飞机根本没飞
实际方案:Zigzag Enroute 巡逻
解决方案是用一系列来回交替的航点模拟巡逻,称为"zigzag"模式:
●────────────→●
|
●←────────────●
|
●────────────→●
代码实现:
matlab
awacsProp = awacs.Route.AvtrPropagator;
awacsM = awacsProp.AvtrMission;
awPh = awacsM.Phases.Add(); awPh.SetDefaultPerfModels();
% 1. 起点:KHQM 基地
addWP(awPh, 47.1, -124.1, 9000);
% 2. 航渡:飞往巡逻区入口
addWP(awPh, 47.5, -126.5, 9000);
% 3. Zigzag 巡逻:纬度在 47.3~47.8 之间来回
awacsPatrol = [...
47.8, -127.5; % 北端
47.3, -127.0; % 南端
47.8, -128.0; % 北端
47.3, -127.5; % 南端
47.8, -127.0; % 北端
47.3, -128.0; % 南端
47.8, -127.5; % 北端
47.3, -127.0; % 南端
47.8, -128.0; % 北端
47.3, -127.5]; % 南端
for k = 1:size(awacsPatrol, 1)
addWP(awPh, awacsPatrol(k,1), awacsPatrol(k,2), 9000);
end
% 4. 返回基地
addWP(awPh, 47.1, -124.1, 5000);
为什么是 10 段 zigzag? 因为默认性能模型的燃油只支持约 108 分钟的连续飞行。10 段 zigzag 巡逻约 70 分钟,加上航渡和返回,总计约 108 分钟------刚好用完燃油。如果飞得更久,传播器会因为燃油耗尽而提前终止。
巡逻航点的设计思路:
- 纬度跨度 0.5°(约 55 km)形成巡逻纵深
- 经度交错(-127.0 ~ -128.0)形成巡逻宽度
- 每段约 60~80 km,飞行约 7 分钟,10 段共约 70 分钟
4.4 第三四架飞机:Fighter(复用代码模式)
两架战斗机复用完全相同的代码模式,只是巡逻区域略有错开:
matlab
fighterPatrol = [...
48.5, -128.0;
47.8, -127.5;
48.5, -127.0;
47.8, -128.0;
48.5, -127.5;
47.8, -127.0];
for fi = 1:2
if fi == 1
capLat = 48.2; % Fighter_01 的 CAP 站偏北
else
capLat = 48.0; % Fighter_02 的 CAP 站偏南
end
fPh = fM.Phases.Add(); fPh.SetDefaultPerfModels();
% 起点 → 中转 → CAP 站 → zigzag 巡逻 → 返回
addWP(fPh, 47.1, -124.1, 32808); % KHQM 基地
addWP(fPh, 47.5, -126.0, 32808); % 中转
addWP(fPh, capLat, -127.5, 32808); % CAP 站
for k = 1:size(fighterPatrol, 1)
addWP(fPh, fighterPatrol(k,1), fighterPatrol(k,2), 32808);
end
addWP(fPh, 47.1, -124.1, 16404); % 返回(低高度)
end
为什么战斗机高度是 32808? 32808 ft = 10000 m,战斗机的典型巡航高度。16404 ft = 5000 m,返航时降低高度。
注意代码的复用:addWP() 函数被所有飞机共用,fighterPatrol 矩阵被两架战斗机共用,只是 capLat 不同------这就是代码化建模的优势,改一个参数就生成一个新方案。
五、传播与数据提取:看到结果
5.1 一行代码完成传播
matlab
prop.Propagate();
这一行做了什么?Aviator 根据飞机性能模型、风速、大气条件等,计算飞机在每个时刻的位置、速度、高度等状态。过程全自动------你只需要定义"飞到哪些点",传播器帮你算"怎么飞过去"。
5.2 提取飞行数据
传播完成后,通过 DataProvider 提取数据:
matlab
dp = ac.DataProviders.Item('LLA State').Group.Item('Fixed');
result = dp.ExecElements(scenario.StartTime, scenario.StopTime, 60, ...
{'Time'; 'Lat'; 'Lon'; 'Alt'});
各参数含义:
'LLA State'--- 经纬高状态数据'Fixed'--- 固定时间步长60--- 每 60 秒采样一次{'Time';'Lat';'Lon';'Alt'}--- 需要的数据字段
提取具体数值:
matlab
t = result.DataSets.GetDataSetByName('Time').GetValues();
lat = result.DataSets.GetDataSetByName('Lat').GetValues();
lon = result.DataSets.GetDataSetByName('Lon').GetValues();
alt = result.DataSets.GetDataSetByName('Alt').GetValues();
注意数据类型! STK 返回的数据可能是 cell 数组也可能是 numeric 数组,需要统一处理:
matlab
if iscell(alt)
altNum = cellfun(@double, alt);
else
altNum = double(alt);
end
altMeters = altNum * 1000; % DataProvider 返回 km,转为 m
5.3 保存场景
matlab
root.SaveScenarioAs('path/to/AWACS_v2.sc');
保存后可以用 STK GUI 打开,查看三维可视化效果。
5.4 预期输出
运行完整代码后,你会看到类似输出:
[Threat] 74 pts | 00:00:00 ~ 01:13:xx | Alt: 7000~8000 m
[AWACS] 104 pts | 00:00:00 ~ 01:42:xx | Alt: 1500~2743 m
[Fighter_01] 80 pts | 00:00:00 ~ 01:15:xx | Alt: 1500~10000 m
[Fighter_02] 80 pts | 00:00:00 ~ 01:15:xx | Alt: 1500~10000 m
4 架飞机全部传播成功,各有完整的时间跨度和空间范围。
六、Aviator 功能全景图:基础版能做什么,Pro 才能做什么
在写代码之前,你需要知道手头有哪些工具可以用。STK Aviator 分为两个许可级别:基础版(Aviator) 和 专业版(Aviator Pro)。下面的内容帮你一次性搞清楚。
6.1 总览
┌─────────────────────────────────────────────────────────────┐
│ Aviator 基础版(你有) │
│ │
│ ✈ 航线建模:Waypoint / Runway / 各种 Site │
│ ✈ 飞行段:Enroute / Takeoff / Landing / Holding ... │
│ ✈ 基础机动:Turn / Loop / Roll / Straight Ahead ... │
│ ✈ 性能模型:Climb / Cruise / Descent / Accel ... │
│ ✈ 高级工具:Advanced Fixed Wing / 外部气动 / Wind │
│ ✈ 搜索模式:Parallel Flight Line / Area Target Search │
│ ✈ 空中加油:Refuel / Dump Tool │
├─────────────────────────────────────────────────────────────┤
│ Aviator Pro(你没有) │
│ │
│ 🔒 高级导航:Stationkeeping / Intercept / Bearing / 编队 │
│ 🔒 空战模拟:Air Combat Simulation Tool │
│ 🔒 导弹模型:User-Defined Missile Models │
│ 🔒 旋翼机模型:User-Defined Rotorcraft Models │
└─────────────────────────────────────────────────────────────┘
6.2 Site 类型(定义"在哪里")
Site 决定了飞机在哪个位置执行动作。以下是基础版可用的所有 Site:
| Site 类型 | COM 枚举 | 说明 | 注意事项 |
|---|---|---|---|
| Waypoint | eSiteWaypoint |
手动指定经纬度 | 最常用,本文全部使用此类型 |
| End of Previous Procedure | eSiteEndOfPrevProcedure |
接上一个航段的终点 | 用于连续动作(如 Basic Maneuver) |
| Runway | eSiteRunway |
指定跑道 | COM 中坐标可能不正确(见踩坑 4) |
| Runway from Catalog | eSiteRunwayFromCatalog |
从目录选取跑道 | 需要 Catalog Manager 数据 |
| Airport from Catalog | eSiteAirportFromCatalog |
从目录选取机场 | 需要 Catalog Manager 数据 |
| Waypoint from Catalog | eSiteWaypointFromCatalog |
从目录选取航点 | 需要 Catalog Manager 数据 |
| Navaid from Catalog | eSiteNavaidFromCatalog |
从目录选取导航台 | 需要 DAFIF/ARINC424 数据 |
| Relative to Previous | eSiteRelativeToPreviousProcedure |
相对上一航段偏移 | 用于精确定位 |
| STK Object Waypoint | eSiteStkObjectWaypoint |
引用场景中其他对象 | 关联卫星、地面站等 |
| STK Vehicle | eSiteStkVehicle |
引用场景中飞行器 | 关联其他飞机 |
| STK Area Target | eSiteStkAreaTarget |
引用区域目标 | 用于搜索任务 |
| STK Static Object | eSiteStkStaticObject |
引用静态对象 | 地面设施等 |
| VTOL Point | eSiteVtolPoint |
垂直起降点 | 直升机/VTOL 专用 |
| VTOL Point from Catalog | eSiteVtolPointFromCatalog |
从目录选取 VTOL 点 | 需要 Catalog 数据 |
| Reference State | eSiteReferenceState |
参考状态 | 高级定位 |
| Super Procedure | eSiteSuperProcedure |
超级过程入口 | 复合过程 |
实际开发建议 :90% 的情况用 eSiteWaypoint 和 eSiteEndOfPrevProcedure 就够了。
6.3 Procedure 类型(定义"做什么")
Procedure 决定了飞机执行什么动作。以下是基础版可用的所有 Procedure:
航线飞行类
| Procedure 类型 | COM 枚举 | 说明 | 典型用途 |
|---|---|---|---|
| Enroute | eProcEnroute |
从当前位置飞到目标点 | 最基本、最常用的飞行段 |
| Basic Point to Point | eProcBasicPoint2Point |
简化的点到点飞行 | 短距离精确飞行 |
| Arc Enroute | eProcArcEnroute |
沿弧线飞行 | 转弯航线、绕飞 |
| Arc Point to Point | eProcArcPoint2Point |
弧线点到点 | 精确弧形航线 |
| Airway | eProcAirway |
沿航路飞行 | 民航航路跟随 |
| Terrain Following | eProcTerrainFollowing |
地形跟随飞行 | 低空突防 |
| Parallel Flight Line | eProcParallelFlightLine |
平行线搜索 | 区域搜索扫描 |
| Area Target Search | eProcAreaTargetSearch |
区域目标搜索 | 搜索救援、侦察 |
起降类
| Procedure 类型 | COM 枚举 | 说明 | 注意事项 |
|---|---|---|---|
| Takeoff | eProcTakeoff |
起飞 | 需配合 eSiteRunway(COM 中坐标有问题) |
| Landing | eProcLanding |
着陆 | 必须配 eSiteRunway,不能配 Waypoint |
| Vertical Takeoff | eProcVerticalTakeoff |
垂直起飞 | VTOL/直升机专用 |
| Vertical Landing | eProcVerticalLanding |
垂直着陆 | VTOL/直升机专用 |
| Launch | eProcLaunch |
发射 | 导弹/无人机发射 |
巡航待命类
| Procedure 类型 | COM 枚举 | 说明 | 注意事项 |
|---|---|---|---|
| Holding Racetrack | eProcHoldingRacetrack |
跑道形待命 | 只能用作最后一个航段,否则堆损坏 |
| Holding Circular | eProcHoldingCircular |
圆形待命 | 在指定点上空画圆等待 |
| Holding Figure-8 | eProcHoldingFigure8 |
8 字形待命 | 适用于特定等待航线 |
| Hover | eProcHover |
悬停 | VTOL/直升机专用 |
| Hover Translate | eProcHoverTranslate |
悬停移动 | 直升机平移 |
基础机动类(eProcBasicManeuver)
Basic Maneuver 是一个通用机动容器,通过 NavigationStrategyType 选择具体的机动类型:
基础版可用:
| 策略名 | 说明 | 用途 |
|---|---|---|
StraightAhead |
直线飞行 | 简单前进 |
SimpleTurn |
简单转弯 | 改变航向 |
SmoothTurn |
平滑转弯 | 柔和转向 |
AileronRoll |
副翼滚转 | 特技机动 |
BarrelRoll |
桶滚 | 特技机动 |
Loop |
筋斗 | 特技机动 |
Pull |
拉起 | 爬升机动 |
RollingPull |
滚转拉起 | 组合机动 |
Weave |
蛇形机动 | 闪避飞行 |
Glide |
滑翔 | 无动力下降 |
Cruise |
巡航机动 | 持续平飞 |
Autopilot (Horiz) |
水平自动驾驶 | 水平面控制 |
Autopilot (Vert) |
垂直自动驾驶 | 垂直面控制 |
Profile Segment (Bezier) |
贝塞尔曲线剖面 | 平滑轨迹 |
Profile Segment (Push/Pull) |
推拉剖面 | 精确高度剖面 |
Fly Angle of Attack |
迎角飞行 | 高级气动控制 |
Pitch 3D |
三维俯仰 | 全姿态控制 |
Hover |
悬停机动 | VTOL 专用 |
需要 Pro 许可证(不可用):
| 策略名 | 说明 | 表现 |
|---|---|---|
Stationkeeping |
保持站位盘旋 | 静默失败,只返回 1 个点 |
Intercept |
截击机动 | 报 "required license" 错误 |
RelativeBearing |
相对方位 | 报 "required license" 错误 |
RendezvousFormation |
编队飞行 | 报 "required license" 错误 |
转换类
| Procedure 类型 | COM 枚举 | 说明 |
|---|---|---|
| Transition to Forward Flight | eProcTrans2FwdFlight |
从悬停转前飞 |
| Transition to Hover | eProcTrans2Hover |
从前飞转悬停 |
| In Formation | eProcInFormation |
编队飞行 |
6.4 Performance Model 类型(定义"飞得怎么样")
Performance Model 定义飞机的飞行性能。通过 SetDefaultPerfModels() 会加载一套默认配置,你也可以为每个 Phase 单独设置:
| 性能模型 | 文件名 | 说明 |
|---|---|---|
| Basic Climb | pm_basicClimb.htm |
基础爬升模型 |
| Advanced Climb | pm_advClimb.htm |
高级爬升(考虑速度/高度剖面) |
| Sequenced Climb | pm_seqClimb.htm |
序列爬升(多段爬升) |
| Basic Cruise | pm_basicCruise.htm |
基础巡航模型 |
| Advanced Cruise | pm_advCruise.htm |
高级巡航 |
| Basic Descent | pm_basicDescent.htm |
基础下降模型 |
| Advanced Descent | pm_advDescent.htm |
高级下降 |
| Sequenced Descent | pm_seqDescent.htm |
序列下降 |
| Basic Takeoff | pm_basicTakeoff.htm |
基础起飞模型 |
| Advanced Takeoff | pm_advTakeoff.htm |
高级起飞 |
| Basic Landing | pm_basicLanding.htm |
基础着陆模型 |
| Advanced Landing | pm_advLanding.htm |
高级着陆 |
| Basic Acceleration | pm_basicAccel.htm |
基础加速模型 |
| Advanced Acceleration | pm_advAccel.htm |
高级加速 |
| Terrain Follow | pm_terrainFollow.htm |
地形跟随模型 |
| VTOL | pm_vtol.htm |
垂直起降模型 |
6.5 其他基础版工具
| 工具 | 说明 |
|---|---|
| Advanced Fixed Wing Tool | 固定翼高级配置:气动、发动机、结构限制 |
| 外部气动文件 | .aero 文件导入(对飞行时间无影响,已验证) |
| Wind / Atmosphere Model | 风场和大气建模 |
| Refuel / Dump Tool | 空中加油和放油 |
| Catalog Manager | 飞机/机场/航路目录管理 |
| 3D Route Editing | 三维航线编辑 |
| Flight Range / Area Tool | 航程和覆盖范围分析 |
| Time / Fuel Ruler | 时间和燃油计算工具 |
| Mission Profile | 任务剖面可视化 |
6.6 Pro 独占功能(不可用)
| 功能 | 说明 | 为什么需要 |
|---|---|---|
| Stationkeeping | 绕目标点圆形盘旋 | 预警机巡逻、目标跟踪 |
| Intercept | 截击机动,实时追踪目标 | 战斗机拦截 |
| Relative Bearing | 保持与目标的相对方位 | 护航、跟踪 |
| Rendezvous / Formation | 编队飞行 | 多机协同 |
| Air Combat Simulation | 双机空战模拟 | 战术对抗分析 |
| Missile Models | 导弹性能模型 | 武器投放仿真 |
| Rotorcraft Models | 旋翼机性能模型 | 直升机任务规划 |
特别注意 :Stationkeeping 是最危险的 Pro 功能------它不报错,只是静默返回 1 个数据点。其他 Pro 功能会直接报 "required license" 错误,很容易发现。但 Stationkeeping 的静默失败会让人以为代码没问题,只是飞机没飞。
七、踩坑实录:那些文档不会告诉你的事
在开发过程中,我遇到了很多官方文档没有提及的问题。以下按严重程度排列,希望能帮你避开这些坑。
坑 1:Stationkeeping 不工作(★★★★★ 最关键)
现象 :eProcBasicManeuver + NavigationStrategyType = 'Stationkeeping' 传播不报错,但只返回 1 个数据点,飞机没有飞行。
根因 :Stationkeeping 是 Aviator Pro 的付费功能。没有 Pro 许可证时,参数接口不锁(你可以设置 DesiredRadius、StopCondition 等),但传播器静默跳过,不产生轨迹。
解决方案:用 zigzag Enroute 替代(详见 4.3 节)。
受影响的功能清单(均需 Aviator Pro 许可证):
| 功能 | NavigationStrategyType | 表现 |
|---|---|---|
| Intercept | 'Intercept' |
报错 "required license" |
| Relative Bearing | 'RelativeBearing' |
同上 |
| Rendezvous/Formation | 'RendezvousFormation' |
同上 |
| Stationkeeping | 'Stationkeeping' |
静默失败(最危险!) |
| Air Combat Simulation | --- | 不可用 |
| Missile Models | --- | 不可用 |
| Rotorcraft Models | --- | 不可用 |
坑 2:默认燃油只够飞 ~108 分钟(★★★★)
现象:无论航线多长,飞机飞行约 1 小时 48 分钟后传播自动终止。
根因 :SetDefaultPerfModels() 加载的默认飞机有 160,000 单位燃油(只读属性),约支持 108 分钟连续飞行。默认配置的燃油属性几乎全部只读,无法通过 COM 接口修改。
解决方案:设计航线时将总飞行时间控制在 108 分钟以内。如果需要更长航时,需要通过 STK GUI 配置自定义飞机性能模型(COM 接口目前无法修改燃油参数)。
坑 3:高度单位不一致(★★★)
现象:设置高度 9000,但 DataProvider 返回的高度在 2~3 之间。
根因 :MSLAltitude 的单位是英尺 ,DataProvider 返回的 Alt 单位是千米。
输入: MSLAltitude = 9000 (ft) = 2743 m
输出: Alt = 2.743 (km)
解决方案:
matlab
% 输入时:米 → 英尺
MSLAltitude = round(meters * 3.28084);
% 读取时:km → 米
altMeters = altFromDP * 1000;
坑 4:eSiteRunway 在 COM 中坐标不正确(★★★)
现象 :使用 eSiteRunway + eProcTakeoff 创建起飞航段时,飞机从坐标 (0, 0) 出发,而不是从跑道位置出发。
根因 :STK 12 的 COM 自动化接口不解析 eSiteRunway 的跑道坐标。
解决方案 :用 eSiteWaypoint 在机场坐标设定起始位置,替代 eSiteRunway。
坑 5:"首相语义"容易误解(★★)
现象:设计了 5 个航点的航线,但第一个航点到第二个航点之间没有飞行轨迹。
根因 :在同一个 Phase 中,第一个 eSiteWaypoint 只设定起始位置(瞬间完成),不产生飞行。
解决方案:在设计航线时,把第一个航点当作"出发点",从第二个航点开始才是实际飞行。如果需要从第一个点飞行到第二个点,确保你的"第一个点"只是设定起始位置。
八、总结
通过这篇教程,我们完成了:
- MATLAB 连接 STK --- 2 行核心代码
- 理解 Aviator 架构 --- Aircraft → Route → Propagator → Mission → Phase → Procedure
- 构建 4 架飞机的完整作战场景 --- 威胁入侵、预警机巡逻、战斗机 CAP
- 掌握 zigzag Enroute 巡逻方案 --- 基础版 Aviator 唯一可靠的巡逻方法
- 数据提取与保存 --- DataProvider 获取轨迹,保存为 STK 场景文件
核心代码模式只有一种:
matlab
ac = scenario.Children.New('eAircraft', '名称');
ac.SetRouteType('ePropagatorAviator');
prop = ac.Route.AvtrPropagator;
m = prop.AvtrMission;
phase = m.Phases.Add();
phase.SetDefaultPerfModels();
% 然后反复调用 addWP(phase, lat, lon, alt) 添加航点
prop.Propagate(); % 传播
% 通过 DataProvider 提取数据
整个场景约 230 行代码,但核心逻辑就是上面的模式。掌握了这个模式,你就可以开始构建自己的飞机航线模型了。
完整代码见 AWACS_Scenario_v2.m。