能力标签:起降建模 / 跑道占用 / 助推段弹道 / 多阶段机动 / 阶段切换
这个 demo 在展示什么
上篇讲了 P6DOF 的"飞行"。但 six_dof 能力真正有意思的是它把 P6DOF 用到了两种带阶段切换的场景:
- 机场运作:飞机不是凭空出现在巡航高度,而是从跑道起飞、爬升、任务、进近、降落。这涉及跑道占用、起飞窗口、起落航线。
- 弹道导弹投送:导弹先靠火箭助推(动力段),关机后进入无动力的弹道滑行(再入段)。同一枚弹,前后两段的机动模型完全不同。
这两类场景的共同点是:一个平台在其生命周期里会切换"怎么动"。这正是 AFSIM 多 mover / 阶段 movers 机制要解决的。
核心机制一:阶段切换的两种实现
#mermaid-svg-LWIK9hUEfOmZT1No{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LWIK9hUEfOmZT1No .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LWIK9hUEfOmZT1No .error-icon{fill:#552222;}#mermaid-svg-LWIK9hUEfOmZT1No .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LWIK9hUEfOmZT1No .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LWIK9hUEfOmZT1No .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LWIK9hUEfOmZT1No .marker.cross{stroke:#333333;}#mermaid-svg-LWIK9hUEfOmZT1No svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LWIK9hUEfOmZT1No p{margin:0;}#mermaid-svg-LWIK9hUEfOmZT1No .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LWIK9hUEfOmZT1No .cluster-label text{fill:#333;}#mermaid-svg-LWIK9hUEfOmZT1No .cluster-label span{color:#333;}#mermaid-svg-LWIK9hUEfOmZT1No .cluster-label span p{background-color:transparent;}#mermaid-svg-LWIK9hUEfOmZT1No .label text,#mermaid-svg-LWIK9hUEfOmZT1No span{fill:#333;color:#333;}#mermaid-svg-LWIK9hUEfOmZT1No .node rect,#mermaid-svg-LWIK9hUEfOmZT1No .node circle,#mermaid-svg-LWIK9hUEfOmZT1No .node ellipse,#mermaid-svg-LWIK9hUEfOmZT1No .node polygon,#mermaid-svg-LWIK9hUEfOmZT1No .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LWIK9hUEfOmZT1No .rough-node .label text,#mermaid-svg-LWIK9hUEfOmZT1No .node .label text,#mermaid-svg-LWIK9hUEfOmZT1No .image-shape .label,#mermaid-svg-LWIK9hUEfOmZT1No .icon-shape .label{text-anchor:middle;}#mermaid-svg-LWIK9hUEfOmZT1No .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LWIK9hUEfOmZT1No .rough-node .label,#mermaid-svg-LWIK9hUEfOmZT1No .node .label,#mermaid-svg-LWIK9hUEfOmZT1No .image-shape .label,#mermaid-svg-LWIK9hUEfOmZT1No .icon-shape .label{text-align:center;}#mermaid-svg-LWIK9hUEfOmZT1No .node.clickable{cursor:pointer;}#mermaid-svg-LWIK9hUEfOmZT1No .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LWIK9hUEfOmZT1No .arrowheadPath{fill:#333333;}#mermaid-svg-LWIK9hUEfOmZT1No .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LWIK9hUEfOmZT1No .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LWIK9hUEfOmZT1No .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LWIK9hUEfOmZT1No .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LWIK9hUEfOmZT1No .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LWIK9hUEfOmZT1No .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LWIK9hUEfOmZT1No .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LWIK9hUEfOmZT1No .cluster text{fill:#333;}#mermaid-svg-LWIK9hUEfOmZT1No .cluster span{color:#333;}#mermaid-svg-LWIK9hUEfOmZT1No div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LWIK9hUEfOmZT1No .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LWIK9hUEfOmZT1No rect.text{fill:none;stroke-width:0;}#mermaid-svg-LWIK9hUEfOmZT1No .icon-shape,#mermaid-svg-LWIK9hUEfOmZT1No .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LWIK9hUEfOmZT1No .icon-shape p,#mermaid-svg-LWIK9hUEfOmZT1No .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LWIK9hUEfOmZT1No .icon-shape .label rect,#mermaid-svg-LWIK9hUEfOmZT1No .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LWIK9hUEfOmZT1No .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LWIK9hUEfOmZT1No .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LWIK9hUEfOmZT1No :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 切换事件
(关机/离地/触地)
一个平台
生命周期
阶段一:动力/滑跑
mover 参数集 A
阶段二:滑行/巡航
mover 参数集 B
统一平台状态
对外暴露
无论起降还是导弹,本质都是"一个平台在不同时间用不同机动规则"。在 AFSIM 里你有两条路:
- 多 mover 列表:给平台挂多个 mover,用脚本/事件控制哪个生效。
- 单 mover + 脚本 :在
WSF_SCRIPT_PROCESSOR的on_update钩子里根据时间/状态改 mover 参数。
简单场景用 1,复杂状态机用 2。
真实可跑的最小片段(AFSIM 2.9 语法,示意)
机场起降在 AFSIM 里不是特殊 movers,而是 P6DOF mover + 一段描述起降的航线(route)+ 控制逻辑的组合。下面用三段式写清"滑跑→离场→巡航":
text
six_dof_type my_fighter_type # 飞机类型(同 02,示意)
mass 8000 kg
reference_area 25 m2
thrust_max 90000 N
end_six_dof_type
platform_type BLUE_FIGHTER WSF_PLATFORM
side blue
mover WSF_P6DOF_MOVER
six_dof_type my_fighter_type
update_interval 0.05 sec
end_mover
end_platform_type
platform ac_01 BLUE_FIGHTER
position 30.0n 30.0e altitude 0 m msl # 跑道头,地面滑跑
route
position 30.0n 30.0e altitude 0 m msl speed 0 m/s # 静止待飞
position 30.1n 30.0e altitude 0 m msl speed 80 m/s # 跑道尾,离地前
position 30.2n 30.1e altitude 300 m msl speed 150 m/s # 离场点(爬升)
position 31.0n 31.0e altitude 8000 m msl speed 250 m/s # 任务点(巡航)
end_route
end_platform
弹道导弹的两阶段 ,则用两个 six_dof_type(助推段含推力、滑行段无推力)指向同一平台的不同时刻,或在脚本里于关机时刻切换:
text
six_dof_type ballistic_booster # 助推段:含推力曲线
mass 12000 kg
reference_area 3 m2
thrust_max 300000 N
end_six_dof_type
six_dof_type ballistic_glider # 滑行/再入段:无动力
mass 4000 kg
reference_area 3 m2
end_six_dof_type
platform_type TBM WSF_PLATFORM
side red
mover WSF_P6DOF_MOVER
six_dof_type ballistic_booster # 初始为助推段
update_interval 0.02 sec
end_mover
end_platform_type
platform tbm_01 TBM
position 40.0n 125.0e altitude 0 m msl
# 关机时刻由脚本/事件把 six_dof_type 切换为 ballistic_glider
end_platform
核心思路是:把"动力段"和"滑行段"当成同一平台的两个机动状态,切换点就是关机时刻。
关键参数速查
| 参数 | 所在组件 | 类型 / 单位 | 默认值 | 取值说明 | 调参影响 |
|---|---|---|---|---|---|
six_dof_type(助推) |
mover (P6DOF) | 类型名 | 无 | 含推力的机型数据 | 决定爬升率/射程;推力曲线形状决定弹道 |
six_dof_type(滑行) |
mover (P6DOF) | 类型名 | 无 | 无动力机型数据 | 决定再入减速/落点;质量差异影响落速 |
update_interval |
mover (P6DOF) | 时间 (sec) | 引擎默认 | 解算步长 | 助推段加速快,步长要更小防发散 |
route 航点 speed |
route | 速度 (m/s) | 无 | 各航点目标速度 | 起降段速度连贯性决定"接得上"否 |
| 切换事件/脚本 | script_processor | 逻辑 | --- | 触发阶段切换 | 切换时机错,机动衔接会"跳变" |
阶段切换的通用心法
无论是起降还是导弹,本质都是"一个平台在不同时间用不同机动规则"。在 AFSIM 里你有两条路:
- 多 mover 列表:给平台挂多个 mover,用脚本/事件控制哪个生效。
- 单 mover + 脚本 :在
WSF_SCRIPT_PROCESSOR的on_update钩子里根据时间/状态改 mover 参数。
简单场景用 1,复杂状态机用 2。
工程实践与常见坑
- 起降不是 movers 的事,是航线 + 逻辑的事 。新手以为有"起飞 mover",其实起降靠 route 航点速度梯度 + 跑道长度约束 + 排队逻辑共同实现。跑道是否被占用、多机能否排队起飞,靠平台可用性管理或外部事件逻辑控制,不在
WSF_P6DOF_MOVER本身。 - 阶段切换时机错,轨迹跳变。助推→滑行若切换晚了,平台还带着推力冲出去;切换早了,高度不够掉下来。切换点要对应真实关机时刻,并验证切换前后速度/高度连续。
- 多 mover 谁生效要明确。给平台挂多个 mover 时,必须脚本显式控制激活哪一个,否则引擎可能一直用第一个,第二阶段机动"没发生"。
- 别拿 P6DOF 跑整条弹道还指望快。助推+全程再入用细步长解算,导弹多了一样拖慢全局。弹道中段可用更轻的 mover 或增大步长过渡。
小结与下一篇
本篇看了 six_dof 的"重"用法:机场起降和弹道投送,本质都是平台机动规则随时间切换。理解了这点,你对 AFSIM "平台=可演化状态机"的模型会更通透。
下一篇换一种高保真机动:(04)Brawler 高保真气动机动 brawler------它和 P6DOF 思路不同,是靠"查表 + 几何"把战斗机飞得既真实又稳。
下一篇预告:(04)Brawler 高保真气动机动 brawler
下一篇换一种高保真机动:(04)Brawler 高保真气动机动 brawler------它和 P6DOF 思路不同,是靠"查表 + 几何"把战斗机飞得既真实又稳。
下一篇预告:(04)Brawler 高保真气动机动 brawler