💻 Взаимодействие роботов: от алгоритмов к коду

Урок 27 | Проектная деятельность в робототехнике

🎯 Миссия: Вдохнуть разум в роботов-партнеров

💻 Сегодня мы превращаем железо в интеллект:

От механических конструкций к мыслящим системам — процесс программирования, где:

  • 🧠 Роботы получают способность принимать решения
  • 🤝 Создаются алгоритмы кооперации и координации
  • 📡 Реализуется “цифровая телепатия” между машинами
  • 🎯 Формируется коллективный интеллект команды роботов

📋 Архитектура программирования сегодня:

  1. Модульное проектирование — разделяй и властвуй
  2. Базовые функции роботов — фундамент поведения
  3. Системы коммуникации — язык машин
  4. Алгоритмы координации — коллективная мудрость
  5. Интеграция и отладка — доведение до совершенства

🧠 Философия программирования роботов-команд

🏗️ Принцип “Модульности как основы жизни”

🤖 Робот = Набор взаимодействующих модулей

Аналогия с биологией:

  • Клетки → Модули кода
  • Органы → Функциональные системы
  • Организм → Полноценный робот
  • Экосистема → Команда роботов

🧮 Математика модульности:

Сложность монолитной системы: $C_{mono} = n^2$

Сложность модульной системы: $C_{mod} = n \log n$

где $n$ — количество функций

Пример: При 16 функциях:

  • Монолитная система: $16^2 = 256$ связей
  • Модульная система: $16 \log_2 16 = 64$ связи

Выигрыш в 4 раза!

🎭 Роли модулей в робототехнической “труппе”

🎪 Театр робототехники:

🎭 Актер (Модуль)🎬 Роль📝 Сценарий (Функции)
🚗 LocomotionДвижениеmove(), turn(), stop()
👁️ PerceptionВосприятиеscan(), detect(), measure()
🤖 ActionДействиеgrab(), manipulate(), release()
📡 CommunicationОбщениеsend(), receive(), broadcast()
🧠 CoordinationКоординацияplan(), synchronize(), resolve()
🎛️ ControlУправлениеinitialize(), monitor(), shutdown()

🚗 Модуль движения: Анатомия робо-локомоции

⚙️ Базовая архитектура движения

class LocomotionModule {
private:
    Motor leftMotor;
    Motor rightMotor;
    Encoder leftEncoder;
    Encoder rightEncoder;
    IMU orientationSensor;
    
    float currentSpeed = 0;
    float currentDirection = 0;
    Position currentPosition;
    
public:
    // Базовые функции движения
    void moveForward(float speed, float distance = 0);
    void moveBackward(float speed, float distance = 0);
    void turnLeft(float angle);
    void turnRight(float angle);
    void stop();
    
    // Продвинутые функции
    void moveToPosition(Position target);
    void followPath(Path trajectory);
    void maintainFormation(Robot* neighbors[], int count);
    
    // Сенсорные функции
    Position getCurrentPosition();
    float getCurrentSpeed();
    float getCurrentDirection();
};

🧮 Математика точного движения

Дифференциальное управление (танковый тип):

$$v_{robot} = \frac{v_{left} + v_{right}}{2}$$$$\omega_{robot} = \frac{v_{right} - v_{left}}{L}$$

где:

  • $v_{robot}$ — скорость робота
  • $\omega_{robot}$ — угловая скорость
  • $L$ — расстояние между колесами

Управление по траектории:

void moveToPosition(float targetX, float targetY) {
    // Вычисляем расстояние и угол к цели
    float dx = targetX - currentPosition.x;
    float dy = targetY - currentPosition.y;
    float distance = sqrt(dx*dx + dy*dy);
    float targetAngle = atan2(dy, dx) * 180.0 / PI;
    
    // Поворачиваемся к цели
    float angleError = targetAngle - currentPosition.angle;
    while (abs(angleError) > 180) {
        angleError += (angleError > 0) ? -360 : 360;
    }
    
    if (abs(angleError) > 5) {  // Допуск 5 градусов
        if (angleError > 0) {
            turnLeft(abs(angleError));
        } else {
            turnRight(abs(angleError));
        }
    }
    
    // Движемся к цели
    moveForward(CRUISE_SPEED, distance);
}

🎯 Система координат и навигация

Глобальная система координат:

struct Position {
    float x, y;      // Координаты в метрах
    float angle;     // Ориентация в градусах
    
    float distanceTo(Position other) {
        float dx = x - other.x;
        float dy = y - other.y;
        return sqrt(dx*dx + dy*dy);
    }
    
    float angleTo(Position other) {
        float dx = other.x - x;
        float dy = other.y - y;
        return atan2(dy, dx) * 180.0 / PI;
    }
};

class NavigationSystem {
private:
    Position home = {0, 0, 0};
    Position current = {0, 0, 0};
    
public:
    void updatePosition() {
        // Одометрия по энкодерам
        float leftDistance = leftEncoder.getDistance();
        float rightDistance = rightEncoder.getDistance();
        
        float deltaDistance = (leftDistance + rightDistance) / 2.0;
        float deltaAngle = (rightDistance - leftDistance) / WHEEL_BASE;
        
        current.x += deltaDistance * cos(current.angle * PI / 180.0);
        current.y += deltaDistance * sin(current.angle * PI / 180.0);
        current.angle += deltaAngle * 180.0 / PI;
        
        // Нормализация угла
        while (current.angle > 180) current.angle -= 360;
        while (current.angle < -180) current.angle += 360;
    }
};

👁️ Модуль восприятия: Цифровые органы чувств

🔍 Архитектура сенсорной системы

class PerceptionModule {
private:
    UltrasonicSensor frontSensor;
    UltrasonicSensor leftSensor;
    UltrasonicSensor rightSensor;
    Camera visionSystem;
    IMU inertialSensor;
    
    struct SensorData {
        float distances[3];  // front, left, right
        bool obstacleDetected;
        float brightness;
        int objectsDetected;
        float acceleration[3];
        unsigned long timestamp;
    };
    
    SensorData currentData;
    
public:
    void updateSensors();
    bool isPathClear(float direction, float distance);
    Position findNearestObstacle();
    Robot* detectNearbyRobots();
    bool recognizeObject(ObjectType type);
};

📊 Алгоритмы обработки сенсорных данных

Фильтрация шумов (медианный фильтр):

class SensorFilter {
private:
    static const int FILTER_SIZE = 5;
    float buffer[FILTER_SIZE];
    int index = 0;
    bool filled = false;
    
public:
    float filter(float newValue) {
        buffer[index] = newValue;
        index = (index + 1) % FILTER_SIZE;
        if (index == 0) filled = true;
        
        if (!filled) return newValue;
        
        // Медианная фильтрация
        float sorted[FILTER_SIZE];
        memcpy(sorted, buffer, sizeof(buffer));
        
        // Простая сортировка
        for (int i = 0; i < FILTER_SIZE-1; i++) {
            for (int j = i+1; j < FILTER_SIZE; j++) {
                if (sorted[i] > sorted[j]) {
                    float temp = sorted[i];
                    sorted[i] = sorted[j];
                    sorted[j] = temp;
                }
            }
        }
        
        return sorted[FILTER_SIZE/2];  // Медиана
    }
};

🎯 Детекция и трекинг объектов

Алгоритм поиска роботов-партнеров:

Robot* PerceptionModule::detectNearbyRobots() {
    static Robot detectedRobots[MAX_ROBOTS];
    int robotCount = 0;
    
    // Сканируем 360 градусов
    for (int angle = 0; angle < 360; angle += 30) {
        // Поворачиваем сенсор (если есть сервопривод)
        sensorServo.write(angle);
        delay(100);  // Время стабилизации
        
        float distance = frontSensor.getDistance();
        
        // Проверяем, подходит ли расстояние для робота
        if (distance > 10 && distance < 200) {  // 10см - 2м
            // Отправляем ping другому роботу
            communication.sendPing(angle);
            
            // Ждем ответ
            if (communication.waitForResponse(1000)) {  // 1 сек таймаут
                Robot newRobot;
                newRobot.distance = distance;
                newRobot.angle = angle;
                newRobot.id = communication.getLastResponderId();
                
                detectedRobots[robotCount++] = newRobot;
                
                if (robotCount >= MAX_ROBOTS) break;
            }
        }
    }
    
    // Возвращаем сенсор в исходное положение
    sensorServo.write(90);
    
    return (robotCount > 0) ? detectedRobots : nullptr;
}

📡 Система коммуникации: Цифровая телепатия

🌐 Протокол межроботного взаимодействия

// Определение типов сообщений
enum MessageType {
    PING = 0x01,           // Проверка связи
    PONG = 0x02,           // Ответ на ping
    COMMAND = 0x10,        // Команда выполнения
    DATA = 0x20,           // Передача данных
    STATUS = 0x30,         // Статус робота
    ERROR = 0x40,          // Сообщение об ошибке
    SYNC = 0x50,           // Синхронизация времени
    ACK = 0x60             // Подтверждение получения
};

// Структура сообщения (32 байта)
struct RobotMessage {
    uint8_t startByte = 0xAA;     // Маркер начала
    uint8_t senderID;             // ID отправителя
    uint8_t receiverID;           // ID получателя  
    uint8_t messageType;          // Тип сообщения
    uint16_t sequenceNumber;      // Номер последовательности
    uint16_t payloadLength;       // Длина полезной нагрузки
    uint8_t payload[20];          // Полезная нагрузка
    uint16_t checksum;            // Контрольная сумма
    uint8_t endByte = 0x55;       // Маркер конца
};

🔐 Надежная передача данных

Алгоритм с подтверждением доставки:

class ReliableCommunication {
private:
    static const int MAX_RETRIES = 3;
    static const int ACK_TIMEOUT = 1000; // миллисекунды
    uint16_t lastSequenceNumber = 0;
    
public:
    bool sendMessageReliable(uint8_t receiverID, MessageType type, 
                           uint8_t* data, uint8_t dataLength) {
        
        RobotMessage msg;
        msg.senderID = MY_ROBOT_ID;
        msg.receiverID = receiverID;
        msg.messageType = type;
        msg.sequenceNumber = ++lastSequenceNumber;
        msg.payloadLength = dataLength;
        
        if (dataLength <= 20) {
            memcpy(msg.payload, data, dataLength);
        }
        
        msg.checksum = calculateChecksum(msg);
        
        // Попытки отправки с повтором
        for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
            // Отправляем сообщение
            bluetooth.write((uint8_t*)&msg, sizeof(msg));
            
            // Ждем подтверждение
            unsigned long startTime = millis();
            while (millis() - startTime < ACK_TIMEOUT) {
                if (checkForAcknowledgment(msg.sequenceNumber)) {
                    return true;  // Успешно отправлено
                }
                delay(10);
            }
            
            Serial.print("Retry attempt ");
            Serial.println(attempt + 1);
        }
        
        Serial.println("Message delivery failed");
        return false;  // Не удалось отправить
    }
    
private:
    uint16_t calculateChecksum(const RobotMessage& msg) {
        uint16_t sum = 0;
        uint8_t* ptr = (uint8_t*)&msg;
        
        for (int i = 0; i < sizeof(msg) - 2; i++) {  // -2 для самой суммы
            sum += ptr[i];
        }
        
        return sum;
    }
};

📊 Мониторинг качества связи

class LinkQualityMonitor {
private:
    struct LinkStats {
        int messagesSent = 0;
        int messagesReceived = 0;
        int messagesFailed = 0;
        unsigned long totalLatency = 0;
        unsigned long lastActivity = 0;
    };
    
    LinkStats stats[MAX_ROBOTS];
    
public:
    float getPacketLossRate(uint8_t robotID) {
        LinkStats& s = stats[robotID];
        if (s.messagesSent == 0) return 0.0;
        
        return (float)s.messagesFailed / s.messagesSent * 100.0;
    }
    
    float getAverageLatency(uint8_t robotID) {
        LinkStats& s = stats[robotID];
        if (s.messagesReceived == 0) return 0.0;
        
        return (float)s.totalLatency / s.messagesReceived;
    }
    
    bool isLinkAlive(uint8_t robotID) {
        return (millis() - stats[robotID].lastActivity) < 5000; // 5 сек
    }
    
    void printNetworkStatus() {
        Serial.println("=== Network Status ===");
        for (int i = 0; i < MAX_ROBOTS; i++) {
            if (stats[i].messagesSent > 0) {
                Serial.print("Robot ");
                Serial.print(i);
                Serial.print(": Loss=");
                Serial.print(getPacketLossRate(i));
                Serial.print("%, Latency=");
                Serial.print(getAverageLatency(i));
                Serial.print("ms, Alive=");
                Serial.println(isLinkAlive(i) ? "Yes" : "No");
            }
        }
    }
};

🧠 Алгоритмы координации: Коллективный интеллект

🎯 Распределение задач по алгоритму аукциона

class TaskAuctionSystem {
private:
    struct Task {
        int taskID;
        Position location;
        int priority;
        int estimatedTime;
        bool assigned = false;
        uint8_t assignedRobot = 255;
    };
    
    std::vector<Task> taskQueue;
    
public:
    void startAuction(Task newTask) {
        // Добавляем задачу в очередь
        taskQueue.push_back(newTask);
        
        // Запрашиваем ставки от всех роботов
        AuctionMessage auctionMsg;
        auctionMsg.taskID = newTask.taskID;
        auctionMsg.taskX = newTask.location.x;
        auctionMsg.taskY = newTask.location.y;
        auctionMsg.priority = newTask.priority;
        
        // Отправляем всем роботам
        for (int robotID = 1; robotID <= MAX_ROBOTS; robotID++) {
            if (robotID != MY_ROBOT_ID && isRobotOnline(robotID)) {
                communication.sendMessage(robotID, AUCTION_REQUEST, 
                                        (uint8_t*)&auctionMsg, sizeof(auctionMsg));
            }
        }
        
        // Ждем ставки и выбираем лучшую
        collectBidsAndAssign(newTask.taskID);
    }
    
private:
    void collectBidsAndAssign(int taskID) {
        struct Bid {
            uint8_t robotID;
            float cost;  // Меньше = лучше
            bool received = false;
        };
        
        Bid bids[MAX_ROBOTS];
        unsigned long auctionStart = millis();
        const unsigned long AUCTION_TIMEOUT = 3000; // 3 секунды
        
        // Собираем ставки
        while (millis() - auctionStart < AUCTION_TIMEOUT) {
            RobotMessage msg;
            if (communication.receiveMessage(msg) && 
                msg.messageType == AUCTION_BID) {
                
                BidMessage* bid = (BidMessage*)msg.payload;
                if (bid->taskID == taskID) {
                    bids[msg.senderID].robotID = msg.senderID;
                    bids[msg.senderID].cost = bid->bidCost;
                    bids[msg.senderID].received = true;
                    
                    Serial.print("Bid from robot ");
                    Serial.print(msg.senderID);
                    Serial.print(": cost=");
                    Serial.println(bid->bidCost);
                }
            }
            delay(10);
        }
        
        // Выбираем лучшую ставку (минимальная стоимость)
        float bestCost = 99999;
        uint8_t winnerID = 255;
        
        for (int i = 0; i < MAX_ROBOTS; i++) {
            if (bids[i].received && bids[i].cost < bestCost) {
                bestCost = bids[i].cost;
                winnerID = bids[i].robotID;
            }
        }
        
        // Назначаем задачу победителю
        if (winnerID != 255) {
            assignTaskToRobot(taskID, winnerID);
            notifyAuctionResult(taskID, winnerID);
        }
    }
};

🕰️ Синхронизация действий во времени

Протокол синхронизированного старта:

class SynchronizedAction {
private:
    unsigned long synchronizedTime = 0;
    bool timeSynchronized = false;
    
public:
    void scheduleSynchronizedAction(unsigned long delayMs, ActionType action) {
        // Время выполнения = текущее время + задержка
        unsigned long executionTime = getSynchronizedTime() + delayMs;
        
        // Отправляем команду синхронизации всем роботам
        SyncActionMessage syncMsg;
        syncMsg.actionType = action;
        syncMsg.executionTime = executionTime;
        syncMsg.coordinatorID = MY_ROBOT_ID;
        
        broadcast(SYNC_ACTION, (uint8_t*)&syncMsg, sizeof(syncMsg));
        
        // Сами тоже ждем этого времени
        waitUntilTime(executionTime);
        executeAction(action);
    }
    
    void synchronizeTime() {
        if (isCoordinator()) {
            // Координатор рассылает свое время
            SyncTimeMessage timeMsg;
            timeMsg.currentTime = millis();
            timeMsg.coordinatorID = MY_ROBOT_ID;
            
            broadcast(TIME_SYNC, (uint8_t*)&timeMsg, sizeof(timeMsg));
            
            synchronizedTime = timeMsg.currentTime;
            timeSynchronized = true;
        }
    }
    
    void waitUntilTime(unsigned long targetTime) {
        while (getSynchronizedTime() < targetTime) {
            delay(1);
            
            // Обрабатываем входящие сообщения во время ожидания
            processIncomingMessages();
        }
    }
    
    unsigned long getSynchronizedTime() {
        if (!timeSynchronized) return millis();
        
        // Возвращаем локальное время относительно синхронизированной точки
        return synchronizedTime + millis();
    }
};

🚧 Предотвращение столкновений (Алгоритм ORCA)

class CollisionAvoidance {
private:
    struct Velocity {
        float x, y;
        
        Velocity operator+(const Velocity& other) const {
            return {x + other.x, y + other.y};
        }
        
        Velocity operator*(float scalar) const {
            return {x * scalar, y * scalar};
        }
        
        float magnitude() const {
            return sqrt(x*x + y*y);
        }
    };
    
    struct Robot {
        Position position;
        Velocity velocity;
        float radius;
        uint8_t id;
    };
    
    std::vector<Robot> nearbyRobots;
    
public:
    Velocity computeSafeVelocity(Velocity preferredVelocity, Position myPosition, 
                                float myRadius, float maxSpeed) {
        
        // Если нет соседей, движемся с предпочтительной скоростью
        if (nearbyRobots.empty()) {
            return preferredVelocity;
        }
        
        std::vector<Velocity> candidateVelocities;
        
        // Генерируем кандидатов скоростей
        for (float angle = 0; angle < 2*PI; angle += PI/8) {
            for (float speed = 0; speed <= maxSpeed; speed += maxSpeed/5) {
                Velocity candidate = {
                    speed * cos(angle),
                    speed * sin(angle)
                };
                
                if (isVelocitySafe(candidate, myPosition, myRadius)) {
                    candidateVelocities.push_back(candidate);
                }
            }
        }
        
        // Выбираем ближайшую к предпочтительной скорости
        Velocity bestVelocity = {0, 0};
        float minDifference = 99999;
        
        for (const auto& candidate : candidateVelocities) {
            float diff = sqrt(pow(candidate.x - preferredVelocity.x, 2) + 
                             pow(candidate.y - preferredVelocity.y, 2));
            
            if (diff < minDifference) {
                minDifference = diff;
                bestVelocity = candidate;
            }
        }
        
        return bestVelocity;
    }
    
private:
    bool isVelocitySafe(Velocity velocity, Position myPosition, float myRadius) {
        const float TIME_HORIZON = 3.0; // секунды в будущее
        
        for (const auto& robot : nearbyRobots) {
            // Предсказываем позиции через TIME_HORIZON секунд
            Position myFuturePos = {
                myPosition.x + velocity.x * TIME_HORIZON,
                myPosition.y + velocity.y * TIME_HORIZON,
                myPosition.angle
            };
            
            Position robotFuturePos = {
                robot.position.x + robot.velocity.x * TIME_HORIZON,
                robot.position.y + robot.velocity.y * TIME_HORIZON,
                robot.position.angle
            };
            
            // Проверяем расстояние между предсказанными позициями
            float futureDistance = myFuturePos.distanceTo(robotFuturePos);
            float minSafeDistance = myRadius + robot.radius + 0.2; // +20см запас
            
            if (futureDistance < minSafeDistance) {
                return false;  // Небезопасная скорость
            }
        }
        
        return true;  // Безопасная скорость
    }
};

🔧 Интеграция и отладка: Доведение до совершенства

🧪 Стратегии пошагового тестирования

class SystemTester {
private:
    enum TestLevel {
        UNIT_TEST,        // Тестирование отдельных функций
        MODULE_TEST,      // Тестирование модулей
        INTEGRATION_TEST, // Тестирование взаимодействия модулей
        SYSTEM_TEST       // Тестирование всей системы
    };
    
public:
    bool runAllTests() {
        Serial.println("=== Starting System Tests ===");
        
        // Уровень 1: Тестирование базовых функций
        if (!runUnitTests()) {
            Serial.println("FAIL: Unit tests failed");
            return false;
        }
        
        // Уровень 2: Тестирование модулей
        if (!runModuleTests()) {
            Serial.println("FAIL: Module tests failed");
            return false;
        }
        
        // Уровень 3: Тестирование интеграции
        if (!runIntegrationTests()) {
            Serial.println("FAIL: Integration tests failed");
            return false;
        }
        
        // Уровень 4: Системное тестирование
        if (!runSystemTests()) {
            Serial.println("FAIL: System tests failed");
            return false;
        }
        
        Serial.println("SUCCESS: All tests passed!");
        return true;
    }
    
private:
    bool runUnitTests() {
        Serial.println("Running unit tests...");
        
        // Тест движения
        TEST_ASSERT(testMovementFunctions(), "Movement functions");
        
        // Тест сенсоров
        TEST_ASSERT(testSensorFunctions(), "Sensor functions");
        
        // Тест коммуникации
        TEST_ASSERT(testCommunicationFunctions(), "Communication functions");
        
        return true;
    }
    
    bool testMovementFunctions() {
        // Тест базового движения
        locomotion.moveForward(50, 100); // 50% скорость, 100мм
        delay(2000);
        
        Position newPos = navigation.getCurrentPosition();
        float distance = abs(newPos.distanceTo(Position{0, 0, 0}));
        
        return (distance > 80 && distance < 120); // Допуск ±20мм
    }
    
    bool testSensorFunctions() {
        // Тест ультразвукового датчика
        float distance1 = perception.frontSensor.getDistance();
        delay(100);
        float distance2 = perception.frontSensor.getDistance();
        
        // Проверяем стабильность показаний
        return (abs(distance1 - distance2) < 5); // Допуск 5мм
    }
    
    bool testCommunicationFunctions() {
        // Тест отправки/получения сообщения
        uint8_t testData[] = {0x12, 0x34, 0x56, 0x78};
        
        bool sent = communication.sendMessage(BROADCAST_ID, DATA, 
                                            testData, sizeof(testData));
        
        // Для самотестирования отправляем себе
        return sent;
    }
};

// Макрос для упрощения тестирования
#define TEST_ASSERT(condition, name) \
    if (!(condition)) { \
        Serial.print("FAIL: "); \
        Serial.println(name); \
        return false; \
    } else { \
        Serial.print("PASS: "); \
        Serial.println(name); \
    }

🐛 Система отладки в реальном времени

class DebugSystem {
private:
    struct DebugMessage {
        unsigned long timestamp;
        uint8_t level;  // INFO=0, WARNING=1, ERROR=2, CRITICAL=3
        char message[100];
    };
    
    DebugMessage debugBuffer[50];
    int bufferIndex = 0;
    bool bufferFull = false;
    
public:
    void log(uint8_t level, const char* format, ...) {
        va_list args;
        va_start(args, format);
        
        DebugMessage& msg = debugBuffer[bufferIndex];
        msg.timestamp = millis();
        msg.level = level;
        vsnprintf(msg.message, sizeof(msg.message), format, args);
        
        // Вывод в Serial
        const char* levelNames[] = {"INFO", "WARN", "ERR", "CRIT"};
        Serial.print("[");
        Serial.print(msg.timestamp);
        Serial.print("] ");
        Serial.print(levelNames[level]);
        Serial.print(": ");
        Serial.println(msg.message);
        
        // Сохранение в буфер
        bufferIndex = (bufferIndex + 1) % 50;
        if (bufferIndex == 0) bufferFull = true;
        
        va_end(args);
    }
    
    void printDebugHistory() {
        Serial.println("=== Debug History ===");
        
        int start = bufferFull ? bufferIndex : 0;
        int count = bufferFull ? 50 : bufferIndex;
        
        for (int i = 0; i < count; i++) {
            int idx = (start + i) % 50;
            DebugMessage& msg = debugBuffer[idx];
            
            Serial.print("[");
            Serial.print(msg.timestamp);
            Serial.print("] ");
            Serial.println(msg.message);
        }
    }
    
    void monitorPerformance() {
        static unsigned long lastCheck = 0;
        static int lastLoopCount = 0;
        static int currentLoopCount = 0;
        
        currentLoopCount++;
        
        if (millis() - lastCheck >= 1000) { // Каждую секунду
            int loopsPerSecond = currentLoopCount - lastLoopCount;
            
            log(INFO, "Performance: %d loops/sec, Free RAM: %d bytes",
                loopsPerSecond, getFreeRAM());
            
            if (loopsPerSecond < 50) {
                log(WARNING, "Low performance detected!");
            }
            
            lastCheck = millis();
            lastLoopCount = currentLoopCount;
        }
    }
    
private:
    int getFreeRAM() {
        extern int __heap_start, *__brkval;
        int v;
        return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval);
    }
};

// Глобальная система отладки
DebugSystem debug;

// Удобные макросы
#define DEBUG_INFO(fmt, ...) debug.log(0, fmt, ##__VA_ARGS__)
#define DEBUG_WARNING(fmt, ...) debug.log(1, fmt, ##__VA_ARGS__)
#define DEBUG_ERROR(fmt, ...) debug.log(2, fmt, ##__VA_ARGS__)
#define DEBUG_CRITICAL(fmt, ...) debug.log(3, fmt, ##__VA_ARGS__)

📊 Мониторинг системы и диагностика

class SystemMonitor {
private:
    struct SystemStats {
        unsigned long uptime;
        float cpuUsage;
        int freeMemory;
        float batteryVoltage;
        int messagesPerSecond;
        int errorsCount;
        
        struct ModuleStatus {
            bool locomotion;
            bool perception;
            bool communication;
            bool coordination;
        } modules;
    };
    
    SystemStats currentStats;
    
public:
    void updateStats() {
        currentStats.uptime = millis();
        currentStats.freeMemory = getFreeRAM();
        currentStats.batteryVoltage = readBatteryVoltage();
        currentStats.cpuUsage = calculateCPUUsage();
        
        // Проверяем статус модулей
        currentStats.modules.locomotion = testLocomotionModule();
        currentStats.modules.perception = testPerceptionModule();
        currentStats.modules.communication = testCommunicationModule();
        currentStats.modules.coordination = testCoordinationModule();
    }
    
    void printSystemStatus() {
        Serial.println("=== System Status ===");
        Serial.print("Uptime: ");
        Serial.print(currentStats.uptime / 1000);
        Serial.println(" seconds");
        
        Serial.print("Free RAM: ");
        Serial.print(currentStats.freeMemory);
        Serial.println(" bytes");
        
        Serial.print("Battery: ");
        Serial.print(currentStats.batteryVoltage);
        Serial.println(" V");
        
        Serial.print("CPU Usage: ");
        Serial.print(currentStats.cpuUsage);
        Serial.println("%");
        
        Serial.println("Module Status:");
        Serial.print("  Locomotion: ");
        Serial.println(currentStats.modules.locomotion ? "OK" : "FAIL");
        Serial.print("  Perception: ");
        Serial.println(currentStats.modules.perception ? "OK" : "FAIL");
        Serial.print("  Communication: ");
        Serial.println(currentStats.modules.communication ? "OK" : "FAIL");
        Serial.print("  Coordination: ");
        Serial.println(currentStats.modules.coordination ? "OK" : "FAIL");
    }
    
    bool isSystemHealthy() {
        return (currentStats.batteryVoltage > 6.5 &&  // Минимальное напряжение
                currentStats.freeMemory > 500 &&       // Минимум свободной памяти
                currentStats.modules.locomotion &&     // Все модули работают
                currentStats.modules.perception &&
                currentStats.modules.communication);
    }
    
private:
    float readBatteryVoltage() {
        int rawValue = analogRead(BATTERY_PIN);
        return rawValue * (5.0 / 1023.0) * VOLTAGE_DIVIDER_RATIO;
    }
    
    float calculateCPUUsage() {
        static unsigned long lastMeasure = 0;
        static unsigned long lastIdle = 0;
        
        unsigned long currentTime = millis();
        unsigned long idleTime = getIdleTime(); // Функция подсчета простоя
        
        if (lastMeasure != 0) {
            unsigned long timeDiff = currentTime - lastMeasure;
            unsigned long idleDiff = idleTime - lastIdle;
            
            return (1.0 - (float)idleDiff / timeDiff) * 100.0;
        }
        
        lastMeasure = currentTime;
        lastIdle = idleTime;
        return 0.0;
    }
};

🎭 Демонстрация результатов: Роботы в действии

🏆 Формат технической демонстрации

Структура презентации (4-5 мин на команду):

🧠 “Архитектура нашего решения” (90 сек)

  • Покажите схему модульной архитектуры
  • Объясните принципы взаимодействия модулей
  • Продемонстрируйте протокол коммуникации
  • Расскажите об алгоритмах координации

🤖 “Живая демонстрация” (120 сек)

  • Запустите роботов в действии
  • Покажите выполнение совместной задачи
  • Продемонстрируйте реакцию на изменения среды
  • Объясните принятие решений в реальном времени

📊 “Метрики и анализ” (60 сек)

  • Показатели производительности системы
  • Статистика коммуникации между роботами
  • Эффективность выполнения задач
  • Сравнение с плановыми показателями

📋 Критерии технической оценки

КритерийМаксимумЧто оценивается
Модульность кода5Структурированность, читаемость, документирование
Функциональность5Выполнение всех заявленных функций
Коммуникация5Надежность, эффективность протокола обмена
Координация5Качество алгоритмов совместной работы
Отладка и тестирование3Полнота тестирования, обработка ошибок

Итого: 23 балла максимум

🔍 Техническое интервью с командами

Вопросы экспертов:

Архитектурные решения:

  • Почему выбрали именно такую модульную структуру?
  • Как обеспечиваете независимость модулей?
  • Какие паттерны проектирования применили?

Алгоритмические решения:

  • Как роботы принимают решения в спорных ситуациях?
  • Что происходит при потере связи между роботами?
  • Как оптимизировали производительность алгоритмов?

Технические детали:

  • Какие самые сложные баги пришлось исправлять?
  • Как тестировали надежность коммуникации?
  • Какие метрики используете для мониторинга производительности?

💡 Peer Code Review: Взаимная оценка кода

Методология “Код-детектив”:

🔍 Анализируемые аспекты:

  1. Читаемость — легко ли понять логику?
  2. Эффективность — оптимально ли используются ресурсы?
  3. Надежность — есть ли обработка ошибок?
  4. Масштабируемость — легко ли добавить новые функции?

📝 Формат обратной связи:

КОМАНДА: _________ РЕВЬЮЕР: _________

СИЛЬНЫЕ СТОРОНЫ:
✓ ________________________________
✓ ________________________________

ОБЛАСТИ ДЛЯ УЛУЧШЕНИЯ:
△ ________________________________
△ ________________________________

ВОПРОСЫ К КОДУ:
? ________________________________
? ________________________________

ОБЩАЯ ОЦЕНКА: ___/10

🧠 Рефлексия: Путь от кода к мудрости

💻 Анализ программистского опыта

Метод “Программный отчет”:

✅ Что удалось реализовать блестяще?

  • Какие алгоритмы работают идеально?
  • Где проявились ваши сильные стороны как программистов?
  • Какие технические решения оказались самыми эффективными?

🐛 Какие проблемы обнаружили?

  • Где код не соответствует ожиданиям?
  • Какие алгоритмические сложности выявились?
  • Что оказалось труднее программировать, чем планировали?

🔄 Планы по улучшению?

  • Какие оптимизации необходимо внести?
  • Как повысить надежность системы?
  • Какие новые возможности можно добавить?

📈 Самооценка программистских компетенций

НавыкДо проектаПосле урокаПрогресс
Модульное программирование__/10__/10+__
Алгоритмы координации__/10__/10+__
Сетевое программирование__/10__/10+__
Отладка и тестирование__/10__/10+__
Системное мышление__/10__/10+__
Коллективная разработка__/10__/10+__

Общий прогресс: +___/60

🎯 Планирование программистского развития

Краткосрочные цели (следующая неделя):

  • Оптимизировать узкие места в коде
  • Добавить дополнительную отладочную информацию
  • Улучшить обработку ошибок коммуникации
  • Протестировать систему в экстремальных условиях

Среднесрочные цели (следующий месяц):

  • Изучить продвинутые алгоритмы роевого интеллекта
  • Освоить профессиональные инструменты отладки
  • Внедрить машинное обучение в алгоритмы координации
  • Создать систему автоматического тестирования

Долгосрочные цели (полгода-год):

  • Участие в соревнованиях по робототехнике
  • Изучение промышленных стандартов разработки
  • Создание собственной библиотеки для роботов
  • Подготовка к профильным олимпиадам и конкурсам

🎯 Домашнее задание: Код-совершенство

📋 Обязательная часть: Рефакторинг и документирование

Техническая документация кода:

Формат: Подробное техническое описание (4-5 страниц)

Содержание:

  1. Архитектурная диаграмма — схема модулей и их взаимосвязей
  2. API-документация — описание всех функций и их параметров
  3. Протокол коммуникации — формат сообщений и их обработка
  4. Алгоритмы координации — логика принятия решений
  5. Результаты тестирования — метрики производительности
  6. Руководство по отладке — как искать и исправлять ошибки

Требования к коду:

  • Все функции должны иметь комментарии
  • Переменные должны иметь понятные имена
  • Код должен быть отформатирован по стандарту
  • Добавить обработку критических ошибок

🌟 Творческая часть: Эволюция алгоритмов

Задача: Усовершенствовать один из алгоритмов

Направления развития:

  1. Адаптивная координация — роботы учатся на опыте
  2. Предсказательное планирование — учет будущих состояний
  3. Fuzzy Logic — нечеткая логика для принятия решений
  4. Swarm Intelligence — алгоритмы роевого интеллекта
  5. Machine Learning — обучение на основе данных

Формат: Описание улучшений + рабочий код + тестирование

📚 Подготовка к финальной демонстрации

Командные задания:

Software Team Lead:

  • Провести финальное code review всего проекта
  • Подготовить техническую презентацию архитектуры
  • Создать демонстрационные сценарии для роботов

Algorithm Specialist:

  • Оптимизировать критические алгоритмы
  • Подготовить анализ эффективности решений
  • Разработать план стресс-тестирования

Communication Expert:

  • Проверить надежность всех протоколов связи
  • Подготовить статистику качества коммуникации
  • Создать систему мониторинга сети роботов

QA Engineer:

  • Провести полное тестирование системы
  • Подготовить отчет о найденных проблемах
  • Создать план демонстрации для презентации

🌟 Заключение: Код как искусство коллективного разума

💭 Главное достижение урока:

“Сегодня вы создали не просто программы — вы создали цифровой симбиоз, где роботы думают, общаются и действуют как единый организм”

🎯 Программистские навыки, которые мы освоили:

  • Системное мышление — видение архитектуры как целостности
  • Алгоритмическое мастерство — создание эффективных решений
  • Коммуникационное программирование — языки машин
  • Отладочные техники — поиск истины в коде

🚀 Готовность к финалу:

  • Программы написаны и оттестированы
  • Алгоритмы координации работают безупречно
  • Системы коммуникации обеспечивают надежную связь
  • Команды роботов готовы к финальной демонстрации

🤖 Следующий шаг — показать миру, как роботы могут работать в команде!