Skip to content

Commit eee2a9f

Browse files
committed
feat(node-fmu): Add FMU node type
Signed-off-by: Jitpanu Maneeratpongsuk <jitpanu.maneeratpongsuk@rwth-aachen.de>
1 parent a960050 commit eee2a9f

7 files changed

Lines changed: 455 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ find_package(Criterion)
8787
find_package(OpalOrchestra)
8888
find_package(LibXml2)
8989
find_package(OpalAsyncApi)
90+
find_package(FMI)
9091

9192
# Check for tools
9293
find_program(PROTOBUFC_COMPILER NAMES protoc-c)
@@ -195,6 +196,7 @@ cmake_dependent_option(WITH_NODE_ETHERCAT "Build with ethercat node-type"
195196
cmake_dependent_option(WITH_NODE_EXAMPLE "Build with example node-type" "${WITH_DEFAULTS}" "" OFF)
196197
cmake_dependent_option(WITH_NODE_EXEC "Build with exec node-type" "${WITH_DEFAULTS}" "" OFF)
197198
cmake_dependent_option(WITH_NODE_FILE "Build with file node-type" "${WITH_DEFAULTS}" "" OFF)
199+
cmake_dependent_option(WITH_NODE_FMU "Build with fmu node-type" "${WITH_DEFAULTS}" "FMI_FOUND" OFF)
198200
cmake_dependent_option(WITH_NODE_FPGA "Build with fpga node-type" "${WITH_DEFAULTS}" "WITH_FPGA" OFF)
199201
cmake_dependent_option(WITH_NODE_IEC60870 "Build with iec60870 node-types" "${WITH_DEFAULTS}" "LIB60870_FOUND; NOT WITHOUT_GPL" OFF)
200202
cmake_dependent_option(WITH_NODE_IEC61850 "Build with iec61850 node-types" "${WITH_DEFAULTS}" "LIBIEC61850_FOUND; NOT WITHOUT_GPL" OFF)
@@ -305,6 +307,7 @@ add_feature_info(NODE_ETHERCAT WITH_NODE_ETHERCAT "Build with
305307
add_feature_info(NODE_EXAMPLE WITH_NODE_EXAMPLE "Build with example node-type")
306308
add_feature_info(NODE_EXEC WITH_NODE_EXEC "Build with exec node-type")
307309
add_feature_info(NODE_FILE WITH_NODE_FILE "Build with file node-type")
310+
add_feature_info(NODE_FMU WITH_NODE_FMU "Build with fmu node-type")
308311
add_feature_info(NODE_FPGA WITH_NODE_FPGA "Build with fpga node-type")
309312
add_feature_info(NODE_IEC60870 WITH_NODE_IEC60870 "Build with iec60870 node-types")
310313
add_feature_info(NODE_IEC61850 WITH_NODE_IEC61850 "Build with iec61850 node-types")

cmake/FindFMI.cmake

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
3+
find_path(FMI_INCLUDE_DIR
4+
NAMES fmilib.h
5+
)
6+
7+
find_library(FMI_LIBRARY fmilib
8+
PATHS /usr/local/lib /usr/local/lib64
9+
)
10+
11+
include(FindPackageHandleStandardArgs)
12+
find_package_handle_standard_args(FMI DEFAULT_MSG FMI_LIBRARY FMI_INCLUDE_DIR)
13+
14+
mark_as_advanced(FMI_INCLUDE_DIR FMI_LIBRARY)
15+
16+
if(FMI_FOUND)
17+
add_library(FMI SHARED IMPORTED)
18+
set_target_properties(FMI PROPERTIES
19+
IMPORTED_LOCATION "${FMI_LIBRARY}"
20+
INTERFACE_INCLUDE_DIRECTORIES "${FMI_INCLUDE_DIR}"
21+
)
22+
endif()

etc/examples/nodes/fmu.conf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
nodes = {
5+
fmu = {
6+
type = "fmu"
7+
# Path to fmu file
8+
fmu_path = "fmu/Feedthrough.fmu"
9+
fmu_unpack_path = "/tmp/fmu_unpack"
10+
fmu_writefirst = false
11+
stopTime = 10.0
12+
startTime = 0.0
13+
stepSize = 0.01
14+
# fmu output list
15+
# name must be same as in fmu model description file
16+
in = {
17+
signals = (
18+
{name = "Float64_discrete_output", type = "float"},
19+
{name = "Int64_output", type = "integer"}
20+
)
21+
}
22+
# fmu input list
23+
out = {
24+
signals = (
25+
{name = "Float64_discrete_input", type = "float"},
26+
{name = "Int64_input", type = "integer"}
27+
)
28+
}
29+
}
30+
}

include/villas/nodes/fmu.hpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Node type: Functional Mock-up unit.
2+
*
3+
* Author: Jitpanu Maneeratpongsuk <jitpanu.maneeratpongsuk@rwth-aachen.de>
4+
* SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, RWTH Aachen University
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
#pragma once
8+
9+
#include <string>
10+
#include <vector>
11+
12+
#include <fmilib.h>
13+
14+
#include <villas/format.hpp>
15+
#include <villas/node.hpp>
16+
17+
namespace villas {
18+
namespace node {
19+
20+
// Forward declarations
21+
struct Sample;
22+
23+
class FmuNode : public Node {
24+
protected:
25+
int parse(json_t *json) override;
26+
27+
int _read(struct Sample *smps[], unsigned cnt) override;
28+
int _write(struct Sample *smps[], unsigned cnt) override;
29+
30+
bool writingTurn;
31+
const char *path;
32+
const char *unpack_path;
33+
34+
timespec ts;
35+
pthread_mutex_t mutex;
36+
pthread_cond_t cv;
37+
38+
fmi3_import_t *fmu;
39+
jm_callbacks callbacks;
40+
fmi_import_context_t *context;
41+
42+
public:
43+
FmuNode(const uuid_t &id = {}, const std::string &name = "");
44+
struct fmu_signal {
45+
unsigned int ref = 0;
46+
fmi3_base_type_enu_t type = fmi3_base_type_enu_t::fmi3_base_type_float64;
47+
std::string name;
48+
};
49+
50+
std::vector<fmu_signal> signal_in, signal_out;
51+
52+
int prepare() override;
53+
54+
int check() override;
55+
56+
int start() override;
57+
58+
int stop() override;
59+
60+
// ~FmuNode();
61+
62+
private:
63+
void parse_signal(json_t *json, bool in);
64+
double currentTime = 0;
65+
double stepSize = 0.1;
66+
double stopTime = 0;
67+
double startTime = 0;
68+
bool stopTimeDef = false;
69+
void get_vr(const char *var_name, fmi3_value_reference_t &ref,
70+
fmi3_base_type_enu_t &type);
71+
};
72+
73+
} // namespace node
74+
} // namespace villas

lib/nodes/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ if(WITH_NODE_WEBRTC)
202202
list(APPEND LIBRARIES LibDataChannel::LibDataChannel)
203203
endif()
204204

205+
# Enable FMU node-type support
206+
if(WITH_NODE_FMU)
207+
list(APPEND NODE_SRC fmu.cpp)
208+
list(APPEND LIBRARIES FMI)
209+
endif()
210+
205211
add_library(nodes STATIC ${NODE_SRC})
206212
target_include_directories(nodes PUBLIC ${INCLUDE_DIRS})
207213
target_link_libraries(nodes PUBLIC ${LIBRARIES})

0 commit comments

Comments
 (0)