Tight Coupling

Tightly-coupled systems involve two processes running simultaneously and interacting with each other in a dependent way. This involves one side sending data to the other process and vice versa, on a regular cycle. This page outlines some considerations which the user should understand when attempting co-simulation with BeamNG.tech.

In simulation, we distinguish between two notions of time:

  • Wall-clock time refers to the time which has passed in the real world.
  • Simulation time refers to the amount of time which has been simulated in the simulation model.

Note that we can simulate ahead in time, so the current simulation time could be ahead of the current wall-clock time.

Physics and Graphics

BeamNG operates within a multi-threaded architecture. Graphics rendering, collision detection, UI etc. all execute on separate threads. Physics computations also run on its own thread.

Figure 1 shows a simplified overview of this, where the physics steps are shown to be running concurrently with various other processes.

Figure 1: BeamNG Architecture Figure 1: BeamNG Architecture

BeamNG has both graphics steps (frames) and physics steps.

  • Frames describe how often the user receives a visual update on screen (ie the refresh rate of the graphics). We usually measure this in frames-per-second (FPS). For example, if we have 30 FPS then we update the image on screen 30 times per second. This quantity is variable, and it is common to see this change significantly when looking frame-to-frame.

    Note: BeamNG.tech tries to guarantee that the FPS will not drop below 20 FPS at any time. If this does happen, the physics will go into a slow-motion mode.

    At the start of a frame, predictions are made as to when the next frame is expected (in wall-clock time). BeamNG.tech can then easily compute the number of physics steps to take the simulation up the predicted start of the next frame (again, in wall-clock time). Execution continues like this.

  • Physics Steps compute exactly 0.5ms of simulation time (by default), often written as 2000Hz (the simulation frequency). Within the frame, even although BeamNG.tech knows how many physics steps must be computed, we do not know when they will be computed during the frame, although they will typically be computed ahead of the true wall-clock time. There are many things competing for resources and scheduling can shift tasks around as required for optimal simulation. Each physics step can also take a different amount of time to compute.

    Although this micro scale appears random and unpredictable, if we take averages over a sufficient amount of time (eg a minute), we will see that there are 2000 physics steps computed per second.

    Note: using the -physicsfps command line argument , it is possible to execute BeamNG at a different simulation frequency, e.g. 4000Hz. However, 2000Hz is the supported standard.

Example Cases

In Figure 1, two possible cases are highlighted:

  • The Left Frame illustrates the case where the physics steps are computed earlier than the work being performed on the other threads. This results in a gap on the physics thread towards the end of the frame. The other threads are the frame bottleneck here, not the physics. This is the more common case. Note the gap in physics steps towards the end of the frame - the physics steps could be said to typically compute in batches with gaps in between.

  • The Right Frame illustrates the opposite case; where the other threads finish earlier than the physics steps. We say here that the physics steps are the frame bottleneck.

An important point to note here, particularly when looking over multiple frames, is the irregular nature of when actual physics steps occur. We cannot predict when future physics steps will be computed, since this depends on many non-deterministic factors (especially within Human-In-The-Loop systems). Further to this, depending on what needs to be computed, some physics steps can take longer than others to compute.

V-Sync

V-Sync (Vertical Sync) is an option that synchronizes the frame rate of a game or application with the refresh rate of the monitor. It is recommended to switch this off in Options (press ESC) → DisplayVertical Sync, because it can add extra latency that leads to non-optimal co-simulation coupling.

Coupling Cases

The coupling cases described below are influenced by the timing values the user provides in the Available Signals window.

Coupling Case 1

In Figure 2, we illustrate the simplest co-simulation case. This is where we have one-for-one data passing between each side, and where the third party (such as Simulink) has a computation time which is similar in length to the BeamNG.tech physics step computation times.

Figure 2: Case 1 Figure 2: Case 1

Here, we say the window size (of the coupled system) is one - for every message we send, we receive one message back. When BeamNG.tech sends a message, the third party is ready to process it, and vice versa.

Note: This simple case is ideal, but it is not typical or even likely. We highlight it here simply for clarity.

Coupling Case 2

Figure 3 illustrates the case where the third party computation time (such as Simulink) is similar in length to the BeamNG.tech physics step, however, the UDP round-trip time is significantly larger.

For efficient coupling here, we need to have multiple messages sent out before any are received back in BeamNG.tech. Internally, BeamNG.tech will use the two given timing measurements (see above) to compute the optimal coupling management (the window size, etc), which will send, receive and block execution at the most appropriate times, with an aim to provide the most-optimal coupling possible between the two sides.

Figure 3: Case 2 Figure 3: Case 2

Coupling Case 3

Figure 4 shows the opposite case; the third party computation time is significantly slower than the BeamNG.tech physics step time, but the UDP round-trip time is fast.

Here, it is optimal to have the coupled system skip sending messages on every second physics step. We say we have a window size of two, in this case. If messages were sent at every physics step, then the third party would still be processing the previous step and would need to buffer the received messages. This buffering would lead to sync problems in a short amount of time, making the coupling unusable. The buffering would also grow over time, making the problem worse and using more and more memory, which is not feasible. The bottleneck in this case is the third party computation time.

Figure 4: Case 3 Figure 4: Case 3

Last modified: April 18, 2025

Any further questions?

Join our discord
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.