This page explains an important change between version 1.3 and version 1.4 of VPL: the handling of events. In VPL 1.3, some events (buttons, proximity and ground sensors) are triggered continuously when they are true, while in VPL 1.4, they are triggered only once, when they become true.
Motivation
Continuously triggering an event is not very clean, not consistent with the events clap and tap, and often misleads the user about the true mechanism behind the events. This can easily be shown with the following simple program:
With the code in version 1.3, as long as one touches the centre button, the music is triggered. This means that the music is continuously restarted, until the button is released. Therefore the button event is not unique, but a series that continues to happen as long as the button is touched. The music is only launched just before the release and can be played entirely.
In version 1.4, the same code has another effect:
In this version, the music is launched when the button becomes touched, and the event is only triggered once.
Implicit events and explicit code
Let us take another example in which one could think it is convenient to have an event triggered continuously:
With this code, as long as the robot is on the ground (sees it with its right ground sensor) it goes forward, and when it sees an obstacle it stops. If the obstacle disappears it starts again, because as long as the robot is on the ground, the first event is triggered. Therefore even if there is an obstacle, this code tells the robot to goes forward and to stop directly, and it is the last command that controls what the robot really does. This behaviour is considered a race condition, it is often unclear for the user and is bad practice, even though it is sometimes comfortable.
In VPL 1.4, this similar code:
… leads to a different behaviour: when it starts Thymio goes forward, and if it encounters an obstacle it stops, as in the previous code. But if the obstacle disappears, the robot does not start again, because the first event is not triggered continuously. For the Thymio to start again, one must make the first condition false, for instance by lifting the robot and putting it back on the ground. This will trigger the first event again, because it will become true again. This behaviour is consistent, because in the program it is nowhere written that the robot must start again if the obstacle disappears. To have a behaviour similar to the version 1.3 above, one must explicitly indicate to start moving again when the obstacle disappears:
New features provided by version 1.4
The way version 1.4 handles events allows programs which are impossible to write in version 1.3. The initial program about music is one example. Here is another:
This code in advanced mode seems logical: by touching the central button one wants to change the colour from red to green, and vice versa, using the internal state. This feature cannot be programmed in version 1.3, because the state would change continuously while the button is touched.
And another example:
This code allows the robot to be launched with the forward button and to make it stop at the second line which it encounters on the ground . To implement this feature with version 1.3, one must explicitly detect the white area between the lines, which requires more code and doubles the number of internal state variables required.
An example of converting a program from version 1.3 to version 1.4: line-following with stopping in front of an obstacle
When one starts combining behaviours, important differences arise between versions 1.3 and 1.4. Let us take as example a robot that has to follow a line and stop when it encounters an obstacle.
In version 1.3, on can write this program:
This program lets the robot turn towards the black line drawn on the ground, and stops if an object is in front of it. When it stops, however, line-following events are still active, but their actions are cancelled by the last line that controls obstacles and gives the last motor command. As soon as an obstacle disappears, the robot continues its line-following behaviour.
If one gives similar commands in version 1.4, the robot will not start again when the obstacle disappears. Indeed there are no orders telling it to start again. Therefore, a specific order to start again must be added:
However, this program has still a different behaviour to the one for version 1.3: when the robot starts again upon the disappearance of the obstacle, it does not know in which state it was when it stopped. Hence it does not know whether it must go straight, or turn, and in which direction. The program below solves this problem in the following way: if the robot, following the line, only sees white, it turns to the left to return the line. When the obstacle disappears, to reset the line-following behaviour, it does the same, but in the opposite direction. This will quickly bring it back on track.
If one wants that the robot starts in the same state as it stopped in, one must memorize that situation and reuse this information when the robot starts again, for instance like this:
However this solution might raise tricky problems. For instance in this example: if the robot that follows the track encounters an obstacle, it stops. The stop is not instantaneous, as the robot needs a little bit of time to brake. If during that time the robot crosses an end of line on the ground, the latter will trigger the line-following event, and therefore the robot will restart ignoring the obstacle. But as the obstacle is always present, it will not trigger the stop again, and the robot will hit the obstacle.
A similar problem can arise if the robot, once stopped in front of the obstacle, is pushed by another robot or by a human, and during this movement it crosses the end of the line on the ground. It will then continue moving while ignoring the obstacle.
This means that in version 1.4, one must think more carefully about the sequence of events than in version 1.3, which is more tricky than to reason in terms of the situation as in version 1.3. Some solutions are cleaner than others. For instance, the problem of line-following and stopping in front of an obstacle can be solved more elegantly in the following program, that also contains a stop and a start order:
This program records the presence of the obstacle and blocks the line-following behaviour until the obstacle disappears or the user requests the robot to go forward.
This book-keeping adds complexity, but allows to be much more precise in the definition of the behaviour. For instance, if one wants to let the robot become red for one second when the obstacle disappears, in version 1.3 internal states must be used to express that the obstacle disappears. Therefore, the following code does not work in version 1.3 because the timer is restarted continuously:
The code in version 1.4 that uses the same elements works as planned: