37 DIR* dir = opendir(path.c_str());
42 return (access(path.c_str(), W_OK) == 0);
47 std::ifstream stream(path.c_str());
48 if (stream.is_open() && stream.good()) {
61 return (fmi2_import_get_causality(variable) == causality);
70 std::vector<fmi2_import_variable_t*> result;
72 fmi2_import_variable_list_t* variableList = fmi2_import_get_variable_list(fmu, 0);
73 const size_t variablesCount = fmi2_import_get_variable_list_size(variableList);
74 for (
size_t index = 0; index < variablesCount; ++index) {
76 if (filter(variable)) {
77 result.push_back(variable);
81 fmi2_import_free_variable_list(variableList);
92 std::vector<std::string> result;
94 fmi2_import_variable_list_t* variableList = fmi2_import_get_variable_list(fmu, 0);
95 const size_t variablesCount = fmi2_import_get_variable_list_size(variableList);
96 for (
size_t index = 0; index < variablesCount; ++index) {
98 if (filter(variable)) {
99 std::string name = fmi2_import_get_variable_name(variable);
100 result.push_back(name);
104 fmi2_import_free_variable_list(variableList);
113 const std::string& tmpPath)
114 : fmuPath_(fmuPath), stepSize_(stepSize), interpolateInput_(interpolateInput), tmpPath_(tmpPath) {
118 throw std::invalid_argument(
"Step size must be positive!");
121 throw std::invalid_argument(
"Given FMU file '" + fmuPath +
"' not found or cannot be read!");
124 char pathPattern[] =
"/tmp/fmi_adapter_XXXXXX";
129 throw std::invalid_argument(
"Cannot access tmp folder '" +
tmpPath_ +
"'!");
147 if (fmuVersion != fmi_version_2_0_enu) {
148 throw std::invalid_argument(
"Could not load the FMU or the FMU does not meet the FMI 2.0 standard!");
153 throw std::invalid_argument(
"Could not parse XML description of FMU!");
156 if (fmi2_import_get_fmu_kind(
fmu_) != fmi2_fmu_kind_cs) {
157 throw std::invalid_argument(
"Given FMU is not for co-simulation!");
160 fmi2_callback_functions_t* fmiCallbacks =
new fmi2_callback_functions_t;
161 fmiCallbacks->logger = fmi2_log_forwarding;
162 fmiCallbacks->allocateMemory = calloc;
163 fmiCallbacks->freeMemory = free;
164 fmiCallbacks->componentEnvironment =
fmu_;
167 jm_status_enu_t jmStatus = fmi2_import_create_dllfmu(
fmu_, fmi2_fmu_kind_cs, fmiCallbacks);
168 if (jmStatus == jm_status_error) {
169 throw std::runtime_error(
"Creation of dllfmu failed!");
172 const fmi2_string_t instanceName = fmi2_import_get_model_name(
fmu_);
173 const fmi2_string_t fmuLocation =
nullptr;
174 const fmi2_boolean_t visible = fmi2_false;
175 const fmi2_real_t relativeTol = 1e-4;
176 jmStatus = fmi2_import_instantiate(
fmu_, instanceName, fmi2_cosimulation, fmuLocation, visible);
177 assert(jmStatus != jm_status_error);
179 const fmi2_real_t startTime = 0.0;
180 const fmi2_real_t stopTime = -1.0;
181 fmi2_status_t fmiStatus = fmi2_import_setup_experiment(
fmu_, fmi2_true, relativeTol, startTime, fmi2_false, stopTime);
182 if (fmiStatus != fmi2_status_ok) {
183 throw std::runtime_error(
"fmi2_import_setup_experiment failed!");
186 fmiStatus = fmi2_import_enter_initialization_mode(
fmu_);
187 if (fmiStatus != fmi2_status_ok) {
188 throw std::runtime_error(
"fmi2_import_enter_initialization_mode failed!");
194 throw std::invalid_argument(
"Default experiment step size from FMU is not positive!");
202 fmi2_import_terminate(
fmu_);
203 fmi2_import_free_instance(
fmu_);
204 fmi2_import_destroy_dllfmu(
fmu_);
205 fmi2_import_free(
fmu_);
208 delete static_cast<fmi2_callback_functions_t*
>(
fmiCallbacks_);
221 std::string result = name;
222 for (
size_t i = 0; i < result.size(); ++i) {
224 if ((
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z') || (
'0' <= c && c <=
'9') || c ==
'_') {
231 while (result.length() > 0 && result[0] ==
'_') {
240 return static_cast<bool>(fmi2_import_get_capability(
fmu_, fmi2_cs_canHandleVariableCommunicationStepSize));
297 throw std::runtime_error(
"FMU is no longer in initialization mode!");
300 fmi2_status_t fmiStatus = fmi2_import_exit_initialization_mode(
fmu_);
301 if (fmiStatus != fmi2_status_ok) {
302 throw std::runtime_error(
"fmi2_import_exit_initialization_mode failed!");
311 if (inputValues.empty() || inputValues.begin()->first > simulationTime) {
312 fmi2_value_reference_t valueReference = fmi2_import_get_variable_vr(variable);
314 fmi2_import_get_real(
fmu_, &valueReference, 1, &value);
315 inputValues[simulationTime] = value;
323 throw std::runtime_error(
"FMU is still in initialization mode!");
334 throw std::invalid_argument(
"Step size must be positive!");
337 throw std::runtime_error(
"FMU is still in initialization mode!");
350 while (inputValues.size() >= 2 && (std::next(inputValues.begin())->first -
fmuTimeOffset_).toSec() <=
fmuTime_) {
351 inputValues.erase(inputValues.begin());
354 double value = inputValues.begin()->second;
356 double t0 = (inputValues.begin()->first -
fmuTimeOffset_).toSec();
357 double t1 = (std::next(inputValues.begin())->first -
fmuTimeOffset_).toSec();
358 double weight = (t1 -
fmuTime_) / (t1 - t0);
360 double x1 = std::next(inputValues.begin())->second;
361 value = weight * x0 + (1.0 - weight) * x1;
364 fmi2_value_reference_t valueReference = fmi2_import_get_variable_vr(variable);
365 fmi2_import_set_real(
fmu_, &valueReference, 1, &value);
368 const fmi2_boolean_t
doStep = fmi2_true;
370 if (fmiStatus != fmi2_status_ok) {
371 throw std::runtime_error(
"fmi2_import_do_step failed!");
379 throw std::runtime_error(
"FMU is still in initialization mode!");
382 fmi2_real_t targetFMUTime = (simulationTime -
fmuTimeOffset_).toSec();
384 ROS_ERROR(
"Given time %f is before current simulation time %f!", targetFMUTime,
fmuTime_);
385 throw std::invalid_argument(
"Given time is before current simulation time!");
398 throw std::runtime_error(
"FMU is still in initialization mode!");
406 if (fmi2_import_get_causality(variable) != fmi2_causality_enu_input) {
407 throw std::invalid_argument(
"Given variable is not an input variable!");
416 if (variable ==
nullptr) {
417 throw std::invalid_argument(
"Unknown variable name!");
425 if (fmi2_import_get_causality(variable) != fmi2_causality_enu_output) {
426 throw std::invalid_argument(
"Given variable is not an output variable!");
429 fmi2_value_reference_t valueReference = fmi2_import_get_variable_vr(variable);
431 fmi2_import_get_real(
fmu_, &valueReference, 1, &value);
439 if (variable ==
nullptr) {
440 throw std::invalid_argument(
"Unknown variable name!");
449 throw std::runtime_error(
"Initial values can be only set in initialization mode!");
452 fmi2_value_reference_t valueReference = fmi2_import_get_variable_vr(variable);
453 fmi2_import_set_real(
fmu_, &valueReference, 1, &value);
455 std::string name = fmi2_import_get_variable_name(variable);
456 ROS_INFO(
"Set initial value of variable '%s' to %f", name.c_str(), value);
462 if (variable ==
nullptr) {
463 throw std::invalid_argument(
"Unknown variable name!");
472 std::string name = fmi2_import_get_variable_name(variable);