We assume that you are familiar with C programming, Linux and Docker containers.
Pull the latest SUMO development environment from Docker Hub. Now the latest image is for SUMO24 on Ubuntu 24.04:
docker pull dynamita/sumo24:u24.04
Set up a shared directory on your host computer and copy the C-API example in it. At the moment you have to ask Dynamita for the files. Let's say that the shared directory on the host is /home/user1/sumo
. You will get the example files in a folder named c-apps
.
Copy the whole directory in the shared/home/user1/sumo
and start the dev container with a directory sharing command like:
docker run -it -v /home/user1/sumo:/home/shared --rm --user root dynamita/sumo24:u24.04
We map the /home/user1/sumo
directory of the host to the /home/shared
directory of the container, where we can access the c-apps
directory. After the container is running, we can list the content of the run-time directory, like in the following image:
Figure 1. - Developer container content.
You will need a container license to compile and run a SUMO project, and the project file itself, let's say A2O plant.sumo.
We can copy a SUMO project into the shared directory (you will need a method to transfer files from your Windows development computer to your Linux host computer.) Copy the SUMO project from the shared directory to the container. Let's say the SUMO project is A2O plant.sumo, and it's in the shared directory. Inside of the container, copy it and compile it with the following commands:
cp /home/shared/A2O\ plant.sumo .
python3 sim.py A2O\ plant
Note, that the extension .sumo
is not needed for the Python script. If your license is working, the script will compile the SUMO project and run it with a very short, 1 min, stop time and data comm interval, just to check if it runs. The following picture shows the run-time folder after compilation:
Figure 2. - The compiled artifacts are in the A2Oplant directory
Copy the initialization script extracted from the SUMO project and the library file to the run-time directory, then edit the SUMO script, with the following commands:
cp A2Oplant/init.scs a2o.scs
cp A2Oplant/libA2Oplant.so .
nano a2o.scs
Note that we renamed init.scs
to a2o.scs
to not mix them up. Add a stop time, a data comm and a start command to the a2o.scs
script. After this the SUMO script should look like:
Figure 3. - Extending the a2o.scs script file
Switch to the shared c-apps
directory:
cd /home/shared/c-apps
The directory should look like:
Figure 4. - SUMO simulation example in C.
Compile the example inside of the container with the following command:
make -f make-sim-l
It will create the binary file sumosim
in the bin
directory. Let's copy it to the run-time directory and switch back to it:
cp bin/sumosim /home/sumo-runtime
cd /home/sumo-runtime
We have everything prepared: license file, model library and the initialization script. Let's run the example with:
./sumosim . -l license.dynlic -m libA2Oplant.so -s a2o.scs
You can read a small usage help by typing the ./sumosim
command without arguments. After running the example the results should look like:
Figure 5. - A2O plant simulation example results.
When we create a SUMO application, we need to implement a couple of functions called by the OS specific base. The base application for Linux is called linux_sumoapp.c
and for Windows is win_sumoapp.c
. The functions to be implemented are:
static char const *process_args(int argc, char *argv[])
- it should return the path of the SUMO core library libsumocore.so
or sumocore.dll
on Windows. In the example the first argument is the path to the library. You can choose to not have any command line arguments; in this case the function could return a fixed path.static void app_logger(char const *message)
- we can implement a logger function for the base and our SUMO application. In the example it is just a simple print to the console.static void app_main()
- our application's main entry point. In the example it contains some important API calls:csumon_create()
- initializing the SUMO corecsumon_use_license(...)
- specifying the license filecsumon_register_datacomm_cb(...)
- registering the data comm callback function (see later)csumon_register_message_cb(...)
- registering the message callbackcsumon_load_model(...)
- loading the model library (libA2Oplant.so
in the example)csumon_send_command(...)
- sending the initialization script, a2o.scs
in our case, to the SUMO core as a core commandwhile ...
- loop for waiting for the simulation to finishcsumon_unload_model()
- removing the model from the SUMO core (we can load a new one if needed)csumon_destroy()
- terminating the SUMO coreThese are typical in a SUMO application, You can add more of your application logic, or restructure the core API calls, but they are required.
The SUMO core can call special functions implemented in a C application (or C++ if it's specified as extern C
). Functions with a specific signature can be registered in the SUMO core as callback functions. There are two types of callbacks:
530004
is sent when the simulation is finished. We can use it to end our wait loop mentioned above.In the callback functions you can call variable accessing functions and message accessing functions. They are described in the C API reference.
You can write your application in C++ and link it to the OS specific base. The three required functions should be specified as extern C
.
If the programming language allows C function calls, they can be used easily to connect to the SUMO core. Python is such a language, SUMO's Python API is a wrapper around the C API.
The SUMO GUI (Graphical User Interface) is a C# application. C# allows as well C function calls, and it uses the C API directly to communicate with the SUMO core. Java is like C# in this regard, but we don't have examples in Java.
Languages that don't allow C function calls can use the SUMO command line interface scli
. In this case, the communication is managed through the standard I/O of the underlying operating system.
The development container is quite large in terms of memory usage, around 670MB. Python and the C/C++ compiler is installed in it. You can build a smaller run-time container based on the developer image. Here is a Docker file example for this:
# We use the latest official development environement.
FROM dynamita/sumo24:u24.04 AS builder
FROM ubuntu:24.04
USER root
ENV SUMO_HOME=/home/sumo-runtime
ENV LD_LIBRARY_PATH=$SUMO_HOME
# Install some utilities.
RUN apt update -y \
&& apt install -y nano libusb-dev iputils-ping \
&& apt clean
WORKDIR $SUMO_HOME
# Copy SUMO files from the development environement (builder).
COPY --from=builder $SUMO_HOME/libQtCore.so.4.8.2 $SUMO_HOME
COPY --from=builder $SUMO_HOME/libsumocore.so $SUMO_HOME
COPY --from=builder $SUMO_HOME/scli $SUMO_HOME
COPY --from=builder $SUMO_HOME/lang.tsv $SUMO_HOME
COPY --from=builder $SUMO_HOME/VERSION $SUMO_HOME
# Create required symbolic links (COPY doesn't handle them correctly).
RUN ln -s libQtCore.so.4.8.2 libQtCore.so.4.8 \
&& ln -s libQtCore.so.4.8.2 libQtCore.so.4 \
&& ln -s libQtCore.so.4.8.2 libQtCore.so
With this Dockerfile
you can build a lighter run-time image, around 190MB, with the following command:
docker build -t sumo24:rt .
It will contain only the files necessary to run an already compiled model, which means that you will need to copy your application, license, the .so
library of the model and the initialization script into the run-time container.