Precommit (#1)

* first commit

* cleanup
This commit is contained in:
tompzf
2025-11-04 13:28:06 +01:00
committed by GitHub
parent dba45dc636
commit 6ed4b1534e
898 changed files with 256340 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# @file CMakeLists.txt
# This file is cmake project file.
# This file was generated by the DBC utility from:
# datalink_4doors_example.dbc
# DBC file version: 1.0.0.1
# Based on CMakeLists.txt from https://github.com/modelica/Reference-FMUs
# only FMI 2.0, only CoSimulation
# without fumsim
# Only valid for Windows
if ( WIN32 )
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
project (Doors4ExampleFMUProject)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
set(VAPI_CORE_SDV_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
set(MODEL_NAME Doors4ExampleFMU)
set(TARGET_NAME ${MODEL_NAME})
set(FMU_FULL_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/fmus/${MODEL_NAME}.fmu")
FUNCTION(cat IN_FILE OUT_FILE)
file(READ ${IN_FILE} CONTENTS)
file(APPEND ${OUT_FILE} "${CONTENTS}")
ENDFUNCTION()
set(FMI_VERSION 2 CACHE STRING "FMI Version")
set_property(CACHE FMI_VERSION PROPERTY STRINGS 2)
set(FMI_TYPE CS CACHE STRING "FMI Version")
set_property(CACHE FMI_TYPE PROPERTY STRINGS CS)
set(FMI_TYPE "")
set (FMI_PLATFORM win32)
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set (FMI_PLATFORM win64)
endif ()
SET(HEADERS
${MODEL_NAME}/config.h
include/cosimulation.h
include/model.h
)
SET(HEADERS
${HEADERS}
include/fmi2Functions.h
include/fmi2FunctionTypes.h
include/fmi2TypesPlatform.h
)
SET(SOURCES
${MODEL_NAME}/model.cpp
src/fmi${FMI_VERSION}Functions.c
src/cosimulation.c
)
add_library(${TARGET_NAME} SHARED
${HEADERS}
${SOURCES}
${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
${MODEL_NAME}/buildDescription.xml
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fmus)
set(FMU_BUILD_DIR temp/${MODEL_NAME})
target_compile_definitions(${TARGET_NAME} PRIVATE
FMI_VERSION=${FMI_VERSION}
DISABLE_PREFIX
)
#[[
if (MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()
]]
target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION)
target_include_directories(${TARGET_NAME} PRIVATE include ${MODEL_NAME})
target_link_libraries(${TARGET_NAME} Winmm Ws2_32 Rpcrt4.lib)
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
)
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME})
# modelDescription.xml
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
"${FMU_BUILD_DIR}/modelDescription.xml"
)
set(ARCHIVE_FILES "modelDescription.xml" "binaries")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources")
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources"
"${FMU_BUILD_DIR}/resources/"
)
set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources")
endif()
# When windows robocopy command (using cmd.exe) is used to copy files its important to set the dependencies
# to assure that the copy command is finished before the next custom action to avoid copy/file access failures
# Copy sdv binaries of this FMU
set(DEST_DIR "${FMU_BUILD_DIR}/resources")
set(SOURCE_DIR_EXAMPLES_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
add_custom_target(copy_function_sdv_files_${TARGET_NAME} DEPENDS ${TARGET_NAME})
add_custom_command(TARGET copy_function_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_EXAMPLES_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_EXAMPLES_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_function_sdv_files_${TARGET_NAME} ${TARGET_NAME})
# Copy framework sdv binaries
set(SOURCE_DIR_CORE_BIN "${SDV_FRAMEWORK_RUNTIME}")
add_custom_target(copy_framework_sdv_files_${TARGET_NAME} DEPENDS copy_function_sdv_files_${TARGET_NAME})
add_custom_command(TARGET copy_framework_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_CORE_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_CORE_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_framework_sdv_files_${TARGET_NAME} copy_function_sdv_files_${TARGET_NAME})
# FMU content created, all files copied
# to zip the files create a new target 'create_zip' which is build after all files have been copied
add_custom_target(create_zip_${TARGET_NAME} ALL DEPENDS copy_framework_sdv_files_${TARGET_NAME} )
add_custom_command(TARGET create_zip_${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${FMU_FULL_FILE_NAME} --format=zip ${ARCHIVE_FILES}
WORKING_DIRECTORY ${FMU_BUILD_DIR}
COMMENT "Creating ZIP ${FMU_FULL_FILE_NAME}"
)
add_dependencies(create_zip_${TARGET_NAME} copy_framework_sdv_files_${TARGET_NAME})
#TODO
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
endif ()

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<fmiModelDescription
fmiVersion = "2.0"
modelName = "Doors4ExampleFMU"
guid = "3fbc9066-6c16-4b98-b5fc-7a7c0735f200"
description = "TargetLink FMU for Doors4ExampleFMU"
generationTool = "TargetLink was generated by the DBC utility: datalink_4doors_example.dbc"
generationDateAndTime = "2025-09-06 14:55:42"
variableNamingConvention = "structured"
numberOfEventIndicators = "0">
<CoSimulation
modelIdentifier = "Doors4ExampleFMU"
canHandleVariableCommunicationStepSize = "false"
canGetAndSetFMUstate = "false"
canSerializeFMUstate = "false"
providesDirectionalDerivative = "false"
canBeInstantiatedOnlyOncePerProcess = "true"
canInterpolateInputs = "false"
canRunAsynchronuously = "false">
<SourceFiles>
<File name="all.c"/>
</SourceFiles>
</CoSimulation>
<DefaultExperiment startTime="0" stepSize="0.01"/>
<ModelVariables>
<!--Index for next variable = 1 -->
<ScalarVariable name = "Door01LeftIsOpen"
valueReference = "0"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 2 -->
<ScalarVariable name = "Door01RightIsOpen"
valueReference = "1"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 3 -->
<ScalarVariable name = "Door02LeftIsOpen"
valueReference = "2"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 4 -->
<ScalarVariable name = "Door02RightIsOpen"
valueReference = "3"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 5 -->
<ScalarVariable name = "LockDoor02Right"
valueReference = "4"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 6 -->
<ScalarVariable name = "LockDoor02Left"
valueReference = "5"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 7 -->
<ScalarVariable name = "LockDoor01Right"
valueReference = "6"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 8 -->
<ScalarVariable name = "LockDoor01Left"
valueReference = "7"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
</ModelVariables>
<ModelStructure>
<Outputs>
<Unknown index="0"/>
</Outputs>
</ModelStructure>
</fmiModelDescription>

View File

@@ -0,0 +1,20 @@
<!--
@file buildDescription.xml
@date 2025-09-06 14:55:42
This file is the fmi Build Description xml.
This file was generated by the DBC utility from:
datalink_4doors_example.dbc
DBC file version: 1.0.0.1
-->
<?xml version="1.0" encoding="UTF-8"?>
<fmiBuildDescription fmiVersion="2.0">
<BuildConfiguration modelIdentifier="Doors4ExampleFMU">
<SourceFileSet language="C++17">
<SourceFile name="fmi2Functions.c"/>
<SourceFile name="model.c"/>
<SourceFile name="cosimulation.c"/>
<PreprocessorDefinition name="FMI_VERSION" value="2"/>
</SourceFileSet>
</BuildConfiguration>
</fmiBuildDescription>

View File

@@ -0,0 +1,62 @@
/**
* @file config.h
* @date 2025-09-06 14:55:42
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_4doors_example.dbc
* DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__CONFIG_H__20250906_145542_578__
#define __DBC_GENERATED__CONFIG_H__20250906_145542_578__
#include <stdint.h>
// define class name and unique id
#define MODEL_IDENTIFIER Doors4ExampleFMU
#define INSTANTIATION_TOKEN "3fbc9066-6c16-4b98-b5fc-7a7c0735f200"
#define FMI_VERSION 2
#define CO_SIMULATION
// define model size
#define NX 0
#define NZ 0
#define GET_INT32
#define SET_INT32
#define GET_FLAOT64
#define SET_FLOAT64
#define EVENT_UPDATE
#define CLEAN_UP
#define FIXED_SOLVER_STEP 0.04
#define DEFAULT_STOP_TIME 10
typedef enum {
vr_Door01LeftIsOpen = 0,
vr_Door01RightIsOpen = 1,
vr_Door02LeftIsOpen = 2,
vr_Door02RightIsOpen = 3,
vr_LockDoor02Right = 4,
vr_LockDoor02Left = 5,
vr_LockDoor01Right = 6,
vr_LockDoor01Left = 7,
} ValueReference;
typedef struct {
int32_t Door01LeftIsOpen;
int32_t Door01RightIsOpen;
int32_t Door02LeftIsOpen;
int32_t Door02RightIsOpen;
int32_t LockDoor02Right;
int32_t LockDoor02Left;
int32_t LockDoor01Right;
int32_t LockDoor01Left;
} ModelData;
#endif // !defined __DBC_GENERATED__CONFIG_H__20250906_145542_578__

View File

@@ -0,0 +1,343 @@
/**
* @file model.cpp
* @date 2025-09-06 14:55:42
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_4doors_example.dbc
* DBC file version: 1.0.0.1
*/
#include <memory>
#include <vector>
#include <iostream>
#include <fstream>
#include <support/timer.h>
#include "signal_identifier.h"
#include <support/signal_support.h>
#include <support/app_control.h>
sdv::core::CSignal g_signalDoor01LeftIsOpen;
sdv::core::CSignal g_signalDoor01RightIsOpen;
sdv::core::CSignal g_signalDoor02LeftIsOpen;
sdv::core::CSignal g_signalDoor02RightIsOpen;
sdv::core::CSignal g_signalLockDoor02Right;
sdv::core::CSignal g_signalLockDoor02Left;
sdv::core::CSignal g_signalLockDoor01Right;
sdv::core::CSignal g_signalLockDoor01Left;
// in case the simulation timer should be used
sdv::core::ITimerSimulationStep* g_pTimerSimulationStep;
std::unique_ptr<sdv::app::CAppControl> g_appcontrol;
bool InitializeAppControl(const std::string& resource, const std::string& configFileName)
{
auto bResult = g_appcontrol->AddModuleSearchDir( resource );
bResult &= g_appcontrol->Startup("");
g_appcontrol->SetConfigMode();
bResult &= g_appcontrol->AddConfigSearchDir( resource );
if (!configFileName.empty())
{
bResult &= g_appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
}
return bResult;
}
sdv::core::EConfigProcessResult RegisterAllSignals()
{
std::string msg = "register all signals: ";
sdv::core::CDispatchService dispatch;
g_signalDoor01LeftIsOpen = dispatch.RegisterRxSignal("CAN_Input_L1.Door01LeftIsOpen");
g_signalDoor01RightIsOpen = dispatch.RegisterRxSignal("CAN_Input_R1.Door01RightIsOpen");
g_signalDoor02LeftIsOpen = dispatch.RegisterRxSignal("CAN_Input_L2.Door02LeftIsOpen");
g_signalDoor02RightIsOpen = dispatch.RegisterRxSignal("CAN_Input_R2.Door02RightIsOpen");
g_signalLockDoor02Right = dispatch.RegisterTxSignal("CAN_Output.LockDoor02Right",0);
g_signalLockDoor02Left = dispatch.RegisterTxSignal("CAN_Output.LockDoor02Left",0);
g_signalLockDoor01Right = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Right",0);
g_signalLockDoor01Left = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Left",0);
if (g_signalDoor01LeftIsOpen && g_signalDoor01RightIsOpen && g_signalDoor02LeftIsOpen && g_signalDoor02RightIsOpen && g_signalLockDoor02Right && g_signalLockDoor02Left
&& g_signalLockDoor01Right && g_signalLockDoor01Left)
{
return sdv::core::EConfigProcessResult::successful;
}
return sdv::core::EConfigProcessResult::failed;
}
bool ResetAllSignals()
{
sdv::core::CDispatchService dispatch;
if (g_signalDoor01LeftIsOpen)
{
g_signalDoor01LeftIsOpen.Reset();
}
if (g_signalDoor01RightIsOpen)
{
g_signalDoor01RightIsOpen.Reset();
}
if (g_signalDoor02LeftIsOpen)
{
g_signalDoor02LeftIsOpen.Reset();
}
if (g_signalDoor02RightIsOpen)
{
g_signalDoor02RightIsOpen.Reset();
}
if (g_signalLockDoor02Right)
{
g_signalLockDoor02Right.Reset();
}
if (g_signalLockDoor02Left)
{
g_signalLockDoor02Left.Reset();
}
if (g_signalLockDoor01Right)
{
g_signalLockDoor01Right.Reset();
}
if (g_signalLockDoor01Left)
{
g_signalLockDoor01Left.Reset();
}
SDV_LOG_INFO("Reset signals");
return true;
}
bool CreateCoreServiceTomlFile(const std::string& resources)
{
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
return true;
}
return false;
}
bool OpenAPILoad(const std::string& resources)
{
bool success = CreateCoreServiceTomlFile(resources);
g_appcontrol = std::make_unique<sdv::app::CAppControl> ();
//
// TODO: Dispatch service must be loaded first, adjust the correct toml file
//
success &= InitializeAppControl(resources, "data_dispatch_config_file.toml");
if (!success)
{
std::cout << "Error: InitializeAppControl() failed" << std::endl;
SDV_LOG_ERROR("Failed InitializeAppControl");
return false;
}
success &= RegisterAllSignals() == sdv::core::EConfigProcessResult::successful;
if (!success)
{
SDV_LOG_ERROR("Signals could not be registered");
}
//
//
// TODO: Load all configurations files
//
//
// Get the simulation task timer service if the simulation timer should be used
success &= g_appcontrol->LoadConfig("simulation_task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
g_pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
if (!g_pTimerSimulationStep)
{
SDV_LOG_WARNING("Simulation timer step not available, use normal task timer ");
success &= g_appcontrol->LoadConfig("task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
}
success &= g_appcontrol->LoadConfig("front_left_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("front_right_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("rear_left_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("rear_right_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("door_comple_service.toml") == sdv::core::EConfigProcessResult::successful;
g_appcontrol->SetRunningMode();
return success;
}
void OpenAPIShutdown()
{
ResetAllSignals();
}
#ifdef __cplusplus
extern "C" {
#endif
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include "config.h"
#include "model.h"
Status cleanup(ModelInstance*)
{
SDV_LOG_INFO("Shutting down...");
OpenAPIShutdown();
return OK;
}
bool setStartValues(ModelInstance* comp)
{
std::string path(comp->resourceLocation);
std::string resourcePath = path.substr(8);
std::replace(resourcePath.begin(), resourcePath.end(), '\\', '/');
if (!OpenAPILoad(resourcePath))
{
std::cout << "Error: OpenAPILoad() failed." << std::endl;
comp->terminateSimulation = true;
return false;
}
// TODO: move this to initialize()?
comp->nextEventTime = 0;
comp->nextEventTimeDefined = true;
return true;
}
Status calculateValues(ModelInstance* comp)
{
UNUSED(comp);
// nothing to do
return OK;
}
Status getFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status getInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
values[(*index)++] = M(Door01LeftIsOpen);
break;
case vr_Door01RightIsOpen:
values[(*index)++] = M(Door01RightIsOpen);
break;
case vr_Door02LeftIsOpen:
values[(*index)++] = M(Door02LeftIsOpen);
break;
case vr_Door02RightIsOpen:
values[(*index)++] = M(Door02RightIsOpen);
break;
case vr_LockDoor02Right:
values[(*index)++] = M(LockDoor02Right);
break;
case vr_LockDoor02Left:
values[(*index)++] = M(LockDoor02Left);
break;
case vr_LockDoor01Right:
values[(*index)++] = M(LockDoor01Right);
break;
case vr_LockDoor01Left:
values[(*index)++] = M(LockDoor01Left);
break;
default:
logError(comp, "Get Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
Status setFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status setInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
M(Door01LeftIsOpen) = values[(*index)++];
break;
case vr_Door01RightIsOpen:
M(Door01RightIsOpen) = values[(*index)++];
break;
case vr_Door02LeftIsOpen:
M(Door02LeftIsOpen) = values[(*index)++];
break;
case vr_Door02RightIsOpen:
M(Door02RightIsOpen) = values[(*index)++];
break;
case vr_LockDoor02Right:
M(LockDoor02Right) = values[(*index)++];
break;
case vr_LockDoor02Left:
M(LockDoor02Left) = values[(*index)++];
break;
case vr_LockDoor01Right:
M(LockDoor01Right) = values[(*index)++];
break;
case vr_LockDoor01Left:
M(LockDoor01Left) = values[(*index)++];
break;
default:
logError(comp, "Set Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
void eventUpdate(ModelInstance* comp)
{
if (g_pTimerSimulationStep) // in case the simulation timer was used, maybe the step size has to be adjusted
{
g_pTimerSimulationStep->SimulationStep(1000);
}
g_signalDoor01LeftIsOpen.Write( M(Door01LeftIsOpen));
g_signalDoor01RightIsOpen.Write( M(Door01RightIsOpen));
g_signalDoor02LeftIsOpen.Write( M(Door02LeftIsOpen));
g_signalDoor02RightIsOpen.Write( M(Door02RightIsOpen));
M(LockDoor02Right) = g_signalLockDoor02Right.Read().get<uint32_t>();
M(LockDoor02Left) = g_signalLockDoor02Left.Read().get<uint32_t>();
M(LockDoor01Right) = g_signalLockDoor01Right.Read().get<uint32_t>();
M(LockDoor01Left) = g_signalLockDoor01Left.Read().get<uint32_t>();
double epsilon = (1.0 + fabs(comp->time)) * DBL_EPSILON;
if (comp->nextEventTimeDefined && comp->time + epsilon >= comp->nextEventTime) {
comp->nextEventTime += FIXED_SOLVER_STEP;
}
comp->valuesOfContinuousStatesChanged = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->terminateSimulation = false;
comp->nextEventTimeDefined = true;
}
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "door_complex_service.sdv"
Class = "Doors Example Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Device"
[[Component]]
Path = "doors_bs_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Device"
[[Component]]
Path = "doors_bs_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Device"
[[Component]]
Path = "doors_bs_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Device"
[[Component]]
Path = "doors_bs_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Service"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "simulation_task_timer.sdv"
Class = "SimulationTaskTimerService"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"

View File

@@ -0,0 +1,26 @@
/**
@file signal_identifier.h
@date 2025-09-06 14:55:42
This file is the signal identifier header.
This file was generated by the DBC utility from:
datalink_4doors_example.dbc
DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__
#define __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__
namespace Doors4ExampleFMU
{
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
static std::string dsDoor01LeftIsOpen = "CAN_Input_L1.Door01LeftIsOpen";
static std::string dsDoor01RightIsOpen = "CAN_Input_R1.Door01RightIsOpen";
static std::string dsDoor02LeftIsOpen = "CAN_Input_L2.Door02LeftIsOpen";
static std::string dsDoor02RightIsOpen = "CAN_Input_R2.Door02RightIsOpen";
static std::string dsLockDoor02Right = "CAN_Output.LockDoor02Right";
static std::string dsLockDoor02Left = "CAN_Output.LockDoor02Left";
static std::string dsLockDoor01Right = "CAN_Output.LockDoor01Right";
static std::string dsLockDoor01Left = "CAN_Output.LockDoor01Left";
} // Doors4ExampleFMU
#endif // __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__

View File

@@ -0,0 +1,7 @@
#pragma once
#include "model.h"
#define EPSILON (FIXED_SOLVER_STEP * 1e-6)
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent);

View File

@@ -0,0 +1,272 @@
#ifndef fmi2FunctionTypes_h
#define fmi2FunctionTypes_h
#include "fmi2TypesPlatform.h"
/* This header file must be utilized when compiling an FMU or an FMI master.
It declares data and function types for FMI 2.0.1
Revisions:
- Sep. 30, 2019: License changed to 2-clause BSD License (without extensions)
- Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216)
- Sep. 6, 2018: Parameter names added to function prototypes
- Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Apr. 3, 2014: Added #include <stddef.h> for size_t definition
- Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179)
- Mar. 26, 2014: Introduced function argument "void" for the functions (#171)
fmiGetTypesPlatformTYPE and fmiGetVersionTYPE
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE
fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE
fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE
fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE
fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed
fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE
Renamed elements of the enumeration fmiEventInfo
upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var
newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded;
- June 13, 2013: Changed type fmiEventInfo
Functions removed:
fmiInitializeModelTYPE
fmiEventUpdateTYPE
fmiCompletedEventIterationTYPE
fmiInitializeSlaveTYPE
Functions added:
fmiEnterModelInitializationModeTYPE
fmiExitModelInitializationModeTYPE
fmiEnterEventModeTYPE
fmiUpdateDiscreteStatesTYPE
fmiEnterContinuousTimeModeTYPE
fmiEnterSlaveInitializationModeTYPE;
fmiExitSlaveInitializationModeTYPE;
- Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE
Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113)
Changed function name "fmiGetNominalContinuousStateTYPE" to
"fmiGetNominalsOfContinuousStatesTYPE"
Removed fmiGetStateValueReferencesTYPE.
- Nov. 14, 2011: First public Version
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
/* make sure all compiler use the same alignment policies for structures */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(push,8)
#endif
/* Include stddef.h, in order that size_t etc. is defined */
#include <stddef.h>
/* Type definitions */
typedef enum {
fmi2OK,
fmi2Warning,
fmi2Discard,
fmi2Error,
fmi2Fatal,
fmi2Pending
} fmi2Status;
typedef enum {
fmi2ModelExchange,
fmi2CoSimulation
} fmi2Type;
typedef enum {
fmi2DoStepStatus,
fmi2PendingStatus,
fmi2LastSuccessfulTime,
fmi2Terminated
} fmi2StatusKind;
typedef void (*fmi2CallbackLogger) (fmi2ComponentEnvironment componentEnvironment,
fmi2String instanceName,
fmi2Status status,
fmi2String category,
fmi2String message,
...);
typedef void* (*fmi2CallbackAllocateMemory)(size_t nobj, size_t size);
typedef void (*fmi2CallbackFreeMemory) (void* obj);
typedef void (*fmi2StepFinished) (fmi2ComponentEnvironment componentEnvironment,
fmi2Status status);
typedef struct {
fmi2CallbackLogger logger;
fmi2CallbackAllocateMemory allocateMemory;
fmi2CallbackFreeMemory freeMemory;
fmi2StepFinished stepFinished;
fmi2ComponentEnvironment componentEnvironment;
} fmi2CallbackFunctions;
typedef struct {
fmi2Boolean newDiscreteStatesNeeded;
fmi2Boolean terminateSimulation;
fmi2Boolean nominalsOfContinuousStatesChanged;
fmi2Boolean valuesOfContinuousStatesChanged;
fmi2Boolean nextEventTimeDefined;
fmi2Real nextEventTime;
} fmi2EventInfo;
/* reset alignment policy to the one set before reading this file */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(pop)
#endif
/* Define fmi2 function pointer types to simplify dynamic loading */
/***************************************************
Types for Common Functions
****************************************************/
/* Inquire version numbers of header files and setting logging status */
typedef const char* fmi2GetTypesPlatformTYPE(void);
typedef const char* fmi2GetVersionTYPE(void);
typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c,
fmi2Boolean loggingOn,
size_t nCategories,
const fmi2String categories[]);
/* Creation and destruction of FMU instances and setting debug status */
typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName,
fmi2Type fmuType,
fmi2String fmuGUID,
fmi2String fmuResourceLocation,
const fmi2CallbackFunctions* functions,
fmi2Boolean visible,
fmi2Boolean loggingOn);
typedef void fmi2FreeInstanceTYPE(fmi2Component c);
/* Enter and exit initialization mode, terminate and reset */
typedef fmi2Status fmi2SetupExperimentTYPE (fmi2Component c,
fmi2Boolean toleranceDefined,
fmi2Real tolerance,
fmi2Real startTime,
fmi2Boolean stopTimeDefined,
fmi2Real stopTime);
typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c);
typedef fmi2Status fmi2ExitInitializationModeTYPE (fmi2Component c);
typedef fmi2Status fmi2TerminateTYPE (fmi2Component c);
typedef fmi2Status fmi2ResetTYPE (fmi2Component c);
/* Getting and setting variable values */
typedef fmi2Status fmi2GetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]);
typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]);
typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]);
typedef fmi2Status fmi2GetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]);
typedef fmi2Status fmi2SetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]);
typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]);
typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]);
typedef fmi2Status fmi2SetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]);
/* Getting and setting the internal FMU state */
typedef fmi2Status fmi2GetFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SetFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate);
typedef fmi2Status fmi2FreeFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t* size);
typedef fmi2Status fmi2SerializeFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size);
typedef fmi2Status fmi2DeSerializeFMUstateTYPE (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate);
/* Getting partial derivatives */
typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c,
const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[], size_t nKnown,
const fmi2Real dvKnown[],
fmi2Real dvUnknown[]);
/***************************************************
Types for Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
typedef fmi2Status fmi2EnterEventModeTYPE (fmi2Component c);
typedef fmi2Status fmi2NewDiscreteStatesTYPE (fmi2Component c, fmi2EventInfo* fmi2eventInfo);
typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c);
typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c,
fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean* enterEventMode,
fmi2Boolean* terminateSimulation);
/* Providing independent variables and re-initialization of caching */
typedef fmi2Status fmi2SetTimeTYPE (fmi2Component c, fmi2Real time);
typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx);
/* Evaluation of the model equations */
typedef fmi2Status fmi2GetDerivativesTYPE (fmi2Component c, fmi2Real derivatives[], size_t nx);
typedef fmi2Status fmi2GetEventIndicatorsTYPE (fmi2Component c, fmi2Real eventIndicators[], size_t ni);
typedef fmi2Status fmi2GetContinuousStatesTYPE (fmi2Component c, fmi2Real x[], size_t nx);
typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx);
/***************************************************
Types for Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
typedef fmi2Status fmi2SetRealInputDerivativesTYPE (fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
const fmi2Real value[]);
typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
fmi2Real value[]);
typedef fmi2Status fmi2DoStepTYPE (fmi2Component c,
fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize,
fmi2Boolean noSetFMUStatePriorToCurrentPoint);
typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c);
/* Inquire slave status */
typedef fmi2Status fmi2GetStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Status* value);
typedef fmi2Status fmi2GetRealStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Real* value);
typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value);
typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value);
typedef fmi2Status fmi2GetStringStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2String* value);
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2FunctionTypes_h */

View File

@@ -0,0 +1,328 @@
#ifndef fmi2Functions_h
#define fmi2Functions_h
/* This header file must be utilized when compiling a FMU.
It defines all functions of the
FMI 2.0.1 Model Exchange and Co-Simulation Interface.
In order to have unique function names even if several FMUs
are compiled together (e.g. for embedded systems), every "real" function name
is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX".
Therefore, the typical usage is:
#define FMI2_FUNCTION_PREFIX MyModel_
#include "fmi2Functions.h"
As a result, a function that is defined as "fmi2GetDerivatives" in this header file,
is actually getting the name "MyModel_fmi2GetDerivatives".
This only holds if the FMU is shipped in C source code, or is compiled in a
static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function
names are used and "FMI2_FUNCTION_PREFIX" must not be defined.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX
are not defined (#173)
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate
fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance
fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode
fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode
fmiTerminateModel, fmiTerminateSlave -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed:
fmiUpdateDiscreteStates -> fmiNewDiscreteStates
- June 13, 2013: Functions removed:
fmiInitializeModel
fmiEventUpdate
fmiCompletedEventIteration
fmiInitializeSlave
Functions added:
fmiEnterModelInitializationMode
fmiExitModelInitializationMode
fmiEnterEventMode
fmiUpdateDiscreteStates
fmiEnterContinuousTimeMode
fmiEnterSlaveInitializationMode;
fmiExitSlaveInitializationMode;
- Feb. 17, 2013: Portability improvements:
o DllExport changed to FMI_Export
o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX
o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used)
Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113)
Changed function name "fmiGetNominalContinuousState" to
"fmiGetNominalsOfContinuousStates"
Removed fmiGetStateValueReferences.
- Nov. 14, 2011: Adapted to FMI 2.0:
o Split into two files (fmiFunctions.h, fmiTypes.h) in order
that code that dynamically loads an FMU can directly
utilize the header files).
o Added C++ encapsulation of C-part, in order that the header
file can be directly utilized in C++ code.
o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX
o stepFinished within fmiCallbackFunctions has as first
argument "fmiComponentEnvironment" and not "fmiComponent".
o New functions to get and set the complete FMU state
and to compute partial derivatives.
- Nov. 4, 2010: Adapted to specification text:
o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform
o fmiInstantiateSlave: Argument GUID replaced by fmuGUID
Argument mimetype replaced by mimeType
o tabs replaced by spaces
- Oct. 16, 2010: Functions for FMI for Co-simulation added
- Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27)
(by M. Otter, DLR)
Added WIN32 pragma to define the struct layout (ticket #34)
(by J. Mauss, QTronic)
- Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize
Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion
Renamed macro fmiModelFunctionsVersion to fmiVersion
Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel
(by J. Mauss, QTronic)
- Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR).
- Dez. 14, 2009: Added eventInfo to meInitialize and added
meGetNominalContinuousStates (by Martin Otter, DLR)
- Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion)
(by A. Junghanns, QTronic)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
meInquireModelTypesVersion -> meGetModelTypesPlatform
meInquireModelFunctionsVersion -> meGetModelFunctionsVersion
meSetStates -> meSetContinuousStates
meGetStates -> meGetContinuousStates
removal of meInitializeModelClass
removal of meGetTime
change of arguments of meInstantiateModel
change of arguments of meCompletedIntegratorStep
(by Martin Otter, DLR):
- July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR).
- March 2, 2009: Changed function definitions according to the last design
meeting with additional improvements (by Martin Otter, DLR).
- Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "fmi2TypesPlatform.h"
#include "fmi2FunctionTypes.h"
#include <stdlib.h>
/*
Export FMI2 API functions on Windows and under GCC.
If custom linking is desired then the FMI2_Export must be
defined before including this file. For instance,
it may be set to __declspec(dllimport).
*/
#if !defined(FMI2_Export)
#if !defined(FMI2_FUNCTION_PREFIX)
#if defined _WIN32 || defined __CYGWIN__
/* Note: both gcc & MSVC on Windows support this syntax. */
#define FMI2_Export __declspec(dllexport)
#else
#if __GNUC__ >= 4
#define FMI2_Export __attribute__ ((visibility ("default")))
#else
#define FMI2_Export
#endif
#endif
#else
#define FMI2_Export
#endif
#endif
/* Macros to construct the real function name
(prepend function name by FMI2_FUNCTION_PREFIX) */
#if defined(FMI2_FUNCTION_PREFIX)
#define fmi2Paste(a,b) a ## b
#define fmi2PasteB(a,b) fmi2Paste(a,b)
#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name)
#else
#define fmi2FullName(name) name
#endif
/***************************************************
Common Functions
****************************************************/
#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform)
#define fmi2GetVersion fmi2FullName(fmi2GetVersion)
#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging)
#define fmi2Instantiate fmi2FullName(fmi2Instantiate)
#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance)
#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment)
#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode)
#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode)
#define fmi2Terminate fmi2FullName(fmi2Terminate)
#define fmi2Reset fmi2FullName(fmi2Reset)
#define fmi2GetReal fmi2FullName(fmi2GetReal)
#define fmi2GetInteger fmi2FullName(fmi2GetInteger)
#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean)
#define fmi2GetString fmi2FullName(fmi2GetString)
#define fmi2SetReal fmi2FullName(fmi2SetReal)
#define fmi2SetInteger fmi2FullName(fmi2SetInteger)
#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean)
#define fmi2SetString fmi2FullName(fmi2SetString)
#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate)
#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate)
#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate)
#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize)
#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate)
#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate)
#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative)
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode)
#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates)
#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode)
#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep)
#define fmi2SetTime fmi2FullName(fmi2SetTime)
#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates)
#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives)
#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators)
#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates)
#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates)
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives)
#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives)
#define fmi2DoStep fmi2FullName(fmi2DoStep)
#define fmi2CancelStep fmi2FullName(fmi2CancelStep)
#define fmi2GetStatus fmi2FullName(fmi2GetStatus)
#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus)
#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus)
#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus)
#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus)
/* Version number */
#define fmi2Version "2.0"
/***************************************************
Common Functions
****************************************************/
/* Inquire version numbers of header files */
FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform;
FMI2_Export fmi2GetVersionTYPE fmi2GetVersion;
FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging;
/* Creation and destruction of FMU instances */
FMI2_Export fmi2InstantiateTYPE fmi2Instantiate;
FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance;
/* Enter and exit initialization mode, terminate and reset */
FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment;
FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode;
FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode;
FMI2_Export fmi2TerminateTYPE fmi2Terminate;
FMI2_Export fmi2ResetTYPE fmi2Reset;
/* Getting and setting variables values */
FMI2_Export fmi2GetRealTYPE fmi2GetReal;
FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger;
FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean;
FMI2_Export fmi2GetStringTYPE fmi2GetString;
FMI2_Export fmi2SetRealTYPE fmi2SetReal;
FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger;
FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean;
FMI2_Export fmi2SetStringTYPE fmi2SetString;
/* Getting and setting the internal FMU state */
FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate;
FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate;
FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate;
FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize;
FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate;
FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate;
/* Getting partial derivatives */
FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative;
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode;
FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates;
FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode;
FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep;
/* Providing independent variables and re-initialization of caching */
FMI2_Export fmi2SetTimeTYPE fmi2SetTime;
FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates;
/* Evaluation of the model equations */
FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives;
FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators;
FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates;
FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates;
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives;
FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives;
FMI2_Export fmi2DoStepTYPE fmi2DoStep;
FMI2_Export fmi2CancelStepTYPE fmi2CancelStep;
/* Inquire slave status */
FMI2_Export fmi2GetStatusTYPE fmi2GetStatus;
FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus;
FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus;
FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus;
FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus;
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2Functions_h */

View File

@@ -0,0 +1,109 @@
#ifndef fmi2TypesPlatform_h
#define fmi2TypesPlatform_h
/* Standard header file to define the argument types of the
functions of the Functional Mock-up Interface 2.0.1
This header file must be utilized both by the model and
by the simulation engine.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar 31, 2014: New datatype fmiChar introduced.
- Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default".
Removed fmiUndefinedValueReference since no longer needed
(because every state is defined in ScalarVariables).
- March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h
- Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0
both for "FMI for model exchange" and for "FMI for co-simulation"
New types "fmiComponentEnvironment", "fmiState", and "fmiByte".
The implementation of "fmiBoolean" is change from "char" to "int".
The #define "fmiPlatform" changed to "fmiTypesPlatform"
(in order that #define and function call are consistent)
- Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h"
for the co-simulation interface
- Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic)
- Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent"
according to meeting on Dec. 18 (by Martin Otter, DLR)
- Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
Changed "version" to "platform", "standard" to "standard32",
Added a precise definition of "standard32" as comment
(by Martin Otter, DLR)
- July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse,
and changed meValueReferenced from int to unsigned int
(by Martin Otter, DLR).
- March 2, 2009: Moved enums and function pointer definitions to
ModelFunctions.h (by Martin Otter, DLR).
- Dec. 3, 2008 : First version by Martin Otter (DLR) and
Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
/* Platform (unique identification of this header file) */
#define fmi2TypesPlatform "default"
/* Type definitions of variables passed as arguments
Version "default" means:
fmi2Component : an opaque object pointer
fmi2ComponentEnvironment: an opaque object pointer
fmi2FMUstate : an opaque object pointer
fmi2ValueReference : handle to the value of a variable
fmi2Real : double precision floating-point data type
fmi2Integer : basic signed integer data type
fmi2Boolean : basic signed integer data type
fmi2Char : character data type
fmi2String : a pointer to a vector of fmi2Char characters
('\0' terminated, UTF8 encoded)
fmi2Byte : smallest addressable unit of the machine, typically one byte.
*/
typedef void* fmi2Component; /* Pointer to FMU instance */
typedef void* fmi2ComponentEnvironment; /* Pointer to FMU environment */
typedef void* fmi2FMUstate; /* Pointer to internal FMU state */
typedef unsigned int fmi2ValueReference;
typedef double fmi2Real ;
typedef int fmi2Integer;
typedef int fmi2Boolean;
typedef char fmi2Char;
typedef const fmi2Char* fmi2String;
typedef char fmi2Byte;
/* Values for fmi2Boolean */
#define fmi2True 1
#define fmi2False 0
#endif /* fmi2TypesPlatform_h */

View File

@@ -0,0 +1,254 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3
#error FMI_VERSION must be one of 1, 2 or 3
#endif
#define UNUSED(x) (void)(x)
#include <stddef.h> // for size_t
#include <stdbool.h> // for bool
#include <stdint.h>
#include "config.h"
#if FMI_VERSION == 1
#define not_modelError (Instantiated| Initialized | Terminated)
typedef enum {
Instantiated = 1 << 0,
Initialized = 1 << 1,
Terminated = 1 << 2,
modelError = 1 << 3
} ModelState;
#elif FMI_VERSION == 2
typedef enum {
StartAndEnd = 1 << 0,
Instantiated = 1 << 1,
InitializationMode = 1 << 2,
// ME states
EventMode = 1 << 3,
ContinuousTimeMode = 1 << 4,
// CS states
StepComplete = 1 << 5,
StepInProgress = 1 << 6,
StepFailed = 1 << 7,
StepCanceled = 1 << 8,
Terminated = 1 << 9,
modelError = 1 << 10,
modelFatal = 1 << 11,
} ModelState;
#else
typedef enum {
StartAndEnd = 1 << 0,
ConfigurationMode = 1 << 1,
Instantiated = 1 << 2,
InitializationMode = 1 << 3,
EventMode = 1 << 4,
ContinuousTimeMode = 1 << 5,
StepMode = 1 << 6,
ClockActivationMode = 1 << 7,
StepDiscarded = 1 << 8,
ReconfigurationMode = 1 << 9,
IntermediateUpdateMode = 1 << 10,
Terminated = 1 << 11,
modelError = 1 << 12,
modelFatal = 1 << 13,
} ModelState;
#endif
typedef enum {
ModelExchange,
CoSimulation,
ScheduledExecution,
} InterfaceType;
typedef enum {
OK,
Warning,
Discard,
Error,
Fatal,
Pending
} Status;
#if FMI_VERSION < 3
typedef void (*loggerType) (void* componentEnvironment, const char* instanceName, int status, const char* category, const char* message, ...);
#else
typedef void (*loggerType) (void* componentEnvironment, int status, const char* category, const char* message);
#endif
typedef void (*lockPreemptionType) (void);
typedef void (*unlockPreemptionType) (void);
typedef void (*intermediateUpdateType) (void* instanceEnvironment,
double intermediateUpdateTime,
bool intermediateVariableSetRequested,
bool intermediateVariableGetAllowed,
bool intermediateStepFinished,
bool canReturnEarly,
bool* earlyReturnRequested,
double* earlyReturnTime);
typedef void(*clockUpdateType) (void* instanceEnvironment);
typedef struct {
double startTime;
double stopTime;
double time;
const char* instanceName;
InterfaceType type;
const char* resourceLocation;
Status status;
// callback functions
loggerType logger;
intermediateUpdateType intermediateUpdate;
clockUpdateType clockUpdate;
lockPreemptionType lockPreemtion;
unlockPreemptionType unlockPreemtion;
bool logEvents;
bool logErrors;
void* componentEnvironment;
ModelState state;
// event info
bool newDiscreteStatesNeeded;
bool terminateSimulation;
bool nominalsOfContinuousStatesChanged;
bool valuesOfContinuousStatesChanged;
bool nextEventTimeDefined;
double nextEventTime;
bool clocksTicked;
bool isDirtyValues;
ModelData modelData;
#if NZ > 0
// event indicators
double z[NZ];
#endif
// internal solver steps
uint64_t nSteps;
// Co-Simulation
bool earlyReturnAllowed;
bool eventModeUsed;
} ModelInstance;
ModelInstance* createModelInstance(
loggerType logger,
intermediateUpdateType intermediateUpdate,
void* componentEnvironment,
const char* instanceName,
const char* instantiationToken,
const char* resourceLocation,
bool loggingOn,
InterfaceType interfaceType);
void freeModelInstance(ModelInstance* comp);
void reset(ModelInstance* comp);
bool setStartValues(ModelInstance* comp);
Status calculateValues(ModelInstance* comp);
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index);
Status getFloat64(ModelInstance* comp, ValueReference vr, double values[], size_t nValues, size_t* index);
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t* index);
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t* index);
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t* index);
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t* index);
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t* index);
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t* index);
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t* index);
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t* index);
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t* index);
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t* index);
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t* index);
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index);
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index);
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index);
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index);
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index);
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index);
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index);
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index);
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index);
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index);
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index);
Status setString(ModelInstance* comp, ValueReference vr, const char* const values[], size_t nValues, size_t* index);
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t sizes[], const char* const values[], size_t nValues, size_t* index);
Status activateClock(ModelInstance* comp, ValueReference vr);
Status getClock(ModelInstance* comp, ValueReference vr, bool* value);
Status setClock(ModelInstance* comp, ValueReference vr, const bool* value);
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier);
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime);
void getContinuousStates(ModelInstance* comp, double x[], size_t nx);
void setContinuousStates(ModelInstance* comp, const double x[], size_t nx);
void getDerivatives(ModelInstance* comp, double dx[], size_t nx);
Status getOutputDerivative(ModelInstance* comp, ValueReference valueReference, int order, double* value);
Status getPartialDerivative(ModelInstance* comp, ValueReference unknown, ValueReference known, double* partialDerivative);
void getEventIndicators(ModelInstance* comp, double z[], size_t nz);
void eventUpdate(ModelInstance* comp);
//void updateEventTime(ModelInstance *comp);
bool invalidNumber(ModelInstance* comp, const char* f, const char* arg, size_t actual, size_t expected);
bool invalidState(ModelInstance* comp, const char* f, int statesExpected);
bool nullPointer(ModelInstance* comp, const char* f, const char* arg, const void* p);
void logError(ModelInstance* comp, const char* message, ...);
Status setDebugLogging(ModelInstance* comp, bool loggingOn, size_t nCategories, const char* const categories[]);
void logEvent(ModelInstance* comp, const char* message, ...);
void logError(ModelInstance* comp, const char* message, ...);
void* getFMUState(ModelInstance* comp);
void setFMUState(ModelInstance* comp, void* FMUState);
// shorthand to access the variables
#define M(v) (comp->modelData.v)
// "stringification" macros
#define xstr(s) str(s)
#define str(s) #s
// assert size of nValues for scalar variables
#define ASSERT_NVALUES(N) do { \
if (*index + (N) > nValues) { \
logError(comp, "Expected nValues > %zu but was %zu.", *index, nValues); \
return Error; \
} \
} while (0)
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,598 @@
#include <stdlib.h> // for calloc(), free()
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "cosimulation.h"
#if FMI_VERSION == 3
#include "fmi3Functions.h"
#endif
#ifdef _MSC_VER
#define strdup _strdup
#endif
ModelInstance *createModelInstance(
loggerType cbLogger,
intermediateUpdateType intermediateUpdate,
void *componentEnvironment,
const char *instanceName,
const char *instantiationToken,
const char *resourceLocation,
bool loggingOn,
InterfaceType interfaceType) {
ModelInstance *comp = NULL;
if (!instanceName || strlen(instanceName) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instance name.");
#endif
}
return NULL;
}
if (!instantiationToken || strlen(instantiationToken) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken.");
#endif
}
return NULL;
}
if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken.");
#endif
}
return NULL;
}
comp = (ModelInstance *)calloc(1, sizeof(ModelInstance));
if (comp) {
comp->componentEnvironment = componentEnvironment;
comp->logger = cbLogger;
comp->intermediateUpdate = intermediateUpdate;
comp->lockPreemtion = NULL;
comp->unlockPreemtion = NULL;
comp->instanceName = strdup(instanceName);
comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL;
comp->status = OK;
comp->logEvents = loggingOn;
comp->logErrors = true; // always log errors
comp->nSteps = 0;
comp->earlyReturnAllowed = false;
comp->eventModeUsed = false;
}
if (!comp || !comp->instanceName) {
logError(comp, "Out of memory.");
return NULL;
}
comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime
comp->type = interfaceType;
comp->state = Instantiated;
comp->newDiscreteStatesNeeded = false;
comp->terminateSimulation = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->valuesOfContinuousStatesChanged = false;
comp->nextEventTimeDefined = false;
comp->nextEventTime = 0;
if (!setStartValues(comp))
{
cbLogger(componentEnvironment, instanceName, Error, "error", "VAPI initialization failed.");
}
comp->isDirtyValues = true;
return comp;
}
void freeModelInstance(ModelInstance *comp) {
free((void *)comp->instanceName);
free(comp);
}
void reset(ModelInstance* comp) {
comp->state = Instantiated;
comp->startTime = 0.0;
comp->time = 0.0;
comp->nSteps = 0;
comp->status = OK;
setStartValues(comp);
comp->isDirtyValues = true;
}
bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) {
if (actual != expected) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected);
return true;
}
return false;
}
bool invalidState(ModelInstance *comp, const char *f, int statesExpected) {
UNUSED(f);
UNUSED(statesExpected);
if (!comp) {
return true;
}
// TODO: add missing states and check state
return false;
// if (!(comp->state & statesExpected)) {
// comp->state = modelError;
// logError(comp, "%s: Illegal call sequence.", f);
// return true;
// }
//
// return false;
}
bool nullPointer(ModelInstance* comp, const char *f, const char *arg, const void *p) {
if (!p) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = NULL.", f, arg);
return true;
}
return false;
}
Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char * const categories[]) {
if (nCategories > 0) {
if (categories == NULL) {
logError(comp, "Argument categories must not be NULL.");
return Error;
}
for (size_t i = 0; i < nCategories; i++) {
if (categories[i] == NULL) {
logError(comp, "Argument categories[%zu] must not be NULL.", i);
return Error;
} else if (strcmp(categories[i], "logEvents") == 0) {
comp->logEvents = loggingOn;
} else if (strcmp(categories[i], "logStatusError") == 0) {
comp->logErrors = loggingOn;
} else {
logError(comp, "Log categories[%zu] must be one of \"logEvents\" or \"logStatusError\" but was \"%s\".", i, categories[i]);
return Error;
}
}
} else {
comp->logEvents = loggingOn;
comp->logErrors = loggingOn;
}
return OK;
}
static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) {
if (!comp->logger) {
return;
}
va_list args1;
int len = 0;
char *buf = "";
va_copy(args1, args);
len = vsnprintf(buf, len, message, args1);
va_end(args1);
if (len < 0) {
return;
}
va_copy(args1, args);
buf = (char *)calloc(len + 1, sizeof(char));
len = vsnprintf(buf, len + 1, message, args);
va_end(args1);
if (len >= 0) {
// no need to distinguish between FMI versions since we're not using variadic arguments
#if FMI_VERSION < 3
comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf);
#else
comp->logger(comp->componentEnvironment, status, category, buf);
#endif
}
free(buf);
}
void logEvent(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logEvents) return;
va_list args;
va_start(args, message);
logMessage(comp, OK, "logEvents", message, args);
va_end(args);
}
void logError(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logErrors) return;
va_list args;
va_start(args, message);
logMessage(comp, Error, "logStatusError", message, args);
va_end(args);
}
// default implementations
#if NZ < 1
void getEventIndicators(ModelInstance *comp, double z[], size_t nz) {
UNUSED(comp);
UNUSED(z);
UNUSED(nz);
// do nothing
}
#endif
#define GET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Getting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef GET_FLOAT32
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index) {
GET_NOT_ALLOWED("Float32");
}
#endif
#ifndef GET_INT8
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int8");
}
#endif
#ifndef GET_UINT8
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef GET_INT16
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int16");
}
#endif
#ifndef GET_UINT16
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef GET_INT32
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int32");
}
#endif
#ifndef GET_UINT32
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef GET_INT64
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int64");
}
#endif
#ifndef GET_UINT64
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef GET_BOOLEAN
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef GET_STRING
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("String");
}
#endif
#ifndef GET_BINARY
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t *index) {
UNUSED(sizes);
GET_NOT_ALLOWED("Binary");
}
#endif
#define SET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Setting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef SET_FLOAT32
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float32");
}
#endif
#ifndef SET_FLOAT64
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float64");
}
#endif
#ifndef SET_INT8
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int8");
}
#endif
#ifndef SET_UINT8
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef SET_INT16
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int16");
}
#endif
#ifndef SET_UINT16
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef SET_INT32
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int32");
}
#endif
#ifndef SET_UINT32
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef SET_INT64
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int64");
}
#endif
#ifndef SET_UINT64
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef SET_BOOLEAN
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef SET_STRING
Status setString(ModelInstance* comp, ValueReference vr, const char *const values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("String");
}
#endif
#ifndef SET_BINARY
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t size[], const char *const values[], size_t nValues, size_t* index) {
UNUSED(size);
SET_NOT_ALLOWED("Binary");
}
#endif
#ifndef ACTIVATE_CLOCK
Status activateClock(ModelInstance* comp, ValueReference vr) {
UNUSED(comp);
UNUSED(vr);
return Error;
}
#endif
#ifndef GET_CLOCK
Status getClock(ModelInstance* comp, ValueReference vr, bool* value) {
UNUSED(comp);
UNUSED(vr);
UNUSED(value);
return Error;
}
#endif
#ifndef GET_INTERVAL
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier) {
UNUSED(comp);
UNUSED(vr);
UNUSED(interval);
UNUSED(qualifier);
return Error;
}
#endif
#ifndef ACTIVATE_MODEL_PARTITION
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime) {
UNUSED(comp);
UNUSED(vr);
UNUSED(activationTime);
return Error;
}
#endif
#if NX < 1
void getContinuousStates(ModelInstance *comp, double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void getDerivatives(ModelInstance *comp, double dx[], size_t nx) {
UNUSED(comp);
UNUSED(dx);
UNUSED(nx);
}
#endif
#ifndef GET_PARTIAL_DERIVATIVE
Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) {
UNUSED(comp);
UNUSED(unknown);
UNUSED(known);
UNUSED(partialDerivative);
logError(comp, "Directional derivatives are not supported.");
return Error;
}
#endif
void* getFMUState(ModelInstance* comp) {
ModelInstance* fmuState = (ModelInstance*)calloc(1, sizeof(ModelInstance));
if (fmuState) {
memcpy(fmuState, comp, sizeof(ModelInstance));
}
return fmuState;
}
void setFMUState(ModelInstance* comp, void* FMUState) {
ModelInstance* s = (ModelInstance*)FMUState;
comp->startTime = s->startTime;
comp->stopTime = s->stopTime;
comp->time = s->time;
comp->status = s->status;
comp->state = s->state;
comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded;
comp->terminateSimulation = s->terminateSimulation;
comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged;
comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged;
comp->nextEventTimeDefined = s->nextEventTimeDefined;
comp->nextEventTime = s->nextEventTime;
comp->clocksTicked = s->clocksTicked;
comp->isDirtyValues = s->isDirtyValues;
comp->modelData = s->modelData;
#if NZ > 0
memcpy(comp->z, s->z, NZ * sizeof(double));
#endif
comp->nSteps = s->nSteps;
}
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent) {
#if NX > 0
double x[NX] = { 0 };
double dx[NX] = { 0 };
getContinuousStates(comp, x, NX);
getDerivatives(comp, dx, NX);
// forward Euler step
for (int i = 0; i < NX; i++) {
x[i] += FIXED_SOLVER_STEP * dx[i];
}
setContinuousStates(comp, x, NX);
#endif
comp->nSteps++;
comp->time = comp->startTime + comp->nSteps * FIXED_SOLVER_STEP;
// state event
*stateEvent = false;
#if NZ > 0
double z[NZ] = { 0.0 };
getEventIndicators(comp, z, NZ);
// check for zero-crossings
for (int i = 0; i < NZ; i++) {
*stateEvent |= (comp->z[i] <= 0 && z[i] > 0) || (comp->z[i] > 0 && z[i] <= 0);
}
// remember the current event indicators
memcpy(comp->z, z, sizeof(double) * NZ);
#endif
// time event
*timeEvent = comp->nextEventTimeDefined && comp->time >= comp->nextEventTime;
bool earlyReturnRequested;
double earlyReturnTime;
// intermediate update
if (comp->intermediateUpdate) {
comp->intermediateUpdate(
comp->componentEnvironment, // instanceEnvironment
comp->time, // intermediateUpdateTime
false, // intermediateVariableSetRequested
true, // intermediateVariableGetAllowed
true, // intermediateStepFinished
false, // canReturnEarly
&earlyReturnRequested, // earlyReturnRequested
&earlyReturnTime); // earlyReturnTime
}
}

View File

@@ -0,0 +1,887 @@
#if FMI_VERSION != 2
#error FMI_VERSION must be 2
#endif
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <math.h>
#include "config.h"
#include "model.h"
#include "cosimulation.h"
// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_.
// Define DISABLE_PREFIX to build a binary FMU.
#ifndef DISABLE_PREFIX
#define pasteA(a,b) a ## b
#define pasteB(a,b) pasteA(a,b)
#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _)
#endif
#include "fmi2Functions.h"
#define ASSERT_NOT_NULL(p) \
do { \
if (!p) { \
logError(S, "Argument %s must not be NULL.", xstr(p)); \
S->state = modelError; \
return (fmi2Status)Error; \
} \
} while (0)
#define GET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
if (S->isDirtyValues) { \
Status s = calculateValues(S); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
S->isDirtyValues = false; \
} \
for (size_t i = 0; i < nvr; i++) { \
Status s = get ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
for (size_t i = 0; i < nvr; i++) { \
Status s = set ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
if (nvr > 0) S->isDirtyValues = true; \
return (fmi2Status)status; \
} while (0)
#define GET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = false; \
size_t index = 0; \
Status s = getBoolean(S, vr[i], &v, nvr, &index); \
value[i] = v; \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = value[i]; \
size_t index = 0; \
Status s = setBoolean(S, vr[i], &v, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
#ifndef DT_EVENT_DETECT
#define DT_EVENT_DETECT 1e-10
#endif
// ---------------------------------------------------------------------------
// Function calls allowed state masks for both Model-exchange and Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform
#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2Instantiate (StartAndEnd)
#define MASK_fmi2FreeInstance (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2SetupExperiment Instantiated
#define MASK_fmi2EnterInitializationMode Instantiated
#define MASK_fmi2ExitInitializationMode InitializationMode
#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode \
| StepComplete | StepFailed)
#define MASK_fmi2Reset MASK_fmi2FreeInstance
#define MASK_fmi2GetReal (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetInteger MASK_fmi2GetReal
#define MASK_fmi2GetBoolean MASK_fmi2GetReal
#define MASK_fmi2GetString MASK_fmi2GetReal
#define MASK_fmi2SetReal (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete)
#define MASK_fmi2SetInteger (Instantiated | InitializationMode \
| EventMode \
| StepComplete)
#define MASK_fmi2SetBoolean MASK_fmi2SetInteger
#define MASK_fmi2SetString MASK_fmi2SetInteger
#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance
#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2GetDirectionalDerivative (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Model-exchange
// ---------------------------------------------------------------------------
#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode)
#define MASK_fmi2NewDiscreteStates EventMode
#define MASK_fmi2EnterContinuousTimeMode EventMode
#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode
#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode)
#define MASK_fmi2SetContinuousStates ContinuousTimeMode
#define MASK_fmi2GetEventIndicators (InitializationMode \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators
#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetNominalsOfContinuousStates ( Instantiated \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode \
| StepComplete)
#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled \
| Terminated | Error)
#define MASK_fmi2DoStep StepComplete
#define MASK_fmi2CancelStep StepInProgress
#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed \
| Terminated)
#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus
#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus
#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus
#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus
// shorthand to access the instance
#define S ((ModelInstance *)c)
#define ASSERT_STATE(S) \
if (!allowedState(c, MASK_fmi2##S, #S)) \
return fmi2Error;
static bool allowedState(ModelInstance *instance, int statesExpected, char *name) {
if (!instance) {
return false;
}
if (!(instance->state & statesExpected)) {
logError(instance, "fmi2%s: Illegal call sequence.", name);
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// FMI functions
// ---------------------------------------------------------------------------
fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
fmi2Boolean visible, fmi2Boolean loggingOn) {
UNUSED(visible);
if (!functions || !functions->logger) {
return NULL;
}
return createModelInstance(
(loggerType)functions->logger,
NULL,
functions->componentEnvironment,
instanceName,
fmuGUID,
fmuResourceLocation,
loggingOn,
(InterfaceType)fmuType);
}
fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
UNUSED(toleranceDefined);
UNUSED(tolerance);
ASSERT_STATE(SetupExperiment)
S->startTime = startTime;
S->stopTime = stopTimeDefined ? stopTime : INFINITY;
S->time = startTime;
return fmi2OK;
}
fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
ASSERT_STATE(EnterInitializationMode)
S->state = InitializationMode;
return fmi2OK;
}
fmi2Status fmi2ExitInitializationMode(fmi2Component c) {
ASSERT_STATE(ExitInitializationMode);
fmi2Status status = fmi2OK;
// if values were set and no fmi2GetXXX triggered update before,
// ensure calculated values are updated now
if (S->isDirtyValues) {
status = (fmi2Status)calculateValues(S);
S->isDirtyValues = false;
}
if (S->type == ModelExchange) {
S->state = EventMode;
} else {
S->state = StepComplete;
}
return status;
}
fmi2Status fmi2Terminate(fmi2Component c) {
ASSERT_STATE(Terminate)
S->state = Terminated;
return fmi2OK;
}
fmi2Status fmi2Reset(fmi2Component c) {
ASSERT_STATE(Reset);
reset(S);
return fmi2OK;
}
void fmi2FreeInstance(fmi2Component c) {
if (S) {
freeModelInstance(S);
}
}
// ---------------------------------------------------------------------------
// FMI functions: class methods not depending of a specific model instance
// ---------------------------------------------------------------------------
const char* fmi2GetVersion(void) {
return fmi2Version;
}
const char* fmi2GetTypesPlatform(void) {
return fmi2TypesPlatform;
}
// ---------------------------------------------------------------------------
// FMI functions: logging control, setters and getters for Real, Integer,
// Boolean, String
// ---------------------------------------------------------------------------
fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
ASSERT_STATE(SetDebugLogging)
return (fmi2Status)setDebugLogging(S, loggingOn, nCategories, categories);
}
fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
ASSERT_STATE(GetReal)
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Float64);
}
fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
ASSERT_STATE(GetInteger)
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Int32);
}
fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
ASSERT_STATE(GetBoolean)
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2GetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
ASSERT_STATE(GetString)
if (nvr>0 && nullPointer(S, "fmi2GetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2GetString", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(String);
}
fmi2Status fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
ASSERT_STATE(SetReal)
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value))
return fmi2Error;
SET_VARIABLES(Float64);
}
fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
ASSERT_STATE(SetInteger)
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value))
return fmi2Error;
SET_VARIABLES(Int32);
}
fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
ASSERT_STATE(SetBoolean)
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "value[]", value))
return fmi2Error;
SET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2SetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
ASSERT_STATE(SetString);
if (nvr>0 && nullPointer(S, "fmi2SetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetString", "value[]", value))
return fmi2Error;
SET_VARIABLES(String);
}
fmi2Status fmi2GetFMUstate (fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(GetFMUstate);
*FMUstate = getFMUState(S);
return fmi2OK;
}
fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {
ASSERT_STATE(SetFMUstate);
if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
setFMUState(S, FMUstate);
return fmi2OK;
}
fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(FreeFMUstate);
free(*FMUstate);
*FMUstate = NULL;
return fmi2OK;
}
fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) {
UNUSED(c);
UNUSED(FMUstate);
ASSERT_STATE(SerializedFMUstateSize);
*size = sizeof(ModelInstance);
return fmi2OK;
}
fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) {
ASSERT_STATE(SerializeFMUstate);
if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
memcpy(serializedState, FMUstate, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
ASSERT_STATE(DeSerializeFMUstate);
if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
if (*FMUstate == NULL) {
*FMUstate = calloc(1, sizeof(ModelInstance));
}
memcpy(*FMUstate, serializedState, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[] , size_t nKnown,
const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
ASSERT_STATE(GetDirectionalDerivative);
// TODO: check value references
// TODO: assert nUnknowns == nDeltaOfUnknowns
// TODO: assert nKnowns == nDeltaKnowns
Status status = OK;
for (size_t i = 0; i < nUnknown; i++) {
dvUnknown[i] = 0;
for (size_t j = 0; j < nKnown; j++) {
double partialDerivative = 0;
Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
dvUnknown[i] += partialDerivative * dvKnown[j];
}
}
return fmi2OK;
}
// ---------------------------------------------------------------------------
// Functions for FMI for Co-Simulation
// ---------------------------------------------------------------------------
/* Simulating the slave */
fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], const fmi2Real value[]) {
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
ASSERT_STATE(SetRealInputDerivatives);
logError(S, "fmi2SetRealInputDerivatives: ignoring function call."
" This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\"");
return fmi2Error;
}
fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], fmi2Real value[]) {
ASSERT_STATE(GetRealOutputDerivatives);
#ifdef GET_OUTPUT_DERIVATIVE
Status status = OK;
for (size_t i = 0; i < nvr; i++) {
const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
}
return (fmi2Status)status;
#else
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
logError(S, "fmi2GetRealOutputDerivatives: ignoring function call."
" This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\"");
return fmi2Error;
#endif
}
fmi2Status fmi2CancelStep(fmi2Component c) {
ASSERT_STATE(CancelStep);
logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending."
" This is not the case.");
return fmi2Error;
}
fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(DoStep);
if (communicationStepSize <= 0) {
logError(S, "Communication step size must be > 0 but was %g.", communicationStepSize);
S->state = modelError;
return fmi2Error;
}
if (currentCommunicationPoint + communicationStepSize > S->stopTime + EPSILON) {
logError(S, "At communication point %.16g a step size of %.16g was requested but stop time is %.16g.",
currentCommunicationPoint, communicationStepSize, S->stopTime);
S->state = modelError;
return fmi2Error;
}
const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON;
while (true) {
if (S->time + FIXED_SOLVER_STEP > nextCommunicationPoint) {
break; // next communication point reached
}
bool stateEvent, timeEvent;
doFixedStep(S, &stateEvent, &timeEvent);
#ifdef EVENT_UPDATE
if (stateEvent || timeEvent) {
eventUpdate(S);
}
#endif
}
return S->terminateSimulation ? fmi2Discard : fmi2OK;
}
/* Inquire slave status */
static fmi2Status getStatus(char* fname, fmi2Component c, const fmi2StatusKind s) {
switch(s) {
case fmi2DoStepStatus: logError(S,
"%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2PendingStatus: logError(S,
"%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2LastSuccessfulTime: logError(S,
"%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
case fmi2Terminated: logError(S,
"%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
}
return fmi2Discard;
}
fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) {
UNUSED(value);
ASSERT_STATE(GetStatus);
return getStatus("fmi2GetStatus", c, s);
}
fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) {
ASSERT_STATE(GetRealStatus);
if (s == fmi2LastSuccessfulTime) {
*value = S->time;
return fmi2OK;
}
return getStatus("fmi2GetRealStatus", c, s);
}
fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) {
UNUSED(value);
ASSERT_STATE(GetIntegerStatus);
return getStatus("fmi2GetIntegerStatus", c, s);
}
fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) {
ASSERT_STATE(GetBooleanStatus);
if (s == fmi2Terminated) {
*value = S->terminateSimulation;
return fmi2OK;
}
return getStatus("fmi2GetBooleanStatus", c, s);
}
fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) {
UNUSED(value);
ASSERT_STATE(GetStringStatus);
return getStatus("fmi2GetStringStatus", c, s);
}
// ---------------------------------------------------------------------------
// Functions for FMI2 for Model Exchange
// ---------------------------------------------------------------------------
/* Enter and exit the different modes */
fmi2Status fmi2EnterEventMode(fmi2Component c) {
ASSERT_STATE(EnterEventMode);
S->state = EventMode;
return fmi2OK;
}
fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) {
ASSERT_STATE(NewDiscreteStates);
#ifdef EVENT_UPDATE
eventUpdate(S);
#endif
eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded;
eventInfo->terminateSimulation = S->terminateSimulation;
eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged;
eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged;
eventInfo->nextEventTimeDefined = S->nextEventTimeDefined;
eventInfo->nextEventTime = S->nextEventTime;
return fmi2OK;
}
fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) {
ASSERT_STATE(EnterContinuousTimeMode);
S->state = ContinuousTimeMode;
return fmi2OK;
}
fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(CompletedIntegratorStep);
if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode))
return fmi2Error;
if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation))
return fmi2Error;
*enterEventMode = fmi2False;
*terminateSimulation = fmi2False;
return fmi2OK;
}
/* Providing independent variables and re-initialization of caching */
fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) {
ASSERT_STATE(SetTime);
S->time = time;
return fmi2OK;
}
fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx){
ASSERT_STATE(SetContinuousStates);
if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x))
return fmi2Error;
setContinuousStates(S, x, nx);
return fmi2OK;
}
/* Evaluation of the model equations */
fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) {
ASSERT_STATE(GetDerivatives);
if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives))
return fmi2Error;
getDerivatives(S, derivatives, nx);
return fmi2OK;
}
fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) {
ASSERT_STATE(GetEventIndicators);
#if NZ > 0
if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ))
return fmi2Error;
getEventIndicators(S, eventIndicators, ni);
#else
UNUSED(c);
UNUSED(eventIndicators);
if (ni > 0) return fmi2Error;
#endif
return fmi2OK;
}
fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) {
ASSERT_STATE(GetContinuousStates);
if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states))
return fmi2Error;
getContinuousStates(S, states, nx);
return fmi2OK;
}
fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) {
ASSERT_STATE(GetNominalsOfContinuousStates);
if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal))
return fmi2Error;
for (size_t i = 0; i < nx; i++)
x_nominal[i] = 1;
return fmi2OK;
}

View File

@@ -0,0 +1,52 @@
/* */
/* This script file uses the Doors4ExampleFMU.fmu to be run in OpenXiL */
/* */
ADD_BBVARI(Loop, UDWORD)
SET_BBVARI(Loop = 0)
/* */
/* Door01Left = 1 represents a open door */
/* wait more then 2 seconds */
/* Open all doors */
/* */
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
SET_BBVARI(Door02LeftIsOpen = 1)
SET_BBVARI(Door02RightIsOpen = 1)
/* */
/* Close each door one by one */
/* wait more then 2 seconds */
/* Open all doors */
/* */
WHILE(Loop < 10)
SET_BBVARI(Door01LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door01RightIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02RightIsOpen = 0)
/* */
/* wait until the doors are locked, < 2 seconds */
/* */
DELAY(1000)
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
SET_BBVARI(Door02LeftIsOpen = 1)
SET_BBVARI(Door02RightIsOpen = 1)
DELAY(100)
SET(Loop = Loop + 1)
ENDWHILE