IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> simulink模型生成C++代码流程 -> 正文阅读

[C++知识库]simulink模型生成C++代码流程

simulink模型生成C++代码流程

本文主要针对我在一个无人机模型的项目中遇到的问题而写,可能和读者遇到的问题有所差异,仅供参考。

0.开发环境

  • 本文使用matlab r2021b。一般来说,matlab的新版本兼容旧版本

  • matlab需含有Embedded Coder功能模块,不要使用classroom license等版本(该许可证不提供Embedded Coder功能)

  • C++ ToolChain(本文使用VisualStudio2019,不同版本matlab支持不同的VS版本,可在中查看)

1.生成前的配置

  1. 打开slx模型文件,文件路径最好为纯英文,避免意外错误

  2. 为模型内各模块、信号等添加名称(英文),提高可读性

  3. 在APP中打开Embedded Coder

  4. 点击Settings或按Ctrl+E打开配置,以下为必须修改的选项,其他选项根据需要自行设置

    • 求解器->求解器选择->类型 定步长;求解器和步长根据需要设定。仿真时间及步长也是重要参数,理想的效果应是在C++中可以自由配置仿真时间,笔者正在研究,欢迎讨论

    • 代码生成,以下均为在代码生成选项下的设置

      • 目标选择->系统目标文件->浏览,本文选择ert.tlc,Create Visual C/C++ Solution File for Embedded Coder,该选项可自动生成sln解决方案文件

      • 目标选择->语言,本文选择C++,->语言标准,本文选择C++11(ISO)

      • 编译过程,本文勾选仅生成代码,编译部分后续交给VS完成

      • 工具链,本文使用VS2019
        在这里插入图片描述

    • 代码生成->接口,若模型中包含continuous非离散环节,需勾选连续时间选项

    • 代码生成->接口,代码接口打包选择C++类,此种模式生成的代码可读性最好,后续更改、调用也最省心

    • 代码生成->注释,勾选包括注释,选择想要使用的注释。至少把simulink模块注释、simulink模块说明选上,其他的根据自己需要

    1. 应用,确定
    2. 点击Build下的小箭头,点击Generate Code,仅生成代码而不编译
    3. 等待代码生成,生成完成后在slx所在文件夹可以找到对应的文件夹,进入后选择msvc文件夹,打开sln解决方案

2. 编译代码时的一些问题

  1. 运行调试时如果出现无法找到xxx.h,可能是移动过文件夹,或更改了debug/release配置,需重新配置项目->属性->C/C+±>常规->附加包含目录

  2. 如果使用了AerospaceBlockset中的6DOF模块,经笔者测试必定出现以下问题,编译文件时报错C2065,未声明的标识符xxx_PeriodicIndX,xxx_PeriodicRngX

    解决方法:在项目中搜索 PeriodicIndX,可以在slx同名.h文件中找到 typedef int_T PeriodicIndX_XXX_T,可以看到该名称与未声明的标识符几乎一致,浏览该头文件后可以发现,该类型仅做了声明,而未创建变量,于是在类型声明后添加变量声明即可(变量名为报错处的名称)

      //Periodic continuous state vector (global)
      typedef int_T PeriodicIndX_xxx_T[3];
      typedef real_T PeriodicRngX_xxx_T[6];
      
      PeriodicIndX_xxx_T xxx_PeriodicIndX;
      PeriodicRngX_xxx_model_T xxx_PeriodicRngX;
    
  3. 编译运行程序,一般可以正确运行。如果没有修改main函数,则程序不会执行任何操作。

3.代码简析

  1. 解决方案中最重要的文件为 slx同名.h 和slx同名.cpp,当需要使用模型的功能时include 同名.h即可

  2. ert_main.cpp文件为默认生成的主文件,可以在其中修改,也可以删掉此文件自己创建新的main函数文件

  3. 同名xxx.h文件中主要为类xxxModelClass的成员变量和成员函数声明

    class xxxModelClass
    {
        struct xxxx_T{};//定义simulink模型中使用到的数据结构
        struct ExtU_xxx_T{};//simulink模型的输入
        struct ExtU_xxx_T{};//simulink模型的输出
        
        void setExternalInputs(const ExtU_xxx_T*){}//设置模型输入
        const ExtY_xxx_T &getExternalOutputs() const//读取模型输出
        
        void initialize();//初始化,一般为设定各种初值
        void step();//调用即可进行一步定长仿真
        static void terminate();//根据名称应该是模型终止仿真时运行的功能
        
        //构造函数和析构函数均为默认空实现
    }
    
  4. 同名xxx.cpp中为类的成员函数的具体定义

  5. ert_main.cpp中的主要函数功能如下

    static xxxModelClass xxx_Obj;//静态全局变量,实例化了一个模型对象
    
    void rt_OneStep(void);//模板中只是加了些注释,让用户参考其注释设计在一步仿真中进行的读写操作。若不作更改,调用效果和step()函数时一样的,进行一步定长仿真
    
    int_T main(int_T argc, const char *argv[]){}//标准的控制台程序主函数,函数中依次调用了初始化initialize,循环仿真step,终止terminate,即为进行一次(不是一步)完整的仿真
    

4.在自己的C++工程中调用simulink模型

其实读了ert_main.cpp的代码后,感觉直接对其修改就好了,在rt_OneStep函数中设计自己每一步想要实现的操作,如保存每一步的输出,设置新的输入,主函数也直接用稍作更改即可。

不过考虑到大家可能只是在一个大项目中要调用其中一些功能,而不是将其作为主函数,笔者在这里依据自己的理解介绍下调用simulink模型的必须步骤

#include"XXX.h"//包含slx同名头文件
//需要注意,除了在生成的msvc文件夹内的头文件,程序实际上还include了一些官方自带的头文件,需要参考生成的sln的项目附加包含目录,将其添加到你的工程项目中,以下贴出我的目录路径,供参考
/*
E:\Program Files\MATLAB\R2021b\extern\include
E:\Program Files\MATLAB\R2021b\simulink\include
E:\Program Files\MATLAB\R2021b\rtw\c\src
E:\Program Files\MATLAB\R2021b\rtw\c\src\ext_mode\common
E:\Program Files\MATLAB\R2021b\rtw\c\ert
*/


static xxxModelClass xxx_Obj;//实例化一个模型对象,这里参考官方main函数使用了static声明,不使用也是可以的

xxxModelClass::ExtU_xxx_T myInput;//存放模型输入
xxxModelClass::ExtY_xxx_T myOutput;//存放模型输出
xxx_Obj.initialize();//初始化模型,可以根据需要修改initialize函数中的内容
while(xxx)
{
    xxx_Obj.setExternalInputs(&myInput);//设置模型输入,如果只设置一次,记得放在循环外
    xxx_Obj.step();//循环进行定步长仿真,也可以用for循环,根据需要选择即可。
    myOutput=xxx_Obj.getExternalOutputs();//获取本步仿真完成时的输出
    //xxxx然后就可以对获得的输出数据进行各种操作
}
xxx_Obj.terminate();//终止仿真
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-21 18:44:48  更:2022-05-21 18:46:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 13:57:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码