You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于fmpy实现同状态不同输入的FMU同时间步联合仿真问题咨询

需求与问题

需求

对同一FMU分别施加标称输入和扰动输入,要求在同一时间步运行,且初始状态完全一致。

遇到的问题

  • 核心难点为FMU状态复制(保存/恢复所有数值状态)
  • 当前使用fmpy工具,但目标FMU不支持其自带的saveState()/restoreState()功能
  • 尝试调用cancelStep()重置状态时返回error 3(对应FMI2错误码:步骤无法取消,因未处于运行状态)

替代解决方案

方案1:双FMU实例并行仿真(最可靠)

直接实例化两个独立的FMU对象,各自维护独立状态空间。只需确保两者初始化参数、初始条件完全一致,分别施加标称/扰动输入即可。该方案无需依赖FMU的状态保存接口,兼容性拉满。

方案2:手动遍历保存所有状态变量

若必须复用单FMU实例,需手动识别并保存所有状态变量:

  • 从ModelDescription中筛选causality="local"、variability="continuous"/"discrete"的变量(这类是核心状态变量)
  • 用getReal()/getInteger()/getBoolean()读取所有状态变量值并缓存
  • 重置时重新设置这些变量值,必要时重新执行初始化流程

方案3:重新初始化FMU

放弃cancelStep(),每次仿真前重新执行实例化、初始化流程,强制回到初始状态。缺点是初始化开销较大,适合小模型或低频次仿真场景。


代码实现(方案1:双实例并行仿真)
from fmpy import read_model_description, extract
from fmpy.fmi2 import FMU2Slave

fmu_filename = 'BouncingBall.fmu'
Ts = 0.01

# 加载模型描述,构建变量引用映射
model_description = read_model_description(fmu_filename)
vrs = {var.name: var.valueReference for var in model_description.modelVariables}
v_ref = vrs['v']
y_ref = vrs['h']

# 提取FMU到临时目录
unzipdir = extract(fmu_filename)

# 初始化FMU实例的通用函数
def init_fmu_instance(fmu):
    fmu.instantiate()
    fmu.setupExperiment(startTime=0.)
    fmu.enterInitializationMode()
    fmu.exitInitializationMode()

# 实例化两个独立FMU:标称输入/扰动输入
fmu_nominal = FMU2Slave(
    guid=model_description.guid,
    unzipDirectory=unzipdir,
    modelIdentifier='BouncingBall',
    instanceName='nominal'
)

fmu_disturbed = FMU2Slave(
    guid=model_description.guid,
    unzipDirectory=unzipdir,
    modelIdentifier='BouncingBall',
    instanceName='disturbed'
)

# 初始化两个实例,确保初始环境一致
init_fmu_instance(fmu_nominal)
init_fmu_instance(fmu_disturbed)

# 设置初始条件
v_t0 = 0
y_t0 = 2
dv = 0.1

# 给两个实例分别设置输入
fmu_nominal.setReal([v_ref, y_ref], [v_t0, y_t0])
fmu_disturbed.setReal([v_ref, y_ref], [v_t0 + dv, y_t0])

# 同一时间步执行仿真
fmu_nominal.doStep(currentCommunicationPoint=0., communicationStepSize=Ts)
fmu_disturbed.doStep(currentCommunicationPoint=0., communicationStepSize=Ts)

# 输出结果
print("标称输入仿真结果:")
print(f"  高度h = {fmu_nominal.getReal([y_ref])[0]}")
print(f"  速度v = {fmu_nominal.getReal([v_ref])[0]}")

print("\n扰动输入仿真结果:")
print(f"  高度h = {fmu_disturbed.getReal([y_ref])[0]}")
print(f"  速度v = {fmu_disturbed.getReal([v_ref])[0]}")

# 清理资源
fmu_nominal.terminate()
fmu_nominal.freeInstance()
fmu_disturbed.terminate()
fmu_disturbed.freeInstance()

内容的提问来源于stack exchange,提问作者Daan Bortels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:41:33