TrueTime 2.0 网络化运动控制仿真环境搭建与调度实践

发布时间:2026/11/4 17:03:49
TrueTime 2.0 网络化运动控制仿真环境搭建与调度实践

简介:面向使用 MATLAB 进行网络化运动控制仿真、资源调度实验的师生与工程人员,这份 docx 文档围绕 TrueTime 2.0 的入门使用与配置展开,适合需要搭建工具箱环境、理解模块组成并复现实例的读者。压缩包内共 1 个 docx 文件,大小约 402KB,以图文形式整理工具箱安装、路径与环境变量配置、模块说明及仿真实验要点,内容集中,便于按章节查阅。已有 1593 人学习,说明其在 TrueTime 入门资料中具有一定参考度。读者可据此了解 TrueTime 2.0 的整体结构、常见配置思路与仿真实验场景,并补充最大误差优先调度、优先级反馈控制等运动控制知识点,适合用于课程实验、课题预研和配置排错时的速查参考。

1. 一套挂机多年的工具箱,为什么现在还有人翻出来装

某高校实验室交付的一份仿真报告里,网络化运动控制回路的调度曲线是在 TrueTime 里跑出来的。真要在纯 Simulink 里拿 Transport Delay 模块硬凑,抖动和丢包一叠加,曲线立刻对不上。TrueTime 2.0 就是一套挂在 MATLAB/Simulink 下的网络化控制系统仿真工具箱,它把实时内核、网络协议栈和被控对象塞进同一张 Simulink 框图,资源调度到底卡在哪一拍,才看得见。这份 truetime2.0使用说明.docx 记录的是从解压、配路径、配环境变量一路走到 make_truetime 出现 successful 的全过程,适合手里有 MATLAB、要复现网络化运动控制仿真、又被 mex 编译器卡在半路的人。下面按我自己的装机顺序重排一遍,顺手把原文档里几处现在容易翻车的地方标出来。

2. 装之前先看清楚:TrueTime 2.0 的三层结构与编译链选型

很多人一上来就照着步骤表敲命令,结果卡在 mex 那一步就开始怀疑人生。问题不在命令,在于没搞清楚这套工具箱到底由哪几块拼成、哪一块必须编译、哪一块只是 M 文件。先把结构理清,后面的报错基本能自己对上号。

2.1 Kernel、Network 与被控对象:三个角色各管什么

TrueTime 的仿真模型里,一个典型的网络化运动控制回路至少要摆三类模块。第一类是 TrueTime Kernel 模块,它代表一台挂在网络上的计算节点,可能是控制器,也可能是传感器或者执行器,内部跑的是用 M 文件写的"内核代码"——任务创建、优先级设定、周期、报文收发,全在这个模块的初始化回调里描述。第二类是 TrueTime Network 模块,它模拟节点之间那根"线",支持总线型、交换式以太网、令牌环之类的常见拓扑,报文延迟、排队、丢包都由它算出来。第三类是被控对象,也就是普通的 Simulink 连续域模块,电机模型、机械臂连杆模型都行,通过 A/D、D/A 端口和 Kernel 对接。

这个结构决定了仿真精度落在哪里。纯 Simulink 加延迟模块,你能看到一个"平均延迟",看不到某个控制任务因为优先级低而被高优先级任务抢占、错过截止期的那一拍。Kernel 模块把调度器显式建模出来,网络模块把排队时间和冲突显式建模出来,两头一夹,控制品质的退化原因才可拆解。做运动控制的人真正关心的往往不是稳态误差,而是"第 37 个采样周期那次抢占到底造成了多大抖动"——这个问题只有把内核和网络都建进去才回答得了。

所以选型上要有个判断:如果你的课题只是验证一个线性控制器在固定延迟下的鲁棒性,纯 Simulink 完全够用,不必引入 TrueTime,因为它的学习成本和编译链麻烦是真实存在的。反过来,只要你的论文或项目里出现"调度策略""优先级""网络丢包""截止期错过率"这类词,TrueTime 几乎是绕不开的,自己从零写一个带调度器的 Simulink 框架,工作量远大于装一次工具箱。

2.2 为什么绕不开 mex:M 文件外壳包着 C++ 内核

原文档里最关键的一步是make_truetime,这一步之前在mex -setup里选编译器。很多人不理解为什么一个"MATLAB 工具箱"非要装 gcc。原因是 TrueTime 的内核调度器和网络仿真引擎是用 C++ 写的,为了速度,编译成 MEX 文件在 MATLAB 进程内直接跑。你解压之后看到的那些 .m 文件只是外壳——初始化函数、模块回调、参数解析,真正的调度逻辑跑在由 .cpp 编译出来的二进制里。

这就解释了为什么会出现"truetime命令能打开模块库、一仿真就报 undefined function"这种诡异现象:库浏览器读的是 .m 和 .mdl,能加载;仿真时内核要调 MEX 文件,那个文件没编译出来或者编译失败,就报未定义。所以编译器不是可选项,是硬性前置依赖。

编译器怎么挑,这里有个现实边界。Win7 时代配 MATLAB R2017b,原文档用的是 tdm64-gcc-5.1.0-2,这套组合当年验证过能过。放到今天,MATLAB 从 R2019a 前后开始对 MinGW 系编译器的支持收紧,版本对不上会直接在mex -setup里拒绝注册。我一般会先把本机 MATLAB 的版本号确认清楚,再去查它官方支持哪个编译器版本,卡死了就退回用 Visual Studio 的 C++ 工具链,虽然装起来重,但兼容性最稳。别死磕一个装不上的 gcc,那是最容易耗掉半天的地方。

2.3 版本三方对齐表:MATLAB、编译器、TrueTime 三者不能乱配

这套东西的版本敏感度比一般工具箱高,因为它同时依赖 MATLAB 的 mex 接口、编译器 ABI 和自身 beta 版的代码。下面这张表是我踩过几次之后总结的判断依据,具体版本号以自己机器上的为准。

组合项老环境(可复现)新环境(需重编)判断依据
MATLABR2017b 附近R2019a 及以后mex -setup的语法在两代之间有差异
编译器tdm64-gcc 5.1.0MSVC 或受支持的 MinGW编译器是否出现在mex -setup列表里
TrueTime2.0 beta 1同版本,但需重新make_truetimeMEX 二进制与 MATLAB 版本绑定
位数64 位64 位MATLAB 是 64 位就必须配 64 位编译器

最要紧的一条:MEX 文件是跟 MATLAB 版本绑定的。你在 R2017b 上编译出来的 mex 文件,换到 R2021b 上多半加载不了,必须在新版本里重新跑一次make_truetime。这不是工具箱的毛病,是 MATLAB 本身的机制,所以任何"把整个 toolbox 目录拷贝到新电脑就能用"的设想都不成立,路径和二进制都得重来。

3. 按顺序落地:从解压到 make_truetime 出现 successful

步骤本身不复杂,复杂的是顺序——先配路径还是先编 MEX、环境变量什么时候生效、startup.m 要不要跟环境变量一起上。原文档的顺序基本可抄,但有几处可以省掉的冗余动作,我在下面按实际操作顺序重排,每一步都写清楚它在解决什么问题。

3.1 目录落位:放 toolbox 下不是必须,但有它的道理

原文档的做法是把解压出来的 truetime-2.0 整个目录复制到 MATLAB 安装目录的 toolbox 文件夹里。这个做法能成,但不是唯一解。放 toolbox 下的好处是路径相对固定,用matlabroot拼路径的时候不容易出错,多个项目共享同一份;坏处是 MATLAB 升级或者重装会把这个目录清掉,而且某些安装位置需要管理员权限才能写入,复制过程中容易半途失败留下个残缺目录。

如果这台机器是你自己的开发机,我一般会把它放在一个独立的、纯英文无空格的工作目录,比如D:\work\matlab\truetime-2.0,然后在 startup.m 里用绝对路径加进去。这样 MATLAB 升级不影响,多个版本共存时也能各自指各自的路径。下面这条原则比具体路径重要:

% 路径里不要出现中文、空格、括号 % 反例:'D:\我的文档\MATLAB 工具箱\truetime-2.0' % 正例:'D:\work\matlab\truetime-2.0'

逻辑说明:gcc 在编译时会把路径原样传给底层工具链,遇到空格会当成参数分隔符,遇到非 ASCII 字符在某些 locale 下编码不一致,表现出来就是"文件明明存在,编译报找不到源文件"。这类错误信息通常很含糊,排查成本极高,索性一开始就别踩。参数说明:路径深度不必刻意压平,但整个路径长度建议控制在 100 字符以内,Windows 的老路径长度限制在编译链里仍然可能触发。

解压完之后先别急着配路径,进去看一眼目录结构。根目录下会有 kernel、init 之类的子目录,kernel 里藏着真正的 M 文件和 .cpp 源文件。这个目录长什么样,直接决定了下一步 setpath 要加到哪一层。

3.2 setpath 到底加哪一层:一次加对,别反复返工

原文档里提到"共包含 4 个关于 truetime-2.0 的文件,最好都包含进去,也可只包含到 kernel 的文件夹,如果出错再重新包含进去"。这段话反映的是实际装机时的反复:加少了找不到函数,加多了路径冲突。稳妥的做法是用genpath一次性把 kernel 下面所有子目录都加进去,比手工点 setpath 对话框一层层勾选可靠得多。

% 在 MATLAB 命令窗口执行,或写进 startup.m ttRoot = 'D:\work\matlab\truetime-2.0'; addpath(genpath(fullfile(ttRoot, 'kernel'))); % 连同子目录一起加入搜索路径 addpath(ttRoot); % 根目录,供 make 脚本定位 savepath; % 把当前路径存下来,下次启动自动生效

逻辑说明:第一行addpath(genpath(...))是核心,genpath会递归返回该目录下所有子目录拼成的路径串,一次调用就把 kernel 及其全部子目录挂上,避免了"加了一层、发现还缺一层"的循环。第二行把根目录也加上,是因为make_truetime这类脚本常常用相对路径去找同级目录里的源文件,只加 kernel 会让它找不到。第三行savepath把结果写进 pathdef,下次启动不用重来;如果你更倾向用 startup.m 管理(见下一节),这一行可以省掉,否则两套机制会互相覆盖。

参数说明:genpath默认会跳过以private、@开头的特殊目录,这是 MATLAB 的既定行为,不用管;但如果你的解压目录里混进了.git、__MACOSX之类的垃圾目录,也会被一并加进路径,虽然通常无害,但会让path输出很乱,装完顺手清一下更舒服。

验证方式很直接,在命令窗口敲which ttInitKernel,能返回一个 .m 文件的完整路径就说明路径通了;返回"not found"就是没加对,别往下走,先把这一步解决。

3.3 环境变量与 startup.m:两条路选一条,别都上

原文档在这一步给了两套动作:先在系统环境变量里新建,再改 startup.m,还额外让你把 matlabrc.m 另存成 matlab.mat。当年这么做大概是因为不同 MATLAB 版本的启动加载机制不一样,索性全都上一遍保证能生效。放到现在,两条路选一条就够了,都上的结果往往是启动时路径被加载两次,path里出现重复条目,虽然多数时候只是警告,但排错时会被误导。

走环境变量这条路,做法是在系统变量里新建一条,变量值指向 truetime-2.0 的根目录,让 MATLAB 启动时从环境里读到初始搜索路径。走 startup.m 这条路,则是在 MATLAB 安装目录的toolbox\local\下编辑 startup.m,写入上一节那几行 addpath。前者对机器上所有 MATLAB 版本生效,后者可以按版本精细控制,我一般选后者。

% toolbox\local\startup.m —— MATLAB 每次启动时自动执行 ttRoot = 'D:\work\matlab\truetime-2.0'; if exist(ttRoot, 'dir') addpath(genpath(fullfile(ttRoot, 'kernel'))); addpath(ttRoot); else warning('TrueTime 目录不存在,检查路径配置'); % 换机器时不会静默失败 end

逻辑说明:exist(ttRoot, 'dir')这个判断很值得加。工具箱目录被移动、被清理、或者换了一台没装 TrueTime 的机器时,没有这个判断,startup.m 会直接报错,MATLAB 启动过程被打断,表现是一堆莫名其妙的红字;加上之后只留一条 warning,不影响其他工作。参数说明:'dir'参数表示只判断目录存在性,返回值是 7;如果你把这段贴进别的脚本,注意ttRoot变量名不要和工程里已有变量冲突。

注意:设置完环境变量不需要重启电脑,把所有 MATLAB 进程关干净再重新打开就够了。环境变量只对新启动的进程生效,已经开着的 MATLAB 窗口读不到新值,这一点原文档里让重启电脑,其实是当年为了省事的一刀切说法。

至于把 matlabrc.m 原样另存为 matlab.mat 那一步,属于老版本的遗留经验,作用接近于强制重建一次启动缓存。新版本里通常不需要,如果你照做之后发现 MATLAB 启动变慢或者行为异常,把那个 matlab.mat 删掉即可复原。

3.4 mex -setup 到 make_truetime:完整执行链和每一步的失败信号

编译器装好之后,先在命令窗口让它被 MATLAB 认出来。这一步的语法在不同版本之间有差异,老版本是交互式选择,新版本要求直接指定语言。

% 先看 MATLAB 认不认这个编译器 mex -setup C++; % R2019a 及以后用这个写法 % mex -setup; % R2018b 及以前,交互式列表里选

逻辑说明:mex -setup C++会在已注册的编译器里找 C++ 工具链并写进 mex 的配置文件,成功时会打印出编译器名称和版本。如果报"找不到支持的编译器",问题不在 MATLAB,在于编译器没装、位数不对、或者版本不被当前 MATLAB 支持,这时候别反复敲同一条命令,去查版本对应关系。

编译器的具体安装这里不展开,但有一个细节必须提:装完之后如果mex -setup仍然看不到,把 MATLAB 完全退出再进。PATH 环境变量的更新对已运行进程不可见,很多人卡在这一步以为是编译器不兼容,其实只是没重启 MATLAB。

接下来是真正编译。先切到 truetime 根目录,再执行 make 脚本。

cd('D:\work\matlab\truetime-2.0'); % 必须先切到根目录 make_truetime; % 编译所有内核与网络的 MEX 文件

逻辑说明:make_truetime是一个 M 脚本,内部用相对路径去遍历各个子目录里的 .cpp 文件并逐个调用 mex,所以工作目录必须是根目录,在别的目录下调用会因为找不到源文件而失败。执行过程中会刷出一大段编译输出,中间夹杂警告(比如某些类型转换、废弃 API),这些警告按原文档的说法可以先不管,只要最后出现 successful 就说明编译通过。

参数说明:如果只想重编某一部分,可以直接对单个 .cpp 调mex,例如mex -O kernel\xxx.cpp,-O是开启优化,速度差别在长时间仿真里能感觉出来。真正要关注的是"failed"字样和它前面的那一行文件路径,那才是问题所在。

编译通过后,在命令窗口输入truetime,会弹出工具箱的模块库浏览器,能看到 Kernel、Network、Battery 之类的模块。到这一步装机完成,可以开始搭模型了。

4. 跑通第一个回路:网络化运动控制的仿真骨架怎么搭

装完只是拿到工具,能不能跑出有意义的曲线是另一回事。这一章用一个最小可运行的网络化运动控制回路把整条链路串起来:被控对象在连续域,控制器在 Kernel 里按周期跑,中间隔一个 Network 模块。这个骨架搭通之后,换被控对象、换调度策略都是局部替换。

4.1 搭骨架:三个模块怎么连、采样时间怎么定

在 Simulink 里新建一个空模型,摆三样东西:一个 TrueTime Kernel 模块当控制器节点,一个 TrueTime Network 模块当总线,一个普通的连续传递函数当被控对象。连线方式是:参考输入和对象输出进 Kernel 的 A/D 端口,Kernel 的 D/A 端口出控制量给对象,Kernel 的收发端口连到 Network。这个拓扑在模块库的示例里能找到近似版本,直接改比从零搭快。

采样时间是第一个要定的参数。控制任务的周期决定了 Kernel 里任务的触发间隔,也决定了这个仿真模型该用什么样的步长。经验上,仿真步长要比最快任务周期小一个量级,否则调度事件会被"跨过去",看到的结果是任务从来不抢占,全是理想调度。

参数建议取值说明
控制任务周期10 ms运动控制的常见量级,可按对象带宽调整
网络比特率依协议设定总线型与交换式差异明显
仿真步长周期的 1/10 左右太大会丢调度事件
仿真时长至少覆盖 50 个周期否则统计量没有意义

网络模块的协议类型要和你的研究场景对得上:讲优先级调度一般用总线型,讲交换式以太网的排队则选交换式。选错了不是跑不出结果,是结果解释不通。

4.2 写内核代码:任务、优先级与周期

Kernel 模块的行为由一个初始化函数定义,函数名填在模块对话框的初始化回调里。这个函数里做三件事:声明调度策略、创建任务、把任务和具体的代码函数绑上。

function node_init % Kernel 模块的初始化回调:声明调度策略并创建周期控制任务 ttInitKernel('prioFP'); % 固定优先级调度 ttCreateTask('ctrl_task', 0.010, 'ctrl_code'); % 名称、周期(s)、入口函数 % 报文到达的处理函数,优先级设得比控制任务高 ttCreateHandler('msg_handler', 1, 'net_msg_handler'); end

逻辑说明:ttInitKernel的第一个参数决定调度器类型,固定优先级是最常用的一种,换成绩效更好的策略只是换这个字符串。ttCreateTask的三个参数分别是任务名、周期和入口函数名,入口函数名不带.m后缀,写错会报找不到函数。ttCreateHandler注册的是中断式处理,网络报文到达时触发,优先级数值越小越高,设得比控制任务高才符合"中断抢占任务"的真实行为。

参数说明:各 beta 小版本之间ttCreateTask的入参顺序可能略有出入,有的版本要求先给偏移量再给周期。动手之前先help ttCreateTask看一眼本机签名,这半分钟能省掉后面半小时的调试。

任务本体就是一个普通的 M 函数,从端口读数、算控制量、写回端口。

function ctrl_code % 控制任务主体:读输入、算控制量、发报文 r = ttAnalogIn(1); % 参考输入 y = ttAnalogIn(2); % 对象输出 u = 1.2 * r - 0.08 * y; % 一个极简的比例控制,先跑通再换算法 ttAnalogOut(1, u); % 送给被控对象 ttSendMsg(2, 64, u); % 发往节点 2,64 字节负载 end

逻辑说明:ttAnalogIn和ttAnalogOut的编号要和 Kernel 模块上端口的顺序对上,对不上就是读数错位,表现出来是曲线形状对但幅值离谱。ttSendMsg的第一个参数是目的节点号,第二个是字节数,第三个是负载,字节数会直接影响网络模块算出来的传输时间,别随手填个 1。

4.3 调度策略换挡:从固定优先级到最大误差优先

跑通之后最有价值的一步是换策略对比。固定优先级简单,但周期任务在过载时的表现很脆;单调速率按周期定优先级,适合周期已知的场合;最早截止期优先在理论上更优,过载时却容易连锁失效。原文档提到的"最大误差优先"属于自定义策略,逻辑是让误差大的回路先拿到计算资源,这在多回路运动控制里很实用。

自定义调度一般通过注册一个优先级函数实现:调度器在每个调度点把当前就绪的任务集合交给你,你返回一组优先级数值。

function prio = prio_mef(now, tasks) % 自定义调度:误差大的任务优先,返回优先级向量 n = numel(tasks); prio = zeros(1, n); for k = 1:n e = tasks(k).err; % 该任务当前的控制误差 prio(k) = n - round(e * 100); % 误差越大,数值越小,优先级越高 end end

逻辑说明:返回值必须是和任务数等长的向量,数值越小代表优先级越高,这一点和很多实时系统的约定相反,写反了就是完全相反的调度效果,而且不报错,只能从波形上看出来。参数说明:tasks结构体里的可用字段随版本变化,误差值可能是内置字段也可能需要自己维护,用之前先打印一次看看里面到底有什么。

换策略的时候一次只改一个变量,别同时改周期和策略,否则结果差异归因不了。我一般会固定同一组初始条件,跑三遍——固定优先级、单调速率、自定义策略——把三条曲线叠在同一张图上,错过截止期的次数直接数得出来。

5. 避坑清单:五个让我返工过的编译与运行故障

装机过程的报错大多集中在编译链,仿真阶段的报错大多集中在路径和绑定关系。下面五条是我自己返工过的,按"现象 → 原因 → 解决"写,遇到同类症状可以直接对号入座。

5.1 现象:mex -setup 里一个编译器都列不出来

现象是敲完命令只回一句"找不到支持的编译器",但编译器明明装了,安装目录里也能看到 exe 文件。

原因是三条中的一条:装的是 32 位编译器而 MATLAB 是 64 位;编译器版本超出当前 MATLAB 的支持范围;或者 PATH 里虽然有,但 MATLAB 进程启动在设置 PATH 之前。

解决顺序是先确认位数,computer命令返回带PCWIN64就说明要 64 位编译器;再确认版本对应关系,对不上就换;最后把 MATLAB 全部退出重开,让新 PATH 生效。这三步走完还不行,就换用 Visual Studio 的 C++ 工具链,装一次虽然重,但它和 mex 的兼容性最稳。

5.2 现象:make_truetime 跑到一半报 error,但 truetime 命令还能打开库

现象是模块库浏览器能弹出来,看上去"装好了",一仿真就报某个函数 undefined。

原因是make_truetime是逐个文件编译的,中途某个 .cpp 失败了,脚本继续往下跑,其余文件都成功,于是你得到一个"半成品"工具箱。库浏览器只读 .mdl 和 .m,所以能开;仿真要调那个没编出来的 MEX,于是崩。

解决方法是把make_truetime的完整输出往上翻,找failed前面的那行文件路径,记下来,单独对它执行一次 mex,报错信息会清晰得多。常见诱因是那个文件用了当前编译器不认的语法特性,换个编译器版本通常就好了。

5.3 现象:仿真跑起来波形是一条直线,Kernel 没有任何输出

现象是模型能编译、能仿真、不报错,但 D/A 端口输出恒为零,示波器上一条平线。

原因多半是 Kernel 模块的初始化回调没绑上:对话框里填的函数名和实际 .m 文件名对不上,或者填的时候带了.m后缀。函数根本没被调用,任务没创建,自然没有输出。

解决办法是把函数名去掉后缀再填一遍,然后在初始化函数第一行临时加一句打印,仿真时看命令窗口有没有输出,有输出就说明绑上了。这一招比反复检查对话框可靠得多。

5.4 现象:换了个 MATLAB 版本,truetime 能开但一仿真就报错

现象是同一台机器上装了第二个 MATLAB 版本,工具箱路径也加了,库浏览器能开,一跑就报某个 MEX 文件无效。

原因是 MEX 二进制和 MATLAB 版本强绑定,老版本编出来的文件在新版本里加载不了。

解决办法是在新版本里重新跑一遍make_truetime。注意别把两个版本的编译产物混在一起,各自编各自的。如果两个版本要长期共存,我一般会给每个版本单独配一份 startup.m 里的路径变量,避免互相踩。

5.5 现象:编译时报找不到源文件,但文件明明就在那儿

现象是 mex 报错说某个 .cpp 打不开,你去目录里看,文件确实存在,路径也没写错。

原因是路径里有空格或中文,编译链把路径拆错了。这种情况在把工具箱放在"Program Files"或者中文用户名目录下时特别常见。

解决办法是把整个 truetime-2.0 目录挪到纯英文、无空格、层级较浅的位置,比如D:\work\matlab\,然后重配路径、重新编译。这个坑最没技术含量但最耗时间,所以我在 3.1 节把它放在最前面讲,一开始就避开比事后排查划算。

6. 把仿真变成数据:批跑脚本与三次结果自检

单次跑出一条好看的曲线,和拿到可以写进报告的结论,中间隔着一层自动化。手工改参数、点仿真、截图,跑五组就烦了,跑二十组必然出错。我一般的做法是写一个小脚本把参数扫描和结果落盘包起来,跑完直接拿到一张表。

% sweep_run.m —— 扫控制周期,把最大误差和均方根误差落成 CSV periods = [0.005 0.010 0.020]; res = zeros(numel(periods), 3); for i = 1:numel(periods) Ts = periods(i); assignin('base', 'Ts', Ts); % 供模型里的变量读取 out = sim('ncs_demo.slx', 'StopTime', '10'); e = out.err.signals.values; % 误差信号,提前在模型里引出 res(i, :) = [Ts, max(abs(e)), sqrt(mean(e.^2))]; end writematrix(res, 'sweep.csv'); % R2019a 起可直接写矩阵

逻辑说明:assignin('base', ...)是把当前周期值塞进基础工作区,模型里的模块参数直接引用Ts就能读到,省去每次手改模块对话框。sim的第二个参数控制仿真时长,取十个秒足够覆盖几百个控制周期。误差信号要提前在模型里用 To Workspace 模块引出来并命名,脚本才能按名字取到。参数说明:writematrix在新版本可用,老版本换成csvwrite或dlmwrite,函数名不对会直接报错,改一行就行。

拿到这张表之后,我不看曲线先看三个数:最大绝对误差有没有随周期缩短而单调下降,均方根误差和最大误差的比值是否稳定,以及有没有某一组的最大误差突然跳一个量级。第三条最关键——跳变通常意味着那一组刚好踩到了某个任务的截止期,而这正是这类仿真想抓的东西,抓到了就别急着调参把它抹平,先想想它对应的是哪个调度事件。

还有一个习惯值得养成:每次改完路径或重编 MEX,先在命令窗口敲一遍which ttInitKernel和truetime,两个都正常再开模型。这三十秒的检查我吃过亏才坚持下来——有一次重装 MATLAB 之后没注意 MEX 没重编,模型跑了四十分钟出来一条全零曲线,白等一场。从那以后我每次换环境都强制走一遍这两条命令再动手,希望帮到你。

本文还有配套的精品资源,点击获取