|
|
ПО для тестовых заездов практически готово (в питоне почти 1000 строк  ) Вот начало (нотация и настроечные параметры): (Оффтоп)
Код: #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Боевой робот (Orange Pi 5, RK3588): - детекция соперника YOLOv8s RKNN (NPU, core_mask=0_1_2) в отдельном потоке - конвейер: инференс (NPU) и постобработка (CPU) в разных потоках - быстрая постобработка: фильтрация по class-уверенности ДО DFL-декодирования, кеш сеток - трекинг цели фильтром Калмана (скорость + ускорение, упреждение задержки), сброс трека на устаревших результатах детекции и при смене переворота - автопереключение основной камеры 31 -> резервной 22 при деградации потока - управление двумя мотор-редукторами по CAN (дифференциальный разворот) - MPU6050 (DMP, библиотека mpu6050): детект переворота «на спину» с нормализацией картинки и моторов (робот функционально симметричный); поток неубиваем — исключения печатаются один раз, работа продолжается - MPU6050 (DMP): трекинг курса (yaw) — счёт сектора при поиске цели - при потере цели — вращение на месте; направление выбирается по тому, куда ушла цель: сначала по скорости цели (быстрый пролёт), затем по знаку последней ошибки (уход за край кадра), иначе случайно - TEST_STEER: тестовый цикл команд моторам без детекции (проверка направлений и страгивания на стенде) - SHOW_WINDOW: окно отладки на стенде; False — headless-режим боя (рендер отключён, метрики раз в секунду уходят в консоль) """
import os import time import queue import threading import random import traceback
import cv2 import numpy as np import can
try: from mpu6050 import MPU6050 except ImportError: MPU6050 = None # робот продолжит работать без контроля переворота
# ================= НАСТРОЙКИ =================
PRIMARY_CAM = 31 # основная камера BACKUP_CAM = 22 # резервная FRAME_W, FRAME_H = 640, 480
MODEL_NAME = "yolov8s.rknn" NET_SIZE = 640 OBJ_THRESH = 0.40 # 0.25 цеплялся за шум на тёмной арене NMS_THRESH = 0.25
# классы COCO, считаем их «соперником» TARGET_CLASSES = {1, 2, 3, 4, 5, 6, 7, 8, 28, 65, 67}
COCO = ( "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush", )
# --- здоровье камеры --- CONSEC_FAIL_LIMIT = 5 # подряд неуспешных чтений кадра FROZEN_LIMIT = 45 # кадров, идентичных предыдущему (~1.5 c при 30 fps) DARK_MEAN = 8.0 # средняя яркость ниже — «объектив закрыт» BRIGHT_MEAN = 248.0 # выше — «пересвет/пелена» BAD_STREAK = 15 # сколько кадров подряд держится чёрное/белое WARMUP_AFTER_SWITCH = 1.5 # сек после переключения здоровье не проверяем
# --- трекер (фильтр Калмана, постоянное ускорение) --- GATE_BASE = 120.0 # базовый радиус ассоциации, px GATE_SPEED = 15.0 # +px радиуса на каждый px/кадр скорости TRACK_MAX_MISSES = 0.6 # сек без детекции до сброса MAX_ACCEL = 3000.0 # ограничение ускорения, px/с² (защита от выбросов) SIZE_EMA = 0.5 # сглаживание размера рамки RESULT_MAX_AGE = 0.5 # сек: результат детекции старше — не используется
# --- управление --- ACTUATION_DELAY = 0.10 # сек: кадр -> команда на моторы. Подобрать на стенде! STEER_SIGN = 1 # робот крутится не в ту сторону -> поставьте -1 KP = 15.0 / 320.0 # скорость на пиксель ошибки DEADBAND_PX = 30 # зона нечувствительности по центру кадра MAX_TURN_SPEED = 15 # максимальная скорость вращения BASE_SPEED = 0 # ход вперёд при захваченной цели по центру (0 = стоять)
# --- поиск потерянной цели (вращение на месте) --- SEARCH_SPIN_SPEED = 25 # выше страгивания редуктора; проверить на стенде SEARCH_DELAY = 0.2 # сек тишины после последнего захвата до старта спина SEARCH_MAX_SWEEP = 360.0 # градусов на один заход; пройдено — меняем направление VX_DIR_MIN = 400.0 # px/с: цель двигалась быстрее — направление по её vx ERR_DIR_MIN_PX = 200.0 # px: цель была дальше от центра — направление по err
CAN_CHANNEL = "can0" CAN_BITRATE = 1_000_000 MOTOR_IDS = (0x141, 0x142)
# --- MPU6050 / контроль переворота (как в рабочем примере) --- I2C_BUS = 5 # из рабочего примера MPU_ADDR = 0x68 FREQ_DIVIDER = 0x14 # DMP выдаёт ~9.5 Гц — согласовано с IMU_RATE, # FIFO не переполняется, NPU не теряет fps MPU_ADDR = 0x68 CALIB_SECONDS = 1.0 # сколько секунд копим эталон гравитации на старте IMU_RATE = 0.105 # период опроса ~10 Гц, чуть больше периода выдачи пакетов GRAV_EMA = 0.15 # сглаживание вектора гравитации от DMP COS_FLIP = -0.50 # переворот засчитывается с наклона ~120° COS_RESTORE = +0.50 # вернулся на колёса с наклона ~60° (гистерезис) FLIP_DEBOUNCE = 3 # подряд отсчётов: 3 × 0.105 ≈ 0.3 с подтверждения
# --- MPU6050 / трекинг курса (yaw) --- YAW_SIGN = 1 # измерение сектора в обратную сторону -> -1
# --- отладка/стенд --- TEST_STEER = False # True — цикл команд моторам без детекции (стенд) SHOW_WINDOW = True # True — окно для стенда; False — headless-бой LOG_INTERVAL = 1.0 # период консольного лога метрик в headless, сек
железо - отдельный головняк - уже три конструктива перепробовали, всё что-то не то - то вес, то защита, то оружие.. Сейчас вроде остановились на одном варианте, - усиленно макет клепаем.. Посещали отборочные - один день были из 4-х. Остальное смотрели в он-лайн репортажах. Ну что сказать, - автономок было с десяток в обеих категориях. И бОльшая часть плохо себя показали - половина вообще просто со старта не поехали  Познакомились с некоторыми командами с автономками, поняли некоторые их ошибки, по которым постараемся научиться... 
|
|