Практическое занятие 4. Объезд с выбором направления поворота

Курс «Основы робототехники. Продвинутый уровень». Занятие 5. Робот, проходящий лабиринт

Добавим роботу возможность объезжать препятствия. Для этого используем ультразвуковой датчик расстояния HC-SR04

Примечание: рекомендуется взять распечатку Занятия 9. Цифровые датчики с информацией об используемом датчике

Практическое занятие 1. Установка и тестирование

Установите датчик расстояния на робота, использовав держатель. Подключите контакты датчика к Arduino (VCC – к 5V). Протестируйте датчик, загрузив в контроллер программу Файл / Примеры / Ultrasonic / Ultrasonic2serial, исправив при необходимости номера контактов.

Практическое занятие 2. Остановка у стены

Запрограммируем робота на езду вперед и остановку у препятствия. Скопируйте в программу разработанные в домашнем задании функции: forward, backward, left, right с передачей значения, сколько времени работать моторам. Если таких функций нет в наличии, шаблон функции дан в конце прошлого занятия

float distance; int min_distance = 20; // переменные, setup и опрос датчика расстояния в переменную distance if (distance > min_distance) { // если расстояние впереди больше заданного forward (50); // едем вперед } else { // иначе, если расстояние впереди меньше заданного stop_motors (); // тормозим } // функции

Примечание: возможна ситуация, когда на датчик не приходит ответный сигнал, в этом случае distance может приравняться к нулю. Чтобы избежать некорректного поведения робота в этом случае, можно после опроса датчика добавить строку if (distance = 0) { distance = 2000; }

Практическое занятие 3. Объезд препятствия

Реализуйте следующий алгоритм:

1. Ехать вперед до тех пор, пока дистанция до препятствия впереди не будет меньше заданной (аналогично прошлой программе)

2. Если дистанция меньше – остановиться, отъехать назад, повернуть на определенный угол

3. Вернуться к пункту 1

Практическое занятие 4. Случайный объезд

Возможны ситуации, например, лабиринты, которые в случае езды робота вдоль одной стены являются непроходимыми. Простым решением проблемы является добавление элемента случайности в движения робота. Добавьте в предыдущую программу при обнаружении препятствия случайное направление поворота, используя логическую (boolean) переменную povorot для хранения направления

boolean povorot = false; … if (distance > min_distance){ // если расстояние впереди больше заданного forward (50); // едем вперед } else { // если расстояние впереди меньше заданного stop_motors (); // тормозим delay(100); backward (200); // едем назад   if (random(0, 2) == 0) {povorot = false;} // кидаем монетку на направление поворота 0 - false, else {povorot = true;} // 1 - true if (povorot == false){ // если выпал 0 left (turn_time); // едем налево } else { // если выпала 1 right (turn_time); // едем направо } }

 

Также можно добавить и случайное время поворота (в заданных пределах), соответственно, будет случайным угол поворота:

turn_time = random (min, max+1)

Практическое занятие 4. Объезд с выбором направления поворота

Попробуем ускорить движение робота по объезду препятствия, убрав отъезд назад и добавив осмысленный выбор направления объезда препятствия. Например, при подъезжании робота к стене под углом (см. рисунок справа) имеет смысл выбрать соответствующее направление поворота, обеспечивающее минимальное время поворота.

Алгоритм работы в этом случае:

1. Ехать вперед до тех пор, пока дистанция до препятствия впереди не будет меньше заданной (аналогично прошлой программе)

2. Сохранить измеренную дистанцию, случайно выбрать направление поворота

3. Повернуть на небольшое расстояние

4. Измерить расстояние впереди

5. Сравнить измеренное расстояние с сохраненным в начале. Если расстояние стало меньше - направление выбрано неправильно и его надо сменить

6. Продолжать повороты до тех пор, пока расстояние впереди не станет больше заданного

 

Приведен код для данного алгоритма, его нужно проверить, провести подбор параметров (speed, turn_time и т.д.) для решения задачи оптимального прохождения лабиринта (за минимальное время) и продемонстрировать работу. Значение turn_time в коде небольшое (порядка 50 мс), так как для отворачивания от препятствия выполняется несколько мелких поворотов, а не один большой

distance = ultrasonic.Ranging(CM); if (distance > min_distance){ // если расстояние впереди больше заданного forward (50); // едем вперед } else { // если расстояние впереди меньше заданного if (random(0, 2) == 0) {povorot = false;} // кидаем монетку на направление поворота 0 - false, else {povorot = true;} // 1 - true   // поворачиваем до тех пор, пока расстояние впереди не станет допустимым, при этом проводим проверку, правильно ли мы повернули while (ultrasonic.Ranging(CM) < min_distance){ if (povorot == false){ // если выпал 0 left (turn_time); // едем налево } else { // если выпала 1 right (turn_time); // едем направо } // если дистанция впереди стала меньше исходной – поворот выполняется в неправильном направлении, меняем направление на противоположное if (ultrasonic.Ranging(CM) < distance) {povorot = !povorot;} } }

 

Примечание 1: сохраните к себе получившийся код программы, он будет использован на соревновании по прохождению лабиринта на аттестационном занятии 8

Примечание 2: теоретически, при определенной конфигурации препятствия, возможно, что в обоих направлениях поворотов расстояние впереди станет меньше, чем было до поворота. В этом случае робот будет дергаться вправо-влево бесконечно. Чтобы избежать этого, можно добавить счетчик смены направлений и при превышении счетчика дать команду роботу выполнить, например, поворот на случайный большой угол.