Create a Manipulation FMU
Tutorial by Johannes Stoljar, Tobias Thummerer
License
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar
# Licensed under the MIT license.
# See LICENSE (https://github.com/thummeto/FMIExport.jl/blob/main/LICENSE) file in the project root for details.
Motivation
This Julia Package FMIExport.jl is motivated by the export of simulation models in Julia. Here the FMI specification is implemented. FMI (Functional Mock-up Interface) is a free standard (fmi-standard.org) that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file. The user is able to create own FMUs (Functional Mock-up Units).
Introduction to the example
ToDo
Target group
The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to export FMUs in Julia.
Other formats
Besides, this Jupyter Notebook there is also a Julia file with the same name, which contains only the code cells and for the documentation there is a Markdown file corresponding to the notebook.
Getting started
Installation prerequisites
Description | Command | Alternative | |
---|---|---|---|
1. | Enter Package Manager via | ] | |
2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " |
2. | Install FMIExport via | add FMIExport | add " https://github.com/ThummeTo/FMIExport.jl " |
2. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " |
Code section
To run the example, the previously installed packages must be included.
using FMI
using FMIExport
using FMICore
ToDo
originalGetReal = nothing # function pointer to the original fmi2GetReal c-function
# custom function for fmi2GetReal!(fmi2Component, Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}}::fmi2Status
# for information on how the FMI2-functions are structured, have a look inside FMICore.jl/src/FMI2_c.jl or the FMI2.0.3-specification on fmi-standard.org
function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})
global originalGetReal
# first, we do what the original function does
status = fmi2GetReal!(originalGetReal, c, vr, nvr, value)
# if we have a pointer to an array, we must interprete it as array to access elements
if isa(value, Ptr{fmi2Real})
value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)
end
if isa(vr, Ptr{fmi2Real})
vr = unsafe_wrap(Array{fmi2Real}, vr, nvr, own=false)
end
# now, we multiply the position sensor output by two (just for fun!)
for i in 1:nvr
if vr[i] == 335544320 # value reference for "positionSensor.s"
value[i] *= 2.0
end
end
# ... and we return the original status
return status
end
# this function is called, as soon as the DLL is loaded and Julia is initialized
# must return a FMU2-instance to work with
FMIBUILD_CONSTRUCTOR = function(resPath)
global originalGetReal
# loads an existing FMU inside the FMU
fmu = fmiLoad(joinpath(resPath, "SpringDamperPendulum1D.fmu"))
# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function
originalGetReal = fmu.cGetReal
# now we overwrite the original function
fmiSetFctGetReal(fmu, myGetReal!)
return fmu
end
### FMIBUILD_NO_EXPORT_BEGIN ###
# The line above is a start-marker for excluded code for the FMU compilation process!
import FMIZoo
tmpDir = mktempdir(; prefix="fmibuildjl_test_", cleanup=false)
@info "Saving example files at: $(tmpDir)"
fmu_save_path = joinpath(tmpDir, "Manipulation.fmu")
sourceFMU = FMIZoo.get_model_filename("SpringDamperPendulum1D", "Dymola", "2022x")
fmu = FMIBUILD_CONSTRUCTOR(dirname(sourceFMU))
# import FMIBuild:fmi2Save # <= this must be excluded during export, because FMIBuild cannot execute itself (but it is able to build)
# fmi2Save(fmu, fmu_save_path; resources=Dict(sourceFMU=>"SpringDamperPendulum1D.fmu")) # <= this must be excluded during export, because fmi2Save would start an infinte build loop with itself
# The following line is a end-marker for excluded code for the FMU compilation process!
### FMIBUILD_NO_EXPORT_END ###
┌ Info: Saving example files at: /tmp/fmibuildjl_test_LhlbJV
└ @ Main In[3]:53
Model name: SpringDamperPendulum1D
Type: 1
Summary
ToDo