TFG · Ingeniería de Telecomunicaciones · UC3M

Diario de tareas

Registro cronológico del trabajo realizado en el desarrollo del sistema de búsqueda y rescate basado en UAV.

SISTEMA OPERATIVO · ÚLT. ACTUALIZACIÓN: 7 SEP 2026
49Registros
58Días documentados
5Repos en GitHub
16Hitos alcanzados
Situación actual · 7 sep 2026

Dónde está el proyecto ahora

Con la entrega de la memoria del TFG el 7 de septiembre, el proyecto queda cerrado y validado de extremo a extremo. Guardian Eye es ya un dron autónomo de búsqueda y rescate, construido y probado en vuelo real, con toda la cadena funcionando junta: percepción visual a bordo, arquitectura IoT en la nube y teleoperación remota.

El dron detecta personas desde el aire con un modelo propio (YOLO11), entrenado sobre un dataset aéreo construido desde cero y ejecutado a bordo sobre el acelerador Hailo-8L, prácticamente en tiempo real. La telemetría se reparte en cuatro dominios independientes (ambiental, sistema, vuelo y detección) con almacenamiento local store-and-forward, y viaja por MQTT hasta un servidor en AWS (InfluxDB y Grafana) sin perder un dato ante cortes de red. Las comunicaciones combinan mando RC directo, telemetría SiK de 433 MHz, enlace 4G/LTE y una VPN en malla con Tailscale, sobre la que se teleopera el dron desde un panel web (PWA) —armado, despegue, misión y vídeo en directo— a través de una cadena de mando API REST → MQTT → MAVLink.

La validación siguió una estrategia escalonada: simulación SITL, banco de integración con la Pixhawk y, por último, un vuelo real en el club Alas de Galapagar, donde el sistema detectó a las personas presentes desde el aire. El detector es una prueba de concepto, con recorrido de mejora por delante, pero el trabajo demuestra que es viable integrar inferencia edge acelerada, comunicaciones de largo alcance y una arquitectura IoT distribuida en una única plataforma de vuelo.

Filtrar por área

Julio 2026

Hasta 11 julio Memoria Hardware Sistema
  • Índice de contenidos de la memoria planteado.
  • Lectura e investigación sobre la normativa. Certificado A1/A3 de AESA y número de operador obtenidos.
  • Investigación sobre dónde volar el dron y cómo pedir permisos: consulta a clubes de aeromodelismo (Majadahonda y Alas de Galapagar) por sus condiciones. Inscripción como socia en Alas de Galapagar, ya que no requiere pedir permisos a AESA y ofrece un lugar seguro y cómodo para volar cuando quiera.
  • Compra de la Raspberry Pi 5 y del primer sensor, el BME680 20,85 € — sensor ambiental que mide temperatura, humedad relativa, presión barométrica y resistencia de gas.
    • Conexión sensor – Raspberry configurada.
  • Instancia EC2 configurada en AWS ~4 $/mes (24 h):
    • AMI Ubuntu sobre t3.small.
    • Grupos de seguridad creados: puerto 1883 para la comunicación MQTT con el broker Mosquitto, puerto 22 para SSH y puerto 8086 para el acceso a la base de datos InfluxDB.
    • Instalación del servicio broker Mosquitto en la EC2 para la comunicación con el sensor.
    • Creación de IP elástica (sin ella la IP pública de la EC2 cambiaba al reiniciarse, obligando a modificar los scripts, peticiones HTTP…).
  • Publicación de datos (del sensor a la EC2):
    • La Raspberry Pi actúa como cliente publicador y en el servidor un segundo cliente actúa como suscriptor, recibiendo los mensajes y publicándolos en InfluxDB. Scripts creados: sensor.py en la Pi y mqtt_to_influx.py en la EC2.
    • Implementación de la arquitectura store-and-forward en sensor.py para que ningún dato se pierda ante una caída temporal de la conexión (cada lectura se almacena primero en una base de datos local SQLite, buffer.db).
  • Recepción y almacenamiento en el servidor:
    • mqtt_to_influx.py actúa como cliente suscriptor; se ejecuta en la EC2 dentro de un entorno virtual propio (env) con las librerías paho-mqtt (comunicación con el broker) e influxdb-client (escritura en la base de datos).
    • Cada lectura recibida se almacena en InfluxDB.
  • Almacenamiento en InfluxDB:
    • Abierta una entrada en el grupo de seguridad para el puerto 8086, de forma que se pueda acceder desde el navegador mediante la dirección pública de la EC2.
  • Configuración de servicios systemctl de Linux en la Pi y en el servidor, para que inicien sus procesos automáticamente en cada arranque sin intervención manual.
  • Publicación de los scripts en GitHub. Cada repo incluye README (documentación de uso), .gitignore (evita subir archivos sensibles o innecesarios), requirements.txt (dependencias reproducibles) y .env.example (plantilla de credenciales, que se mantienen fuera del repositorio).
  • Compra del dominio gorostiditfg.com en Cloudflare 10,41 $, para acceder a los servicios mediante subdominios legibles en vez de la IP del servidor.
  • Creación de dos páginas (HTML + CSS sencillo) que usaré más adelante: una para la presentación del proyecto y otra para el control del dron.
11 julio Sistema Vuelo
  • Creación de servidores web:
    • Instalación del servidor web nginx y aprendizaje de la configuración de varios servidores virtuales web en la misma máquina.
    • Alta en el servidor DNS de Cloudflare de los nombres de host necesarios (ya puedo acceder a las páginas creadas con el dominio): www.gorostiditfg.com y control.gorostiditfg.com.
    • Configuración de nginx como reverse proxy para acceder a la interfaz de InfluxDB igual que a las demás webs: como usa el puerto 8086 en la petición HTTP, había que indicarlo y ya no es necesario especificarlo → influxdb.gorostiditfg.com.
  • Gestión de claves públicas / privadas:
    • Limpieza y ordenación de las claves públicas/privadas, que estaban mezcladas. Configuración del fichero .ssh en la EC2 para permitir el acceso con mi clave pública en lugar del .pem (habilitando esta otra forma editando el .ssh).
  • Mission Planner:
    • Configuración del simulador de vuelo Mission Planner. Vuelos de prueba en dos zonas distintas.
    • Desarrollo de un script en Python (con pymavlink) que se conecta al simulador vía MAVLink para enviar comandos de vuelo: armado/desarmado, despegue y modo AUTO para ejecutar misiones por waypoints. La conexión se establece mediante reenvío UDP de Mission Planner al puerto local 14550.
12 julio Vuelo ★ Primer vuelo real
  • Visita al club de Galapagar: recogida del carnet de socia y las llaves de acceso, y presentación con el presidente.
  • Contactos en el club:
    • Presidente: Darco.
    • Primer vuelo acompañada por José Manuel.
    • Contacto por correo: Paco (Francisco). También me presentan a otro socio con un DJI (me enseña su maletín) y a alguien con mucho conocimiento sobre baterías.
  • Me muestran en Mission Planner la zona por la que debo volar, y por qué aparece marcada en amarillo.
  • Primer vuelo real de un dron: uso de la cuenta de mi padre (instalación y configuración de la app DJI en mi móvil).
  • Me recomiendan comprar mejores adaptadores/cables para el dron (uno de carga más rápida).
  • Grabación de vídeos con el DJI en el primer vuelo. Los datos deberían quedar almacenados.
  • Importante: pegar en el dron mi número de operador.
13 julio Memoria Vuelo Sistema
  • Investigación sobre la posibilidad de volar el dron en Comillas (Cantabria), con vistas a realizar un vuelo allí este fin de semana: consulta de la normativa y de las restricciones de la zona.
  • Configuración del dron en su aplicación y colocación física de mi propio número de operador sobre el dron, según exige la normativa.
  • Actualización y mejora de la página web del proyecto para dejarla presentable de cara al tutor.
    • Creación de la página del diario de tareas y de la página de operador.
    • Generación de un código QR que enlaza con la página de operador, para pegarlo en el dron: al escanearlo muestra los datos del operador.
  • Subida de los logs del primer vuelo a Airdata y a PhantomHelp Log Viewer para revisar y analizar los datos del vuelo.
  • Eliminación del puerto 8086 del grupo de seguridad de la EC2, ya innecesario: el acceso a la interfaz de InfluxDB se realiza ahora a través de nginx configurado como reverse proxy (influxdb.gorostiditfg.com), sin exponer el puerto directamente a internet.
  • Comunicación al tutor del avance del proyecto, compartiéndole la web para que pueda hacer el seguimiento del progreso a través del diario de tareas.
14 julio Vuelo Sistema
  • He retomado el control del dron simulado desde Python (Mission Planner + ArduPilot SITL): Había un problema del armado (los pre-arm checks y el GPS del simulador) y he conseguido que vuelva a funcionar. He comprobado que efectivamente funcione el ciclo completo —armado, despegue y misión por waypoints en modo AUTO—, viendo el dron moverse en Mission Planner.
  • Pasar el control de vuelo a la Raspberry Pi, para que las órdenes salgan del nodo edge y no del PC:
    • Configuración de la conexión por red entre la Pi y Mission Planner, usando las IP reales de cada máquina en lugar de 127.0.0.1, el reenvío UDP y el puerto 14550.
    • Entender la lógica de quién envía y quién escucha (udpin/udpout) y por qué en MAVLink la Pi escucha mientras recibe la telemetría del autopiloto.
    • Conseguir que la Pi de órdenes al dron simulado por MAVLink a través de la red, validando así la arquitectura edge-first.
15 julio Sistema ★ Control web completo
  • Implementación del control del dron por MQTT, montando el patrón publicador–receptor:
    • Creación de un publicador (comandos.py, en el EC2) que envía las órdenes por MQTT, y de un receptor (receptor.py, en la Pi) que las traduce a MAVLink y las ejecuta sobre el dron simulado.
    • He empezado por argumentos como armar/desarmar para comprobar que funcione y después he añadido más: despegue, aterrizaje, RTL (volver a casa), mantener posición e iniciar misión.
  • Conversión del publicador en una API REST con Flask (api.py, en el EC2) para poder invocar los comandos por HTTP en lugar de por terminal, y para ello se ha abierto el puerto 5000 en el grupo de seguridad de AWS.
  • Modificación de la página de control web añadiendo botones para cada comando, que llama a esa API: control.gorostiditfg.com
16 julio Sistema
  • Repaso conceptual a fondo de la API REST (api.py) para entender no solo qué hace, sino por qué existe y qué papel tiene dentro de la arquitectura. Se ha revisado la cadena completa de comunicación: navegador (HTTP) → api.py en el EC2, que traduce HTTP a MQTT → broker Mosquitto (puerto 1883) → receptor.py en la Raspberry Pi, que traduce MQTT a MAVLink → autopiloto → dron.
    • El HTTP aparece únicamente porque el emisor es el navegador, que solo habla ese protocolo.
    • api.py y receptor.py no están conectados directamente: se comunican a través del broker, gracias al modelo publicador/suscriptor desacoplado de MQTT.
    • comandos.py y api.py son alternativas paralelas para enviar los mismos comandos, no pasos consecutivos.
    • El formato JSON solo se usa en los tramos HTTP y MQTT; el tramo MAVLink es binario, por ser un enlace de telemetría con ancho de banda limitado.
    • Los puertos son por servicio: Flask en el 5000 y Mosquitto en el 1883. receptor.py no abre ningún puerto porque actúa como cliente, no como servidor.
  • Comprobación de que la página de control con botones funciona correctamente y envía las señales al simulador.
  • Error «puerto 5000 en uso» al relanzar la API: se debía a un proceso zombi que quedó vivo tras un Ctrl+C incompleto. Resuelto con pkill -f api.py.
  • A raíz de esto se ha decidido convertir api.py y receptor.py en servicios systemd, igual que ya lo están mqtt_to_influx.py y sensor.py, para que arranquen solos y no dependan de una terminal abierta. PENDIENTE
  • Creación de clave SSL para proteger con HTTPS todas las páginas creadas, lo que ha implicado abrir también el puerto 443 en el grupo de seguridad del servidor.
  • Al pasar las páginas a HTTPS, la API ha dejado de funcionar. El diagnóstico es un bloqueo de contenido mixto: el navegador impide que una página servida por HTTPS haga peticiones a un recurso HTTP.
    • Solución planteada: crear el subdominio api.gorostiditfg.com en Cloudflare en modo Proxied, configurar nginx como reverse proxy hacia localhost:5000 y actualizar la URL del fetch en el JavaScript del panel. PENDIENTE
  • Nota: la API sigue sin autenticación, decisión deliberada mientras se trabaja en simulación. Habrá que añadirla antes de conectarla al hardware real.
17 julio Hardware Sistema
  • Actualización del repositorio del servidor en GitHub, dividiéndolo en carpetas (www/web/, control/ y api-rest/) e incluyendo las páginas HTML, que hasta ahora solo existían en el servidor.
  • Al ir a actualizar el repositorio de la Pi, se ha detectado que no se puede acceder a ella por SSH. La tarjeta microSD se ha estropeado, probablemente por cortar la corriente bruscamente en lugar de hacer un sudo poweroff. Se ha intentado volver a cargar la imagen de Raspberry Pi OS en la tarjeta y no es capaz de leerla.
  • Lección aprendida: apagar siempre la Pi con sudo poweroff y mantener todo actualizado en GitHub, para no perder los códigos ni el trabajo hecho hasta el momento.
20 julio Hardware
  • Sustitución de la tarjeta microSD de la Raspberry Pi, repitiendo todo el proceso con la nueva SD:
    • Grabación de la imagen del sistema operativo y configuración inicial de la Raspberry (acceso por SSH, red, habilitación del bus I2C).
    • Clonado del repositorio desde GitHub y recuperación del entorno de trabajo.
    • Reescritura de receptor.py, único script que no estaba subido al repositorio y que se perdió con la tarjeta.
  • Actualización del README y publicación de los cambios en GitHub.
21 julio Memoria Sistema
  • Revisión de todo lo realizado hasta el momento y comienzo de la redacción en la memoria del TFG de la arquitectura diseñada: capítulo 5, apartado 5.4 (Arquitectura IoT con AWS EC2 y Mosquitto):
    • Infraestructura de la instancia EC2.
    • Sensor BME680.
    • Flujo de datos con arquitectura store-and-forward.
    • Almacenamiento en InfluxDB.
    • Ejecución autónoma mediante systemd.
  • Revisión del estado de los certificados TLS de los subdominios para identificar cuáles quedaban pendientes de configurar.
  • Resuelto el problema de mixed content: creado el subdominio api.gorostiditfg.com, configurado nginx como reverse proxy hacia localhost:5000, emitido el certificado TLS y actualizada la URL del fetch en el panel de control.
  • Eliminada la regla del puerto 5000 del grupo de seguridad de la instancia, ya innecesaria al accederse a la API a través del reverse proxy de nginx.
22 julio Sistema Memoria
  • Creación de los servicios systemd para receptor.py en la Raspberry Pi y para api.py en la instancia EC2, de forma que ambos arranquen automáticamente y se reinicien ante cualquier interrupción, sin depender de una sesión SSH abierta.
  • Continuación de la redacción del capítulo 5 de la memoria: infraestructura de servicios web y control remoto, y simulación SITL con ArduPilot.
  • Instalación y prueba de Claude Code, para desarrollar una interfaz web más completa y con mayor número de funcionalidades.
27 julio Memoria
  • Reorganización estructural de la memoria: división del antiguo capítulo 5 en capítulo 5 (control de vuelo y telemetría: MAVLink, GCS, pymavlink, SITL, FPV) y capítulo 6 (arquitectura IoT: EC2, BME680, MQTT, servicios web).
  • Reconstrucción del capítulo 2 (estado del arte):
    • 2.1 UAV en SAR · 2.2 Comunicaciones más allá de la línea de visión (BVLOS) · 2.3 Detección de personas con YOLO.
    • Reubicación del contenido mal colocado: comparativa de chasis → 4.2.1; fusión IMU/GPS/Kalman → 4.2.2; justificación de MQTT/EC2 → 6.3; detalles de FPV → 5.5.
28 julio Memoria
  • Redacción del capítulo 3 (normativa), secciones 3.1–3.4 y 3.6: Reglamento (UE) 2019/947, categoría abierta A3, Remote ID obligatorio desde enero de 2026, RD 517/2024, sentencia del TS de junio de 2025, doble registro (operador AESA + aeronave) y Ley 11/2022.
  • Mensaje al tutor (Dani) para preguntar por la posible financiación de la universidad para los materiales del dron. PENDIENTE de respuesta
29 julio Memoria
  • Revisión de la arquitectura del sistema de cara al capítulo 4 (apartado 4.1): repaso del diseño extremo a extremo y preparación del esquema de arquitectura (queda a medias, se continuará).
  • Construcción de la bibliografía en formato IEEE, según la guía de la biblioteca de la UC3M, para los capítulos ya redactados (normativa y estado del arte).
30 julio IA
  • Primer contacto con Roboflow de cara a construir el dataset y entrenar YOLOv8 para el Hailo-8L: investigación, tutoriales y pruebas de anotación para entender cómo funciona, ver la división de los datos y qué es la augmentation.

Agosto 2026

5 agosto Hardware
  • Un socio del club de Galapagar me presta un hexacóptero de fibra de carbono para reutilizar piezas.
  • Análisis de las piezas del dron prestado:
    • Reutilizables: chasis de fibra de carbono, 6 motores T-Motor MN3110-780KV, ESCs, hélices de carbono, tren de aterrizaje, receptor FlySky FS-iA10B y conectores.
    • No reutilizables: controladora DJI NAZA-M Lite (propietaria, incompatible con ArduPilot/MAVLink), GPS DJI, cadena FPV analógica y PDB (sin confirmar).
  • Comparativa de opciones de compra:
    • Plan A (reutilizar piezas): ~545–550 € en componentes nuevos.
    • Plan B (kit nuevo Holybro X500 v2 con Pixhawk 6X): ~943 € y agotado. Se opta por el Plan A.
  • Elaboración de la lista de compra de componentes nuevos: Pixhawk 6C + PM02, GPS Holybro M10, radio de telemetría 433 MHz, batería LiPo 6S, cargador iMAX B6AC, emisora FlySky FS-i6X y consumibles de montaje.
    • La Raspberry Pi 5 + Hailo requiere un UBEC dedicado de ≥5 A (el BEC del PDB no basta).
  • Al estar el kit agotado, llamada a RC-Innovations; me indican mandar un correo para reservar el kit, que tendrán disponible la próxima semana.
6 agosto Hardware IA ★ Primer modelo YOLO
  • Envío del correo a RC-Innovations pidiendo disponibilidad y presupuesto de los componentes.
  • Primera práctica completa con Roboflow para entender de primera mano cómo funciona la herramienta y el flujo de trabajo de un detector YOLO de principio a fin, sobre un caso de prueba sencillo (detección de frutas):
    • Preparación del entorno de trabajo en local (Python, VS Code y Claude Code) y comprobación de que todo ejecuta correctamente.
    • Partiendo de un dataset público de Roboflow Universe, he añadido fotos propias y las he etiquetado a mano (bounding boxes) para personalizar el conjunto.
    • Aplicación del preprocesado y el augmentation, y generación de la versión final del dataset.
    • Descarga del dataset y entrenamiento de un modelo YOLO en local con Ultralytics, obteniendo el modelo entrenado (best.pt).
  • Con esto he cubierto todo el proceso hasta obtener el modelo. El siguiente paso es probar el modelo entrenado sobre vídeo (inferencia), para ver las detecciones en imágenes en movimiento y comprobar si detecta correctamente cada fruta.
7 agosto IA
  • Partiendo del modelo entrenado el día anterior, he profundizado en el ajuste del entrenamiento probando distintos números de épocas:
    • Primera prueba con 15 épocas: insuficiente.
    • Ampliación a 80 épocas con parada temprana (patience=20); la métrica de validación se estabiliza en torno a la época 40, por lo que ese número resulta suficiente para la convergencia.
  • He medido el coste real del entrenamiento en local: ha tardado 2 h 40 min ejecutándose sobre CPU, a pesar de tratarse de un modelo ligero y un dataset pequeño (~300 imágenes con aumentación). Este dato es una referencia clave de cara al proyecto: al ser el dataset real de personas mucho mayor y más complejo, su entrenamiento tendrá que realizarse en la nube.
  • He realizado la inferencia sobre vídeo que quedaba pendiente, guardando el resultado anotado en output.mp4. La he probado tanto con un vídeo grabado con el móvil como con uno grabado desde el dron.
  • Revisión de resultados: analizando las curvas de aprendizaje y la matriz de confusión he visto que el modelo confunde con cierta frecuencia manzana y pera, por tratarse de clases visualmente parecidas y un dataset reducido.
  • Publicación de todo el código en un repositorio de GitHub, con su README documentando el flujo, los parámetros de entrenamiento e inferencia y las limitaciones observadas: github.com/nereagorostidi/yolo-pipeline-test
8 agosto Hardware Memoria ★ Kit reservado
  • Recepción de la respuesta de RC-Innovations por correo con el presupuesto total. Contestación confirmando la reserva del kit para poder recibirlo cuanto antes.
  • Redacción de la memoria, centrada en el cierre de los capítulos 1, 2, 3, y 6.
9 agosto Vuelo IA ★ Primeras grabaciones del dataset
  • He hecho un par de vuelos en el club de aeromodelismo (por la mañana) para empezar a construir mi dataset de detección de personas: grabación de vídeos con el dron sobre mis padres.
  • Procesado del material: extracción de frames de los vídeos y selección de 35 imágenes distintas para el dataset.
10 agosto Sistema
  • Me he centrado en la arquitectura, en cómo estructurar la adquisición de datos del nodo edge. La primera idea que planteo es un proceso único con un scheduler cooperativo por reloj: un solo hilo que en cada vuelta mira qué colector toca según su intervalo, con todos escribiendo en una única base SQLite compartida.
  • Al analizarlo veo que esta opción tiene riesgo de bloqueos y concurrencia sobre la base compartida, y que un fallo en un colector perjudica al resto. He optado por un proceso independiente por dominio (ambiental, sistema, vuelo y detección), cada uno con su propia base SQLite. Con eso elimino los bloqueos, gano resiliencia (si uno cae, los demás siguen) y me queda un sistema mucho más fácil de mantener y ampliar.
    • Topics MQTT jerárquicos (sar/{dron_id}/{dominio}) y client_id como {dron_id}-{dominio} para que Mosquitto no tire conexiones por IDs duplicados.
    • Lectura del dron_id desde un .env compartido.
    • Buffers store-and-forward con QoS 1 para no perder ni un dato si se cae la red.
    • Comunicación directa entre vuelo.py y deteccion.py mediante escrituras atómicas en posicion_actual.json.
11 agosto Sistema IA Memoria ★ Arquitectura de datos implementada
  • Paso el diseño a código y desarrollo los cuatro colectores:
    • ambiental.py para leer los datos del sensor BME680.
    • sistema.py para monitorizar las métricas y el estado de la Raspberry Pi.
    • vuelo.py de forma provisional con telemetría simulada (a la espera de integrar la Pixhawk).
    • deteccion.py integrando YOLO, afinando parámetros como flags explícitos (--mqtt y --preview), un --anti-spam por defecto a 5 s y haciendo que cada proceso infiera automáticamente su base de datos según el dominio, sin configuraciones extra.
  • Actualizo el bridge MQTT en el servidor:
    • Uso un receptor universal suscrito a sar/#: así identifica automáticamente de qué sensor viene el dato leyendo el topic y simplifica la estructura del JSON para que la base de datos lo trague sin procesado extra.
  • Monto el modo fake para agilizar pruebas:
    • Configuro mi propio ordenador como dron-02 para levantar y validar todo el flujo de datos en local con simulación, para no tener que depender de la Pi y su conexión por SSH en cada prueba.
  • Documentación:
    • Documentación de lo configurado para tener toda la arquitectura y las decisiones de diseño en un documento, con diagramas explicativos para repasar.
12 agosto Sistema IA
  • Prueba de la detección de personas sobre vídeo real::
    • Ejecuto deteccion.py con YOLO sobre un vídeo real, corriéndolo en mi propia máquina
    • Al detectar una persona, salta una alerta por MQTT en sar/{dron_id}/deteccion (con buffer store-and-forward), que incluye la caja en píxeles, la posición del dron y la foto.
    • La foto se guarda con overlay de coordenadas (posición del dron) y fecha/hora, y las alertas llevan un throttling anti-spam (5 s) para no saturar el topic con la misma persona.
  • Fallo en el armado desde el panel web:
    • La función de armado deja de responder de repente, así que me pongo a depurar qué está fallando en la comunicación entre la web y la API.
  • Identificación de los dos problemas principales:
    • Bloqueo por Mixed Content: el panel carga bajo HTTPS, pero el API_BASE del index.html seguía apuntando por HTTP directamente a la IP pública de la instancia EC2. Como el navegador bloquea las llamadas HTTP inseguras, cambio la URL para que apunte a https://api.gorostiditfg.com.
    • Pérdida del identificador del dron: al cambiar de dron en la interfaz, la web no incluye el drone_id en el cuerpo de la petición. La API asigna por defecto dron-01, pero como el receptor está escuchando en dron-02, el comando se pierde y nunca llega a ejecutarse.
  • Solución e integración:
    • Añado un desplegable de selección de dron (dron-01 / dron-02) en el panel de control.
    • Modifico la función enviar() para que capture el valor seleccionado y lo adjunte en cada petición a la API.
    • Con esto el flujo queda resuelto: el desplegable define en qué topic publica la API y, siempre que el receptor esté escuchando en ese mismo dron, los comandos entran sin problema.
13 agosto Vuelo Memoria ★ Landing page publicada
  • Depuración del enlace con Mission Planner: aunque la parte web ya está resuelta, el dron sigue sin armar debido a un conflicto de puertos:
    • receptor.py falla al arrancar con WinError 10013 porque Mission Planner tiene ocupado el puerto 14550. Cambio la conexión a MAVLINK_CONN = "udpin:127.0.0.1:14551".
    • Aun así, el script se queda bloqueado esperando en wait_heartbeat() porque el reenvío UDP de Mission Planner sigue apuntando al puerto antiguo. Entro al menú avanzado de Mission Planner (Ctrl + F) y redirijo el forward UDP a 127.0.0.1:14551.
    • En cuanto entran los heartbeats por el nuevo puerto, el receptor se suscribe correctamente y el dron vuelve a armar de extremo a extremo sin problemas.
  • Creación de la landing page para pedir colaboración en el proyecto: ayuda en la compra de materiales o patrocinio, y también de personas que puedan mandarme vídeos que aporten valor a mi dataset de detección de personas: drone-sar.gorostiditfg.com
14 agosto Sistema
  • Doy por terminada la landing de micromecenazgo (drone-sar.gorostiditfg.com): repaso de los textos finales, la sección de colaboración con los dos tipos de ayuda (vídeos aéreos y patrocinio), y añadido del journal. Publicada y operativa.
  • Empiezo a montar la estructura de la web técnica del proyecto (Guardian Eye), la página donde desarrollaré todo el proyecto a fondo: una documentación navegable, dividida en secciones, que recogerá el sistema completo de extremo a extremo.
    • Parte de proyecto: introducción, objetivos, metodología, filosofía y normativa.
    • Parte de arquitectura: comunicaciones, hardware y software/cloud.
    • Parte de exploración: inteligencia artificial, multimedia, impacto y colaboradores.
  • Publicación en YouTube del vídeo del primer test de detección de personas.
  • Repaso a fondo del perfil de GitHub: descripciones cortas para los seis repos con el patrón TFG ·, definición de topics y creación del README del perfil con badges.
15 agosto Sistema ★ Web técnica publicada
  • Continúo con la web técnica y la dejo bastante cerrada, aunque todavía me queda algún detalle por pulir. Desarrollo el contenido de las secciones principales:
    • Arquitectura: comunicaciones (con la redundancia multicanal), hardware y software/cloud.
    • Inteligencia artificial: sistema de detección.
    • Páginas de proyecto.
  • Dejo la web técnica enlazada con la landing, los repos de GitHub y el journal.
  • Repaso a fondo del perfil de GitHub: descripciones cortas para los seis repos con el patrón TFG ·, definición de topics y creación del README del perfil con badges.
16 agosto Memoria Sistema
  • Repaso de la página web del proyecto, con modificación de alguna sección.
  • Reorganización de la estructura de la memoria para reflejar la arquitectura IoT multidominio. Decisión principal: partir el antiguo capítulo 6 en dos:
    • Cap. 6 → adquisición de datos IoT (edge a nube, los cuatro dominios, store-and-forward, InfluxDB).
    • Cap. 7 → servicios web y control remoto (DNS, nginx, TLS, API REST, cadena de mando).
  • El capítulo 5 se queda con el control de vuelo local (MAVLink, GCS, pymavlink, SITL); la detección (YOLO/Hailo) pasa al capítulo 8 y la validación al capítulo 9.
  • Añado figuras nuevas para que quede más claro: 6.2 (arquitectura multidominio), 6.3 (store-and-forward genérico), 5.3 (secuencia de misión autónoma), 7.5 (cadena de mando completa) y 4.1 (arquitectura general del sistema).
  • Compra de tarjeta SIM prepago 10 €.
17 agosto Sistema ★ VPN en malla y enlace 4G
  • Repaso de la memoria.
  • Levanto una VPN en malla (mesh) con Tailscale para conectar de forma segura los tres equipos (servidor AWS, Raspberry y mi PC). Funciona como red Zero Trust: cada equipo recibe su propia IP dentro de la red y todos se comunican de forma cifrada de extremo a extremo, sin abrir puertos al exterior.
    • Dejo Tailscale en el autoarranque de la máquina de AWS y de la Raspberry, para que se unan solas a la malla al encenderse.
    • Configuro el módem USB 4G/LTE: la Raspberry lo reconoce como interfaz de red, pero no sale a Internet hasta crear un perfil APN de DIGI (SIM de prepago DIGI).
    • Desactivo el PIN de la SIM para que el módem arranque solo, sin meterlo a mano.
    • Reviso las tablas de rutas de la Raspberry: por defecto todo el tráfico sale por 4G/LTE, y la Wi-Fi solo entra si se retira el pincho USB (a mano o por script) o para conectarme a un equipo de la misma red local.
  • Mejora futura: un script en Python que vigile la cobertura 4G y desactive esa ruta si se cae. PENDIENTE
18 agosto Sistema Memoria ★ Multi-dron verificado
  • Sigo avanzando con la página web de Guardian Eye.
  • Clono de nuevo el repositorio de edge companion directamente en la Raspberry Pi, ya que últimamente lo estaba probando en local desde mi máquina. Tras el clonado compruebo que todo funciona correctamente.
  • Añado al requirements.txt las dependencias necesarias para dejar el entorno completo.
  • Verifico la ingesta de datos con varios drones: ejecuto sistema.py por separado en mi equipo y en la Pi, y confirmo que ambos flujos llegan bien a la base de datos, uno identificado como dron-01 y otro como dron-02.
  • Cambio el nombre del bucket de InfluxDB, que al principio se llamaba sensores y no había llegado a renombrar; ahora se llama telemetria.
  • Retomo la teoría de la VPN (Tailscale) que configuré el día anterior y lo redacto en la memoria.
19 agosto Hardware ★ Dron construido
  • Dedico el día completo a la construcción del dron.
  • Termino el montaje: el dron queda ya completamente construido.
20 agosto IA Sistema ★ Grabación por sesiones
  • Estudio los formatos de despliegue del modelo de cara a la Raspberry Pi: .pt (pesos nativos de PyTorch, muy completos pero pesados), .onnx (formato "puente" universal, más ligero de cargar), la versión .onnx cuantizada a INT8 (menor tamaño y, en teoría, más velocidad en CPU) y .ncnn (motor optimizado para CPUs ARM como la de la Pi). Dejo también situado el .hef, formato compilado exclusivo del Hailo que solo se puede generar en un PC Linux/x86_64 (a la Pi solo se manda el .hef ya hecho).
  • Añado al repositorio una carpeta conversion/ con tres utilidades para regenerar cada formato a partir de weights/best.pt siempre que reentrene: exportar_onnx.py, cuantizar_onnx.py y exportar_ncnn.py.
  • Añado a deteccion.py el parámetro --runtime (pt / onnx / onnx-int8 / ncnn) para elegir en cada ejecución con qué motor cargo el modelo, sin tocar el código.
  • Meto en el código un pequeño benchmark que, al terminar, imprime el total de frames procesados, la latencia media por frame y el rendimiento medio en FPS.
    • Pruebo todos los formatos sobre el vídeo de prueba (vuelo1) y mido en cada uno rendimiento y consumo de CPU.
    • Resultados: con .onnx a pelo ronda los 5,4 FPS pero la CPU se va casi al 98%. Con la versión INT8 el consumo baja a la mitad pero el rendimiento no mejora (~5,1 FPS). Con .ncnn saco claramente el mejor resultado: unos 8 FPS de media y en torno a un 55% de CPU.
    • El motivo: he hecho cuantización dinámica, que apenas aporta porque solo cuantiza los pesos; para sacarle partido de verdad en CPU haría falta cuantización estática. El Hailo queda como vía INT8 por hardware dedicado, aparte. Me quedo con NCNN, el que mejores números da.
  • Añado grabación por sesiones controlada desde la web:
    • En la web de control añado los botones de "Empezar grabación" y "Parar grabación", enlazados con el nodo edge por MQTT: hasta que no llega el start_recording, deteccion.py no arranca nada y se queda solo escuchando.
    • Cada sesión genera su propio vídeo con su propio timestamp.
    • Al terminar cada grabación se publica un JSON de resumen (dronsar/{dron_id}/video/resumen) con la duración, el total de frames, el rendimiento (runtime, FPS y latencia) y las detecciones (alertas y confianza media).
21 agosto Sistema ★ Cierre de la programación
  • Cambio el valor por defecto de --preview a false en deteccion.py: en la Raspberry normalmente no habrá pantalla conectada, así que abrir una ventana no tiene sentido y puede fallar sin entorno gráfico. Se puede forzar a true a mano el día que lo pruebe con un monitor.
  • Convierto la web de control en una PWA (manifest, service worker e iconos), para poder instalarla como app tanto en el móvil como en el escritorio.
  • Configuro la cámara en la Pi: la cámara CSI que tenía no me funciona, así que opto por una cámara USB que tenía en casa.
  • Monto streaming en directo:
    • Monto un servidor MediaMTX en la EC2; deteccion.py, además de grabar el vídeo en local, lo emite en paralelo por RTSP (streaming.py), y MediaMTX lo retransmite como WebRTC para verlo en el navegador. Va en baja resolución y es un extra que nunca tumba la detección: si falla el streaming, la grabación y las alertas siguen igual.
    • Primero lo sirvo por HLS, pero la latencia es demasiado alta; me paso a WebRTC, casi en tiempo real. Configuro MediaMTX con autenticación e indico la IP pública de la EC2 en webrtcAdditionalHosts.
    • Monto nginx como reverse proxy con TLS (Certbot) en el subdominio stream.gorostiditfg.com, dado de alta en Cloudflare, y abro únicamente el puerto 8189/UDP en el grupo de seguridad. La Raspberry publica por RTSP (8554) a través de Tailscale, así que ese tramo va cifrado por la VPN sin exponer el RTSP a internet.
    • Dejo todo configurable por .env, incluidos los parámetros del streaming (STREAM_HOST/USER/PASS/PATH) y las carpetas VIDEOS_DIR/FOTOS_DIR.
  • Añado en el panel de control una pantallita de cámara en directo (iframe WebRTC), junto a los botones de grabar. Quito el vuelo1.mp4 que estaba por defecto: ahora por defecto va siempre la cámara y el runtime queda en ncnn. La pantalla se queda en negro hasta pulsar "Empezar grabación".
  • Doy por terminada toda mi parte de programación (quedan mejoras posibles, pero de momento la doy por cerrada) y subo todo a GitHub para que quede guardado.
22 agosto IA
  • Grabo y proceso más material aéreo y extraigo nuevos frames para el dataset de personas.
  • Subo y etiqueto las imágenes en Roboflow, priorizando personas a mayor distancia (el punto débil detectado). Parto de 659 imágenes y empiezo la ampliación dirigida.
23 agosto IA
  • Entreno el modelo YOLO11 (variante small) en Google Colab con GPU (NVIDIA Tesla T4), 70 épocas, resolución 1024 y transfer learning desde COCO.
  • Reviso las curvas de pérdida y la matriz de confusión: el recall sube de 0,542 a 0,659 tras la ampliación, manteniendo fijos validación y test para comparar de forma justa.
24 agosto IA
  • Entreno la variante nano (yolo11n), la que voy a desplegar a bordo: más ligera y rápida, con recall 0,601.
  • Confirmo con un experimento que la augmentation estándar perjudica en este dataset (imágenes reales muy variadas y objetos muy pequeños).
  • Guardo los pesos best.pt en Drive en cuanto termino cada entrenamiento.
25 agosto IA
  • Sobre la Raspberry Pi, comparo el modelo en PyTorch, ONNX FP32, ONNX INT8 y NCNN con el mismo vídeo de referencia (944 frames), midiendo FPS, latencia, uso de CPU y RAM.
  • NCNN vuelve a ser el mejor en CPU (≈8,3 FPS); la cuantización INT8 apenas aporta velocidad.
26 agosto IA ★ Benchmark del Hailo-8L
  • Compilo el modelo al formato .hef y ejecuto la inferencia en la NPU Hailo-8L.
  • Resultados: 29,49 FPS y 33,91 ms de latencia, único motor que sigue el ritmo de la cámara en tiempo real. Cierro así la tabla comparativa de los cinco formatos (PyTorch, ONNX, ONNX-INT8, NCNN y HEF).
27 agosto Vuelo Hardware
  • Conecto la Raspberry Pi 5 a la Pixhawk 6X por UART (puerto TELEM3), con las hélices retiradas por seguridad.
  • Valido sobre la electrónica real la cadena de mando completa (panel PWA → API → MQTT → Tailscale → receptor → MAVLink): armado, cambio de modos y lectura de telemetría directamente en el autopiloto.
28 agosto Vuelo Hardware
  • Planifico la misión en Mission Planner sobre el campo de Galapagar (coordenadas de origen del club).
  • Peso la plataforma completa: MTOW de 1.817 g. Como el UBEC no llega a tiempo, decido alimentar la Pi y el acelerador con una batería externa; y como la cámara CSI no se reconoce, preparo una cámara USB como alternativa.
29 agosto Vuelo IA ★ Vuelo real con IA a bordo
  • Realizo el vuelo del sistema integrado completo a bordo, con inferencia de YOLO en tiempo real sobre el vídeo de la cámara.
  • El modelo detecta a las dos personas que entran en el campo de visión y genera sus alertas georreferenciadas (con un falso positivo puntual al inicio, esperable en un prototipo).
  • El enlace 4G aguanta a baja altura, pero el streaming se corta hacia los 10 m; la grabación local funciona sin problemas y confirmo el store-and-forward en vuelo real. Grabo el vídeo de la demostración.
  • Las vibraciones del vuelo degradan la imagen: lo anoto como justificación de un gimbal a futuro.
30 agosto Vuelo Memoria
  • Subo el vídeo del vuelo y reviso los registros y los eventos de detección generados durante la prueba.
  • Empiezo a volcar los resultados del vuelo en el capítulo de validación experimental.
31 agosto Memoria
  • Redacto el pipeline de detección (Cap. 8): construcción del dataset, particionado por vídeos (para evitar data leakage), entrenamiento en Colab y métricas de referencia.

Septiembre 2026

1 septiembre Memoria
  • Redacto la comparativa de motores de inferencia y el despliegue final con el Hailo-8L (8.6), incorporando las tablas de rendimiento, latencia y consumo.
2 septiembre Memoria
  • Escribo el capítulo de validación experimental (Cap. 9): simulación SITL, banco semi-HITL, vuelo real y la matriz de cumplimiento de objetivos.
3 septiembre Memoria
  • Redacto el marco regulador (categoría A3, Remote ID, AI Act, RGPD, vía BVLOS para SAR) y el entorno socioeconómico con el diagrama de Gantt, los hitos y los ODS (Caps. 10 y 11).
4 septiembre Memoria
  • Redacto las conclusiones y el trabajo futuro, y cierro el resumen/abstract y los agradecimientos (incluido el Club Alas de Galapagar).
5 septiembre Memoria
  • Repaso la bibliografía en formato IEEE (referencias, huecos pendientes y numeración) y cuadro los índices de tablas y figuras con el contenido real del documento.
6 septiembre Memoria
  • Última lectura completa: coherencia de figuras y tablas con los datos, actualización del apartado de normativa tras la sentencia del TS, formato UC3M y añadido de la Declaración de Uso de IA Generativa.
7 septiembre Memoria ★ Entrega de la memoria
  • Reviso por última vez el documento completo y entrego la memoria del TFG. El proyecto queda cerrado y validado de extremo a extremo.