Saltearse al contenido

Detecciones de IA DJI a bordo de la aeronave

Las aeronaves DJI Dock 3 incluyen una funcionalidad de reconocimiento de objetivos por IA a bordo (personas, coches, embarcaciones). Cuando está habilitada, la aeronave incrusta cajas delimitadoras de detección en el bitstream H.264 como mensajes SEI (Supplemental Enhancement Information). ARGUS parsea esos mensajes SEI en el navegador y renderiza cajas de superposición en vivo sobre el tile del stream del dron.

Habilitar IA en la aeronave

  1. Abre el tile del stream del dron para una aeronave Dock 3 en la vista de operaciones.
  2. Abre el cajón de Ajustes del dron (icono de engranaje, esquina superior derecha del tile).
  3. Desplázate a Percepción → IA a bordo de DJI y conmuta a on.
  4. ARGUS llama al servicio DRC drc_ai_identify con on=1, ruteado a través de argus-dji como una publicación MQTT a la aeronave. Los mensajes SEI empiezan a aparecer en el bitstream en ~1–2 segundos.

Opcional: en Dock 3 con múltiples modelos de reconocimiento cargados, elige el modelo activo del dropdown debajo del toggle. ARGUS publica drc_ai_model_select con el índice elegido. El predeterminado es modelo 0 (el detector de propósito general de persona + vehículo + embarcación).

Cómo funciona el pipeline SEI

Las detecciones de IA de DJI no son un canal de datos separado — cabalgan dentro del propio bitstream H.264. El decoder ve un frame de vídeo normal; ARGUS extrae el payload de detección a nivel de bytes:

  1. Escaneo Annex-B. El buffer entrante es una unidad de acceso H.264 — una o más unidades NAL separadas por códigos de inicio 00 00 01 o 00 00 00 01. iterateNalUnits produce cada cuerpo NAL.
  2. NAL tipo 6 (SEI). Sólo las unidades NAL donde (byte[0] & 0x1f) === 6 llevan SEI. Las demás se omiten.
  3. Strip de prevención de emulación. Por RFC 3984 §5.4, cualquier secuencia 00 00 03 dentro de un NAL tiene el 03 insertado para evitar que el payload se parezca a un código de inicio. stripEmulationPrevention elimina todos esos escapes antes del parseo — leer el NAL crudo como bytes daría offsets equivocados en caso contrario.
  4. Decodificación de longitud multi-byte. H.264 §7.3.2.3.1 codifica tanto payload_type como payload_size como la suma de bytes 0xFF iniciales más un byte final < 0xFF. readMultiByteLength decodifica ambos.
  5. Tipo de payload DJI. DJI usa payload_type = 5 (user_data_unregistered); algunos builds de dev también emiten tipo 4.
  6. Marcador de transporte. El primer byte del payload DJI distingue el transporte:
    • 0xF5WebRTC (firmware post-Dock 3, la ruta moderna).
    • 0x65Agora (transporte legacy, mantenido para firmware antiguo).
    • cualquier otro → fallback crudo, el caller puede inspeccionar los bytes sin parsear.
  7. Decodificación de struct DJI. Layout little-endian — magic DJIF opcional, byte de versión, conteo de objetivos, timestamp de 64 bits, luego N × (índice de objetivo, tipo de objeto, confianza, x, y, w, h, estado, reservado). Las coordenadas son fijo-punto de 12 bits 0–4095, relativas al frame — no coordenadas de píxel. El parser divide por 4095 para devolver rectángulos normalizados 0–1 para que el renderer de superposición no necesite conocer la resolución del vídeo.

Todo esto corre en TypeScript puro — sin dependencia nativa de decodificación.

Tipos de objeto

ValorTipo
1UNKNOWN
2PERSON
3CAR
4BOAT

El tipo de objeto determina el color de la caja de superposición — persona verde, coche cian, embarcación azul, desconocido gris.

Estados de objetivo

Cuando el gestor de seguimiento de la aeronave está activo, cada detección lleva un estado por objetivo:

ValorEstado
0TRACKED — bloqueo estable frame-a-frame.
1LOST — el tracker perdió el objetivo; la caja desaparecerá en el siguiente frame.
2NEW — primera aparición, aún no estable.
3OBSCURED — parcialmente oculto; el tracker mantiene la última posición conocida.

El estado determina el estilo de borde de la caja — sólido para TRACKED, discontinuo para NEW, contorno ámbar para OBSCURED, atenuado para LOST.

Normalización de confianza

DJI emite la confianza en una de dos convenciones dependiendo del firmware: 0–100 (porcentaje) o 0–10000 (basis points). El parser auto-detecta — si el byte crudo es mayor que 100, se trata como basis-points y se divide por 10000; de lo contrario porcentaje y se divide por 100. La salida se limita a [0, 1].

Renderizado de superposición

Cada detección se renderiza como una caja de color más una etiqueta en la esquina PERSON 87% (o similar). Hacer clic en una caja selecciona el objetivo — su targetIndex se convierte en el tracker activo. Acciones posteriores:

  • Spotlight-zoom opcional (Dock 3 con payload de foco) — ARGUS llama a drc_ai_spotlight_zoom_track con el índice de objetivo seleccionado. El gimbal de la aeronave auto-sigue y el foco acompaña.
  • Doble clic en una caja — suelta un banderín de mapa en el centroide de espacio-mundo de la detección (ray-cast desde la pose de la cámara a través del centro de la caja sobre el terreno Cesium). Útil para marcar una persona de interés o un vehículo sospechoso.

Cableado upstream — parcial

La mitad downstream de este pipeline (parseo SEI → flujo de detección → renderizado de superposición) está cableada y se entrega. La mitad upstream — extraer los bytes de unidad de acceso H.264 fuera de un receptor WebRTC en vivo para que el parser pueda ingerirlos — es parcial. Existen dos rutas por navegador, y la correcta la elige el componente de vista que posee el stream:

  • RTCRtpScriptTransform (Chrome, Edge, Firefox-nightly) — adjunta un worker de transform al RTCRtpReceiver entrante. El worker recibe RTCEncodedVideoFrames cuyo .data son los bytes NAL H.264 crudos. Aliméntalos a DjiAiDetectionsService.ingestAnnexB(buf, meta).
  • VideoDecoder + MediaStreamTrackProcessor (Chrome + Edge hoy, Safari 17+) — extrae chunks codificados en el hilo principal, parsea SEI, y luego re-decodifica normalmente para visualización. Más portable pero cuesta un salto de decodificación en hilo principal.
  • Parseo del lado del servidor (fallback) — argus-dji se suscribe al ingreso WHIP, extrae SEI de RTP, publica detecciones parseadas en el canal de datos TACLINK. Funciona en cada navegador pero necesita un parser C/GStreamer de H.264; programado por separado si las rutas de navegador resultan frágiles.

Aspiracional hasta que el upstream esté finalizado. Hoy, las detecciones se renderizan en navegadores donde la ruta RTCRtpScriptTransform está cableada para la familia específica de firmware del dock (Dock 3 post-04.00). En Safari, la ruta VideoDecoder es el fallback planificado. Espera huecos en navegadores más antiguos hasta que aterrice la ruta del lado del servidor.

Reinicio entre streams

Cuando el operador cambia cámaras (p. ej. wide → zoom) o el stream se desmantela y re-aprovisiona, DjiAiDetectionsService.clear() vacía el historial de detección y resetea el último frame — para que las cajas obsoletas del stream previo no persistan en el nuevo vídeo.

Relacionado

  • DRC — el pipeline de comandos usado para conmutar la IA a bordo de la aeronave y seleccionar el modelo de reconocimiento.
  • Tile del dock — el tile padre que hospeda la superposición del stream del dron.
  • Auto-stream — la capa de ingreso sobre la que cabalgan los mensajes SEI.