tag 标签: 联合仿真

相关博文
  • 热度 3
    2024-8-8 09:46
    332 次阅读|
    0 个评论
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(终)
    在之前的文章中,我们介绍了如何构建简单的车辆模型,并基于FMI2.0构建了其FMU,其最终结构为: 今天将会和大家分享如何在aiSim中,通过UDP和aiSim车辆动力学API(Vehicle Dynamics Interface, VDI)来实现和外部的FMU车辆动力学模型的联合仿真。 一、操作步骤 车辆动力学仿真是aiSim的核心组件,能够根据驾驶指令来确定车辆的运动变化。基于准确可靠的车辆动力学模型,可以确保车辆模拟更加真实。在aiSim可以将FMU单独视作动态库来实现车辆动力学,也可以基于VDI和UDP来实现和FMU的联合仿真。 1、实例化VDI VDI中提供了5种不同的车辆动力学模型,包括: (1)2d:横向自行车模型 (2)23d:底盘俯仰和侧倾分离的横向自行车模型 (3)3d:具有3D刚性车身和独立车轮悬挂的横向轮胎模型(计算量很大) (4)拖车模型:用于牵引车辆 (5)FMU:基于FMI对于车辆动力学的不同描述 整个联合仿真的进程可以分四个部分: (1)根据车辆名称匹配对应的ego (2)在VehicleDB.json或是ego自己的asset包中确认所定义的车辆动力学模型 (3)实例化专属的VDI来处理FMU,定义必须的输入/输出数据 (4)通过socket和pyfmi处理FMU 在实例化VDI时,我们将会遵循以下四个部分来获取车辆动力学的相关数据 2、通过UDP实现FMU的读取 在实例化VDI的同时,初始化一个UDP接口来处理收到的数据。 如果我们通过UDP来实现FMU的读取(为了分布式系统),那么我们还需要pyfmi和socket来协助我们读取和写入FMU的数据,整个脚本主要实现功能为: (1)创建UDP的socket,用于监听和读取来自VDI的数据 (2)解析来自VDI的数据,获取动力学数据和标志信号,后者主要用于步进操作 (3)基于标志信号步进式执行仿真 (4)基于fmipy读取FMU中定义的各种动力学数据,并将其打包成UDP,在读取时,同样遵循modelDescription.xml中的定义。 3、效果展示 在完成以上工作后,可以启动整个进程,看一下分布式联合仿真的效果。FMU和对应的脚本运行在PC1上,aiSim运行在PC2上。 以上就是关于功能模型接口FMI的联合仿真的全部内容,通过FMU我们可以快速的在不同工具之间进行集成,而不需要进行大规模的模型移植或是繁琐的联调。 如果涉及到联合仿真,每个子系统都需要对应的仿真器进行求解,在通信时数据的交换频率和吞吐量都会对延时造成影响,从而造成仿真的偏差,可以优化不同的通信机制或是采用案例中主动触发的方式来减少负面影响。
  • 热度 1
    2024-7-25 13:27
    332 次阅读|
    0 个评论
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(四)
    在上一篇文章:“ 康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(三) ”,我们讲述了在构建FMU中,如何通过fmi_simple_car.cpp来实现FMI2.0,即如何实现一个简单的车辆模型来进行车辆动力学仿真。今天康谋接着展示如何通过simple_car.cpp和simple_car.h构建车辆模型本身。 一、操作步骤 首先simple_car.cpp主要构建了车辆所需的多个动力学参数,包括底盘的位姿、车轮的状态等,而simple_car.h提供多个函数来实现基于FMI2.0标准将参数写入到车辆中。 simple_car.cpp主要分为三部分: 初始化车辆动力学参数 计算参数并更新车辆的运动变化 根据车辆的位姿计算车轮的坐标 在头文件中,除了定义相关函数外,还提供了车辆的一些静态参数,用于协助动力学参数的计算,比如给定车辆的转向传动比、轴距、最大附着加速度、车轮半径等。 1、实例化 我们来看一个simple_car.cpp中实现车辆状态更新的简单示例: constdouble wheel_angle =val_refs / m_steer_transmission_ratio; constdouble curvature = wheel_angle / m_wheelbase constdouble yaw_rate = curvature * val_refs 这三个分别计算了转向角、曲率和偏航率。基于这个三个值,再结合车辆的静态参数,我们可以计算并推算出其他的车辆运动姿态参数。 我们也会通过加速踏板和刹车踏板的状态来计算车辆(底盘的纵向加速度),其中m_max_adh_acc为在头文件中预先定义的最大附着加速度: if val_refs < 0.0 { val_refs = val_refs * m_max_adh_acc; } 可以注意到我们使用了宏定义的 、 和 。 使用这一方式的原因:一是为了计算不同参数时清晰明了,此外更重要的是这和FMU中的modelDescription.xml文件所对应,modelDescription.xml规定了FMU的结构,其结构可以参考FMI系列的第二篇文章:“ 康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(二) ”。 2、关注参数 在XML文件中,需要关注的参数类型为name和valuReference,STEERING_ANGLE这一name对应的valuReference值为3,那么为了方便我们使用这些参数,可以把这些定义的宏写入到value_reference_ids.h中,当然也可以写入simple_car.h这一头文件里。 3、Cmake 编译 在完成simple_car.cpp、simple_car.h和FMU描述文件modelDescription.xml文件的构建,最后一步就是要将其编译成为所需FMU文件并生成我们的动态库文件(.so/.dll)。 我们采用Cmake来进行编译,除了定义源文件、添加库、指定目录、链接库(主要是glm和fmi2_interface)以外,我们还需要针对FMI平台进行配置: 以上就是基于FMI2.0构建FMU的全部内容,在下一期中我们将介绍在仿真软件aiSim中通过车辆动力学API来实现和FMU的联合仿真。
  • 热度 2
    2024-7-11 14:42
    386 次阅读|
    0 个评论
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(三)
    在之前的两篇文章中(文末往期回顾中可查看),我们主要介绍了功能模型接口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实现车辆模型时所需的基本内容,剩余的内容我们将在后续的文章中进行分享。
  • 热度 3
    2024-6-27 13:10
    445 次阅读|
    0 个评论
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(二)
    FMU中时间概念的连续性和离散性实际上是变量的属性。并且FMU都能够包含连续时间的变量或是离散时间的变量。在模型交换类型和联合仿真类的FMU通信中可以看到这一点。 在FMI2.0中通过通信点来进行数据交换的通信结构是离散的。 一、模型交换:导入工具提供求解器 仿真工具之间模型集成非常紧密。 在导入工具和模型之间的接口非常复杂。 导入工具必须提供合适的求解器。 二、联合仿真:导出工具提供求解器 模型和求解器之间有着紧密的耦合关系。 导入工具和模型之间的接口相对简单。 可以选择不同的联合仿真算法和通信步长来实现更稳定精确的仿真方案。 三、联合仿真的接口Interface 通信时间步长可以和内部步长不同,通信时间步长主要是不同FMU之间交换信息,而在各自的内部可以时是不同的可变时间步长。 在联合仿真接口中,参数会根据FMI标准有着典型的调用顺序: 得到输出:fmiGetXXX(...) 触发计算直到下一个通信节点:fmidoStep(...) 设置输入值:fmi2SetXXX(...) 以C代码为例: 使用FMI2Instantiate函数实例化FMU CALL instantiationToken, fmi2Flase, fmi2Flase)) 其中涉及到的参数分别是FMI实例、FMU资源的URI、声明FMU的类型为联合仿真、唯一标识符、是否显示FMU的GUI和是否启动日志记录的参数。 应用初始值和输出 CALL (applyStartValues(S, settings)); CALL startTime, true , true , false )); 设置参数并进入初始化模式,如果有FMU初始状态文件的话,可以在实例化FMU后执行 CALL 0 startTime, fmiFalse, 0 )); CALL (FMI2EnterInitializationMode(S)); CALL (FMI2ExitInitializationMode(S)); 进入仿真循环,按照时间步长进行采样和应用输入 for (ubsigned long step = 0 ;; step++) { const outputInterval; ... CALL (FMISample(S, time, result)); CALL (FMIApplyInput(S, input, time, true , true , false )); ...... const outputInterval, fmiTrue); ...... CALL (FMIGetBooleanStatues(S, fmi2Terminated, &terminated)) ...... CALL (FMI2GetRealStatus(S, fmi2LastSuccessfulTime, &lastSuccessfulTime)); CALL (FMISample(S, lastSuccessfulTime, result)); ...... 联合仿真算法作用 联合仿真算法不属于FMI标准的一部分,其作用主要是用于: 推进整个仿真系统的时间,使得各个子系统的FMU组件在 每个时间步长上同步执行仿真计算,即代码中仿真循环的部分。 交换输入和输出数据。 触发时钟信号,用于同步不同仿真组件或触发某些操作,即代码中。 settings startTime + step * settings outputInterval; FMI2DoStep (S, time, settings outputInterval, fmiTrue); 处理事件,例如状态变化、外部输入、内部条件触发等,即代码中。 CALL (FMI2GetRealStatus(S, fmi2LastSuccessfulTime, &lastSuccessfulTime)); CALL (FMISample(S, lastSuccessfulTime, result)); 四、模型描述文件是并行的 模型描述文件modelDescription.xml包含了关于FMU所有的静态信息,其定义了FMU支持的接口类型,无论是模型交换或是联合仿真,同时解释了模型变量,包括了输入、输出以及相关参数,以便导入工具进行访问。 除此之外也会包含模型接口的一些信息,比如模型连接时数据是符合输入输出的。 并且在模型描述文件中还会声明一些属性标志,比如“needsExcutionTool”,这一属性表示需要特定的程序或是特定的库文件才能够执行FMU,所以在导入FMU时,在导入工具中需要一个额外的包装Wrapper,并不真正的参与计算,而是用来实现模型、求解工具和执行之间进行通信。
  • 热度 3
    2024-6-13 10:49
    888 次阅读|
    2 个评论
    功能模型接口FMI(Functional Mock-up Interface)是一个开放且与工具解耦的标准。FMI包含了一个C-API(接口),一个用于描述接口的XML文件以及可交换的功能模型单元FMU(Functional Mock-up Unit),通常会是“zip”文件。FMI实际上是提供了容器化形式的模型,能够在不同的目标上轻松进行重复使用和部署,实现在不同的自动驾驶仿真工具之间动态交换仿真模型和联合仿真。 一、FMI的使用 1、导入和导出工具 通常来说在使用FMI时会有包含导入和导出工具。 导出工具通常是开发模型的地方,能够将模型按照FMI标准打包为FMU;导入工具通常独立于导出工具,可以在外部设置由C-API定义的一个变量、一个值或是触发一个计算步骤,在接收FMU后在,可以在导入工具中与其他模型结合并实现联合仿真。 实际上FMI标准只定义了一个FMU的接口,在多个FMU进行耦合并实现联合仿真时,FMI标准并不涉及到的联合仿真算法或是FMU 的求解器。 2、FMU文件结构 FMU作为模型的容器能够自由的进行分发,通常来说是一个以".fmu"结尾的zip文件。 在一个FMU文件中,至少包含了一个模型描述文件,其描述了模型变量、接口、能力以及模型架构扩展限制的元数据信息。 还至少包含了一个二进制的模型表示,在Linux系统下是.so文件,在window系统中是dll文件。也可以是C源码,能够让使用者进行重新编译创建一个新的二进制文件用于新的目标,这一部署机制可以方便的扩展到不同的系统平台上。 除此以外,可能还包括额外的文件,比如模型文档和相关的头文件。 3、FMI 2.0和FMI 3.0 FMI2.0包括: 带有事件的常微分方程(ODEs),这些方程描述了系统的动态行为,需要通过数值求解器来进行求解; 连续和离散变量,即FMI的模型中,变量可能是随时间变化,也可以是在特定时间点发生变化; 时间概念,或可以理解为更广泛的独立变量,或是自变量,比如可以是一个角度,从而表述系统的动态变化。 FMI3.0增加: 不仅限于动态方程,也支持纯代数方程,可以处理不随时间变化的静态关系; 进一步支持了复杂的离散行为,即通过使用始终和模型分区来管理模型的顺序和同步; 同时不仅仅是基于物理的方程还可以: vECU模型 机器学习模型 AI模型 ...... 二、FMI 3.0.1中的联合仿真 1、多个仿真程序耦合 联合仿真时将多个仿真程序耦合在一起,最终实现由多个子系统组成整理自动驾驶HiL系统的行为。 2、子系统耦合 子系统之间是互相耦合的,也就是每个子系统的行为依赖于其他子系统的行为,所以联合仿真必须是以逐步计算的方式进行。 3、示例 每个仿真程序负责计算一个子系统的行为,比如在自动驾驶HiL系统中,aiSim负责场景和传感器仿真,CarSim负责车辆动力学,两个仿真程序互相使用对方产生的输出来进行计算。 CarSim中车辆动力学更新的频率时1kHz,那么需要同步aiSim中场景更新的频率也为1kHz,而且只有在收到动力学信息后才会进行下一步的仿真。 4、同步和误差管理 在联合仿真的过程中,可能会产生附加误差,需要通过合适的联合仿真算法或是通信模式来将其限制在可接受的范围内,比如设置更新步长等。 作者介绍 崔工 康谋科技仿真测试业务技术主管,拥有超过5年的汽车仿真测试及自动驾驶技术研发经验,熟练掌握仿真测试工具和平台,如aiSim、HEEX等,能有效评估和优化自动驾驶系统的性能和安全性。拥有出色的跨文化沟通能力,成功带领团队完成多项海外技术合作项目,加速了公司在自动驾驶技术上的国际化进程。作为技术团队的核心,领导并实施过大规模的自动驾驶仿真测试项目,对于车辆行为建模、环境模拟以及故障诊断具有独到见解。擅长运用大数据分析和人工智能技术,优化仿真测试流程,提高测试效率和结果的准确性。
相关资源
  • 所需E币: 4
    时间: 2019-12-25 01:55
    大小: 1.28MB
    上传者: wsu_w_hotmail.com
    关于QuartusII与ModelSimSE的联合仿真,感兴趣的可以看看啊基于QuartusII+ModelSimSE的后仿真――我的方法可能是比较笨的,有些东西可能是没有必要的,请高手指正!Bychenhongyi2007.04.07首先大家必须把QuartusII和ModelSim都安装好,并成功破解,在这里这个就不说了。下面我以一个简单的线性反馈移位寄存器(LFSR)的程序作为例子(文件名:lfsr4.vhd和lfsr4_tb.vhd)!一、Quartus中的相关设置1.在Quartus中建立名为lfsr4的工程,设置仿真工具为ModelSim(VHDL),这一步您可以在NewProjectWizard中指定(如图1所示),也可以在后面的Assignments->EDAToolSettings中设置(如图2所示)。图1指定仿真工具图2在Setting中指定仿真工具2.设置完以后,在Quartus中进行全编译lfsr4.vhd,这样在工程目录下会生成simulation文件夹,内部ModelSim文件夹中有三个文件分别是lfsr4.vho(布局布线后的仿真模型文件),lfsr4_modelsim.xrf(好像是实例化的元件),lfsr4_vhd.sdo(标准延时输出文件)。到这里可以关闭QuartusII了!二、ModelSim中手工添加Altera的仿真库在您的Mod……