
多机接力中继这个方向我在Simulink里前前后后折腾了小半年。最开始以为只是把几台无人机的模型拼在一起跑真正动手才发现最难的不是旋翼动力学也不是某个通信模块怎么配而是“接力”这两个字——什么时候切、按什么切、切换瞬间链路状态怎么连续这些逻辑用代码写能跑但想看明白整个系统的行为Simulink几乎是绕不开的选择。这篇就把我完整的建模思路、关键模块配置和踩过的坑都摊开讲适合正在做无人机通信中继、想用Simulink做系统级仿真的朋友也适合刚接触建模、想找一个完整项目练手的人。1. 多机接力中继到底在解决什么问题不少人一听到“多机接力中继”第一反应是“不就是几架飞机轮流当路由器吗”。真要做起来这句话每个字都不简单。“轮流”这件事里藏着链路切换时机、机间协同、动态拓扑变化、信号覆盖连续性等一系列问题。如果一开始不把这些想清楚后面仿真模型搭得再漂亮也是空中楼阁。1.1 单机中继的天然瓶颈单机中继的场景大家比较熟悉一架无人机飞到空中把地面A端的信号转发给远处的B端。这个方案的瓶颈非常直观——功率有限、高度有限、天线增益有限。飞行高度提高了可以拉远通信距离但路径损耗随着距离增长得非常快实测里自由空间传播损耗和距离的平方成正比实际环境里还有遮挡、多径损耗指数能达到3.5甚至更高。这意味着单机覆盖半径的提升需要付出远超线性增长的能量和重量代价。更麻烦的是单点就是单点一旦这架飞机因为电量、故障或者被干扰退出任务整条链路就断了。做过实际外场测试的人都有体会现场各种突发状况远比仿真里的故障注入要诡异得多。所以工程上自然的思路就是上多机——用数量换覆盖、换可靠性。可多机一旦进来新的问题就来了飞机之间怎么协同信号走哪条路径谁来裁决当前该哪架飞机转发这些问题单靠通信协议解决不彻底必须在系统级建模层面去验证。1.2 Simulink在系统级仿真中的角色定位我之前也试过纯代码方案用Python或者C去搭整个系统的仿真。代码方案的优点是灵活缺点是“看不见”。无人机是典型的连续-离散混合系统飞行动力学是连续的微分方程飞控里的控制律是离散采样通信链路的切换又是事件驱动的。当这么多性质不同的模块耦合在一起时纯代码调试的体验会非常痛苦——你很难直观看到“到底是哪一环让链路断了”。Simulink这类图形化建模环境的优势恰好在这里。它天然支持连续模块、离散模块、事件驱动逻辑的混合仿真Stateflow可以清晰地描述状态切换Simulink的数据流可视化可以直观看到信号在哪一级衰减、在哪一个时刻切换。用我自己的话说代码方案适合验证算法Simulink适合验证系统。而多机接力中继恰恰是系统级的问题不是单个算法的问题。提示如果你只是验证某一个中继协议的性能比如AF和DF的信噪比差异用Python的通信库就够了。但如果你要回答“三架无人机在某个任务场景下能不能始终维持链路”这种问题Simulink是更合适的选择。2. 顶层架构设计把系统拆成可仿真的模块建模的第一步不是打开Simulink拖模块而是先在纸上把系统拆清楚。我常用的拆分方法是按“物理域”和“决策层级”两个维度切。物理域维度无人机平台位置、姿态、速度、任务载荷通信收发信机、信道环境传播损耗、噪声、干扰、地面站或任务节点。决策层级维度单机控制飞控、导航、多机协同编队保持、任务分配、中继决策切换判断、路由选择。这两个维度交叉起来整张系统图就清楚了。Simulink模型的组织结构也按这个来每个无人机是一个独立的子系统通信链路是子系统之间的连接中继决策逻辑用Stateflow实现放在最高层。2.1 整机模型的组成从顶层往下看模型文件目录大概长这样relay_system.slx ├── Ground_Station │ ├── TX_Signal_Gen │ └── RX_Signal_Process ├── UAV1 │ ├── UAV_Dynamics │ ├── Flight_Controller │ ├── Relay_Payload │ └── Battery_Model ├── UAV2 │ └── (同UAV1) ├── UAV3 │ └── (同UAV1) ├── Channel │ ├── Path_Loss_Model │ ├── Shadowing_Model │ └── Noise_Injection └── Relay_Manager ├── Link_Quality_Estimation ├── Relay_Selection_Logic └── Command_Distribution这个结构看起来规整但要注意一个原则每个子系统之间的接口要定义清楚否则模型一复杂就乱。我的经验是各无人机子系统之间的接口只传三类信息——位置姿态用于信道计算、飞行状态和指令用于协同、中继转发信号用于通信链路计算。不要传中间计算量否则模块耦合度会急剧上升改一个地方全链路报错。2.2 为什么要把中继逻辑单独抽出来这是我最想强调的一点。很多人搭模型图省事直接把中继判断逻辑写在某个无人机的子系统内部。看起来代码少了但一旦做场景扩展——比如从三机扩展到五机、从单跳中继扩展到多跳中继——你就会发现改起来几乎等于重写。把中继逻辑单独抽成Relay_Manager模块本质上是在模拟“一种超视距的集中决策视角”。虽然实际系统中各无人机可能是分布式决策的但在系统级仿真阶段先假设存在一个中央决策器可以大幅降低验证难度。先验证“正确的接力策略长什么样”再往下细化到“每个节点如何通过局部信息逼近这个全局最优”这是我在多次项目里验证过的高效路线。Relay_Manager内部用Stateflow实现状态设计成等待接力→评估链路→执行切换→确认切换完成。每个状态里再以MATLAB Function实现具体的链路计算和判断这样事件逻辑和数值计算分离既好读又好调。3. 无人机平台建模必要的细节与可忽略的细节无人机平台建模是很多人容易走极端的地方。要么一上来就搞六自由度刚体动力学加气动导数模型精确实在但仿真速度感人要么图省事直接用纯运动学模型位置靠积分算结果信道仿真算得再准飞行控制层面的问题根本暴露不出来。我的做法是分用途对待如果关注的是中继策略对单机平台做“适度简化”的动态模型就够了如果关注的是飞行控制和中继切换的耦合那就必须上完整的飞控模型。下面详细说。3.1 六自由度动力学怎么取舍纯六自由度模型包含质心平动和绕质心转动的12个状态方程。在Simulink里可以用Aerospace Blockset或UAV Toolbox直接生成不推荐从零搭除非你想练手。但直接把这种模型接到中继仿真里会有两个实际问题。第一是仿真步长。六自由度动力学模型为了保证数值稳定性步长通常要取到毫秒级甚至更小。而中继链路的切换判断时间常数通常在几百毫秒到秒级。这意味着仿真计算量绝大部分浪费在了“对中继决策没有直接影响”的快速动态上。第二是参数获取问题。完整的六自由度模型需要转动惯量、气动导数、螺旋桨系数等一堆参数。你手里如果是自研或者改装过的飞机这些参数很难拿到准确的。硬套别人的参数模型“看起来像无人机”但关键时刻的动态响应可能差得很远反而不如用一个保守的简化模型来得可靠。所以我在中继仿真的主体里用的是简化的三自由度质点模型加一阶延迟控制环。具体说把无人机看作一个可加速、可转向的质点加速度指令到实际加速度之间加一个一阶惯性环节时间常数按实际飞机的响应能力取0.5~2秒。这个模型精度足够捕捉中继任务的空域变化又不会拖慢仿真。3.2 飞控与电机模型的分层处理飞控部分我在Simulink里分了内环和外环两层。内环是姿态控制外环是位置控制。中继仿真里必须保留的是外环——因为位置决定信道、决定接力切换内环可以适当简化因为中继策略不会去干预飞机的姿态级响应。电机模型则是另一个容易被高估重要性的部分。如果仿真目标不是“验证某个电机的响应速度是否导致位置超调”完全可以不用Simscape Electrical去建模真实的电机驱动链路——那套东西用在功率级仿真里合适用在系统级中继仿真里纯粹是拖累。我用的是一个简化推力响应模型推力指令经过一个一阶环节输出实际推力推力再通过重力方向的加减来影响垂直加速度水平方向直接用力与质量的比得到加速度。注意如果你要做的项目后来还要往“飞控硬件在环”方向发展那这一节的简化就不能太狠。硬件在环测试需要飞行控制律本身跑在真实飞控硬件里模型给的至少要是完整的刚体动力学才能有意义。这种时候建议在主模型之外保留一个高保真版本用模型引用Model Reference的方式切换。4. 信号中继链路建模通信工具箱的正确用法把平台模型搞定后重头戏来了——信号中继链路本身。这里要搞清楚一件事Simulink里做通信链路模型有两种完全不同的粒度。一种是样本级的基带波形仿真把每个符号、每个比特都仿真出来另一种是系统级的链路预算仿真用信噪比、误码率、中断概率这些指标来描述链路质量。多机接力中继的系统级验证必须用后者原因很简单——样本级仿真的计算复杂度跟数据速率成正比而中继系统的数据速率动辄几十Mbps根本算不动。4.1 信道模型的搭建策略Communications Toolbox提供了很丰富的信道模型比如stdchan可以生成标准信道冲激响应rayleighchan可以模拟多径衰落。但直接把这些模块拿来用在中继仿真里会有一个维度不匹配的问题这些模型通常是时间驱动的样本级仿真而我们的顶层模型里无人机的位置是连续变化的。我的解决办法是分两层建信道。外层是几何信道模型根据无人机之间的实时距离、相对方位角用传播模型公式计算大尺度路径损耗和阴影衰落。自由空间路径损耗公式是PL(dB) 20*log10(d) 20*log10(f) 32.44其中d的单位是公里f的单位是兆赫兹。这个公式看起来简单但要注意多跳中继的总损耗不是每跳损耗简单相加而是要考虑每一跳的收发天线增益、馈线损耗等。实际中继系统中每一跳都要重新算链路预算而不是直接套总距离。内层是小尺度衰落模型我在Simulink里用MATLAB Function块写了一个简化的莱斯衰落生成器参数取K因子这样可以在“纯视距”和“部分遮挡”之间连续调节。这个分层思路的好处是你可以分别验证“几何位置变化对中继链路的影响”和“多径环境对链路质量的影响”不会因为耦合在一起导致定位问题时无从下手。4.2 中继工作模式AF还是DF中继的工作模式直接决定了信号在转发节点上的处理方式。放大转发AF最简单——收到信号放大后直接转出去延迟低但噪声也被放大了。译码转发DF把接收信号先解调、译码再生后再转发噪声不会累积但延迟高、设备复杂度高。在Simulink里实现这两种模式差异其实就在转发节点内部的一个开关。AF模式下转发信号 接收信号 × 放大增益DF模式下转发信号 重新编码后的信号。但如果做系统级仿真这两种模式最终都要折算成对链路信噪比的影响。我建议用端到端信噪比公式来等效而不是真的在模型里做完整译码再编码。AF的端到端SNR近似公式SNR_end (SNR1 * SNR2) / (SNR1 SNR2 1)DF的端到端SNR近似公式SNR_end min(SNR1, SNR2)这里SNR1是中继节点收到的信噪比SNR2是目的节点收到的中继转发信号信噪比。这两个公式在仿真代码里实现起来非常快而且物理意义清晰。做接力切换判断时用的就是这两个公式算出来的端到端SNR。5. 多机协同与接力策略Stateflow的实战用法模型框架搭好了信道模型也通了剩下的核心就是接力策略本身。这一部分我用一个具体的三机场景来展开一架地面站发射机固定在地面一个远端任务节点需要接收信号中间有两架无人机作为中继节点初始时一架靠近地面站、一架靠近远端形成一个两跳链路。远端节点持续移动导致靠近远端的那架无人机需要不断调整位置当它的电量下降到某个阈值或者链路质量恶化到一定程度就需要另一架飞机接替它的角色。5.1 接力场景的事件驱动逻辑这个场景里切换触发条件有两类链路质量驱动的切换和资源驱动的切换。链路质量驱动的切换很好理解——当前中继链路信噪比低于某个门限而另一条候选链路的信噪比高于当前链路就触发切换。资源驱动的切换则是我在实测场景中发现很重要的一个点——中继节点的剩余电量。电量的建模我会在无人机子系统中放一个简单的放电模型放电功率由发射功率、飞行功耗两部分组成。当节点电量低于20%时Relay_Manager就会评估是否有替代节点可以接管。这个触发的意义是电磁环境再好飞机没电了链路照样会断。Stateflow里的状态图我简化描述一下State: 初始化 → 起飞到指定中继点 State: 任务执行当前节点A为中继 → 周期评估链路质量 → 若A的SNR 门限或A的电量 20% → 进入切换评估 State: 切换评估 → 搜索候选B节点 → 计算以B为中继的端到端SNR → 若B的SNR A的SNR 迟滞量 → 发送切换指令 → 否则保持在A State: 切换执行 → A降低功率B接管 → 确认链路连续 → 回到任务执行这个状态机里最核心的细节是“迟滞量”。没有迟滞量系统会在两个节点之间来回切换这就是通信领域所谓的“乒乓效应”。Simulink里模拟乒乓效应特别直观——你可以在Scope里看到SNR曲线在两个值之间反复横跳。加迟滞量后切换次数显著下降。5.2 接力策略和无人机路径规划的耦合接力切换不是仅仅在通信层面做决策就够了它同时要指挥无人机飞过去。所以Relay_Manager的指令输出其实包含两路一路是通信层面的切换指令哪个节点开始发射、哪个节点停止发射另一路是协同层面的航迹指令接替节点飞向新的中继悬停点。路径规划这部分我比较建议在MATLAB Function里复用现成的算法比如PRM概率路线图或RRT快速搜索随机树。如果你用的UAV Toolbox里面甚至有uavPlanning相关的接口可以直接调用。但在系统级仿真里路径规划的输出不是一条曲线而是一系列航点无人机动力学模型把这些航点作为外环位置控制器的输入。这是整个模型耦合最强的地方也是最容易出bug的地方。我最开始把路径规划的输出连到了无人机的内环姿态指令上结果模型直接炸了——因为位置航点转换不成姿态角需要经过位置控制率和姿态控制率两级解算。改成外环输入后整个系统就顺了。这个错误给了我一个教训在这个混合系统里模块之间的“信号语义”必须严格一致差一层都不行。6. 参数选取与仿真结果分析用数据说清楚“接力成功”模型跑通之后真正让项目产生价值的是仿真实验设计和结果分析。这一节我把自己常用的参数配置和几个典型结果直接分享出来你可以把这些当成基准配置再根据你的场景去修改。6.1 仿真参数配置参考这个三机中继场景仿真里的核心参数我给一个可以直接用的起步配置参数名数值说明通信频率2.4 GHz常见无人机数传频段发射功率27 dBm约0.5W典型数传功率发射天线增益3 dBi全向天线接收天线增益3 dBi全向天线接收机灵敏度-100 dBm低于此值认为链路中断中继节点飞行高度100 m保证视距任务节点移动速度10 m/s模拟移动车辆/行人SNR切换门限15 dB低于此值启动切换评估切换迟滞量3 dB防止乒乓切换仿真时长600 s覆盖典型的任务周期注意这里的接收机灵敏度和SNR门限它们不是同一个概念。灵敏度是用dBm表示的绝对功率门限SNR门限是信号与噪声的比值。在链路预算里接收功率要同时大于灵敏度门限且SNR要满足解调需求两者都要满足才认为链路有效。我在模型里用了一个Enable逻辑实现“双门限同时满足”的判断。6.2 用覆盖率曲线评估中继效能仿真结果怎么评估我常用的指标是中继覆盖时间率——即整个任务时间段内远端节点成功接收到有效信号的时间占比。这个指标直接回答“中继策略到底有没有用”这个终极问题。三机接力策略跑出来的覆盖率通常能达到95%以上相比之下单机中继的覆盖率可能只有60%~80%差别就非常直观。用这个指标做横轴对比还能观察一个有意思的现象当任务节点移动速度从5m/s增加到20m/s时固定切换迟滞量的场景覆盖率会下降。原因是移动速度加快时链路质量变化速率变快同样3dB的迟滞量需要更长的“确认时间”切换响应显得迟缓。这时候把迟滞量适当减小或者用基于速率的自适应迟滞量覆盖率能回到正常水平。另一个值得分析的是链路切换次数。在Scope里统计切换指令的上升沿次数你会发现加了迟滞量的版本比不加的版本切换次数少了一个数量级。每次切换都意味着一段时间的数据中断或者至少是时延抖动过多切换本身就是一种性能损失。所以在调试时我会同时盯两个目标覆盖率要高切换次数要低。这两个指标有时是矛盾的——追求极致覆盖率会导致频繁切换压制切换次数又可能牺牲覆盖率。找到可接受的平衡点就是参数整定的核心工作。提示仿真结果一定要保存到工作区里做二次分析不要在Scope里看一眼就完事。我一般会把端到端SNR、切换标志、节点位置都记到MATLAB的timeseries里仿真结束后用脚本统一画图这样出报告和复盘都方便。Simulink里用“日志记录”功能把信号标记为日志信号就能把这些数据导出来。7. 仿真调试的深坑与自查清单这部分我总结一下做这个项目过程中踩过的几个高频率的坑每一个都花过我不少冤枉时间。7.1 代数环问题中继决策和信道计算的互相依赖第一个大坑是代数环。Relay_Manager要算端到端SNR而SNR又依赖于中继节点的位置中继节点的飞行位置由路径规划给出路径规划又受Relay_Manager当前决策影响。当这些模块在一个仿真步里互相引用时Simulink会报“Algebraic Loop”错误或者即使不报错仿真速度也会急剧下降。我的解决办法是在反馈回路上显式插入单位延迟Unit Delay或内存Memory模块。这样割断了代数依赖代价是决策和状态之间有一个仿真步的延迟。对于中继切换这种秒级的事件一个仿真步的延迟完全不是问题。千万不要为了消除代数环而把整个模型改成纯离散系统那会把连续动力学和事件逻辑搅在一起后期调试更痛苦。7.2 采样时间不一致导致的隐性错误第二个坑是采样时间不一致。飞控模块用了1kHz的采样率信道模块用了100HzStateflow里的事件触发又用了1Hz的定时器。看起来每个模块单独工作都正常但结果可能完全错误——因为信道模块采到的位置信息是1kHz更新出来的还是100Hz更新出来的计算出的路径损耗会有细微差异这种差异在覆盖率的边缘判断上可能就决定了链路“通”还是“断”。解决方法是统一规划采样时间层级我在模型里通常用三种速率高频连续层无人机动力学连续求解器、中频离散层飞控和信道100Hz~1kHz、低频事件层中继决策1Hz。层与层之间用Rate Transition模块显式转换。用Simulink的“采样时间彩色标注”功能Sample Time Colors可视化检查绿色的模块表示离散采样红色是连续采样一眼就能看出来哪个模块的采样时间设置错了。7.3 外部模式仿真跑不通的常见原因如果你后面打算做硬件在环或者半实物仿真Simulink的外部模式External Mode会是一个绕不开的功能。但这个场景下最难受的问题是外部模式要求整个模型能在实时目标上运行而很多方便的仿真模块——比如MATLAB Function里的某些动态内存分配、文件读写操作——在实时目标上是不支持的。我做过的项目里最常见的外部模式报错是“不支持的数据类型”或者“无法为MATLAB Function生成代码”。排查思路是把模型里的MATLAB Function逐个替换成Simulink原生模块或者用C语言重写S-Function。这个工作量不小所以一开始建模时就要有“代码生成友好”的意识——避免在MATLAB Function里写复杂的动态数组操作尽量用固定大小的变量避免使用eval、load这类运行时函数。7.4 调试自查清单最后给一份我每次调试模型都会过一遍的清单模型中的连续模块是否有代数环如果有是否已显式插入延迟模块各模块采样时间是否已经用Rate Transition做了明确转换信号的数据类型是否一致uint8和double混用会在某些比较运算里产生难以发现的错误。事件触发逻辑是否有迟滞量是否已将迟滞量参数设为可调变量以便实验对比无人机初始位置是否避开了“切换临界点”初值取在临界点会导致一开始就频繁切换影响对整体策略的判断。仿真求解器设置是否合理中继系统建议用变步长求解器如ode45最大步长设为0.01s确保路径损耗更新的时间精度。8. 从仿真到实飞哪些模型产物可以直接用仿真做得再漂亮最终还是要回答一个问题这些模型产物拿到实际项目中哪些能用、哪些不能直接用。我在整个多机接力中继仿真项目中最后沉淀下来并真正迁移到实际系统的主要有三类东西。第一类是链路预算计算逻辑——这个直接写成机载端的C代码跑在数传模块的嵌入式处理器上实时估算与地面站的链路余量。第二类是切换决策状态机——Stateflow生成的逻辑代码几乎可以原样移植到飞控的辅助处理器上只需要把输入输出接口从仿真信号改成实际的串口或CAN数据。第三类是仿真过程中确定的参数整定策略——比如迟滞量怎么根据速度自适应调整这些直接沉淀成了实际任务的参数配置表。不能直接用的是那些连在Simulink图表上的漂亮Scope和可视化模块——实机环境里没有这个。我的习惯是在实机代码里保留一个最小化的链路日志模块把每次切换判定的关键变量SNR估算值、门限、电量都存到非易失存储里。这个习惯帮我解决过不少实机场次里“链路异常”的追责难题——因为日志里直接就能定位到是切换策略触发了不该触发的切换还是链路本身物理上就断了。关于Simulink里的模型和实机系统的对应关系再补一句Simulink里能仿真通过不代表实机一定能工作但Simulink里出现的问题实机大概率也会出现。它没办法消除实机的所有不确定性但至少能帮你把“设计逻辑本身有没有问题”这个层面的事情彻底搞清楚。我个人的项目流程一直是先把这个模型作为“逻辑验证平台”跑透再往实体机上迁移。这套流程看起来慢但恰恰是它让我在外场调试时少熬了无数个夜。