Занятие 12. Маршрут, препятствия и обнаружение объектов (задачи 3.6–3.9, 3.11, 3.15)
Занятие 12. Маршрут и препятствия
Цель занятия: обучающиеся проезжают заданный судьёй маршрут по решётке перекрёстков (3.6) и обрабатывают препятствия: стоп (3.7, 3.11), объезд с возвратом на линию (3.8), объект сбоку со стопом и сигналом (3.9, 3.15).
Разминка-вспоминание (5 мин)
- Признак перекрёстка? Чем подтверждаем событие?
- Зачем довод на L_д перед поворотом?
- Две фазы поворота на перекрёстке?
- Как из журнала: ваша причина провала лотереи манёвров?
Разбор (worked examples)
3.6: маршрут — данные, а не код
Соревновательный паттерн: маршрут задаётся строкой, исполнитель один. Судья меняет маршрут — меняется строка, не программа:
// S — прямо через крест, R — направо, L — налево, U — разворот, F — финиш (стоп)
const char *route = "SRLSU F"; // выдаётся судьёй перед попыткой
void runRoute(const char *r) {
for (int i = 0; r[i]; i++) {
followToCross(); // едем по линии до события
switch (r[i]) {
case 'S': crossForward(); break;
case 'R': crossTurn(+1); break;
case 'L': crossTurn(-1); break;
case 'U': crossUturn(); break;
case 'F': stopBrake(); return;
}
}
}Это кульминация модуля с точки зрения программирования: переменные + цикл + ветвление + функции-кирпичи — ровно компетенции регламента («работа с переменными, составление логических выражений»).
3.7 / 3.11: стоп перед препятствием на линии
В PD-контур добавляется вторая причина остановки:
while (true) {
lineStep();
if (distMM() < 80 && distMM() < 80) { stopBrake(); break; } // два чтения подряд
}3.11 отличается только семантикой («объект на линии») — код тот же; допуск остановки судья меряет от объекта, поэтому порог 80 мм пересчитывается из требуемого зазора + вылет корпуса L_у (карта конфигурации!).
3.8: объезд банки с возвратом на линию — конечный автомат из кирпичей
stateDiagram-v2
ЛИНИЯ --> СТОП : dist < порог
СТОП --> ОБЪЕЗД : поворот 90 от линии
ОБЪЕЗД --> ПОИСК : П-образная траектория driveMM/tankTurn
ПОИСК --> ЗАХВАТ : любой датчик увидел чёрное
ЗАХВАТ --> ЛИНИЯ : доворот до центра + PD
void bypassCan() { // объезд справа; размеры под банку 0,33 + запас
stopBrake();
tankTurn(90); driveMM(180); // шаг вбок
tankTurn(-90); driveMM(300); // вдоль банки (длина > диаметра банки + 2 запаса)
tankTurn(-90); // носом к линии
drive(90, 90); // ПОИСК: медленно вперёд до чёрного любым датчиком
while (!anyBlack()) { /* предохранитель по пути! */ }
driveMM(L_D * 0.6); // наехать датчиками за линию
tankTurn(90); // довернуть вдоль линии
while (normCenter() < 700) drive(60, -60); // точный захват центра
stopBrake(); // дальше — lineStep()
}Разобрать: фаза ПОИСК не считает сантиметры до линии (их никто не знает точно) — она едет до события, как 4.23. Слепые размеры (180/300 мм) — только там, где событие невозможно (вдоль банки).
3.9 + 3.15: объект сбоку + сигнал
Боковой дальномер (лазерный предпочтителен: узкий луч не цепляет поле) + сигнализация:
while (true) {
lineStep();
if (distMM_side() < 350) { // регламент: объект в 15–30 см от линии,
stopBrake(); // порог 35 см покрывает диапазон с запасом
tone(BUZZ, 1000, 500); // 3.15: звук; вариант — RGB-подсветка
break;
}
}Подтверждение двумя чтениями и здесь обязательно. Сигнал — любой доступный способ по регламенту: звук, светодиод, надпись на дисплее; главное — судья должен его однозначно наблюдать.
Практика
3.7/3.11: стоп перед препятствием
Судья ставит банку в разных местах трассы, включая сразу за поворотом (жёсткий случай: банка появляется в поле зрения поздно — проверка скорости и порога).
3.8: объезд
Сдача с возвратом: после объезда робот проезжает по линии ещё ≥50 см. Размеры П-траектории — в карту калибровки.
3.9 + 3.15: объект сбоку
Судья ставит объект на вспомогательной линии на 15, 22 и 30 см — все три без правки кода (переменная-порог, не константы на каждый случай).
3.6: маршрут-лотерея
Судья пишет строку из 5–7 команд на бланке за 2 минуты до старта. Пара переносит её в код (одна строка!), заезд.
Типичные ошибки:
- объезд «слепыми» размерами до самой линии без фазы поиска — работает на одной банке и падает на банке, стоящей чуть иначе;
- нет предохранителя в фазе поиска — банка у края поля, линии за ней нет, робот уезжает с поля;
- сигнал 3.15 внутри быстрого цикла — пищит непрерывно/не слышно: сигнал по фронту события, один раз;
- маршрут «захардкожен» последовательностью вызовов вместо строки — правка под судейский маршрут за 2 минуты превращается в лихорадочное редактирование кода.
Мини-проверка выхода
Маршрут-лотерея сдана + 3.8 с возвратом. Вопрос: «какие фазы объезда — слепые, какие — событийные, и почему именно так?»