Tuesday 27 March 2018

TrafficControl: Displaying the Simulated Time

A very important feature of trafficControl is the simulated time. Since it is possible to adjust the speed of the simulations, the simulated time (system time) should be visible in the user interface.

Adding a QTime variable (simulatedTime) is easy. That parameter is incremented by one for every tick, and a signal is sent.

The signal is relayed from trafficClock via NetworkControl to trafficControl


Finally, the corresponding label is updated. 


For every tick, the time is incremented by one second.

When running the program in test mode, there is no listener to the signals. This won't cause any crashes.

In the next blog post, I'll review the trafficClock objects. I hope that I'll be able to connect the signal directly fom trafficClock to trafficControl.

Tuesday 20 March 2018

TrafficControl: UI Fixes for Time Visibility

In order to make TrafficControl demo-able, there are some fixes I need to do for the user interface:
  • Simplify the time control buttons
  • Display the simulated time
  • Show the system load (calculation time divided by interval)
Simplifying the time control buttons:

The two spinboxes are not intuitive and should be replaced by only one spin box. The spinbox will contain a double parameter for the forward speed. If that is 1, one second in real time will correspond to one second in simulated time. If that is less than one, the network will move slower. If that is more than one, the network will move faster.

Whenever the value in the new spinbox is changed, a signal is sent to a slot:
The spinbox is defined to accept values from 0,5 to 50, so the check for non-zero denominators shouldn't be necessary. I added the check for futureproofing the code.

I'll discuss the other two changes in the next blog post.

Thursday 15 March 2018

TrafficControl: Analysing TrafficClock

As I mentioned in the last blog post, there are some refactoring and UI fixes that I need to do for the trafficClock.

The first step is to analyze the behaviour of qThread and qTime. I want to know how accurate the timing is (does the thread wake up after the specified time) and how much time the train/track/station operations take. I've done this by adding some qDebug statements:


For an interval of 100 ms, the output is:


The time difference between "BEFORE EMIT" and "AFTER EMIT" is almost always 0 ms, so the estimated time consumption for emitting stepTimeSignal command can be neglected.

The time between "BEFORE SLEEP" and "WOKE UP" is between 1 ms up to 15 ms more than expected. This is a minor issue, but the target time tends to drift as the small delays accumulate. The solution to this behaviour is the following code change:

After printing the time at the start and end of tcNetworkControl::stepTimeForNetwork(), I am able to track the time consumption for three trains in a small network.
In this case, the interval is 100 ms.
The system configured for low performance and the build is debug.

In this case, the interval is 20 ms.
  The computer is set to have high performance and the build is release, the operations take 2-3 ms.
It seems that the time intervals are irregular.

In this case, the interval is 20 ms, but the operations take 30 ms.
The next signal is trigged as soon as the former is done.
The behaviour is expected. 
Finally, I tested without QML.
The time consumption is far below one millisecond. This means that QML will be critical for optimizations.
In the next blog post, I'll make three changes in the user interface:

  1. Display the simulated time
  2. Show the time needed for stepTimeForNetwork, as a percentage of the intervals
  3. Replace the two time spinboxes with one spinbox for fast forward factor and add a button that will toggle between "play" and "pause".


Further, I need to investigate if it is possible to make the QML operations run without affecting the performance of the train operations.

Tuesday 6 March 2018

TrafficControl: TrafficClock

TrafficControl is using a thread that makes the network act on a specific pace, according to the user's preferences.

A QThread called clockThread is created and trafficClock is assigned to that thread. The thread loops as long as isAlive is true and does the following:
  • Calculate the time of the next tick
  • If the boolean variable simulationIsRunning is true, the stepTimeSignal is emitted, letting all trains move one second on the network and updating tracks and stations.
  • The thread sleeps until the next tick
The following table illustrates this:

System Time Simulated Time Speed Factor Time Interval
10:00:00 00:00:00 2x 500 ms
10:00:01 00:00:00.5 2x 500 ms
10:00:02 00:00:01.0 3x 333 ms
10:00:03 00:00:01.333 4x 250 ms
10:00:04 00:00:01.583 4x 250 ms

At 10:00:02, the user is increasing the speed factor to 3x. One second later, the user is increasing it to 4x.


I'll do some changes of the code in the next blog post. This is needed to simplify the user interface and refactor the time handling code.