Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
fmi2Functions.c
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2020-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
19// Implementation of the FMI2 interface functions
20/****************************************************************************/
21
22#ifdef _MSC_VER
23// Avoid warnings in windows build because of strcpy instead of strcpy_s,
24// because the latter is not available on all platforms
25#define _CRT_SECURE_NO_WARNINGS
26#pragma warning(disable:4820 4514 5045)
27#endif
28
29#include <string.h>
30#include <stdio.h>
31#include <stdarg.h>
33#include "sumo2fmi_bridge.h"
34#include "libsumocpp2c.h"
35
36/* Explicit definition of unused parameters to avoid compiler warnings */
37#define UNUSED_PARAMETER(x) ((void)(x))
38
39/* **********************************************************************************************
40 * * IMPLEMENTATION OF GENERIC FUNCTIONALITY
41 * **********************************************************************************************/
42const char* fmi2GetTypesPlatform(void) {
43 return fmi2TypesPlatform;
44}
45
46const char* fmi2GetVersion(void) {
47 return fmi2Version;
48}
49
50/* ***********************************************************************************************
51 * CREATION AND DESTRUCTION OF AN FMU
52 ***********************************************************************************************/
53
54/* Define what should be logged - if logging is enabled globally */
56fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
57
58 ModelInstance* comp = (ModelInstance*)c;
59
60 if (loggingOn) {
61 for (size_t i = 0; i < nCategories; i++) {
62 if (categories[i] == NULL) {
63 sumo2fmi_logError(comp, "Log category[%d] must not be NULL", i);
64 return fmi2Error;
65 } else if (strcmp(categories[i], "logStatusError") == 0) {
66 comp->logErrors = true;
67 } else if (strcmp(categories[i], "logEvents") == 0) {
68 comp->logEvents = true;
69 } else {
70 sumo2fmi_logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]);
71 return fmi2Error;
72 }
73 }
74 } else {
75 // Logging is disabled globally, no need for a more fine grained logging
76 comp->logEvents = false;
77 comp->logErrors = false;
78 }
79
80 return fmi2OK;
81}
82
83/* The function returns a new instance of an FMU. If a null pointer is returned, then instantiation
84 failed.*/
86fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
87 fmi2String fmuResourceLocation, const fmi2CallbackFunctions* functions,
88 fmi2Boolean visible, fmi2Boolean loggingOn) {
89 UNUSED_PARAMETER(fmuType);
90 UNUSED_PARAMETER(fmuGUID);
91 UNUSED_PARAMETER(visible);
92
93 allocateMemoryType funcAllocateMemory = (allocateMemoryType)functions->allocateMemory;
94 ModelInstance* comp = (ModelInstance*) funcAllocateMemory(1, sizeof(ModelInstance));
95
96 if (comp) {
98
99 /* Callback functions for specific logging, malloc and free;
100 we need callback functions because we cannot know, which functions
101 the environment will provide for us */
102 comp->logger = (loggerType)functions->logger;
104 comp->freeMemory = (freeMemoryType)functions->freeMemory;
105
106 comp->instanceName = (char*)comp->allocateMemory(1 + strlen(instanceName), sizeof(char));
107 strcpy((char*)comp->instanceName, (char*)instanceName);
108
109 if (fmuResourceLocation) {
110 comp->resourceLocation = (char*)comp->allocateMemory(1 + strlen(fmuResourceLocation), sizeof(char));
111 strcpy((char*)comp->resourceLocation, (char*)fmuResourceLocation);
112 } else {
113 comp->resourceLocation = NULL;
114 }
115
116 comp->logEvents = loggingOn;
117 comp->logErrors = true; // always log errors
118 }
119
120 return comp;
121}
122
123/* Disposes the given instance, unloads the loaded model, and frees all the allocated memory
124and other resources that have been allocated by the functions of the FMU interface. */
125void
127 ModelInstance* comp = (ModelInstance*)c;
128
129 /* Store the pointer to the freeMemory function, because we
130 are going to free comp as well */
131 freeMemoryType freeMemoryFunc = comp->freeMemory;
132
133 /* We want to free everything that we allocated in fmi2Instantiate */
134 freeMemoryFunc((void*)comp->instanceName);
135 freeMemoryFunc((void*)comp->resourceLocation);
136 freeMemoryFunc((void*)comp->libsumoCallOptions);
137 freeMemoryFunc((void*)comp->getterParameters);
138 for (int i = 0; i < comp->bufferArrayLength; i++) {
139 freeMemoryFunc((void*)comp->bufferArray[i]);
140 }
141 freeMemoryFunc((void*)comp->bufferArray);
142 freeMemoryFunc((void*)comp);
143}
144
147 fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
148
149 UNUSED_PARAMETER(toleranceDefined);
150 UNUSED_PARAMETER(tolerance);
151 UNUSED_PARAMETER(stopTimeDefined);
152
153 // ignore arguments: toleranceDefined, tolerance
154 ModelInstance* comp = (ModelInstance*)c;
155
156 // Store the start and stop times of the experiment
157 comp->startTime = startTime;
158 comp->stopTime = stopTime;
159
161
162 return fmi2OK;
163}
164
165// Will be called after instantiation and after initial variables have been set
172
173// Informs the FMU to exit Initialization Mode
176 ModelInstance* comp = (ModelInstance*)c;
177
178 sumo2fmi_logEvent(comp, "Calling libsumo with the following options: \"%s\"", comp->libsumoCallOptions);
180
181 return fmi2OK;
182}
183
184// Informs the FMU that the simulation run is terminated
185// --> let libsumo know, that we want to close the simulation
189
191 return fmi2OK;
192}
193
194// Is called by the environment to reset the FMU after a simulation run
198
199 // Should we set some start values?
200 return fmi2OK;
201}
202
203// Implementation of the getter features
205fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
208 UNUSED_PARAMETER(nvr);
209 UNUSED_PARAMETER(value);
210
211 return fmi2Error;
212}
213
215fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
216
217 ModelInstance* comp = (ModelInstance*)c;
218
219 // Check for null pointer errors
220 if (nvr > 0 && (!vr || !value)) {
221 return fmi2Error;
222 }
223
224 fmi2Status status = fmi2OK;
225
226 // Go through the list of arrays and save all requested values
227 for (size_t i = 0; i < nvr; i++) {
228 fmi2Status s = sumo2fmi_getInteger(comp, vr[i], &(value[i]));
229 status = s > status ? s : status;
230
231 if (status > fmi2Warning) {
232 return status;
233 }
234 }
235
236 return status;
237}
238
240fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
243 UNUSED_PARAMETER(nvr);
244 UNUSED_PARAMETER(value);
245
246 return fmi2Error;
247}
248
250fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
251
252 ModelInstance* comp = (ModelInstance*)c;
253
254 // Check for null pointer errors
255 if (nvr > 0 && (!vr || !value)) {
256 return fmi2Error;
257 }
258
259 fmi2Status status = fmi2OK;
260
262 for (int b = 0; b < comp->bufferArrayLength; b++) {
263 comp->freeMemory((void*)comp->bufferArray[b]);
264 }
265 comp->freeMemory((void*)comp->bufferArray);
266 comp->bufferArray = (fmi2String*)comp->allocateMemory(nvr, sizeof(fmi2String));
267 comp->bufferArrayLength = (int)nvr;
268
269 // Go through the list of arrays and save all requested values
270 for (size_t i = 0; i < nvr; i++) {
271 fmi2Status s = sumo2fmi_getString(comp, vr[i], &(comp->bufferArray[i]));
272 value[i] = comp->bufferArray[i];
273 if (value[i] == NULL) {
274 s = fmi2Error;
275 }
276
277 status = s > status ? s : status;
278 if (status > fmi2Warning) {
279 return status;
280 }
281 }
282
283 return status;
284}
285
286// Implementation of the setter features
288fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
291 UNUSED_PARAMETER(nvr);
292 UNUSED_PARAMETER(value);
293 return fmi2Error;
294}
295
297fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
300 UNUSED_PARAMETER(nvr);
301 UNUSED_PARAMETER(value);
302
303 return fmi2Error;
304}
305
307fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
310 UNUSED_PARAMETER(nvr);
311 UNUSED_PARAMETER(value);
312
313 return fmi2Error;
314}
315
317fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
318
319 ModelInstance* comp = (ModelInstance*)c;
320 fmi2Status status = fmi2OK;
321
322 for (size_t i = 0; i < nvr; i++) {
323 fmi2Status s = sumo2fmi_setString(comp, vr[i], value[i]);
324 status = s > status ? s : status;
325 if (status > fmi2Warning) {
326 return status;
327 }
328 }
329
330 return status;
331}
332
336 UNUSED_PARAMETER(FMUstate);
337 return fmi2Error; /* Dummy implementation */
338}
339
343 UNUSED_PARAMETER(FMUstate);
344 return fmi2Error; /* Dummy implementation */
345}
346
350 UNUSED_PARAMETER(FMUstate);
351 return fmi2Error; /* Dummy implementation */
352}
353
357 UNUSED_PARAMETER(FMUstate);
358 UNUSED_PARAMETER(size);
359 return fmi2Error; /* Dummy implementation */
360}
361
363fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte state[], size_t size) {
365 UNUSED_PARAMETER(FMUstate);
366 UNUSED_PARAMETER(state);
367 UNUSED_PARAMETER(size);
368 return fmi2Error; /* Dummy implementation */
369}
370
372fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
374 UNUSED_PARAMETER(serializedState);
375 UNUSED_PARAMETER(size);
376 UNUSED_PARAMETER(FMUstate);
377 return fmi2Error; /* Dummy implementation */
378}
379
381fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
382 const fmi2ValueReference vKnown_ref[], size_t nKnown, const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
384 UNUSED_PARAMETER(vUnknown_ref);
385 UNUSED_PARAMETER(nUnknown);
386 UNUSED_PARAMETER(vKnown_ref);
387 UNUSED_PARAMETER(nKnown);
388 UNUSED_PARAMETER(dvKnown);
389 UNUSED_PARAMETER(dvUnknown);
390 return fmi2Error; /* Dummy implementation */
391}
392
393/* Further functions for interpolation */
395fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[]) {
398 UNUSED_PARAMETER(nvr);
399 UNUSED_PARAMETER(order);
400 UNUSED_PARAMETER(value);
401
402 return fmi2Error; /* Ignoring - SUMO cannot interpolate inputs */
403}
404
406fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[]) {
409 UNUSED_PARAMETER(order);
410
411 for (size_t i = 0; i < nvr; i++) {
412 value[i] = 0; /* We cannot compute derivatives of outputs */
413 }
414 return fmi2Error;
415}
416
417/* Stepping */
419fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
420 UNUSED_PARAMETER(noSetFMUStatePriorToCurrentPoint);
421
422 ModelInstance* comp = (ModelInstance*)c;
423
424 if (communicationStepSize <= 0) {
425 return fmi2Error;
426 }
427
428 return sumo2fmi_step(comp, currentCommunicationPoint + communicationStepSize);
429}
430
434
435 return fmi2Error; /* We will never have a modelStepInProgress state */
436}
437
438/* Status functions */
443 UNUSED_PARAMETER(value);
444
445 return fmi2Discard;
446}
447
452 UNUSED_PARAMETER(value);
453
454 return fmi2Discard;
455}
456
465
474
@ fmi2OK
@ fmi2Error
@ fmi2Discard
@ fmi2Warning
fmi2StatusKind
#define UNUSED_PARAMETER(x)
const char * fmi2GetVersion(void)
const char * fmi2GetTypesPlatform(void)
#define fmi2GetStringStatus
#define fmi2GetFMUstate
#define fmi2GetReal
#define fmi2SetRealInputDerivatives
#define fmi2SerializeFMUstate
#define fmi2SerializedFMUstateSize
#define fmi2CancelStep
#define fmi2ExitInitializationMode
#define fmi2GetString
#define fmi2GetBoolean
#define fmi2GetBooleanStatus
#define fmi2DoStep
#define fmi2SetString
#define fmi2Terminate
#define fmi2FreeInstance
#define fmi2GetRealOutputDerivatives
#define fmi2FreeFMUstate
#define fmi2SetFMUstate
#define fmi2EnterInitializationMode
#define fmi2DeSerializeFMUstate
#define fmi2GetRealStatus
#define fmi2Version
#define fmi2SetReal
#define fmi2GetInteger
#define fmi2GetIntegerStatus
#define fmi2GetStatus
#define fmi2SetDebugLogging
#define fmi2Instantiate
#define fmi2GetDirectionalDerivative
#define fmi2SetInteger
#define fmi2SetBoolean
#define fmi2Reset
#define fmi2SetupExperiment
int fmi2Integer
#define fmi2TypesPlatform
void * fmi2FMUstate
double fmi2Real
unsigned int fmi2ValueReference
char fmi2Byte
void * fmi2Component
int fmi2Boolean
const fmi2Char * fmi2String
void libsumo_load(char *callOptions)
void libsumo_close(void)
void * componentEnvironment
char * getterParameters
Parameters stored for the next (libsumo) getter call. Workaround for FMIv2 not allowing input values ...
const char * resourceLocation
fmi2String * bufferArray
allocateMemoryType allocateMemory
const char * instanceName
freeMemoryType freeMemory
loggerType logger
char * libsumoCallOptions
fmi2CallbackAllocateMemory allocateMemory
fmi2CallbackLogger logger
fmi2CallbackFreeMemory freeMemory
fmi2ComponentEnvironment componentEnvironment
fmi2Status sumo2fmi_getString(ModelInstance *comp, const fmi2ValueReference vr, fmi2String *value)
void sumo2fmi_set_startValues(ModelInstance *comp)
fmi2Status sumo2fmi_step(ModelInstance *comp, double tNext)
fmi2Status sumo2fmi_getInteger(ModelInstance *comp, const fmi2ValueReference vr, int *value)
void sumo2fmi_logError(ModelInstance *comp, const char *message,...)
fmi2Status sumo2fmi_setString(ModelInstance *comp, fmi2ValueReference vr, fmi2String value)
void sumo2fmi_logEvent(ModelInstance *comp, const char *message,...)
void *(* allocateMemoryType)(size_t nobj, size_t size)
void(* freeMemoryType)(void *obj)
void(* loggerType)(void *componentEnvironment, const char *instanceName, int status, const char *category, const char *message,...)