- Структура описания ограничений
- Условия
- Атомарные условия
- Типы переменных и арифметические операции
- Триггеры
- Названия датчиков
- Дополнительные свойства робота
- Работа с экраном контроллера
- Пример добавления ограничений
Для подготовки упражнений для учеников существует возможность внесения ограничений с помощью редактирования XML-файла.
Ограничения бывают трех видов:
-
Временны́е.
Например, лимит времени на исполнение задачи или конкретное действие в конкретный временной отрезок.\ -
Пространственные.
Например, добавление регионов («Старт», «Финиш») или запрет / принуждение робота, его датчика или какого-то подвижного предмета находиться в определенные промежутки времени в определенном месте.\ -
Ограничения на устройства.
Например, ограничение на набор датчиков или на поведение устройств.
Для описания ограничений используется главный тег <constraints>…</constraints>
, в который вписываются все ограничения. Используется как контейнер. Ограничения описываются внутри тега, каждый дочерний тег должен быть одним из четырех:
Тег | Описание |
---|---|
timelimit | Временное ограничение. |
constraint | Ограничение с произвольным условием, при нарушении которого будет выдана заданная ошибка. |
event | Основной инструмент задания динамических ограничений. Используется как контейнер. |
init | Безусловное событие, выполняющееся перед началом выполнения программы. |
Основной тег, в который вписываются все ограничения. Используется как контейнер.
<constraints>
<!-- Временное ограничение -->
<timelimit value="30000"/>
<!-- Ограничение с условием. При нарушении условия будет выдана ошибка -->
<constraint checkOnce="true" failMessage="Робот должен находиться на старте перед запуском!">
<inside objectId="robot1" regionId="start_zone"/>
</constraint>
<!-- Инициализация переменной x со значением 2 -->
<init>
<setter name="x">
<int value="2"/>
</setter>
</init>
</constraints>
Временное ограничение. Является обязательным.
Атрибут | Описание |
---|---|
value="значение" | Количество миллисекунд, через которое исполнение будет прекращено и выдана ошибка «Превышен лимит времени». |
<timelimit value="35000"/>
Ограничение с произвольным условием, при нарушении которого будет выдана заданная ошибка. Может использоваться как контейнер. Имеет один дочерний тег: <conditions>...</conditions>
.
Атрибут | Описание |
---|---|
checkOnce="true" | Логический атрибут. Если в значении стоит true, то ограничение будет проверено 1 раз при старте программы и больше проверяться не будет. Полезно, например, если нужно 1 раз проверить, что датчики расставлены верно, а дальше во время исполнения ничего не поменяется. |
failMessage="Ошибка!" | Сообщение об ошибке, которое будет показано при нарушении ограничения. |
<constraint checkOnce="true" failMessage="Робот должен находиться на старте перед запуском!">
<!-- Проверяет при запуске, что на порту А1 установлен инфракрасный датчик расстояния -->
<constraint checkOnce="true" failMessage="У робота должен быть установлен инфракрасный датчик расстояния на порту А1">
<equals>
<typeOf objectId="robot1.A1"/>
<string value="twoDModel::robotModel::parts::RangeSensor"/>
</equals>
</constraint>
<!-- Проверяет, что робот находится в допустимом регионе на протяжении всего времени выполнения программы -->
<constraint failMessage="Робот покинул допустимую зону!">
<inside objectId="robot1" regionId="warzone"/>
</constraint>
Основной инструмент задания динамических ограничений. Используется как контейнер.
Событие - это просто пара (условие, триггер).
Атрибут | Описание |
---|---|
settedUpInitially="true" | Атрибут, позволяющий указать взведено ли событие при старте программы. Событие может быть взведено или спущено (setted up и dropped). Во взведенном состоянии событие выполняет свой триггер по выполнению своего условия, в спущенном оно просто игнорируется системой. Значение по умолчанию — false. |
id="finish checker" | Уникальный идентификатор события. По этому идентификатору можно обращаться к данному событию из других. Опциональный. |
dropsOnFire = "true" | Логический атрибут, который указывает, продолжать ли быть событию взведенным после его срабатывания или нет. Опциональный. Значение по умолчанию -- true. |
<event id="finish checker" settedUpInitially="false">
<condition>
<inside objectId="robot1" regionId="finish"/>
</condition>
<trigger>
<success/>
</trigger>
</event>
Безусловное событие, выполняющееся перед началом выполнения программы.
<!-- Перед началом выполнения программы заводим переменную "my_value" со значением два -->
<init>
<setter name="my_value">
<int value="2"/>
</setter>
</init>
Теперь обсудим, какими могут быть условия в элементах <constraint> и <event>. Условия задаются с помощью тега <condition> в случае, если проверяется только одно из атомарных условий, или тега <conditions>, если проверяется составное условие.
Внутри этого тега описывается проверяемое условие.
<condition>
<!-- Внутри тега описано условие равенства двух значений -->
<equals>
<objectState object="robot1.display.smiles"/>
<bool value="true"/>
</equals>
</condition>
Используется для создания составных условий. Обязательным атрибутом должна быть указана логическая связка. Связкой может быть and
или or
. Отрицание выражения задается тегом <not>
без атрибутов. Среди подвыражений могут также встречаться другие элементы <conditions>.
Атрибут | Описание |
---|---|
glue="and" | Логическая связка. |
<conditions glue="and">
<!-- Условие1 -->
<!-- Условие2 -->
<!-- ... -->
<!-- УсловиеN -->
</conditions>
<conditions glue="and">
<not>
<!-- Условие1 -->
</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>
Атомарное условие представляет собой один из следующих элементов:
Тег | Описание |
---|---|
equals, notEqual, greater, less | Операции сравнения значений. |
****inside | Позволяет задавать пространственные ограничения. |
settedUp и dropped | Позволяет проверить, взведено событие или нет. |
timer | Позволяет задать время в мс, после которого данное условие считается истинным. |
Равно. Операция сравнения значений функциональных символов. Может использоваться как контейнер.
<equals>
<objectState object="robot1.display.labels.first.text"/>
<string value="finish"/>
</equals>
Не равно. Операция сравнения значений функциональных символов. Может использоваться как контейнер.
<notEqual>
<objectState object="robot1.display.labels.first.text"/>
<string value="finish"/>
</notEqual>
Больше. Операция сравнения значений функциональных символов. Может использоваться как контейнер.
<greater>
<objectState object="robot1.display.labels.size"/>
<int value="0"/>
</greater>
Меньше. Операция сравнения значений функциональных символов. Может использоваться как контейнер.
<less>
<objectState object="robot1.display.labels.size"/>
<int value="10"/>
</less>
Позволяет задавать пространственные ограничения.
Атрибут | Описание |
---|---|
objectId="id" | id взятого объекта. |
regionId="id" | id взятого региона. |
objectPoint="center|all|any" | Осуществляет проверку того, что: center — центр объекта находится в зоне, |
<!-- Задаем ограничение на то, что объект робот находится в регионе с id=”start” -->
<inside objectId="robot1" regionId="start"/>
Позволяет проверить, взведено событие или нет.
Атрибут | Описание |
---|---|
id="event1" | Идентификатор проверяемого события |
<!-- Условие, что событие с id=”event1” взведено -->
<condition>
<settedUp id="event1"/>
</condition>
<!-- Условие, что событие с id=”event2” опущено -->
<condition>
<dropped id="event2"/>
</condition>
В условиях события “check event” проверяется, что другое событие с id=”Try move” находится во взведенном состоянии, а событие с id=”Go back” опущено и не выполняется. Если оба эти условия после проверки возвращают значение true, то программа успешно завершается.
<event id="check event" settedUpInitially="true">
<conditions glue="and">
<settedUp id="Try move"/>
<dropped id="Go back"/>
</conditions>
<trigger>
<success/>
</trigger>
</event>
Предикат, который начинает выдавать true, когда с момента взведения данного события прошло заданное время, а до этого момента выдает false.
Атрибут | Описание |
---|---|
timeout="1000" | Промежуток времени, через которой данный предикат станет истинным. Обязательный, значение должно быть неотрицательным и целочисленным. |
forceDropOnTimeout="true" | Логический атрибут, позволяющий опустить событие, которое имеет в условии данный таймер. Если выставлен в true, событие будет опущено даже при наличии других активных таймеров и невыполненных условий. Опциональный. Значение по умолчанию -- true |
<timer timeout="1000" forceDropOnTimeout="false"/>
Рассмотрим использование <timer/> c различными значениями атрибута forceDropOnTimeout .
В событии “check region” проверяются временное и пространственное ограничения. Первое условие (timer) становится истинным спустя 1000мс, а до этого момента ложно. После этого его значение больше не изменяется. Второе условие (inside) проверяет, что робот находится в регионе с id=”start_zone”. В тот момент, когда оба этих условия будут выполнены одновременно, программа будет выполнена успешно.
1. Т. к. атрибут forceDropOnTimeout равен "false", то после заданного количества времени событие будет продолжать оставаться взведенным и ждать выполнения второго условия.
<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. Т. к. атрибут forceDropOnTimeout равен "true", то после заданного количества миллисекунд событие будет опущено, несмотря на наличие .другого условия. Таким образом, если в момент времени 1000 мс робот не находится в нужном регионе, то сообщение об успешном выполнении не будет выведено даже в случае, если робот окажется там спустя некоторое время.
<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>
Переменная | Описание |
---|---|
int, double, string, bool | Целочисленная, дробная, строковая и логическая константы. |
****variableValue | Значение переменной. |
objectState | Взять состояние объекта. |
typeOf | Взять метатип объекта с заданным идентификатором. |
minus, abs | Унарные арифметические функции, имеют ровно 1 дочерний элемент, значение которого должно быть целочисленным. |
sum, difference, min, max | Бинарные арифметические функции, имеют ровно 2 дочерних элемента, значение каждого из которых должно быть целочисленным. |
Задание константы.
Атрибут | Описание |
---|---|
value="0″ | Значение заданной константы. |
<int value="0"/>
<string value="finish"/>
Значение переменной.
Возможно взятие свойства какой-либо переменной, для этого используется точка. Например, значение rect.width вернет ширину прямоугольника, сохраненного в переменной rect.
Атрибут | Описание |
---|---|
name="my_value" | Имя переменной |
<variableValue name="rotation"/>
Взять состояние объекта.
Атрибут | Описание |
---|---|
object="robot1.display.labels.size" | id взятого объекта. |
<objectState object="robot1.display.labels.first.text"/>
<!-- Присвоим переменной rotation значение угла поворота робота -->
<setter name="rotation">
<objectState object="robot1.rotation"/>
</setter>
<!-- Проверяем равно ли значение переменной rotation значению угла поворота робота -->
<equals>
<variableValue name="rotation"/>
<objectState object="robot1.rotation"/>
</equals>
Взять метатип объекта с заданным идентификатором. Например: если взять typeOf
объекта wall
с id=777
, то он вернет, что тип этого объекта wall
.
Чаще всего этот элемент будет нужен для проверки типа подключенных датчиков и моторов.
Атрибут | Описание |
---|---|
objectId="id" | Уникальный идентификатор взятого объекта. |
<typeOf objectId="robot1.A3"/>
Унарные арифметические операции отвечающие за изменение знака и взятие модуля числа.
<minus>
<objectState object="robot1.rotation"/>
</minus>
<abs>
<objectState object="robot1.rotation"/>
</abs>
<!-- Модуль разности переменной rotation и значения угла поворота робота -->
<abs>
<difference>
<variableValue name="rotation"/>
<objectState object="robot1.rotation"/>
</difference>
</abs>
Сумма и разность значений. Минимальное и максимальное значение.
<!-- Разность между переменной rotation и значением угла поворота робота -->
<difference>
<variableValue name="rotation"/>
<objectState object="robot1.rotation"/>
</difference>
<!-- Сумма переменной counter и единицы -->
<sum>
<variableValue name="counter"/>
<int value="1"/>
</sum>
Тег | Описание |
---|---|
trigger | Действие или группа действий, которые будут выполнены один или множество раз по факту выполнения условия события. |
fail | Показать ошибку пользователю, завершить проверку задания. |
success | Показать пользователю сообщение об успешном прохождении задания и завершить проверку. |
setter | Установить значение переменной. |
setUp, drop | Взводит или опускает событие |
message | Выводит текст |
Действие или группа действий, которые будут выполнены один или множество раз по факту выполнения условия события.
<trigger>
<success/>
</trigger>
Показать ошибку, завершить проверку задания.
Атрибут | Описание |
---|---|
message="Неверный ответ!" | текст выведенной ошибки |
<fail message="Неверный ответ!"/>
Задание успешно пройдено.
Атрибут | Описание |
---|---|
deffered="false" | Опциональный. По умолчанию равен "false". При выставлении его в true данный триггер не остановит выполнение программы, т. е. чекер дождется конца программы и, либо скажет, что программа выполнена успешно, если ошибок не было, либо выпадет с ошибкой в противном случае. Другими словами атрибут deferred не позволяет получить ошибку "Программа закончилась, но задание не выполнено": программа либо завершится с успехом, либо с содержательной ошибкой типа "Превышен лимит времени". |
<success/>
Установить значение переменной
Атрибут | Описание |
---|---|
name="my_value" | Название переменной |
<!-- Создаем переменную total_score со значением 0.-->
<setter name="total_score">
<int value="0"/>
</setter>
<!-- Добавляем к переменной total_score + 2. -->
<setter name="total_score">
<sum>
<variableValue name="total_score"/>
<int value="2"/>
</sum>
</setter>
Взводит или опускает событие
Атрибут | Описание |
---|---|
id="finish checker" | id выбранного события |
<!-- Запустить событие "finish checker" -->
<triggers>
<setUp id="finish checker"/>
</triggers>
Выводит текст в консоль
Атрибуты
Атрибут | Описание |
---|---|
text="Hello, world!" | Необходимый текст |
<trigger>
<message text="Hello, world!"/>
</trigger>
При срабатывании такого триггера в консоль робота будет выведен текст "Hello, world!"
Название | Описание |
---|---|
twoDModel::robotModel::parts::RangeSensor | Датчик расстояния |
trik::robotModel::twoD::parts::TwoDLightSensor | Датчик освещенности |
twoDModel::robotModel::parts::TouchSensor | Датчик касания |
trik::robotModel::twoD::parts::LineSensor | Датчик линии |
Название | Описание |
---|---|
twoDModel::robotModel::parts::RangeSensor | Датчик расстояния |
twoDModel::robotModel::parts::LightSensor | Датчик освещённости |
twoDModel::robotModel::parts::TouchSensor | Датчик касания |
twoDModel::robotModel::parts::ColorSensorRed | Датчик цвета (красный) |
twoDModel::robotModel::parts::ColorSensorGreen | Датчик цвета (зеленый) |
twoDModel::robotModel::parts::ColorSensorBlue | Датчик цвета (синий) |
twoDModel::robotModel::parts::ColorSensorPassive | Датчик цвета (пассивный) |
twoDModel::robotModel::parts::ColorSensorFull | Датчик цвета EVX/NXT (цвет) |
twoDModel::robotModel::parts::ColorSensorAmbient | Датчик цвета EV3 (рассеянный) |
ev3::robotModel::twoD::parts::GyroscopeSensor | Гиродатчик |
ev3::robotModel::twoD::parts::GyroscopeSensor | Компас |
Свойство | Описание |
---|---|
robot1.rotation | Позволяет узнать текущий угол поворота робота |
robot1.x и robot1.y | Позволяет узнать координаты робота |
robot1.led.color | Позволяет узнать цвет диода |
robot1.marker.isDown | Проверяет, что у робота установлен маркер и он рисует линию на поле. Возвращает значения true или false |
robot1.shell.lastPhrase | Узнать текст, который сказал робот |
Свойство | Описание |
---|---|
robot1.display.sadSmiles | Проверяет, что на экране контроллера установлен грустный смайлик. Возвращает значение true или false. |
robot1.display.smiles | Проверяет, что на экране контроллера установлен веселый смайлик. Возвращает значение true или false. |
robot1.display.labels.first.text | Текст сообщения (label), которое было выведено на экран первым. |
robot1.display.labels.last.text | Тест сообщения (label), которое было выведено на экран последним. |
robot1.display.labels.size | Узнать количество label-ов, выведенных на экран. |
Проверяем, что на экран контроллера было выведено слово “сообщение”. Регистр слова важен.
<equals>
<objectState object="robot1.display.labels.first.text"/>
<string value="сообщение"/>
</equals>
Стартовав в синем квадрате, необходимо проехать вдоль стены с помощью датчика расстояния ИК до красного квадрата.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<world>
<background />
<walls>
<!-- Стена -->
<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>
<!-- Регионы -->
<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 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>
<!-- Лимит на выполнение программы (30 секунд) -->
<timelimit value="30000" />
<!-- Зональное ограничение на начало езды. Проверяется один раз в начале программы -->
<constraint checkOnce="true" failMessage="Робот должен находиться в синем квадрате перед запуском!">
<inside regionId="start_zone" objectId="robot1" />
</constraint>
<!-- Ограничение на наличие и тип датчиков -->
<constraint checkOnce="true" failMessage="Должен быть подключен только Датчик расстояния ИК на A1">
<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>
<!-- Контроль езды робота -->
<constraint failMessage="Робот попытался выехать из разрешенной зоны!">
<conditions glue="or">
<inside regionId="warzone_1" objectId="robot1" />
<inside regionId="warzone_2" objectId="robot1" />
<inside regionId="warzone_3" objectId="robot1" />
</conditions>
</constraint>
<!-- Событие, проверяющее не заехал ли робот в зону финиша -->
<event settedUpInitially="true">
<condition>
<timer timeout="100" forceDropOnTimeout="true" />
</condition>
<trigger>
<setUp id="finish checker" />
</trigger>
</event>
<!-- Событие, оповещающее об успешном выполнении программы -->
<event id="finish checker" settedUpInitially="false">
<condition>
<inside regionId="finish" objectId="robot1" />
</condition>
<trigger>
<success />
</trigger>
</event>
</constraints>
</root>