主要内容

与POSIX消息队列集成的基于消息的通信模型

这个例子展示了如何将生成的c++代码与POSIX集成起来以促进消息通信。示例应用程序是一个多传感器定位系统,旨在估计车辆的位置。多传感器定位系统由传感器(多个模型)和估计模型两部分组成。概述的工作流展示了如何准备每个组件、生成代码以及集成生成的代码以在系统组件之间传递消息。本示例假设您熟悉在Simulink环境中使用消息。金宝app有关更多信息,请参见生成c++消息以在Simulink和操作系统或中间件之间通信数据金宝app

传感器模型

多传感器定位系统的第一个部件是传感器。定位系统使用加速度计和GPS传感器来估计车辆的位置。每个传感器模型由功能模块、发送模块和输出端口组成。每个传感器模型通过POSIX消息向估计模型发送消息。

准备模型

打开传感器模型rtwdemo_accel_sendrtwdemo_gps_send

对于每个模型,执行以下步骤:

  1. 在“应用程序库”中,单击嵌入式编码器

  2. 在工具条上,设置停止时间One hundred.秒。停车时间定义了在估计车辆位置时数据收集的持续时间。

  3. 在模型中,打开函数块的块参数,并设置样品时间0.01

生成代码

1.对于每个传感器型号,在“配置参数”对话框中设置以下参数:

  • 代码生成窗格中,设置语言c++

  • 接口窗格,设置代码接口打包c++类多实例代码错误诊断没有一个.在“高级参数”下,选择MAT-file日志

2.生成的代码。在c++代码选项卡上,单击构建

集成代码

为了将每个传感器模型生成的c++代码与POSIX集成在一起,手工编写send类的实现和生成的主程序(或创建自己的)。此示例提供了一个自定义的主程序,其中包含一个已实现的send类。要集成来自每个传感器模型的代码,请将生成的主文件替换为定制的主文件。

检查每个传感器的定制主文件:

1.每个传感器的自定义主文件以相同的方式实现。以打开定制的主文件为例rtwdemo_accel_send_ert_main_customized.cpp

2.查看已实现的send类:

  • send类函数,SendData,调用POSIX API (mq_send)传送讯息。

  • 为了提供对消息队列的访问,将POSIX消息队列作为类变量添加,并实现set方法来设置队列。

类accelSendModelClassSendData_real_T:公共SendData_real_T{mqd_t msgQueue;
public: //使用POSIX发送消息void SendData(const real_T* data, int32_T length, int32_T* status) {unsigned int priority = 1;*status = mq_send(msgQueue, (char*)数据,长度,优先级);}
//设置类POSIX队列的方法无效SetMQ(mqd_t mq) {msgQueue = mq;}};

在发送类实现之后,将创建发送类的实例(发送对象)。然后将send对象附加到传感器模型,以使传感器能够向估计模型发送消息。

//创建静态发送对象accelSendModelClassSendData_real_T Out1SendData_arg;
//附加发送对象到传感器模型发送消息静态accelSendModelClass rtObj(Out1SendData_arg);

3.查看添加的POSIX队列行为函数。main函数使用这些函数来打开和关闭POSIX队列。

mqd_t openMQ(const char *name, int flags, int maxmsg, int msgsize) {struct mq_attr attr;attr。Mq_flags = 0;attr。Mq_maxmsg = maxmsg;attr。Mq_msgsize = msgsize;
mqd_t msgQueue = mq_open(name, flags, 0664, &attr);
if (msgQueue < 0) {printf("mq_open failed\n");退出(1);}
返回msgQueue;}
void closeMQ(mqd_t msgQueue) {mq_close(msgQueue);}

4.回顾主要功能。实现的主函数使用前面定义的类和队列函数来发送消息和管理POSIX消息队列。main函数执行如下操作:

  • 打开POSIX消息队列。

  • 发送消息。

  • 关闭POSIX队列。

int_T main(int_T argc, const char *argv[]){//未使用的参数(void)(argc);(空白)(argv);
//初始化模型rtObj.initialize();
//打开POSIX消息队列mqd_t msgQueue = openMQ("/PosixMQ_accel", O_CREAT | O_WRONLY, 2,16);Out1SendData_arg.SetMQ (msgQueue);
//发送消息时(rtmGetErrorStatus(rtObj.getRTM()) == (NULL)) {rt_OneStep();}
// Matfile日志rt_StopDataLogging(Matfile, rtObj.getRTM()->rtwLogInfo);
//禁用rt_OneStep(
//关闭POSIX消息队列closeMQ;
返回0;}

估计模型

第二部分是评估模型。估计模型接收来自传感器模型的输入数据的消息,并计算车辆的估计位置。

准备模型

打开模型rtwdemo_pos_estimate

  1. 在“应用程序库”中,单击嵌入式编码器

  2. 在工具条上,设置停止时间One hundred.秒。

  3. 在模型中,双击打开每个导入。在“块参数”中设置数据类型港维3.,样品时间0.01

  4. 打开每个Message Receive块。清除使用内部队列参数使模型能够使用POSIX消息队列。

  5. 打开函数块,查看估计算法的实现。

生成代码

1.在“配置参数”对话框中,设置以下参数:

  • 代码生成窗格中,设置语言c++

  • 接口窗格中,设置代码接口打包c++类并设置多实例代码错误诊断没有一个.在“高级参数”下,选择MAT-file日志

2.生成的代码。在c++代码选项卡上,单击构建

集成代码

要将评估模型生成的c++代码与POSIX集成在一起,需要手工编写接收类的实现和生成的主程序(或者创建自己的)。估计模型接收来自传感器模型的信息并计算出车辆的估计位置。这个例子提供了一个自定义的主程序和一个实现的接收类。要集成来自评估模型的代码,请将生成的主文件替换为定制的主文件。

查看定制的主文件:

1.打开定制的主文件rtwdemo_pos_estimate_ert_main_customized.cpp

2.查看已实现的接收类:

  • 接收类函数,RecvData,调用POSIX API (mq_receive)接收讯息。

  • 为了提供对消息队列的访问,将POSIX消息队列作为类变量添加,并实现set方法来设置队列。

类positionEstimateModelClassRecvData_real_T:公共RecvData_real_T{mqd_t msgQueue;
public: //使用POSIX API mq_receive接收消息void RecvData(real_T* data, int32_T length, int32_T* status){//在这里添加接收数据逻辑unsigned int优先级= 1;*status = mq_receive(msgQueue, (char *)数据,长度和优先级);}
//设置类POSIX队列的方法无效SetMQ(mqd_t mq) {msgQueue = mq;}};

在接收类实现之后,为每个传感器模型创建接收类的实例(接收对象)。然后将接收对象附加到估计模型,以使模型能够接收来自每个传感器的消息。

//创建接收对象静态positionEstimateModelClassRecvData_real_T In1RecvData_arg;静态positionEstimateModelClassRecvData_real_T In2RecvData_arg;
//附加接收对象到估计模型接收消息静态positionEstimateModelClass rtObj(In1RecvData_arg, In2RecvData_arg);

3.查看添加的POSIX队列行为函数。main函数使用这些函数打开、关闭和解除POSIX队列的链接。

mqd_t openMQ(const char *name, int flags, int maxmsg, int msgsize) {struct mq_attr attr;attr。Mq_flags = 0;attr。Mq_maxmsg = maxmsg;attr。Mq_msgsize = msgsize;
mqd_t msgQueue = mq_open(name, flags, 0664, &attr);
if (msgQueue < 0) {printf("mq_open failed\n");退出(1);}
返回msgQueue;}
void closeMQ(mqd_t msgQueue) {mq_close(msgQueue);}
void unlinkMQ(const char *name) {if (mq_unlink(name) < 0) {printf("mq_unlink failed\n");退出(1);}}

4.回顾主要功能。实现的主函数使用前面定义的类和队列函数来接收消息和管理POSIX队列。main函数执行如下操作:

  • 打开POSIX消息队列。

  • 接收消息。

  • 关闭POSIX队列。

int_T main(int_T argc, const char *argv[]){//未使用的参数(void)(argc);(空白)(argv);
//初始化模型rtObj.initialize();
//打开POSIX消息队列mqd_t msgQueueAccel = openMQ("/PosixMQ_accel", O_CREAT | O_RDONLY, 2,16);mqd_t msgQueueGPS = openMQ("/PosixMQ_gpspos", O_CREAT | O_RDONLY, 2,16);
In1RecvData_arg.SetMQ (msgQueueAccel);In2RecvData_arg.SetMQ (msgQueueGPS);
//接收消息while (rtmGetErrorStatus(rtObj.getRTM()) == (NULL)) {rt_OneStep();}
// Matfile日志rt_StopDataLogging(Matfile, rtObj.getRTM()->rtwLogInfo);
//禁用rt_OneStep(
关闭POSIX消息队列closeMQ(msgQueueAccel);closeMQ (msgQueueGPS);
unlinkMQ (" / PosixMQ_accel ");unlinkMQ (" / PosixMQ_gpspos ");
返回0;}

执行多传感器定位系统

为了执行多传感器定位系统,重建并运行所有模型的可执行文件。要查看结果,请运行提供的构建脚本rtwdemo_positioning_system_script.图中显示了一个结果示例。