It is possible to add restrictions by editing an XML file to prepare exercises for students.
There are three types of restrictions:
Time restrictions. For example, a time limit to complete a task or a specific action in a specific time frame.
Spatial. For example, adding regions ("Start", "Finish") or prohibiting/forcing a robot, its sensor, or some moving object to be at a certain time in a certain place.
Device restrictions. For example, a limitation on the set of sensors or on the behavior of devices.
The main tag<constraints>...</constraints>
which contains all the restrictions is used to describe them. Used as a container. Restrictions are described inside the tag, each inner tag must be one of four:
The main tag containing all restrictions. Used as a container.
Time limit. Mandatory.
A constraint with an arbitrary condition. If the condition is violated a specified error message will be displayed. Can be used as a container. Has one child tag: <conditions>...</conditions>
.
The main tool for setting dynamic constraints. Used as a container.
An event is just a pair (condition, trigger).
Unconditional event executing before the program starts.
Example:
Now lets talk about the conditions in the <constraint> and <event> elements. Conditions are set using the <condition> tag if only one of the atomic conditions is tested, or the <conditions> tag if a compound condition is tested.
The condition being checked is described inside this tag.
Example:
Used to create compound conditions. The logical bond is the mandatory attribute. The bond may be and
or or
. Negation is specified by the <not>
tag without attributes. Other <conditions>
elements may also appear among subexpressions.
Atomic condition is one of the following elements:
Equals. The functional symbols value comparison operation. Can be used as a container.
Not equal. The functional symbols value comparison operation. Can be used as a container.
Greater. The functional symbols value comparison operation. Can be used as a container.
Less. The functional symbols value comparison operation. Can be used as a container.
Sets spatial constraints.
Checks whether the event set up or not.
The "check event" event conditions check that the other "Try move" event is set up and the "Go back" event is dropped. If both of them return "true" after the check the program successfully ends.
A predicate that starts to return "true" when the specified time has passed since the moment when this event was set, and up to that moment it returns "false".
Let's look at using <timer/> with different forceDropOnTimeout attribute values.
The "check region" event checks time and spatial limits. The first condition (timer) becomes true after 1000ms. Its value doesn't change after that. The second one (inside) checks that the robot is inside the "start_zone" region. When both conditions will be met simultaneously the program will end successfully.
1. Since the forceDropOnTimeout attribute is "false", the event will be still set up after a specified timeframe and wait for the second condition to be met.
2. Since the forceDropOnTimeout attribute is "true", the event will be dropped after the specified timeframe despite the presence of a second condition. Therefore, if the robot is not in the required region right after 1000 ms, then the success message will not be displayed even if the robot will be there after some time.
Setting a constant.
Variable value.
It is possible to take the property of any variable using a dot. For example, "rect.width" will return the width of the rectangle stored in "rect".
Get the object state.
Get the objects with specified ID meta-type. For example, the type of the wall
object with id=777
will be wall
.
Most often, this element will be needed to check the type of connected sensors and motors.
Unary arithmetic operations for changing the sign and taking the modulus of a number.
Sum and difference of values. Minimum and maximum value.
An action or a group of actions that will be performed one or many times after the event condition is met.
Display an error message. Finish checking the task.
The task is successfully done.
Set the variable value.
Setting up or dropping an event.
Checking that the word “message” was displayed on the controller screen. The case is important.
You need to start in the blue square then drive along the wall to the red one using the IR distance sensor.
This article is automatically translated from Russian by Google Translator.
Setting constraints is a unique feature of TRIK Studio designed for an automated check of tasks. This tool has many uses:
self-examination of homework by students,
accelerating the process of checking tasks by the teacher,
online competitions with automatic checking of the participants' solutions.
The TRIK Studio constraint language is a very powerful tool that allows you to check almost all aspects of program execution and robot behavior and may seem complicated at first glance. However, don't be upset - in this article we will walk you through the process of creating constrained tasks, ranging from simple constraints that cover most of the tasks to complex constraints, which can be useful for enthusiasts.
For those who are just starting to get acquainted with the TRIK Studio constraint language, we suggest starting with simple restrictions on the program run time, the "Start" and "Finish" zones. This is more than enough for most robotic tasks.
1. Define the following conditions and parameters for the task and the world model.
Optimal program execution time. If the program exceeds the timelimit, the checking system will generate an error "The program ran too long".
Start zone. The zone from which the robot must start executing the program, otherwise the checking system will generate an error.
Finish zone. The zone where the robot must arrive at the end of the program, otherwise the checking system will generate an error.
2. Edit the value of the <regions>
tag in the world XML file to add the Start and Finish zones. By changing the x
, y
, width
and height
values, you can edit the location and size of the zones. To check the position of a zone, load the file into the virtual world model and check the location of the zones. After that, if necessary, you can make the "Start" and "Finish" zones invisible by setting the attribute visible="false"
.
3. Copy the <constraints>
block template below into the XML file of the world for which you want constraints.
4. Fill in the <timelimit value="300000">
tag. Specify what you think is the best execution time for the program. Note that the time is in milliseconds, i.e., 300000ms = 5 minutes, 120,000ms = 2 minutes, etc.
5. The constraint task is ready! Now you know how to check the start and end positions of the robot and the execution time of the program.
Now let's break down the application of this technique to different tasks and consider options for more detailed checks.
The task of passing the labyrinth. Having started in the blue square, it is necessary to pass to the finish area. In order to check that the user actually passes the labyrinth and not bypasses it, a spatial constraint is set.
Below is the complete code to test this task.
Let's take a closer look at how the check takes place.
1. Set a time limit for passing the task. This limit is mandatory. The time is specified in milliseconds.
2. Set a constraint on the area where the robot should be before starting the program. According to the condition of the problem, it should be a blue square - the start area. This restriction will be checked once, at the beginning of the program, since the attribute checkOnce
is true
.
3. In order to verify that the user actually goes through the maze and not bypasses it, let's set another spatial constraint.
Let's edit the <regions>
tag in the XML file of the world by adding the region with id = "warzone"
.
If the robot is outside the specified region at any time, the program will terminate with an error, the text of which is specified in the failMessage
attribute.
4. Now we have to check that the robot reaches the finish area.
To do this, let's create an event that will check if the robot is in the right zone or not. The attribute settedUpInitially="true"
means that the event will be started (fired) immediately when the program starts.
The task is to pass forward and stop in the finish area.
This task is slightly different from Example 1 in that another condition is added for successful completion of the program - the robot must not only be in the finish area, but also stop.
Below is the complete code to test this task.
Now let's take a closer look at how the check takes place.
1. Let's set a time limit for passing the task.
2. Let's set a constraint on the initial position of the robot. It will be checked once at the beginning of the program.
3. Set a restriction on the area that the robot cannot leave.
4. Now create an event that verifies that the robot is in the finish zone and that it has stopped in the finish zone and has not moved on.
Thus, this event checks three conditions: the robot is in the finish area, the power on motor M3
is zero and the power on motor M4
is also zero. If these conditions are met the user will be shown a message about the successful execution of the program.
Having started in the blue square, you must drive along the wall with the IR distance sensor to the red square.
Below is the complete code for checking this task.
Now let's take a closer look at how the check takes place.
1. Let's set a time limit for the task.
3. Let's check that no sensors are connected to the other ports. To do this, compare the value on each port with the "undefined"
string.
4. Let's set a constraint on the initial position of the robot. It will be checked once at the beginning of the program because the checkOnce
flag is set.
5. Let's set a restriction on the zone that the robot can't leave. In the previous examples, we considered a situation where the robot needed to stay in one zone. In this case, the allowed zone consists of several rectangles, so we need to check that the robot is in one of those zones. To do that we use the <conditions></conditions>
tag with the glue = "or"
attribute.
6. Finally, let's create an event that will notify you if the robot is in the finish area.
Linear traffic with intersection counting: when entering an intersection, the robot should display the number of this intersection on the screen.
Below is the complete code for checking this task.
Let's take a look at how verification works.
3. Let's set a constraint on the initial position of the robot.
5. We will display an error message if the wrong number is displayed. To do this, compare the message that was displayed with the expected correct value. If the messages don't match, the user will get the specified error message and the program will stop executing.
6. Set the event that will display a message about the successful execution of the program, if all the specified intersections are passed correctly.
The robot must push all pins outside the circle.
Below is the complete code for checking this task.
Now let's look in more detail at how the check takes place.
2. Let's set a time limit for the task.
3. Let's set a constraint on the initial position of the robot.
4. Set an event that checks that all pins are outside the circle, and then displays a message that the program has been successfully executed.
In the start position the robot must be in the start area at a distance from the wall and a touch sensor must be connected to port A1. A successful pass is when the robot approaches the wall, touches it with the touch sensor, moves away from it, and so on 5 times.
The idea of the checking program is that at any given time either the event waiting for the robot to drive up to the wall or that it has gone back is triggered. Both of these events arm each other. When the robot returns to its original position, the iteration counter is incremented. There is an extra event that checks the counter value. It will display a message about the successful execution of the program when the value is five.
Below is the complete code for checking this task.
Now let's take a closer look at how the check takes place.
1. Let's set a time limit for the task.
3. Let's check that no sensors are connected to the other ports. To do this, compare the value on each port with the "undefined"
string.
4. Set a restriction on the area that the robot cannot leave.
5. Let's set an event that verifies that the robot has started to move forward. As a condition, we specify that the power applied to the motor on port M3 must be greater than zero. If this condition is fulfilled, two triggers are triggered. The first one triggers the event with id = "Touching wall"
, and the second one assigns the value zero to the variable counter
.
Since the attribute settedUpInitially
is set to true
, the event will be triggered (activated) immediately at the program startup.
7. Set an event that checks that the robot has traveled to the wall. The condition checks that the value of the touch sensor located on port A1 is one (this means that the touch sensor has been triggered). If this condition is met, the trigger is triggered and the event id="Returned back"
is triggered.
8. Let's define an event that checks if the robot has returned to the start zone after touching the wall. To do this, we need to set an inside
condition with attributes objectId="robot1"
(our robot) and regionId="start_zone"
(the zone to return to).
When this condition is met, two events are triggered and the iteration counter is incremented. The first event checks if the robot has touched the wall, the second event checks if the problem condition has been met.
9. Let's set an event that will display a message about the successful execution of the program if the value of counter
is at least 5.
With the tag we set the spatial constraint. It has two attributes. In the first (objectId) we specify the id of the object whose location we want to check, in our case, it is a robot. In the second (regionId) we specify the id of the region in which our object should be located.
If the condition described in <inside>
is not met, the program will be terminated with an error. For this, the tag has an attribute failMessage
, which allows you to specify the text of the error message.
This constraint will be checked at all times of program execution. In the tag we will specify the object id and the region id, in our case, it is the robot and the black rectangle limiting the maze.
In the tag we specify which condition to check. In our case the condition is the same as described above - we are checking that the robot is in the region with id = "finish"
. If that condition is true, then the user will see a message saying that the program was executed successfully. To do that, we write a child tag in the tag.
The zone limit is set with the tag. In order to check that the robot has stopped, we need to check that the power on both motors is zero. To do this we use the tag. With the tag we define the object whose value we want to compare. In our case this is the power of the motors, so we will write robot1.M3.power
or robot1.M4.power
in the attribute object
, where M3
and M4
are the ports to which the motors are connected in the current configuration. And the value to be compared we write using thetag and its value
attribute.
2. According to the problem condition, the robot must have only the distance sensor connected (there must be no other sensors). To be sure of this, let's compare the value of the object on port A1
with the value of the distance sensor. For more information about the names of the sensors for different constructors, see the .
1. After each intersection, set the zones where it will be checked that the correct intersection number is displayed. To do this, edit the value of the tag in the XML file of the world, adding there the necessary number of zones to check. By changing the values of x
, y
, width
and height
, you can edit the location and size of the zones. To check the position of a zone, load the file into the virtual world model and check the location of the zones. After that, if necessary, you can make zones invisible by setting the attribute visible="false"
.
2. After that, in the block set the constraint check. First we will specify the limit on the execution time of the task.
4. In each zone after the intersection, we will check that the correct number is displayed. To do this, specify the id
of the desired region in the tag and check that the last displayed message (robot1.display.labels.last.text
) equals the number of the passed intersection. After that, we will call the same events for the rest of the zones.
1. Let's edit the XML file of the world by adding a circle zone to the tag.
2. According to the problem condition, the robot must have only the touch sensor connected (there must be no other sensors). To be sure of this, compare the value of the object on port A1
with the value of the touch sensor. For more information about the names of the sensors for different constructors, see this .
6. Let's define an event that will show an error in case after 1000ms (=1sec)
the robot hasn't started moving forward (i.e. the event with id="First move"
is still on and hasn't been executed). Since several conditions are checked in this event, the tag is used with the logical connectors.
Tag
Description
Time limit.
A constraint with an arbitrary condition in violation of which a specified error will be generated.
The main tool for setting dynamic constraints. Used as a container.
An unconditional event that runs before the program starts executing.
Attribute
Description
value="value"
Timeout in milliseconds after which the execution will be terminated and the "Time limit exceeded" error will be displayed.
Attribute
Description
checkOnce="true"
Boolean attribute. If the value is true, then the restriction will be checked once at program startup. Is useful for one-time checks such as sensor layout etc.
failMessage="Error!"
An error message will be displayed when a restriction is violated.
Attribute
Description
settedUpInitially="true"
An attribute that allows you to indicate whether the event is set up at the start of the program. The event can be set up or dropped. In the setup state, the event pulls its trigger if its condition is met, otherwise it's just ignored by the system.
The default value is false.
id="finish checker"
Events unique ID. The event can be referred by id from others. Optional.
dropsOnFire = "true"
A boolean attribute that indicates whether the event should continue to be set up after it is triggered or not. Optional. The default value is true.
Attribute
Description
glue="and"
Logical bond.
Tag
Description
Value comparison operations.
Sets spatial constraints.
Checks whether an event is set up or not.
Sets the time in ms after which the specified condition is considered true.
Attribute
Description
objectId="id"
Object ID.
regionId="id"
Region ID.
Attribute
Description
id="event1"
The ID of the event is checked
Attribute
Description
timeout="1000"
The time interval after which this predicate will become true. Mandatory. The value must be a non-negative integer.
forceDropOnTimeout="true"
A Boolean attribute that allows you to drop the event that has this timer in a condition.
If set to true, the event will be dropped even if there are other active timers and unmet conditions. Optional. The default value is true.
Variable or operation
Description
Integer, fractional, string, and boolean constants.
Variable value.
Get the object state.
Get the meta-type of the object with the specified identifier.
Unary arithmetic functions that have exactly one child, which must be an integer value.
Binary arithmetic functions that have exactly two child elements, each of them must be an integer.
Attribute
Description
value="0″
Constant value.
Attribute
Description
name="my_value"
Variable name
Attribute
Description
object="robot1.display.labels.size"
Object ID
Attribute
Description
objectId="id"
Objects unique ID.
Tag
Description
An action or a group of actions that will be performed one or many times after the event condition is met.
Display an error message. Finish checking the task.
Display success message, finish the check.
Set the variable value.
Setting or dropping the event.
Attribute
Description
message="Wrong answer!"
Error message text
Attribute
Description
deffered="false"
Optional. The default value is "false". If set to "true" the trigger won't stop the program, I. e. the checker will wait until the program finishes and either reports the success if there were no errors, or otherwise, it will finish with an error. In other words, you won't get the error "The program has finished, but the task is not completed": the program will either terminate successfully or with a meaningful error like "Time limit exceeded".
Attribute
Description
name="my_value"
Variable name
Attribute
Description
id="finish checker"
The ID of the event.
Name
Description
twoDModel::robotModel::parts::RangeSensor
Distance sensor
trik::robotModel::twoD::parts::TwoDLightSensor
Light sensor
twoDModel::robotModel::parts::TouchSensor
Touch sensor
trik::robotModel::twoD::parts::LineSensor
Line sensor
Name
Description
twoDModel::robotModel::parts::RangeSensor
Distance sensor
twoDModel::robotModel::parts::LightSensor
Light sensor
twoDModel::robotModel::parts::TouchSensor
Touch sensor
twoDModel::robotModel::parts::ColorSensorRed
Color sensor (red)
twoDModel::robotModel::parts::ColorSensorGreen
Color sensor (green)
twoDModel::robotModel::parts::ColorSensorBlue
Color sensor (blue)
twoDModel::robotModel::parts::ColorSensorPassive
Color sensor (passive)
twoDModel::robotModel::parts::ColorSensorFull
Color sensor EVX/NXT (color)
twoDModel::robotModel::parts::ColorSensorAmbient
Color sensor EV3 (ambient)
ev3::robotModel::twoD::parts::GyroscopeSensor
Gyroscope
ev3::robotModel::twoD::parts::GyroscopeSensor
Compass
Property
Description
robot1.rotation
A current robot's rotation angle
robot1.x and robot1.y
Robots coordinate
robot1.led.color
LED color
robot1.marker.isDown
Checks if the robot has a marker and it draws a line on the field. Returns "true" or "false".
robot1.shell.lastPhrase
Get the last robots phrase.
Property
Description
robot1.display.sadSmiles
Checks if there is a sad smile on the controller display. Returns "true" or "false".
robot1.display.smiles
Checks if there is a happy smile on the controller display. Returns "true" or "false".
robot1.display.labels.first.text
Message (label) text that was displayed first.
robot1.display.labels.last.text
Message (label) text that was displayed last.
robot1.display.labels.size
Get the displayed label number.