在之前的两篇文章中(文末往期回顾中可查看),我们主要介绍了功能模型接口FMI的主要组成部分和一些使用场景,今天就以康谋自动驾驶仿真软件aiSim为例,来展示一下如何建立一个FMU并实现基于UDP和FMI联合仿真(co-simulation)数据通信。 一、相关配置 OS:Ubuntu22.05 仿真软件:aiSim 5.2.0 首先是要构建所需要的FMU,在一些动力学仿真软件上,如CarSim,可以直接导出动力学模型对应的FMU文件,但本次我们基于C++从零构建FMU文件。 需要编辑的6份文件分别是: fmi_simple_car.cpp:根据FMI2.0标准实现一个车辆模型 simple_car.h:车辆模型的头文件 simple_car.cpp:车辆模型的实现文件 value_reference_ids.h:定义值应用ID的头文件 modelDescription.xml:定义FMU结构的根文件 simple_car_fmu.json文件:用于将构建的FMU文件映射到aiSim的车辆动力学中(非构建FMU所必须) 二、操作步骤 首先是fmi_simple_car.cpp文件主要包含了6个部分,最终实现为模拟控制一个简单的车辆模型,包括了实例化、设置参数,执行仿真步骤以及获取和设置模型参数的功能。 头文件: include "fmi2Functions.h" (是FMI2.0标准的头文件,请参考FMI官网) include include include "simple_car.h" 1、实例化 实例化FMU,在之前的文章中我们以C语言为例,本次采用C++来做示范。 fmi2Component fmi2Instantiate ( fmi2String /*实例名称*/ , fmi2Type fmuType /*实例类型(ME/CO)*/ , fmi2String /*唯一标识符*/ , fmi2String /*资源位置*/ , const fmi2CallbackFunctions* /*回调函数*/ , fmi2Boolean /*是否可见*/ , fmi2Boolean /*是否启用日志*/ ) { /*此处可以与用判断车辆实例是否在使用、检查FMU的类型是ME模型交换还是CO联合仿真、执行实例化车辆*/ car_is_used = True; //预先设置的标志变量,用于表示表示车辆是否正在使用 returen &only_one_car; //预先定义的全局SimpleCar对象only_one_car } 2、FMU交互 实例化完成后,我们要实现一系列函数用于FMU交互的具体实现,主要包含获取和设置变量,执行仿真步骤等。 ①获取类型 获取实数,通过遍历引用数组vr,获取对应的值并存储。 fmi2Status fmi2GetReal (fmi2Component /*c*/ , const fmi2ValueReference vr ) { for ( size_t i = 0 ; i < nvr; ++i) { value = only_one_car. GetValue (vr ); } return fmi2OK; } 同样还能够实现获取整数、布尔值和字符串值。 ②设置类型 设置实数,同样通过only_one_car.SetValue(vr , value )设置对应的值。 fmi2Status fmi2SetReal (fmi2Component /*c*/ , const fmi2ValueReference vr ) { for ( size_t i = 0 ; i < nvr; ++i) { only_one_car. SetValue (vr , value ); } return fmi2OK; } 同样还能够实现获取整数、布尔值和字符串值。 ③执行仿真 获取实联合仿真函数(CO),可以是根据之前实数和证书引入导数计算,又或是引入仿真步骤的执行和取消数,通过遍历引用数组vr,获取对应的值并存储。 比如执行仿真步骤,其中DoStep将会在Simple_car.cpp中实现: fmi2Status fmi2DoStep (fmi2Component /*c*/ , fmi2Real /*currentCommunicationPoint*/ , fmi2Real communicationStepSize, fmi2Boolean /*newStep*/ ) { log_to_file ( "fmi2DoStep()" ); only_one_car. DoStep (communicationStepSize); return fmi2OK; } 同样还能够实现获取整数、布尔值和字符串值。 3、初始化和释放 除此之外,我们还需要注意在仿真过程中FMU实例的初始化和释放。 比如我们可以简单的通过设置car_is_used= false实现实例的释放,可以通过only_one_car = SimplerCar()来实现FMU的重置,其中SimplerCar类的具体实现在simple_car.cpp中。 以上就是基于FMI2.0实现车辆模型时所需的基本内容,剩余的内容我们将在后续的文章中进行分享。