pythonfmipyfmi

FMU - Problem reassigning a new value to a variable


Main Goal

Start the FMU with defined start_values ​​and change it in the middle of the process at "ModelExachange".

Approach

  1. Take the FMU already created from the FMI standard web.
  2. Launch it with FMPY.
  3. Change value every step with step_finished parameter from simulate_fmu with my_callback function.

First step

FMU is loaded perfectly, and the same code is working perfectly at "CoSimulation" but the goal is "ModelExchange".

The problem

im trying to modify a value at my_callback function, but this give me the next error:

[ERROR] Variable e can only be set after instantiation, in initialization mode, or in event mode.

i have tried run event mode before the assignment, or initialization mode, but nothing works.

In this line we modify the value, setting the reference from XML first parameter, and the value second parameter:

recorder.fmu.setReal([2], [count])

at this point exactly is where im getting the exposed error.

Python Code:

import fmpy
from fmpy import *
from ctypes import *

fmpy.plot_library = 'plotly'  # experimental

global count

filename = 'BouncingBall.fmu'


start_values = {
    # variable    start   unit       description
    'g':         (-9.81, 'm/s2'),  # Gravity acting on the ball
    'e':            0.7,           # Coefficient of restitution
}

output = [
    'h',  # Position of the ball
    'v',  # Velocity of the ball
]

def my_callback(time, recorder):
    # use recorder.fmu to access the FMU instance
    count = 0

    if time < 1:
        count = 3
    else:
        count = 1

    recorder.fmu.setReal([2], [count])

    return True

result = simulate_fmu(filename, start_values=start_values, output=output, stop_time=3.0,fmi_type = 'ModelExchange',solver = 'Euler', step_size = 0.001, output_interval = 0.001, step_finished = my_callback)

plot_result(result)

My questions:

Any idea how could i solve this?, is possible to do what im trying for ModelExchange?

Thanks.


Solution

  • Try setting these variables using the input argument to fmpy. Using the input argument you can define "timeseries" of inputs. If you set "g" at t=0, it will be applied in the initialization mode (you could also eliminate the need of your my_callback() function).

    You can take a look at the code to simulate_fmu here.