Eclipse SUMO - Simulation of Urban MObility
fmi2Functions.c
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2020-2022 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 UNREFERENCED_PARAMETER(P) (P)
38
39/* **********************************************************************************************
40 * * IMPLEMENTATION OF GENERIC FUNCTIONALITY
41 * **********************************************************************************************/
42const char* fmi2GetVersion(void) {
43 return fmi2Version;
44}
45
46const char* fmi2GetTypesPlatform(void) {
47 return fmi2TypesPlatform;
48}
49
50/* ***********************************************************************************************
51 * CREATION AND DESTRUCTION OF AN FMU
52 ***********************************************************************************************/
53
54/* The function returns a new instance of an FMU. If a null pointer is returned, then instantiation
55 failed.*/
57fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
58 fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
59 fmi2Boolean visible, fmi2Boolean loggingOn)
60{
64
65 allocateMemoryType funcAllocateMemory = (allocateMemoryType)functions->allocateMemory;
66 ModelInstance* comp = (ModelInstance *) funcAllocateMemory(1, sizeof(ModelInstance));
67
68 if (comp) {
69 comp->componentEnvironment = functions->componentEnvironment;
70
71 /* Callback functions for specific logging, malloc and free;
72 we need callback functions because we cannot know, which functions
73 the environment will provide for us */
74 comp->logger = (loggerType)functions->logger;
75 comp->allocateMemory = (allocateMemoryType)functions->allocateMemory;
76 comp->freeMemory = (freeMemoryType)functions->freeMemory;
77
78 comp->instanceName = (char *)comp->allocateMemory(1 + strlen(instanceName), sizeof(char));
79 strcpy((char *)comp->instanceName, (char *)instanceName);
80
81 if (fmuResourceLocation) {
82 comp->resourceLocation = (char *)comp->allocateMemory(1 + strlen(fmuResourceLocation), sizeof(char));
83 strcpy((char *)comp->resourceLocation, (char *)fmuResourceLocation);
84 } else {
85 comp->resourceLocation = NULL;
86 }
87
88 comp->logEvents = loggingOn;
89 comp->logErrors = true; // always log errors
90 }
91
92 return comp;
93}
94
95/* Disposes the given instance, unloads the loaded model, and frees all the allocated memory
96and other resources that have been allocated by the functions of the FMU interface. */
97void
99 ModelInstance *comp = (ModelInstance *)c;
100
101 /* Store the pointer to the freeMemory function, because we
102 are going to free comp as well */
103 freeMemoryType freeMemoryFunc = comp->freeMemory;
104
105 /* We want to free everything that we allocated in fmi2Instantiate */
106 freeMemoryFunc((void *)comp->instanceName);
107 freeMemoryFunc((void *)comp->resourceLocation);
108 freeMemoryFunc((void *)comp->libsumoCallOptions);
109 freeMemoryFunc((void *)comp->getterParameters);
110 int i;
111 for (i = 0; i < comp->bufferArrayLength; i++) {
112 freeMemoryFunc((void *)comp->bufferArray[i]);
113 }
114 freeMemoryFunc((void *)comp->bufferArray);
115 freeMemoryFunc((void *)comp);
116}
117
118/* Define what should be logged - if logging is enabled globally */
120fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
121
122 ModelInstance *comp = (ModelInstance *)c;
123
124 if (loggingOn) {
125 size_t i;
126 for (i = 0; i < nCategories; i++) {
127 if (categories[i] == NULL) {
128 sumo2fmi_logError(comp, "Log category[%d] must not be NULL", i);
129 return fmi2Error;
130 } else if (strcmp(categories[i], "logStatusError") == 0) {
131 comp->logErrors = true;
132 } else if (strcmp(categories[i], "logEvents") == 0) {
133 comp->logEvents = true;
134 } else {
135 sumo2fmi_logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]);
136 return fmi2Error;
137 }
138 }
139 } else {
140 // Logging is disabled globally, no need for a more fine grained logging
141 comp->logEvents = false;
142 comp->logErrors = false;
143 }
144
145 return fmi2OK;
146}
147
150 fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
151
152 UNREFERENCED_PARAMETER(toleranceDefined);
153 UNREFERENCED_PARAMETER(tolerance);
154 UNREFERENCED_PARAMETER(stopTimeDefined);
155
156 // ignore arguments: toleranceDefined, tolerance
157 ModelInstance *comp = (ModelInstance *)c;
158
159 // Store the start and stop times of the experiment
160 comp->startTime = startTime;
161 comp->stopTime = stopTime;
162
164
165 return fmi2OK;
166}
167
168// Will be called after instantiation and after initial variables have been set
172
173 return fmi2OK;
174}
175
176// Informs the FMU to exit Initialization Mode
179 ModelInstance *comp = (ModelInstance *)c;
180
181 sumo2fmi_logEvent(comp, "Calling libsumo with the following options: \"%s\"", comp->libsumoCallOptions);
183
184 return fmi2OK;
185}
186
187// Informs the FMU that the simulation run is terminated
188// --> let libsumo know, that we want to close the simulation
192
194 return fmi2OK;
195}
196
197// Is called by the environment to reset the FMU after a simulation run
201
202 // Should we set some start values?
203 return fmi2OK;
204}
205
206// Implementation of the getter features
208fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
209
210 ModelInstance *comp = (ModelInstance *)c;
211
212 // Check for null pointer errors
213 if (nvr > 0 && (!vr || !value)) {
214 return fmi2Error;
215 }
216
217 fmi2Status status = fmi2OK;
218
219 // Go through the list of arrays and save all requested values
220 size_t i;
221 for (i = 0; i < nvr; i++) {
222 fmi2Status s = sumo2fmi_getInteger(comp, vr[i], &(value[i]));
223 status = s > status ? s : status;
224
225 if (status > fmi2Warning) {
226 return status;
227 }
228 }
229
230 return status;
231}
232
234fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
239
240 return fmi2Error;
241}
242
244fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
249
250 return fmi2Error;
251}
252
254fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
255
256 ModelInstance *comp = (ModelInstance *)c;
257
258 // Check for null pointer errors
259 if (nvr > 0 && (!vr || !value)) {
260 return fmi2Error;
261 }
262
263 fmi2Status status = fmi2OK;
264
266 int b;
267 for (b = 0; b < comp->bufferArrayLength; b++) {
268 comp->freeMemory((void *)comp->bufferArray[b]);
269 }
270 comp->freeMemory((void *)comp->bufferArray);
271 comp->bufferArray = (fmi2String *)comp->allocateMemory(nvr, sizeof(fmi2String));
272 comp->bufferArrayLength = (int)nvr;
273
274 // Go through the list of arrays and save all requested values
275 size_t i;
276 for (i = 0; i < nvr; i++) {
277 fmi2Status s = sumo2fmi_getString(comp, vr[i], &(comp->bufferArray[i]));
278 value[i] = comp->bufferArray[i];
279 if (value[i] == NULL) {
280 s = fmi2Error;
281 }
282
283 status = s > status ? s : status;
284 if (status > fmi2Warning) {
285 return status;
286 }
287 }
288
289 return status;
290}
291
292// Implementation of the setter features
293
295fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
300
301 return fmi2Error;
302}
303
305fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
310 return fmi2Error;
311}
312
314fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
319
320 return fmi2Error;
321}
322
324fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
325
326 ModelInstance *comp = (ModelInstance *)c;
327 fmi2Status status = fmi2OK;
328
329 size_t i;
330 for (i = 0; i < nvr; i++) {
331 fmi2Status s = sumo2fmi_setString(comp, vr[i], value[i]);
332 status = s > status ? s : status;
333 if (status > fmi2Warning) return status;
334 }
335
336 return status;
337}
338
339/* Further functions for interpolation */
341fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[]) {
347
348 return fmi2Error; /* Ignoring - SUMO cannot interpolate inputs */
349}
350
352fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[]) {
356
357 size_t i;
358 for (i = 0; i < nvr; i++) {
359 value[i] = 0; /* We cannot compute derivatives of outputs */
360 }
361 return fmi2Error;
362}
363
364/* Stepping */
366fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
367 UNREFERENCED_PARAMETER(noSetFMUStatePriorToCurrentPoint);
368
369 ModelInstance *comp = (ModelInstance *)c;
370
371 if (communicationStepSize <= 0) {
372 return fmi2Error;
373 }
374
375 return sumo2fmi_step(comp, currentCommunicationPoint + communicationStepSize);
376}
377
381
382 return fmi2Error; /* We will never have a modelStepInProgress state */
383}
384
385/* Status functions */
391
392 return fmi2Discard;
393}
394
400
401 return fmi2Discard;
402}
403
409
410 return fmi2Discard;
411}
412
418
419 return fmi2Discard;
420}
421
427
428 return fmi2Discard;
429}
fmi2Status
@ fmi2OK
@ fmi2Error
@ fmi2Discard
@ fmi2Warning
fmi2StatusKind
fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[])
fmi2Status fmi2EnterInitializationMode(fmi2Component c)
fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[])
fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[])
fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value)
fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value)
fmi2Status fmi2CancelStep(fmi2Component c)
fmi2Status fmi2Reset(fmi2Component c)
fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime)
fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[])
fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[])
fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value)
fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions, fmi2Boolean visible, fmi2Boolean loggingOn)
Definition: fmi2Functions.c:57
fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[])
fmi2Status fmi2ExitInitializationMode(fmi2Component c)
fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[])
fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[])
fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[])
fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value)
#define UNREFERENCED_PARAMETER(P)
Definition: fmi2Functions.c:37
fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[])
void fmi2FreeInstance(fmi2Component c)
Definition: fmi2Functions.c:98
fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value)
fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[])
fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint)
const char * fmi2GetVersion(void)
Definition: fmi2Functions.c:42
fmi2Status fmi2Terminate(fmi2Component c)
const char * fmi2GetTypesPlatform(void)
Definition: fmi2Functions.c:46
#define fmi2Version
int fmi2Integer
#define fmi2TypesPlatform
double fmi2Real
unsigned int fmi2ValueReference
void * fmi2Component
int fmi2Boolean
const fmi2Char * fmi2String
void libsumo_load(char *callOptions)
void libsumo_close(void)
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
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,...)