Adding restrictions to the 2D Model

It is possible to add restrictions by editing an XML file to prepare exercises for students.

There are three types of restrictions:

  1. Time restrictions. For example, a time limit to complete a task or a specific action in a specific time frame.

  2. 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.

  3. Device restrictions. For example, a limitation on the set of sensors or on the behavior of devices.

Constraint description structure

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:

<constraints>...</constraints>

The main tag containing all restrictions. Used as a container.

<constraints>
     <!-- Time limit -->
     <timelimit value="30000"/>
     
     <!-- Conditional constraint. An error message will be shown at violation. -->
     <constraint checkOnce="true" failMessage="The robot must be at start before run!">
          <inside objectId="robot1" regionId="start_zone"/>
     </constraint>
     
     <!-- Initializing variable x with value 2 -->
     <init>
          <setter name="x">
               <int value="2"/>
          </setter>
      </init>

</constraints>

<timelimit/>

Time limit. Mandatory.

Attributes

Syntax:

<timelimit value="35000"/>

<constraint>...</constraint>

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>.

Attributes

Syntax:

<constraint checkOnce="true" failMessage="The robot must be at start before run!">
<!-- Checks if the IR distance sensor is connected to the A1 port -->
<constraint checkOnce="true" failMessage="The IR distance sensor must be connected to the robots A1 port!">
    <equals>
        <typeOf objectId="robot1.A1"/>
        <string value="twoDModel::robotModel::parts::RangeSensor"/>
    </equals>
</constraint>
<!-- Checks if the robot is inside the specified region for the entire program execution time-->
<constraint failMessage="The robot has left the allowed zone!">
    <inside objectId="robot1" regionId="warzone"/>
</constraint>

<event>...</event>

The main tool for setting dynamic constraints. Used as a container.

An event is just a pair (condition, trigger).

Attributes

Syntax:

<event id="finish checker" settedUpInitially="false">
	<condition>
		<inside objectId="robot1" regionId="finish"/>
	</condition>
	<trigger>
		<success/>
	</trigger>
</event>

<init>...</init>

Unconditional event executing before the program starts.

Example:

<!-- Setting the "my_value" variable to the value of two-->
<init>
    <setter name="my_value">
        <int value="2"/>
    </setter>
</init>

Conditions

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.

<condition>...</condition>

The condition being checked is described inside this tag.

Example:

<condition>
    <!-- The condition of equality of two values is described inside the tag -->
    <equals>
        <objectState object="robot1.display.smiles"/>
        <bool value="true"/>
    </equals>
</condition>

<conditions>...</conditions>

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.

Attributes:

Syntax:

<conditions glue="and">
   <!-- Condition1 -->
   <!-- Condition2 -->
   <!--    ...   -->
   <!-- ConditionN -->
</conditions>

<conditions glue="and">
   <not>
      <!-- Condition1 -->
   </not>
</conditions>

<conditions glue="and">
   <timer timeout="1000" forceDropOnTimeout="true"/>
   <conditions glue="or">
      <greater>
         <objectState object="robot1.display.labels.size"/>
         <int value="20"/>
      </greater>
      <less>
         <objectState object="robot1.display.labels.size"/>
         <int value="19"/>
       </less>    
    </conditions>
</conditions>

Atomic conditions

Atomic condition is one of the following elements:

<equals>...</equals>

Equals. The functional symbols value comparison operation. Can be used as a container.

Syntax:

<equals>
	<objectState object="robot1.display.labels.first.text"/>
	<string value="finish"/>
</equals>

<notEqual>...</notEqual>

Not equal. The functional symbols value comparison operation. Can be used as a container.

Syntax:

<notEqual>
	<objectState object="robot1.display.labels.first.text"/>
	<string value="finish"/>
</notEqual>

<greater>...</greater>

Greater. The functional symbols value comparison operation. Can be used as a container.

Syntax:

<greater>
	<objectState object="robot1.display.labels.size"/>
	<int value="0"/>
</greater>

<less>...</less>

Less. The functional symbols value comparison operation. Can be used as a container.

Syntax:

<less>
    <objectState object="robot1.display.labels.size"/>
    <int value="10"/>
</less>

<inside/>

Sets spatial constraints.

Attributes

Syntax:

<!-- Limits the location of the "robot1" robot to the "start" zone -->
<inside objectId="robot1" regionId="start"/>

<settedUp/> and <dropped/>

Checks whether the event set up or not.

Attributes

Syntax:

<!-- The "event1" event is set up condition -->
<condition>
    <settedUp id="event1"/>
</condition>

<!-- The "event2" event is dropped condition -->
<condition>
    <dropped id="event2"/>
</condition>

Example:

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.

<event id="check event" settedUpInitially="true">
    <conditions glue="and">
        <settedUp id="Try move"/>
        <dropped id="Go back"/>
    </conditions>
    <trigger>
        <success/>
    </trigger>
</event>

<timer/>

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".

Attributes

Syntax:

<timer timeout="1000" forceDropOnTimeout="false"/>

Example

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.

<event id="check region" settedUpInitially="true">
    <conditions glue="and">
        <timer timeout="1000" forceDropOnTimeout="false"/>
        <inside objectId="robot1" regionId="start_zone"/>
    </conditions>
    <trigger>
        <success/>
    </trigger>
</event>

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.

<event id="check region" settedUpInitially="true">
    <conditions glue="and">
        <timer timeout="1000" forceDropOnTimeout="true"/>
        <inside objectId="robot1" regionId="start_zone"/>
    </conditions>
    <trigger>
        <success/>
    </trigger>
</event>

Variable types and arithmetic operations

<int/>, <double/>, <string>, <bool/>

Setting a constant.

Attributes

Syntax:

<int value="0"/>

<string value="finish"/>

<variableValue/>

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".

Attributes

Syntax:

<variableValue name="rotation"/>

<objectState/>

Get the object state.

Attributes

Syntax:

<objectState object="robot1.display.labels.first.text"/>

Example

<!-- Assign to the "rotation" variable the robots rotation angle -->
<setter name="rotation">
     <objectState object="robot1.rotation"/>
 </setter>
<!-- Checking if the "rotation" value equals to the robots rotation angle -->
<equals>
   <variableValue name="rotation"/>
   <objectState object="robot1.rotation"/>
</equals>

<typeOf/>

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.

Attributes

Syntax:

<typeOf objectId="robot1.A3"/>

<minus>..</minus>, <abs>...</abs>

Unary arithmetic operations for changing the sign and taking the modulus of a number.

Syntax:

<minus>
    <objectState object="robot1.rotation"/>
</minus>

<abs>
    <objectState object="robot1.rotation"/>
</abs>

Example:

<!-- Modulus of the difference of the "rotation" variable and the robots rotation angle -->
<abs>
    <difference>
        <variableValue name="rotation"/>
        <objectState object="robot1.rotation"/>
    </difference>
</abs>

<sum>, <difference>, <min>, <max>

Sum and difference of values. Minimum and maximum value.

Example:

<!-- The difference of the "rotation" variable and the robots rotation angle -->
<difference>
       <variableValue name="rotation"/>
       <objectState object="robot1.rotation"/>
</difference>

<!-- The sum of the "counter" variable and one -->
<sum>
       <variableValue name="counter"/>
       <int value="1"/>
</sum>

Triggers

<trigger>...</trigger>

An action or a group of actions that will be performed one or many times after the event condition is met.

Syntax:

<trigger>
	<success/>
</trigger>

<fail/>

Display an error message. Finish checking the task.

Attributes

Syntax:

<fail message="Wrong answer!"/>

<success/>

The task is successfully done.

Attributes

Syntax:

<success/>

<setter>...</setter>

Set the variable value.

Attributes

Example:

<!-- Creating the "total_score" variable with the value of zero -->
<setter name="total_score">
       <int value="0"/>
 </setter>

<!-- Addind 2 to the "total_score" -->
<setter name="total_score">
       <sum>
              <variableValue name="total_score"/>
              <int value="2"/>
       </sum>
</setter>

<setUp/>, <drop/>

Setting up or dropping an event.

Attributes

Example:

<!-- Set up the "finish checker" event -->
<triggers>
				<setUp id="finish checker"/>
</triggers>

Sensor names

TRIK Robot Sensors

Lego EV3 Robot sensors

Additional robot properties

Working with the controller display

Example

Checking that the word “message” was displayed on the controller screen. The case is important.

<equals>
        <objectState object="robot1.display.labels.first.text"/>
        <string value="message"/>
</equals>

Restrictions example

You need to start in the blue square then drive along the wall to the red one using the IR distance sensor.

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <world>
      <background />
      <walls>
         <!-- The wall-->
         <wall id="{wall1}" end="300:150" begin="0:100" />
         <wall id="{wall2}" end="550:100" begin="300:150" />
         <wall id="{wall3}" end="650:200" begin="550:100" />
         <wall id="{wall4}" end="850:300" begin="650:200" />
         <wall id="{wall5}" end="1200:300" begin="850:300" />
         <wall id="{wall6}" end="1600:50" begin="1200:300" />
      </walls>
      <skittles />
      <balls />
      <colorFields />
      <images />
      <regions>
         <!-- Regions-->
         <region visible="true" id="finish" x="1300" color="#ff0000" text="Finish" type="rectangle" width="300" textX="0" textY="0" y="-200" filled="true" height="300" />
         <region visible="true" id="start_zone" x="-50" color="#0000ff" text="Start" type="rectangle" width="150" textX="0" textY="0" y="100" filled="true" height="-150" />
         <region visible="false" id="warzone_1" x="-50" color="#ffff00" text="warzone1" type="rectangle" width="650" textX="0" textY="0" y="-50" filled="true" height="200" />
         <region visible="false" id="warzone_2" x="600" color="#ffff00" text="warzone2" type="rectangle" width="250" textX="0" textY="0" y="0" filled="true" height="250" />
         <region visible="false" id="warzone_3" x="850" color="#ffff00" text="warzone3" type="rectangle" width="750" textX="0" textY="0" y="50" filled="true" height="250" />
      </regions>
   </world>
   <robots>
      <!-- Robot description -->
      <robot id="trikKitRobot" position="0:0" direction="0">
         <sensors>
            <sensor port="A1###input###А1###sensorA1" position="75:25" type="trik::robotModel::parts::TrikInfraredSensor" direction="45" />
            <sensor port="M3###output###JM3$$$C$$$3###" position="75:25" type="kitBase::robotModel::robotParts::Motor" direction="0" />
            <sensor port="M4###output###JM4$$$D$$$4###" position="75:25" type="kitBase::robotModel::robotParts::Motor" direction="0" />
         </sensors>
         <startPosition id="{ee2c46c1-23fc-4cda-98f4-77d9de775305}" x="25" y="25" direction="0" />
         <wheels left="M3###output###М3###" right="M4###output###М4###" />
      </robot>
   </robots>
   <constraints>
      <!-- Time limit (30 seconds) -->
      <timelimit value="30000" />
      <!-- Spatial restriction of the start region. Checks once at the program start -->
      <constraint checkOnce="true" failMessage="The robot must be inside the blue square at the start!">
         <inside regionId="start_zone" objectId="robot1" />
      </constraint>
      <!-- Sensors type and presence restriction -->
      <constraint checkOnce="true" failMessage="Only the IR distance sensor must be connected to the A1 port">
         <conditions glue="and">
            <equals>
               <typeOf objectId="robot1.A1" />
               <string value="trik::twoDModel::robotModel::parts::RangeSensor" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A2" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A3" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A4" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A5" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A6" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.D1" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.D2" />
               <string value="undefined" />
            </equals>
         </conditions>
      </constraint>
      <!-- Robot ride control -->
      <constraint failMessage="The robot tried to move out of the permitted area!">
         <conditions glue="or">
            <inside regionId="warzone_1" objectId="robot1" />
            <inside regionId="warzone_2" objectId="robot1" />
            <inside regionId="warzone_3" objectId="robot1" />
         </conditions>
      </constraint>
      <!-- An event that checks if the robot has entered the finish area -->
      <event settedUpInitially="true">
         <condition>
            <timer timeout="100" forceDropOnTimeout="true" />
         </condition>
         <trigger>
            <setUp id="finish checker" />
         </trigger>
      </event>
      <!-- Event reporting the successful finish -->
      <event id="finish checker" settedUpInitially="false">
         <condition>
            <inside regionId="finish" objectId="robot1" />
         </condition>
         <trigger>
            <success />
         </trigger>
      </event>
   </constraints>
</root>

Last updated