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-2020 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 /****************************************************************************/
18 // Implementation of the FMI2 interface functions
19 /****************************************************************************/
20 
21 #ifdef _MSC_VER
22 // Avoid warnings in windows build because of strcpy instead of strcpy_s,
23 // because the latter is not available on all platforms
24 #define _CRT_SECURE_NO_WARNINGS
25 #endif
26 
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdarg.h>
31 #include "sumo2fmi_bridge.h"
32 #include "libsumocpp2c.h"
33 
34 /* Explicit definition of unused parameters to avoid compiler warnings */
35 #define UNREFERENCED_PARAMETER(P) (P)
36 
37 /* **********************************************************************************************
38  * * IMPLEMENTATION OF GENERIC FUNCTIONALITY
39  * **********************************************************************************************/
40 const char* fmi2GetVersion() {
41  return fmi2Version;
42 }
43 
44 const char* fmi2GetTypesPlatform() {
45  return fmi2TypesPlatform;
46 }
47 
48 /* ***********************************************************************************************
49  * CREATION AND DESTRUCTION OF AN FMU
50  ***********************************************************************************************/
51 
52 /* The function returns a new instance of an FMU. If a null pointer is returned, then instantiation
53  failed.*/
55 fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
56  fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
57  fmi2Boolean visible, fmi2Boolean loggingOn)
58 {
59  UNREFERENCED_PARAMETER(fmuType);
60  UNREFERENCED_PARAMETER(fmuGUID);
61  UNREFERENCED_PARAMETER(visible);
62 
63  allocateMemoryType funcAllocateMemory = (allocateMemoryType)functions->allocateMemory;
64  ModelInstance* comp = (ModelInstance *) funcAllocateMemory(1, sizeof(ModelInstance));
65 
66  if (comp) {
67  comp->componentEnvironment = functions->componentEnvironment;
68 
69  /* Callback functions for specific logging, malloc and free;
70  we need callback functions because we cannot know, which functions
71  the environment will provide for us */
72  comp->logger = (loggerType)functions->logger;
73  comp->allocateMemory = (allocateMemoryType)functions->allocateMemory;
74  comp->freeMemory = (freeMemoryType)functions->freeMemory;
75 
76  comp->instanceName = (char *)comp->allocateMemory(1 + strlen(instanceName), sizeof(char));
77  strcpy((char *)comp->instanceName, (char *)instanceName);
78 
79  if (fmuResourceLocation) {
80  comp->resourceLocation = (char *)comp->allocateMemory(1 + strlen(fmuResourceLocation), sizeof(char));
81  strcpy((char *)comp->resourceLocation, (char *)fmuResourceLocation);
82  } else {
83  comp->resourceLocation = NULL;
84  }
85 
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
96 and other resources that have been allocated by the functions of the FMU interface. */
97 void
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);
110 }
111 
112 /* Define what should be logged - if logging is enabled globally */
113 fmi2Status
114 fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
115 
116  ModelInstance *comp = (ModelInstance *)c;
117 
118  if (loggingOn) {
119  for (size_t i = 0; i < nCategories; i++) {
120  if (categories[i] == NULL) {
121  sumo2fmi_logError(comp, "Log category[%d] must not be NULL", i);
122  return fmi2Error;
123  } else if (strcmp(categories[i], "logStatusError") == 0) {
124  comp->logErrors = true;
125  } else if (strcmp(categories[i], "logEvents") == 0) {
126  comp->logEvents = true;
127  } else {
128  sumo2fmi_logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]);
129  return fmi2Error;
130  }
131  }
132  } else {
133  // Logging is disabled globally, no need for a more fine grained logging
134  comp->logEvents = false;
135  comp->logErrors = false;
136  }
137 
138  return fmi2OK;
139 }
140 
141 fmi2Status
142 fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
143  fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
144 
145  UNREFERENCED_PARAMETER(toleranceDefined);
146  UNREFERENCED_PARAMETER(tolerance);
147  UNREFERENCED_PARAMETER(stopTimeDefined);
148 
149  // ignore arguments: toleranceDefined, tolerance
150  ModelInstance *comp = (ModelInstance *)c;
151 
152  // Store the start and stop times of the experiment
153  comp->startTime = startTime;
154  comp->stopTime = stopTime;
155 
156  return fmi2OK;
157 }
158 
159 // Will be called after instantiation and after initial variables have been set
160 fmi2Status
163 
164  return fmi2OK;
165 }
166 
167 // Informs the FMU to exit Initialization Mode
168 fmi2Status
170  ModelInstance *comp = (ModelInstance *)c;
171 
173  return fmi2OK;
174 }
175 
176 // Informs the FMU that the simulation run is terminated
177 // --> let libsumo know, that we want to close the simulation
178 fmi2Status
181 
182  libsumo_close();
183  return fmi2OK;
184 }
185 
186 // Is called by the environment to reset the FMU after a simulation run
187 fmi2Status
190 
191  // Should we set some start values?
192  return fmi2OK;
193 }
194 
195 // Implementation of the getter features
196 fmi2Status
197 fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
198 
199  ModelInstance *comp = (ModelInstance *)c;
200 
201  // Check for null pointer errors
202  if (nvr > 0 && (!vr || !value))
203  return fmi2Error;
204 
205  fmi2Status status = fmi2OK;
206 
207  // Go through the list of arrays and save all requested values
208  for (int i = 0; i < nvr; i++) {
209  fmi2Status s = sumo2fmi_getInteger(comp, vr[i], &(value[i]));
210  status = s > status ? s : status;
211 
212  if (status > fmi2Warning)
213  return status;
214  }
215 
216  return status;
217 }
218 
219 fmi2Status
220 fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
224  UNREFERENCED_PARAMETER(value);
225 
226  return fmi2Error;
227 }
228 
229 fmi2Status
230 fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
234  UNREFERENCED_PARAMETER(value);
235 
236  return fmi2Error;
237 }
238 
239 fmi2Status
240 fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
241 
242  ModelInstance *comp = (ModelInstance *)c;
243 
244  // Check for null pointer errors
245  if (nvr > 0 && (!vr || !value))
246  return fmi2Error;
247 
248  fmi2Status status = fmi2OK;
249 
250  // Go through the list of arrays and save all requested values
251  for (int i = 0; i < nvr; i++) {
252  fmi2Status s = sumo2fmi_getString(comp, vr[i], value[i]);
253  status = s > status ? s : status;
254 
255  if (status > fmi2Warning)
256  return status;
257  }
258 
259  return status;
260 }
261 
262 // Implementation of the setter features
263 
264 fmi2Status
265 fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
269  UNREFERENCED_PARAMETER(value);
270 
271  return fmi2Error;
272 }
273 
274 fmi2Status
275 fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
279  UNREFERENCED_PARAMETER(value);
280  return fmi2Error;
281 }
282 
283 fmi2Status
284 fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
288  UNREFERENCED_PARAMETER(value);
289 
290  return fmi2Error;
291 }
292 
293 fmi2Status
294 fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
295 
296  ModelInstance *comp = (ModelInstance *)c;
297  fmi2Status status = fmi2OK;
298 
299  for (int i = 0; i < nvr; i++) {
300  fmi2Status s = sumo2fmi_setString(comp, vr[i], value[i]);
301  status = s > status ? s : status;
302  if (status > fmi2Warning) return status;
303  }
304 
305  return status;
306 }
307 
308 /* Further functions for interpolation */
309 fmi2Status
310 fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[]) {
314  UNREFERENCED_PARAMETER(order);
315  UNREFERENCED_PARAMETER(value);
316 
317  return fmi2Error; /* Ignoring - SUMO cannot interpolate inputs */
318 }
319 
320 fmi2Status
321 fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[]) {
324  UNREFERENCED_PARAMETER(order);
325 
326  for (int i = 0; i < nvr; i++)
327  value[i] = 0; /* We cannot compute derivatives of outputs */
328  return fmi2Error;
329 }
330 
331 /* Stepping */
332 fmi2Status
333 fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
334  UNREFERENCED_PARAMETER(noSetFMUStatePriorToCurrentPoint);
335 
336  ModelInstance *comp = (ModelInstance *)c;
337 
338  if (communicationStepSize <= 0) {
339  return fmi2Error;
340  }
341 
342  return sumo2fmi_step(comp, currentCommunicationPoint + communicationStepSize);
343 }
344 
345 fmi2Status
348 
349  return fmi2Error; /* We will never have a modelStepInProgress state */
350 }
351 
352 /* Status functions */
353 fmi2Status
357  UNREFERENCED_PARAMETER(value);
358 
359  return fmi2Discard;
360 }
361 
362 fmi2Status
366  UNREFERENCED_PARAMETER(value);
367 
368  return fmi2Discard;
369 }
370 
371 fmi2Status
375  UNREFERENCED_PARAMETER(value);
376 
377  return fmi2Discard;
378 }
379 
380 fmi2Status
384  UNREFERENCED_PARAMETER(value);
385 
386  return fmi2Discard;
387 }
388 
389 fmi2Status
393  UNREFERENCED_PARAMETER(value);
394 
395  return fmi2Discard;
396 }
fmi2Status
@ fmi2OK
@ fmi2Error
@ fmi2Discard
@ fmi2Warning
fmi2StatusKind
fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[])
fmi2Status fmi2EnterInitializationMode(fmi2Component c)
const char * fmi2GetTypesPlatform()
Definition: fmi2Functions.c:44
fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[])
fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[])
const char * fmi2GetVersion()
Definition: fmi2Functions.c:40
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:55
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:35
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)
fmi2Status fmi2Terminate(fmi2Component c)
#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()
const char * resourceLocation
const char * instanceName
freeMemoryType freeMemory
char * libsumoCallOptions
fmi2CallbackAllocateMemory allocateMemory
fmi2CallbackLogger logger
fmi2CallbackFreeMemory freeMemory
fmi2ComponentEnvironment componentEnvironment
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, const char *value)
fmi2Status sumo2fmi_getString(ModelInstance *comp, const fmi2ValueReference vr, const char *value)
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,...)