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

如何通过Python fmpy设置Model Exchange类型FMU的全局参数

我来帮你解决这个问题——你之前的误区是把**全局参数(parameter)当成了输入信号(input)**来处理,所以用input参数设置根本不起作用。咱们一步步来修正:

首先明确:FMI里的「参数」和「输入」是完全不同的概念。你看到GUI里用fmi2SetReal设置的l1是模型的全局参数,属于静态配置项,不是动态输入信号,所以不能通过simulate_fmu的input参数传递,得用专门的参数设置方式。

方法1:直接用simulate_fmu的start_values参数(最简单)

simulate_fmu本身就支持通过start_values参数设置模型的初始参数,你不需要自己处理value reference,直接传「变量名-数值」的字典就行,非常直观。修改你的代码如下:

from fmpy.util import plot_result
import numpy as np
import matplotlib.pyplot as plt
from fmpy import *

fmu = 'CrankCase_ME2.fmu'
dump(fmu)

# 定义要设置的参数值
L = 412
hPLug = 215
alphaDrvie = 60

# 直接用start_values传递参数,不用手动找value reference
result = simulate_fmu(
    fmu,
    start_time=0,
    stop_time=0.1,
    relative_tolerance=1e-7,
    output_interval=1e-5,
    start_values={
        'l1': L,
        'h_plug': hPLug,
        'Alpha_drive': alphaDrvie
    },
    # 可以指定输出变量,减少结果数据量
    output=['time', 'expseu_.Out2']
)

# 绘图
t = result['time']
y_Force = result['expseu_.Out2']
plt.plot(t, y_Force)
plt.show()

这个方法和GUI里调用fmi2SetReal的逻辑一致,simulate_fmu会在初始化FMU时自动帮你调用对应的FMI接口设置参数。

方法2:手动控制FMU实例(更灵活)

如果需要更精细地控制仿真流程(比如在初始化阶段做更多配置),可以手动实例化FMU并调用setReal方法,就像GUI里做的那样:

from fmpy import FMU2Slave, read_model_description
import numpy as np
import matplotlib.pyplot as plt

fmu = 'CrankCase_ME2.fmu'
model_description = read_model_description(fmu)

# 收集变量的value reference
vrs = {var.name: var.valueReference for var in model_description.modelVariables}

# 定义参数值
L = 412
hPLug = 215
alphaDrvie = 60

# 实例化FMU slave
fmu_slave = FMU2Slave(
    guid=model_description.guid,
    modelIdentifier=model_description.modelIdentifier,
    fmuResourceLocation=fmu,
    instanceName='CrankCaseInstance'
)

# 实例化后、初始化前设置参数
fmu_slave.instantiate()
# 设置l1
fmu_slave.setReal([vrs['l1']], [L])
# 设置h_plug
fmu_slave.setReal([vrs['h_plug']], [hPLug])
# 设置Alpha_drive
fmu_slave.setReal([vrs['Alpha_drive']], [alphaDrvie])

# 初始化仿真
fmu_slave.setupExperiment(startTime=0)
fmu_slave.enterInitializationMode()
fmu_slave.exitInitializationMode()

# 运行仿真并收集结果
stop_time = 0.1
print_interval = 1e-5
time = 0.0
result_data = []

while time < stop_time:
    # 执行仿真步
    fmu_slave.doStep(currentCommunicationPoint=time, communicationStepSize=print_interval)
    time += print_interval
    # 获取输出值
    force = fmu_slave.getReal([vrs['expseu_.Out2']])[0]
    result_data.append((time, force))

# 转换结果并绘图
result = np.array(result_data, dtype=[('time', np.double), ('expseu_.Out2', np.double)])
plt.plot(result['time'], result['expseu_.Out2'])
plt.xlabel('Time')
plt.ylabel('Output Force')
plt.show()

# 清理FMU实例
fmu_slave.terminate()
fmu_slave.freeInstance()

为什么之前的input参数没用?

simulate_fmu的input参数是用来定义动态输入信号的——也就是模型里标记为input类型的变量,这类变量可以在仿真运行过程中动态改变值。而你的l1是全局参数(parameter类型),属于模型的静态属性,只能在初始化阶段设置,所以用input传递完全不匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:14:59