2.4 代码生成讲解
2.4.1 编译器的安装与配置
注:本小节较多例子都需要使用VS编译器,推荐提前安装
1. 安装Visual Studio 2017 (也可以用其他版本,MATLAB能识别即可)
- 后续课程很多地方都需要用到Visual Studio编译器,例如MATLAB中S-Function Builder模块的使用、Simulink自动生成C/C++模型代码等,这里推荐安装Visual Studio 2017,在线安装步骤(需联网)如下:
- 双击
RflySimAPIs\SimulinkControlAPI\VS2017Installer\vs_community2017.exe
- 本课程内容只需勾选右图的“C++的桌面开发”即可。
- 注意:高版本MATLAB也可安装VS2019,但是MATLAB只能识别到低于自己版本的Visual Studio,因此MATLAB 2017b无法识别VS 2019。
- 注意:请不要不要更改VS默认安装目录(例如装到D盘),会导致MATLAB无法识别。
- 不能使用Mingw编译器,只能使用Visual Studio。
- 双击
2. 为MATLAB配置C++编译器
- 在MATLAB的命令行窗口中输入指令“mex -setup”
- 一般来说会自动识别并安装上VS 2017编译器,如下图所示显示“MEX配置使用‘Microsoft Visual C++ 2017’以进行编译”说明安装正确
- 若有其他编译器,本页面还可以切换选择 VS 2013/2015等其他编译器
2.4.2 自主生成C/C++代码例子
- 按下图搭建Simulink模型
- 输入命名为Uin
- 输出命名为Yout
- 积分的初值定义为X0
- 上述变量的名字需要记住,它们对应了生成C++代码的变量名
- 双击Uin图标,进入参数设置页面
- 进入Signal Attributes页面
- 设置数据类型“Data Type”为“double”
- 设置数据维度“Port dimensions”为“1”
- 这样我们就定义了,代码生成后输入接口的数据格式。
- 同理设置“Uout”输出接口
- 双击积分模块,进入参数设置页面。
- 设置一个带名字的参数“X0”
- 打开Simulink-菜单栏-File-Model-Property-Model-Property页面(MATLAB R2019b及以上版本如下面第一张图所示,MATLAB R2017b~2019a版本如下面第二张图所示)
- 在Callbacks-InitFcn标签页加入初始化脚本“X0=0”
- 点击Simulink运行按钮,看能否正确运行。
- 打开“设置” 页面,设置仿真为定步(Fixed-step)长,四阶龙格库塔法(ode4 Runge-Kutta)求解器,步长为0.001s(也可以根据需求设置成其他)。
- 代码生成方式选择ert.tlc,可用于windows,Linux和各类嵌入式平台;语言选择C++,便于通过继承方式调用生成代码;工具选择Visual Studio C++。
ert.tlc目标语言
- ert.tlc生成的嵌入式系统运行示意图。step()函数可选龙格库塔法、欧拉法等近似积分方法;参数接口允许实时改变模型参数;输入输出接口允许其他程序调用。
- 因为包含连续模块(积分模块)因此需要勾选continuous time,不然编译报错。
此外将参数可见性Parameter visibility设为public,是的参数结构体为共有变量,便于访问。
注:MATLAB 2021a开始不会出现选项Parameter visibility ,可跳过本配置
在Code placement页设置文件打包类型为compact,尽量避免生成多余文件,使得代码的可读性最强
- 设置参数为Tunable是的我们可以运行时修改参数。注:inline形式更省内存,但是不便于访问参数,不便于实现参数实时修改或者模型故障注入。MATLAB R2019b及以上版本如下面第一张图所示,MATLAB R2017b~2019a版本如下面第二张图所示)
点击Simulink的编译按钮,即可生成C/C++代码,方法如下
- 对于MATLAB 2019a及之前版本,工具栏样式见下图,直接点击它的编译按钮“Build”即可。
- 对于对于2019b及之后版本,如下图所示,点击APPS - CODE GENERATION – Embedded Coder才能弹出代码生成工具栏,在其中如下图所示点击“C++ CODE”-“Generate Code”-“Build”按钮就能编译生成代码。
- 对于MATLAB 2019a及之前版本,工具栏样式见下图,直接点击它的编译按钮“Build”即可。
生成三个文件,分别是:
- “ert_main.cpp” 该文件包含一个调用生成代码的例子
- “****.cpp” 和“****.h” 这两个文件包含了刚才的Simulink项目生成的一个C++类
注:可以去当前目录下的***_ert_rtw文件夹寻找上述文件的源代码进行查看。
注:Simulink目前生成的代码已经能够满足DO-178C等标准,但在编程时需尽量遵循其编程准则。
- 下图为生成的C++类(****.h文件中):****ModelClass
- ****_P为参数结构体
- ****_U为输入结构体
- ****_Y为输出结构体
- step()为单步更新函数
- initializie()为初始化函数
- terminate()为终止函数
ert_main.cpp文件的运行框架
- 该文件需要用户自行编写
- 在程序运行开始前,新建一个TestModelClass实例,并初始化
- 例如 : TestModelClass m_testClass; m_testClass.initializie();
- 生成一个中断或者定时器,每0.001s调用一次回调函数,在该函数中进行如下操作:1.更新输入信息;2.更新参数信息;3.调用step()函数;4.更新输出信息。
- m_testClass. Test_U. Uin\=***;
- m_testClass. Test_P.X0=***;
- m_testClass.step();
- ***= m_testClass. Test_Y.Yout;
- 退出时m_testClass. Terminate();
2.4.3 Pixhawk代码生成工具箱生成代码解析
本平台PX4代码相对原始固件进行的改动总结:
- PX4-1.8及之前固件,在
Firmware\cmake\configs\****.cmake
文件中,添加modules/px4_simulink_app
语句;后续固件在Firmware\boards\px4\fmu-v*\default.cmake
的“MODULES”栏目下添加px4_simulink_app
模块。 - 在
Firmware\src\modules
目录下建立px4_simulink_app
文件夹,和empty_file.c
+CMakeLists.txt
。 - 在
Firmware\ROMFS\px4fmu_common\init.d\rcS
文件中添加开机启动指令:px4_simulink_app start
- PX4-1.8及之前固件,在
任意打开一个slx例程文件(例如LED例程px4demo_rgbled.slx)编译后生成的***_ert_rtw后缀文件夹,生成的主要文件包括:
- CMakeLists.txt
- ert_main.c
- ***.h
- ***.c
- ***.mk 该文件用于在MATLAB完成代码生成后,将代码拷贝到合适位置(px4_simulink_ app文件夹),并调用PX4编译指令编译固件
PX4固件编译原理(以PX4 1.10固件fmu-v3为例):
- 打开编译器
Win10WSL/Cygwin/Msys2
。 - 输入
make px4_fmu-v3_default
该指令会调用cmake去打开Firmware\boards\px4\fmu-v3\default
文件( PX4 1.8及之前版本会调用cmake\configs\ nuttx_px4fmu-v3_default.cmake
)文件。 - 编译
px4_simulink_app
文件夹。 - 在px4_simulink_app文件夹找到CmakeLists.txt文件,该文件中定义了编译该app线程的方式,首先是包含源文件的路径,其次是该app的主要依赖文件和线程优先级。
- 打开编译器
2.4.4 Pixhawk代码生成工具箱模块编程
- 这些模块都是由S函数加上tlc (Target Language Compiler)文件组成
- 其中,tlc文件为代码生成模板,定义了该模块如何生成代码来访问PX 4的驱动接口,来与底层硬件交互信息
- tlc文件的格式可以参考MATLAB相关教程
- 从Simulink模块属性中获取S函数(tlc)位置