Pet Monitor con Raspberry Pi 5 & Hailo-8 (AI HAT+) Sistema de monitorización inteligente para mascotas utilizando aceleración por hardware NPU (chip Hailo-8) para visión por computador y detección de audio local en CPU para ladridos/sonidos anómalos. --- 1. Hardware Utilizado Placa: Raspberry Pi 5. Coprocesador IA: Raspberry Pi AI HAT (Hailo-8, 26 TOPS). Cámara: cámara IP TP-Link Tapo accesible por RTSP en la red local. Entrada de audio: Micrófono USB (pendiente de conectar). > **Corrección respecto a la primera versión de este documento:** el módulo instalado identifica como Hailo-8, no Hailo-8L. Verificado con `hailortcli fw-control identify`: > ``` > Board Name: Hailo-8 > Device Architecture: HAILO8 > Firmware Version: 4.23.0 > ``` > Por eso el modelo cargado es `yolov8s_h8.hef` (el de 8 carriles de cómputo de la NPU), no la variante `_h8l`. --- 2. Configuración del Sistema y Hardware Habilitar PCIe Gen 3 Para maximizar el ancho de banda con el chip Hailo, se configuró el bus PCIe en `/boot/firmware/config.txt`: ```ini dtparam=pciex1 dtparam=pciex1_gen=3 ``` Paquetes del Sistema Instalados Se instalaron las utilidades de cámara, controladores del kernel y librerías dinámicas de audio requeridas por el sistema operativo: ```bash sudo apt update && sudo apt full-upgrade -y sudo apt install -y hailo-all rpicam-apps libportaudio2 portaudio19-dev libasound2-dev python3-picamera2 ``` Verificación de hardware NPU Hailo: `lspci` muestra el coprocesador Hailo Technologies y `hailortcli fw-control identify` responde con el firmware cargado. Cámara: `ffprobe -rtsp_transport tcp rtsp://usuario:clave@IP:554/stream2` debe describir un stream H.264. --- 3. Cámara IP Tapo (RTSP) La cámara Tapo **no expone RTSP con la cuenta de TP-Link**: hay que crear una cuenta local de cámara en la app Tapo (Ajustes de la cámara → Configuración avanzada → Cuenta de cámara). El usuario y la contraseña de esa cuenta son los que van en el `.env`. Streams disponibles (verificados con `ffprobe`): - `stream1`: 2304x1296 @ 15 fps (máxima calidad) - `stream2`: 1280x720 @ 15 fps (el que usa el monitor: menos CPU de decodificación) - `stream3`: no existe en este modelo (devuelve 404) El vídeo va por H.264, así que la decodificación es por software (la Pi 5 solo acelera HEVC por hardware). A 720p el coste es asumible; con `stream1` sube bastante sin mejorar la detección, porque el modelo trabaja a 640x640 en cualquier caso. Credenciales en `~/pet_monitor/.env` (no se versiona): ``` CAMERA_IP=192.168.178.234 CAMERA_USER=camera_dog CAMERA_PW=... # Opcionales: # CAMERA_STREAM=stream2 # stream1 | stream2 # CAMERA_RTSP_URL=rtsp://... # URL completa; tiene prioridad sobre lo anterior ``` --- 4. Entorno de Desarrollo Python (`uv`) Se configuró el entorno virtual utilizando `uv` con acceso a los paquetes del sistema (`--system-site-packages`) para reutilizar los bindings compilados de `picamera2`, `hailo_platform` y `OpenCV` instalados por Debian/Raspberry Pi OS: ```bash cd ~/pet_monitor # Creación del entorno con acceso a librerías nativas uv venv --system-site-packages # Instalación de librerías en el entorno virtual uv pip install sounddevice numpy scipy requests onnxruntime ``` > **Nota técnica:** Se seleccionó `onnxruntime` en lugar de `tflite-runtime` para garantizar compatibilidad con versiones modernas de Python en ARM64 sin necesidad de compilar desde fuente. > **Nota:** `uv` vive en `~/.local/bin/uv` y no está en el PATH de sesiones SSH no interactivas; usa `bash -lc 'uv run ...'` o `~/.local/bin/uv run ...`. --- 5. Estado Actual del Software `pet_speed.py`: Script de visión artificial optimizado con aceleración por hardware que: - Lee el vídeo de la cámara Tapo por **RTSP en un hilo aparte** (`RtspVideoStream`), que se queda siempre con el fotograma más reciente y descarta los antiguos. Así no se acumula latencia si el análisis va más lento que la cámara. - Se **reconecta automáticamente** con retroceso exponencial (2 s → 30 s) si la cámara se cae, se reinicia o cambia de IP. - Escala el fotograma con **letterbox** (mantiene la relación de aspecto, relleno gris) hasta los 640x640 que espera el modelo, y deshace esa transformación para dar las cajas y el centroide en píxeles del fotograma original. - Utiliza la API nativa de aceleración `picamera2.devices.hailo.Hailo` (parte del paquete del sistema, no requiere la cámara CSI) cargando el modelo optimizado (`/usr/share/hailo-models/yolov8s_h8.hef`). - Filtra detecciones del conjunto COCO para gato (id: 15) y perro (id: 16). - Calcula el centroide del animal y evalúa el desplazamiento entre fotogramas consecutivos para alertar si la velocidad supera el umbral de carrera (`SPEED_THRESHOLD = 0.30` por segundo). - Imprime estadísticas cada 10 s (fps de captura, fps de análisis, latencia de inferencia, reconexiones). - Libera el stream RTSP y el acelerador Hailo al recibir `SIGINT` (`Ctrl+C`) o `SIGTERM`, de cara a ejecutarlo como servicio systemd. Rendimiento medido en la Pi 5 con `stream2`: ``` [STATS] captura 14.7 fps | análisis 12-15 fps | inferencia 11.8 ms | reconexiones 0 ``` Nota sobre el orden de color: los HEF de YOLOv8 esperan **RGB**, y así se alimenta al modelo. Comprobado con imágenes de prueba: con un perro la confianza pasa de 0.42 (BGR) a 0.85 (RGB), y con un gato de 0.79 a 0.87. Si algún día hiciera falta comparar, `PET_COLOR_ORDER=bgr uv run pet_speed.py`. Ejecución: ```bash uv run pet_speed.py ``` --- 6. Próximos Pasos (Hoja de Ruta) Fase A: Integración de Audio (Ladridos y Sonidos) Conectar el micrófono USB. Identificar el índice del dispositivo con: ```bash uv run python -m sounddevice ``` Descargar el modelo YAMNet en formato ONNX (`yamnet.onnx`) y el diccionario de clases de AudioSet (`yamnet_classes.csv`). Desarrollar el listener en un hilo secundario (`threading.Thread`) analizando fragmentos de audio de 0.975 segundos en busca de la clase `Bark`. Fase B: Sistema de Alertas y Notificaciones Crear un bot en Telegram con `@BotFather` y obtener el `TELEGRAM_BOT_TOKEN` y `CHAT_ID`. Programar un despachador asíncrono con control de enfriamiento (cooldown de 30-60 s) para evitar spam. Guardar una captura JPEG con la caja delimitadora en el momento de la carrera o ladrido y enviarla a Telegram (las cajas ya se calculan en píxeles del fotograma original, solo falta dibujarlas y guardarlas). Fase C: Despliegue Autónomo (Systemd) Crear una unidad de servicio `/etc/systemd/system/pet_monitor.service`. Habilitar arranque automático al encender la Raspberry Pi: ```bash sudo systemctl enable --now pet_monitor.service ```