🏆 Соревнования!

Урок 2.4 | Level 2: Оператор

От учебного робота к соревновательной машине

Зачем соревнования?

Учебный проект:          Соревнования:
──────────────           ─────────────
✓ Работает как-то        ✓ Работает НАДЁЖНО
✓ Дома на столе          ✓ На ЛЮБОЙ поверхности
✓ Время неважно          ✓ БЫСТРЕЕ всех
✓ Один запуск            ✓ 10 запусков подряд

Соревнования — это стресс-тест! 💪

Популярные форматы

🏁 Line Following (Линия)

┌─────────────────────────────────────┐
│ START                               │
│   ══╗                               │
│     ║   ╔════════╗                  │
│     ║   ║        ║                  │
│     ╚═══╝        ╚═══════╗          │
│                          ║   FINISH │
│ ─────────────────────────╝          │
└─────────────────────────────────────┘

Критерии: время, сход с линии

🤖 Кегельринг (Сумо + кегли)

        ┌─────────────┐
       ╱    ●  ●  ●    ╲
      │    ●  🤖  ●    │
      │    ●  ●  ●    │
       ╲              ╱
        └─────────────┘
        
Цель: вытолкнуть кегли за 60 секунд

🚗 Дрэг-рейсинг

│ START │═══════════════════════│ FINISH │
│       │                       │        │
│ 🤖A   │ → → → → → → → → → →  │        │
│       │                       │        │
│ 🤖B   │ → → → → → → → → → →  │        │
│       │                       │        │

Кто быстрее проедет прямую?

🧩 Лабиринт (Maze)

┌─┬───┬─┬───┬─┐
│S│   │ │   │ │
├─┘ ┌─┘ └─┐ └─┤
│   │     │   │
├───┴─┬───┴───┤
│     │       │
├─┬───┤ ┌───┬─┤
│ │   │ │   │F│
└─┴───┴─┴───┴─┘

Найти выход за минимум времени

🎯 Мини-сумо (3 кг)

        ╱‾‾‾‾‾‾‾‾‾‾‾╲
      ╱               ╲
     │   🤖A   🤖B    │
     │                │
      ╲   (чёрный   ╱
        ╲  круг) ╱
          ‾‾‾‾‾‾
          
Белая граница — не выезжать!
Цель: вытолкнуть соперника

Подготовка робота

Hardware чек-лист

□ Надёжные соединения (пайка > dupont)
□ Защита от вибраций (резинки, термоклей)
□ Лёгкий доступ к батарее
□ Запасной комплект (датчики, провода)
□ Кнопка аварийной остановки
□ Индикатор заряда батареи
□ Датчики защищены от света

Software чек-лист

□ Калибровка датчиков перед стартом
□ Несколько программ (профили трассы)
□ Настройка PID через Serial/кнопки
□ Логирование данных (для анализа)
□ Watchdog (перезагрузка при зависании)
□ Graceful degradation (работа при отказе)

Механика чек-лист

□ Колёса не проскальзывают (резина!)
□ Центр тяжести низко
□ Датчики на правильной высоте
□ Ничего не болтается
□ Провода не цепляют колёса
□ Шасси жёсткое (не гнётся)

Стратегии для Line Following

Калибровка — ключ к победе!

int whiteValue[8];  // Массив для белого
int blackValue[8];  // Массив для чёрного

void calibrate() {
  Serial.println("Поставь на БЕЛОЕ, нажми кнопку");
  waitButton();
  for (int i = 0; i < 8; i++) {
    whiteValue[i] = analogRead(sensorPins[i]);
  }
  
  Serial.println("Поставь на ЧЁРНОЕ, нажми кнопку");
  waitButton();
  for (int i = 0; i < 8; i++) {
    blackValue[i] = analogRead(sensorPins[i]);
  }
  
  Serial.println("Калибровка завершена!");
}

int readSensor(int i) {
  int raw = analogRead(sensorPins[i]);
  return map(raw, whiteValue[i], blackValue[i], 0, 1000);
}

Адаптивная скорость

void loop() {
  float error = readLineError();
  float absError = abs(error);
  
  // На прямой — быстро, на повороте — медленно
  int speed;
  if (absError < 10) {
    speed = MAX_SPEED;  // Прямая!
  } else if (absError < 30) {
    speed = MEDIUM_SPEED;
  } else {
    speed = MIN_SPEED;  // Крутой поворот
  }
  
  float correction = computePID(0, error);
  setMotors(speed + correction, speed - correction);
}

Обнаружение перекрёстков

int lineWidth = countSensorsOnLine();

if (lineWidth >= 6) {
  // Перекрёсток или финиш!
  if (lapCount >= 3) {
    stop();  // Финиш!
  } else {
    // Продолжаем по правилу (например, всегда прямо)
    goStraight();
    lapCount++;
  }
}

Восстановление после схода

unsigned long lastLineTime = 0;

void loop() {
  if (lineDetected()) {
    lastLineTime = millis();
    normalDriving();
  } else {
    // Линия потеряна!
    unsigned long lostTime = millis() - lastLineTime;
    
    if (lostTime < 200) {
      // Недавно потеряли — продолжаем в том же направлении
      continueLastDirection();
    } else if (lostTime < 1000) {
      // Давно потеряли — ищем
      searchPattern();  // Спираль или зигзаг
    } else {
      // Совсем потерялись — стоп
      stop();
    }
  }
}

Стратегии для Сумо

Базовая тактика

enum State { SEARCH, ATTACK, ESCAPE };
State state = SEARCH;

void loop() {
  bool enemyDetected = (frontDistance < 50);
  bool onEdge = (floorSensor == WHITE);
  
  switch (state) {
    case SEARCH:
      // Крутимся, ищем соперника
      spin();
      if (enemyDetected) state = ATTACK;
      if (onEdge) state = ESCAPE;
      break;
      
    case ATTACK:
      // Таран!
      fullSpeedForward();
      if (!enemyDetected) state = SEARCH;
      if (onEdge) state = ESCAPE;
      break;
      
    case ESCAPE:
      // Отъезжаем от края
      reverse();
      delay(200);
      turn180();
      state = SEARCH;
      break;
  }
}

Продвинутые приёмы

1. ЗАСАДА
   Стоим у края, ждём атаки, уворачиваемся
   → Соперник вылетает за ринг!

2. КЛЕЩИ  
   Заезжаем сбоку, толкаем под углом
   → Соперник не может упереться

3. ЛИФТ
   Низкий клин под соперника
   → Поднимаем и выталкиваем

4. ЛОЖНОЕ ОТСТУПЛЕНИЕ
   Отъезжаем назад
   → Соперник разгоняется
   → Уворачиваемся, он вылетает!

День соревнований

За день до

□ Полностью заряди все батареи
□ Проверь запасные части
□ Распечатай регламент
□ Подготовь инструменты (отвёртки, изолента)
□ Сделай backup кода
□ Выспись!

На площадке

□ Осмотри трассу/ринг
□ Проверь освещение (влияет на датчики!)
□ Откалибруй на РЕАЛЬНОЙ поверхности
□ Сделай тестовый заезд
□ Запомни особенности трассы
□ Познакомься с соперниками 🤝

Между заездами

□ Анализируй: что пошло не так?
□ Меняй ОДНУ переменную за раз
□ Записывай настройки
□ Следи за зарядом батареи
□ Не паникуй!

Частые ошибки

ОшибкаКак избежать
Сели батареиЗапасной комплект!
Отвалился проводПайка + термоклей
Не та программаПодписывай профили
Датчик ослеп от светаЭкран или юбка
Перегрев моторовПаузы между заездами

Документация и анализ

Журнал настроек

Заезд 1: Kp=1.5, Ki=0, Kd=0.3
         Время: 12.4с, сход на повороте 3
         
Заезд 2: Kp=1.2, Ki=0, Kd=0.5
         Время: 13.1с, без сходов
         
Заезд 3: Kp=1.2, Ki=0.05, Kd=0.5
         Время: 11.8с, без сходов ← ЛУЧШИЙ!

Видеоанализ

1. Снимай КАЖДЫЙ заезд
2. Смотри в замедленном режиме
3. Отмечай:
   - Где теряет скорость?
   - Где колеблется?
   - Где сходит?
4. Сравнивай с победителями

Post-mortem после соревнований

ЧТО СРАБОТАЛО:
+ Калибровка перед каждым заездом
+ Запасная батарея
+ Низкий центр тяжести

ЧТО НЕ СРАБОТАЛО:
- Датчики слепли от прожекторов
- PID не успевал на резких поворотах
- Провода мешали

ПЛАН НА СЛЕДУЮЩИЙ РАЗ:
□ Добавить экран над датчиками
□ Увеличить частоту loop до 200 Hz
□ Переделать проводку

Ресурсы

Где участвовать?

  • FIRST Robotics — международные соревнования
  • World Robot Olympiad (WRO) — олимпиада
  • РобоФест — Россия
  • Локальные хакатоны — ищи в своём городе!

Где тренироваться?

  • Строй трассу дома (изолента на полу)
  • Симуляторы (Wokwi, Webots)
  • Найди команду/клуб

🎉 Level 2 Пройден!

Ты освоил:

  • ✅ Робот по линии с PID
  • ✅ Продвинутый объезд препятствий
  • ✅ Подготовку к соревнованиям

Что дальше?

Level 3 — Инженер ждёт тебя:

  • Кинематика манипуляторов
  • Sensor Fusion и фильтр Калмана
  • SLAM и автономная навигация
  • ROS 2 — промышленный стандарт

Перейти к Level 3 →

Удачи на соревнованиях! 🏆🤖