Mise en Place de la communication Video sur un ArDrone avec le Sdk Windows

Introduction

L'AR.Drone est un drone de la société Parrot SA destiné au grand public. C'est un quadricoptère contrôlable depuis un PC sous Windows ou Linux, depuis un appareil sous iOS (iPhone par exemple) ou depuis un appareil sous Android. Il embarque de nombreux capteurs, et deux caméras (une à l'avant et une en dessous). Le lien avec le contrôleur est effectué via WiFi.
En plus de pouvoir utiliser l'AR.Drone avec les applications fournies par défaut, Parrot fournit un SDK pour Windows et Linux pour pouvoir communiquer avec le drone dans des programmes personnels. Parrot fournit également plusieurs programmes de démonstration faisant usage de ce SDK, avec leur code source. La version Windows n'est plus supportée par Parrot SA pour les dernières versions du SDK et du firmware.

Problème

En utilisant le SDK en version 1.8 ou supérieure, sous Windows, et un drone avec un firmware récent (version supérieure à 1.7.1), dans le programme de démonstration ardrone_navigation, le flux vidéo freeze (le rafraîchissement de l'image s'arrête) au bout d'un court instant (moins d'une seconde).
Nous avions comme objectif de trouver les raisons de ce freeze, et de le corriger si possible.

I) Les pistes étudiées

1) Une erreur se produit-elle lors de l’exécution du thread de la vidéo ?

2) Le flux vidéo est-il bien reçu par l’ordinateur ?

3) L'AR.Drone n'envoie-t-il pas une image fixe ?

4) Utilisation d'un SDK de version inférieure ou downgrade du firmware de l'AR.Drone

5) Nous nous sommes demandé si le changement de codec au cours de la vidéo pouvait ne pas être supporté par le programme. Nous avons donc essayé de détecter le changement de codec au cours de l’exécution. Et nous avons aussi essayé de modifier les appels de fonctions.

II) Recherches

Une erreur se produit-elle lors de l’exécution du thread de la vidéo ?

Bug interne dans le programme appelant

Nous avons tout d'abord émis l'hypothèse d'une erreur dans le programme de démonstration quelconque qui empêcherait le flux vidéo d'arriver ou bien de se décoder. Toute la chaîne de traitements du flux vidéo est assurée par un thread indépendant, ainsi que l'affichage dans l'application (via la SDL). Nous avons testé plusieurs des fonctions pour savoir si elles s'exécutaient bien. Nous avons constaté que le rafraîchissement de la surface vidéo dans le programme s'effectue bien. Cela tend à confirmer que l'origine du bug se trouve dans les fonctions internes à l’API.

Bug dans l’API

La structure du code étant compliquée et le code non commenté, il est difficile de vérifier s’il y a bien un bug dans une des fonctions de l’API. Nous avons essayé de remplacer les appels de fonctions mais rien de décelable ne s’est produit.

Le flux vidéo est-il bien reçu par l’ordinateur ?

Nous avons imaginé une origine interne au drone du bug : il aurait pu arrêter de transmettre les données de la caméra. On sait que le flux vidéo est envoyé par le drone en UDP, sur le port 5555. L’utilisation de Wireshark nous a permis de vérifier que le flux vidéo était bien reçu par l’ordinateur, même après le freeze de la vidéo. Cette piste est donc écartée. Nous nous orientons donc vers des pistes mettant en cause l’API, côté contrôleur, pour le freeze.

L'AR.Drone n’envoie-t-il pas une image fixe ?

L’utilisation de Wireshark a montré que les paquets reçus sont de taille différentes même après le freeze de la vidéo, donc les paquets reçus ne correspondent certainement pas à une image fixe. Cette piste est donc elle aussi écartée.

Downgrade du firmware ou utilisation d'un SDK de version inférieure

La seule combinaison avec laquelle nous avons relevé le bug de la vidéo est : SDK 1.8 et firmware 1.7.4. L'utilisation de versions antérieures, soit pour le firmware, soit pour le SDK empêchent l'apparition du bug.

Changement de codec non supporté ?

L'AR.Drone compresse la vidéo pour la transmission par le réseau. Trois méthodes peuvent être utilisées :

a. UVLC (ou VLIB) – proche du MJPEG
b. P264 – proche du H.264
c. P263 – proche du H.263

On remarquera que le P263, bien que présent dans le code source du SDK 1.8, n'apparaît pas dans le manuel du développeur du SDK 1.7. Au contraire, dans le manuel du SDK 1.6, n'est cité qu'une version simplifiée du H.263 UVLC. Le manuel indique que seuls UVLC et P264 sont supportés ; un passage en P263 du côté du drone entraînerait alors le freeze.

Dans le code des SDK versions 1.6 et 1.8 (donc celle qui fonctionne et celle qui plante), on voit que l'utilisation des formats MJPEG et P263 n'est pas prévue : dans le fichier video_codec.h, un commentaire l'indique et ils n'ont pas de valeur particulière dans l'énumération codec_type_t listant les codecs disponibles. Cependant on trouve des fonctions servant à faire marcher le flux vidéo en P263, p263_codec_alloc() par exemple. Et cette fonction est bien appelée depuis video_codec_open_private().

Nous souhaitions voir à partir de quel point/paquet l'AR.Drone changeait de compresseur vidéo.
En observant les paquets échangés sur le canal vidéo (port 5555), on voit qu'une fois assemblés, ils font tous environ 18 ko. Au vu du niveau de qualité des images en bout de chaîne, une fois décodés, on suppose que chaque paquet contient une image (ou l'équivalent d'une image pour le p264 – et peut-être le p263, qui ne compressent pas les images indépendamment). En conditions optimales, on constate que la vidéo est assez fluide donc au moins à une quinzaine, vingtaine d'images par seconde au moins. On compte les paquets, on en trouve une vingtaine par seconde. Cela signifie bien qu'un paquet correspond à une « image ». En théorie, les images envoyées commencent toutes par un PSC (Picture Start Code) pour indiquer quel type de compression a été appliqué à l'image.
On en a deux possibles :

UVLC :
0000 0000 0000 0000 1000 00xx
P264 :
0000 0000 0000 0001 0000 00xx

Cela correspond en hexadécimal à :
00 00 8X, avec X dans {0, 1, 2, 3}
00 01 0X, avec X dans {0, 1, 2, 3}

Un ou l'autre de ces deux codes devrait donc être présent quelque part dans chacun des paquet-frame du flux vidéo ; cependant, en examinant les paquets « à la loupe », il nous a été impossible de trouver ce PSC. Par exemple, prenons un paquet vidéo au hasard et regardons son contenu :
i. La recherche de 00 01 0 (P264) ne nous donne rien.
ii. La recherche de 00 00 8 donne dans l'ordre :
- un premier résultat au 1114ème octet (00 00 81) ;
- un second résultat au 4774ème octet (00 00 80) ;
- un troisième au 9367ème octet (00 00 80).

Ces trois résultats semblent correspondre à des PSCs, puisque leur 6ème demi-octet est bien inférieur à 3. Mais ils sont au nombre de trois, ce qui indiquerait trois images différentes. Or, on peut (en théorie) repérer la fin d'une image grâce au message de 22 bits EOS (End Of Sequence) :
0000 0000 0000 0001 0111 11
Soit en hexadécimal
00 01 7X, avec X dans {C, D, E, F}
Mais un problème se pose : on ne trouve dans le paquet examiné nulle part cette séquence... On tend donc à penser que les motifs semblant indiquer des débuts d'image n'étaient que dus au hasard des données de l'image.
Nous avons envisagé la possibilité de mettre en parallèle les différents taux de compression des algorithmes utilisés et la taille des images, mais cette méthode nous a semblé trop hasardeuse pour être employée.
Nous avons ensuite recherché une AT commande susceptible de changer le codec vidéo du drone. Elle existe ; elle s'appelle AT*CONFIG et permet de changer les paramètres du drone. Entre autres, il y a un paramètre « video_codec ». Cependant on ne retrouve pas dans une capture réseau contenant les AT commandes envoyées au drone avant et après plantage cette commande.
Nous avons fait quatre captures réseau différentes, selon ce tableau :
tableau

Le seul cas générant le freeze de la vidéo est le 4.cap où on associe le SDK en version 1.8 avec un drone en firmware 1.7.4.
Nous avons développé deux outils pour pouvoir examiner plus facilement les AT commandes envoyées au drone. Le code source (en C) de ces deux programmes est disponible en annexe.

ATreader.exe extrait toutes les commandes du fichier de capture et les liste dans l'ordre.

listAT.exe fait la liste des différentes commandes envoyées

Nous utilisons d'abord ATreader.exe pour lister les AT commandes d'une session. On peut ensuite facilement rechercher dans le fichier texte généré des paramètres de commande particuliers. On remarque que dans toutes les sessions, y compris celle où le plantage a eu lieu, on ne trouve pas AT*CONFIG modifiant le paramètre video_codec. On a vérifié l'intégrité de la liste des commandes grâce au premier numéro suivant le '=' (par exemple AT*REF=5,290717696, le 5 ici), qui s'incrémente à chaque AT commande envoyée.
On regarde ensuite les différents paquets utilisés dans chaque session grâce à listAT.exe. On voit tout de suite que l'éventail des commandes utilisées n'est pas strictement identique : les deux sessions utilisant le SDK 1.8 font appel à la commande AT*CONFIG_IDS, contrairement au sessions utilisant le SDK 1.6. On remarque aussi que l'ancienne version du SDK commence par un AT*CONFIG, suivi d'un AT*PMODE, alors que la nouvelle version commence directement par un AT*PMODE.
On trouve bien une commande AT*CONFIG modifiant un paramètre vidéo (AT*CONFIG=53,"video:bitrate_control_mode","1"), mais elle se trouve dans la capture 1.cap, c'est à dire dans une situation sans bug.

Nous avons envisagé l'envoi d'AT commandes « à la main », via un programme indépendant du SDK ; cela devrait être possible puisque les AT commandes sont simplement transmises en texte ASCII en UDP au drone. Nous aurions pu alors tester différentes commandes AT*CONFIG modifiant les paramètres vidéo du drone pour peut-être rétablir la vidéo. Mais nous avons abandonné cette idée à cause du numéro de séquence de chaque commande (celui juste après le '='). Il s'incrémente à chaque commande et donc en dehors du programme principal, il paraît très complexe de se synchroniser avec le rythme du programme. La seule solution que nous avions envisagée était d'envoyer une commande avec un grand nombre de numéros de séquence dans un laps de temps court, pour « rattraper » l'ordre des commandes du programme principal. Mais cette méthode pose des problèmes au niveau des numéros de séquence du programme principal.

Ainsi, nous n'avons pas trouvé de méthode efficace pour savoir quel type de compression est appliqué sur les images à un instant t, ni trouvé de commande qui aurait entraîné un changement de codec.

III) La solution retenue

Au vu de tout ce que nous avons fait et de nos difficultés à comprendre le code, nous avons donc décidé de downgrader le firmware de la version 1.7.4 vers la version 1.4.7, avec laquelle il n’y a pas de problème de freeze. Nous allons donc décrire la procédure à suivre pour downgrader :
- Envoyer le firmware (ardrone_update.plf) sur l'ardrone par ftp.
- Se connecter en telnet a l'AR.Drone.
- Copier le firmware (qui se trouve dans /data/video) dans /update.
- Changer le contenu de version.txt a 0.0.0.0 dans /firmware et /update.
- Supprimer les fichiers /data/trims.bin et /data/fact_trims.bin s'ils existent ; ces fichiers semblent causer une instabilité du drone en vol.
- Redémarrer l'ardrone ("reboot").

Conclusion

Nous n'avons pas réussi à corriger, ni même à identifier l'origine du freeze de la vidéo affectant l'AR.Drone sous Windows. La seule solution que nous ayons donc est le downgrade du firmware. Nous avons cependant appris sur le réseau en général et sur l'utilisation de Wireshark en particulier. Nous avons également eu un aperçu clair des difficultés rencontrées lors du débogage d'une grosse application (et de la difficulté à comprendre un code non commenté).

Annexes

voir le fichier annexe attaché

tableau_ardrone.png - tableau (2.7 KB) Adrien Joseph, 06/13/2013 02:47 PM

Annexe_CR_Projet_ARDrone_Connier_Joseph.pdf (185 KB) Adrien Joseph, 06/13/2013 02:48 PM