Détection d'obstacles par nuage de points

a marqué ce sujet comme résolu.

Bonjour à tous,
Je m’excuse par avance de la longueur de ce message.

Voilà maintenant 4 mois que nous travaillons (une équipe de 4 élèves dont moi-même) sur notre projet de fin d’étude, la détection temps-réels d’obstacles par nuage de points. Je suis en charge du développement du logiciel, qui est réalisé en C++17. Pour vous donner un peu de contexte au projet, en voici une brève description :

Piloter un rover lunaire à distance est complexe car le pilote ne peut pas regarder toutes les caméras en même temps. Notre projet doit donc streamer la vue frontale et si un obstacle est détecté dans les 180° alors il faut incruster la vue de cette obstacle à la vue frontale afin que le pilote soit prévenu de la présence de l’obstacle. Je vous ai joins une image pour vous faire une idée de l’interface que l’on a actuellement :

Interface du pilote
Interface du pilote

Le logiciel est donc purement un système d’alerte et de prévention et non un système qui doit piloter le rover. Aujourd’hui ce logiciel est codé et fonctionnel, je suis vraiment très satisfait d’en être arrivé là.

Seulement voilà, il faut maintenant améliorer, car on est loin d’atteindre les performances désirées. Sur mon PC (i7 6700HQ @ 2.60GHz, GTX 980M 4GB), j’arrive à traiter en moyenne une dizaine de nuages de points par seconde, afin d’avoir du vrai temps réel il faudrait que je monte à une trentaine de nuages de points par seconde. Et là n’est pas le pire… Le logiciel est sensé tourner sur une Raspberry Pi 4 et honnêtement j’ai de plus en plus de doute sur la faisabilité de la chose, je pense que la RPi4 n’est pas assez puissante. Je vous explique succinctement le fonctionnement du logiciel :

Pour capturer les nuages de points et la vidéo, nous utilisons une caméra stéréoscopique Intel RealSense D435. Avec la librairie librealsense2 nous récupérons deux flux, le nuage de points à l’instant x et la vidéo à l’instant x. On les sépare et en fonction du type de flux:

  • Si c’est un nuage de points, on l’ajoute à une variable qui va être lue par le thread qui va le traiter. Tant que ce nuage de points n’est pas traité, on ignore les nouveaux nuages de points (donc on traite que les nuages de points lorsque le précédent est terminé et que le thread est libre). Si des obstacles sont détectés, ils sont ajoutés à une liste. Pour le traitement, nous utilisons les filtres de la librealsense pour nettoyer et réduire le nombre de point (filtre: threshold pour enlever les points plus loin que 10 mètres et decimation pour réduire le nombre de point), puis avec la PointCloudLibrary nous voxelisons le nuage de points et enfin nous appliquons une clusterisation, un cluster étant un obstacle. Ça fonctionne à merveille.
  • Si c’est un flux vidéo, on l’ajoute à une queue où, dans un autre thread, on regarde si on a des obstacles dans la liste. Si oui, on les encadre dans la vidéo, si non on laisse la vidéo telle quelle. La frame traitée est ensuite ajoutée à une queue.

On a enfin un dernier thread qui, avec GStreamer, regarde la queue des frames traitées et quand une nouvelle frame est là, il l’envoie vers le serveur de réception qui s’occupe de l’affichage à l’utilisateur.

Ce qu’on peut remarquer là c’est que les nuages de points et la vidéo sont complètement désynchronisés. Si un obstacle est détecté sur le nuage de points de l’instant x, il sera encadré sur la vidéo de l’instant x+t, t étant le temps de traitement du nuage de points (en moyenne 100–200 ms). Ce n’est pas du tout un problème au vus de la vitesse du rover, au contraire, ça nous permet de garder une vitesse de stream fluide et de ne traiter des points clouds que lorsqu’on le peut. Le logiciel a donc 4 threads:

  • Le thread principal qui récupère les données et les dispatch
  • Le thread de traitement du nuage de points
  • Le thread du traitement de la vidéo et de l’incrustation des obstacles si détectés
  • Le thread d’envoi de la vidéo finale

Le seul qui utilise son cœur à 100% est le thread du traitement de nuage de points, les autres tournent autour de 30%.

Bref, voici mes questions :

  • Comment mesurer concrètement la performance de mon logiciel ? J’ai bien fait un flamegraph, mais je ne vois rien de choquant.
  • L’organisation de mon logiciel est-elle bonne ? Je sais qu’il n’y a pas d’organisation parfaite, mais je me dis que faire un thread par nuage de points pourrait peut-être améliorer mes performances, comment le savoir avant de tester ?
  • La Raspberry Pi 4 est-elle pas assez puissante pour ce genre d’application ou en optimisant correctement mon logiciel je peux m’approcher des performances voulues ? Peut-être pas 30, mais 15 nuages de points par seconde serait déjà incroyable.

Je sais que sans le code, ni même le projet devant vous il est difficile de répondre à ces questions, j’ai essayé de vous donner un maximum de détails. Si certains points vous semblent encore obscurs, n’hésitez pas à demander.

Je vous remercie d’avoir lu jusqu’ici ! Et merci d’avance pour vos retours.

Etne.

Comment mesurer concrètement la performance de mon logiciel ? J’ai bien fait un flamegraph, mais je ne vois rien de choquant.

Tu peux procéder en 2 étapes :

  • localiser la partie du code qui consomme le plus (par exemple avec valgrind callgraph)
  • puis voir quoi optimiser. Il faut vérifier les allocations (a eviter), les copies (a eviter aussi), la gestion de la mémoire cache (valgrind cachegraph).

Virer les copies, c’est généralement de la correction de syntaxe (faire des moves ou des références plutôt que des copies). Les allocations et mémoire cache, ca risque d’etre plus des changements de structures de données et d’algo.

L’organisation de mon logiciel est-elle bonne ? Je sais qu’il n’y a pas d’organisation parfaite, mais je me dis que faire un thread par nuage de points pourrait peut-être améliorer mes performances, comment le savoir avant de tester ?

Tu feras quoi des données traitées par tes autres threads ? Si ça rallonge le temps de traitement et que tu les utilises qu’un temps très courts, ca ne sera pas forcément pertinent.

Si tu as des cores non utilisés par contre, ça peut être pertinent.

Mais du coup, ca veut dire que ce type d’optimisation est dépendant du matériel. C’est à dire que sur un CPU de bureau a 8 cores, tu ne feras peut être pas les mêmes choix que sur un CPU à 4 cores (RPi?)

Ca veut dire qu’à un moment donné, il faudra travailler sur la plateforme cible (ton RPi) pour bosser sur les performances, pour être sûr de ne pas faire des optis qui n’ont pas de sens dessus.

La Raspberry Pi 4 est-elle pas assez puissante pour ce genre d’application ou en optimisant correctement mon logiciel je peux m’approcher des performances voulues ? Peut-être pas 30, mais 15 nuages de points par seconde serait déjà incroyable.

Aucune idée. Mais en pratique, c’est pas la bonne question. La question est plutôt : quel compromis faire sur la qualité de détection de façon à augmenter les performances ?

Je ne sais pas quel algo tu utilises dans PCL pour faire la clusterisation, mais c’est en général quelque chose d’assez gourmand. Peut être qu’il faut filtrer plus. Peut être qu’il faut utiliser d’autres algos. Peut être que l’implémentation de PCL est trop générique et peut être optimisée pour votre cas particulier.

Il faudra forcément passer par la phase de profiling pour comprendre où partent les perfs puis faire des corrections si perte de perfs inutiles ou des choix sur la qualité de détection.

+0 -0

Effectivement on dirait que le goulot d’étranglement en performances c’est librealsense et PointCloudLibrary, donc c’est sans doute là qu’il faut regarder pour trouver comment réduire la quantité de calculs demandés.

Quelques idées:

  • comme le suggère @gbdivers, essayer de filtrer plus aggressivement
  • éventuellement regarder le code de la bibliothèque PointCloudLibrary et réfléchir à si tu pourrais faire plus simple/rapide pour ton application particulière (mais ça me paraît l’approche à tenter en dernier)
  • te faire une idée du coût des opérations en en retirant, tout simplement: si tu vires la PointCloudLibrary temporairement, et tu essaies juste d’afficher les points filtrés en rouge par-dessus l’image caméra, est-ce que ça reste trop lent ou tu obtiens la fluidité que tu veux ? Ça te donne une idée de comment sont répartis les coûts entre les deux bibliothèques, et accessoirement le fait de "voir" les points avant pré-traitement peut te donner des idées.

Je ne parviens pas à comprendre le workflow avec cet outil.

Pour moi il y a en fait deux machines dans ton projet :

  • Le rover, qui est piloté et a des capteurs sur lui pour connaître son environnement ;
  • Une machine distante pour piloter le rover et afficher les informations à son pilote et aux ingénieurs qui surveillent son état.

Il est peu probable que la machine distante soit un téléphone ou un petit appareil, dans la vraie vie c’est sans doute un PC puissant.

Or on ne retrouve pas ce découpage matériel, tu sembles considérer que tout doit se faire au niveau local du rover, d’où le choix du RPi pour les calculs je présume. Mais en vrai il pourrait être pertinent de bien séparer l’acquisition et son traitement. Le rover avec le RPi 4 collecte les données d’intérêt, avec éventuellement un prétraitement simple. Et envoie les informations pertinente à la machine plus puissante qui va faire les calculs très complexes et gourmands.

De toute façon dans l’espace, si on part de conditions réelles, tu as une latence de plusieurs secondes entre la Terre et la Lune dans tes communications. En somme la conduite est lente et ajouter quelques millisecondes de plus pour le traitement n’est pas critique non plus car négligeable devant le reste. ;)

Après j’ai peut être mal compris le projet et son but, mais si le but est de faire le plus réaliste possible, le découpage matériel et logiciel serait différent et ton RPi ferait finalement des tâches très simples.

+0 -0

Salut,

afin d’avoir du vrai temps réel il faudrait que je monte à une trentaine de nuages de points par seconde

Est-ce que tu as vraiment besoin de 30FPS ?

Si c’est un nuage de points, on l’ajoute à une variable qui va être lue par le thread qui va le traiter. Tant que ce nuage de points n’est pas traité, on ignore les nouveaux nuages de points

Le soucis avec cette approche est que tu ne traites pas toujours les données les plus récentes ; tu pourrais réduire la latence en traitant le dernier nuage de point reçu. J’ai fait ce changement dans un projet où un processus envoyait des frames en temps réel à un appli front (qui n’arrivait pas à suivre) et utiliser la dernière frame plutôt que la première non lue a grandement réduit la latence.

J’aurai une question par rapport à ton projet du coup : n’as-tu pas eu de problèmes de latence ? Je n’ai pas réussi à avoir un flux vidéo sans latence en utilisant GStreamer, FFMPEG ou VLC comme clients (avec des flux non encodés) et je n’ai jamais trouvé de solution. La latence ne venait pas du processus d’émission du flux.

Bonne chance dans ton projet, le sujet à l’air intéressant.

Bonsoir!

Merci pour vos retours, je vais détailler un peu plus le projet (peut-être faire un billet pour en parler plus en détail quand il sera fini et que le code source sera open source).

Tu peux procéder en 2 étapes :

  • localiser la partie du code qui consomme le plus (par exemple avec valgrind callgraph)
  • puis voir quoi optimiser. Il faut vérifier les allocations (a eviter), les copies (a eviter aussi), la gestion de la mémoire cache (valgrind cachegraph).

Virer les copies, c’est généralement de la correction de syntaxe (faire des moves ou des références plutôt que des copies). Les allocations et mémoire cache, ca risque d’etre plus des changements de structures de données et d’algo.

Après analyse avec valgrind comme tu l’as indiqué, j’ai pu corriger divers petit problèmes mais rien de très grave. Merci pour ce conseil. Un de mes objectif pour ce projet était justement de mettre à profit la sémantique de mouvement avec le C++17. Il n’y a donc absolument aucune copie de points cloud, tout se fait à coup de pointeurs intelligents et de move. Le programme consomme 500 Mo de RAM constant, même après avoir tourné pendant une heure.

Mais du coup, ca veut dire que ce type d’optimisation est dépendant du matériel. C’est à dire que sur un CPU de bureau a 8 cores, tu ne feras peut être pas les mêmes choix que sur un CPU à 4 cores (RPi?)

J’ai oublié de préciser que j’étais justement parti sur 4 threads pour les 4 cœurs de la RPi.

Je ne sais pas quel algo tu utilises dans PCL pour faire la clusterisation, mais c’est en général quelque chose d’assez gourmand. Peut être qu’il faut filtrer plus. Peut être qu’il faut utiliser d’autres algos. Peut être que l’implémentation de PCL est trop générique et peut être optimisée pour votre cas particulier.

Un énorme merci pour ton aide. En effet, en filtrant de façon plus agressive (notamment le decimation filter de la librealsense2) je réduis fortement la densité de point à traiter pour la voxelisation. Je tourne désormais à 40 FPS sur mon PC ! Sur la RPi, ça donne environ 15 FPS ce qui est largement acceptable ! Je vais encore jouer avec les paramètres afin de m’assurer d’en tirer un maximum.

Il faudra forcément passer par la phase de profiling pour comprendre où partent les perfs puis faire des corrections si perte de perfs inutiles ou des choix sur la qualité de détection.

À part le FlameGraph qui est la seule méthode que je connaisse, qu’est-ce que je peux faire pour profiler mon programme ?

éventuellement regarder le code de la bibliothèque PointCloudLibrary et réfléchir à si tu pourrais faire plus simple/rapide pour ton application particulière (mais ça me paraît l’approche à tenter en dernier)

Héhé, j’y ai pensé. J’avais regardé un moment pour utiliser le GPU de la RPi, mais je partirai beaucoup trop loin par rapport au projet de base donc j’ai préféré réussir sans faire ça. Cependant, une fois le projet terminé, je compte regarder d’un peu plus près les possibilités, car j’étais extrêmement surpris que PCL n’utilise absolument pas le GPU.

Pour moi il y a en fait deux machines dans ton projet 

C’est exactement ça. Une des contraintes que nous a donné l’ESA est que l’algorithme doit tourner intégralement sur le rover car on peut avoir plusieurs pilotes à la fois. La gestion de la priorité de pilote fait parti d’un autre projet et sors du cadre de celui-ci. Mais comme plusieurs pilotes peuvent co-exister (par exemple un sur la lune, un dans l’ISS et un sur Terre), ils doivent recevoir la même vidéo et donc le traitement est à effectuer à bord du rover.

Nous avons choisi la RPi 4 car nous pensions que le problème principal allait être la RAM, et la dernière version existe avec 8 giga de ram. Sauf que le problème est actuellement le CPU et nous devons maintenant faire avec.

Est-ce que tu as vraiment besoin de 30FPS ?

C’est une demande de mon tuteur. Il a demandé à ce qu’on s’approche le plus possible des 30 FPS sur mon PC comme la RPi fait en moyenne mon nombre de FPS divisé par deux.

Le soucis avec cette approche est que tu ne traites pas toujours les données les plus récentes ; tu pourrais réduire la latence en traitant le dernier nuage de point reçu.

Comment ça ? Je traite les nuages de points aussi rapidement que je le peux, si je traite le dernier possible, il m’est impossible de traiter un seul nuage entièrement, ils arrivent trop vite.

J’aurai une question par rapport à ton projet du coup : n’as-tu pas eu de problèmes de latence ? Je n’ai pas réussi à avoir un flux vidéo sans latence en utilisant GStreamer, FFMPEG ou VLC comme clients (avec des flux non encodés) et je n’ai jamais trouvé de solution. La latence ne venait pas du processus d’émission du flux.

Héhé c’est justement un autre gros problème que l’on a actuellement. Encore une fois, nous avons une contrainte de l’ESA, une latence de maximum 500ms est acceptable pour piloter un rover, idéalement 300ms c’est mieux. Et après des mois de bataille avec GStreamer, nous avons réussi. Donc on envoie les frames en h264 avec GStreamer et la réception est également effectuée par GStreamer. Pour les afficher on utilise OpenCV dans une fenêtre Qt. Je ne suis pas la personne en charge de cette partie, si tu as des questions n’hésite pas, j’irais lui les poser.

Bonne chance dans ton projet, le sujet à l’air intéressant.

Merci, c’est un sujet qui me passionne et dans lequel j’espère vraiment travailler très prochainement. :)


Je me permet de poser une autre question. Voici le graphique représentant le temps de calcul complet d’un traitement d’une frame:

Temps de calcul des frames
Temps de calcul des frames

On peut voir notre moyenne à 25 ms (donc 40 FPS). Mais on peut voir une ligne autour des 75 ms également. Je voudrais savoir à pourrait être due cette ligne. La taille des nuages de points est globalement constante grâce à la voxelisation donc ce n’est pas du à ça. Ces résultats ont été obtenus sur mon PC (8 cœurs) donc le thread à normalement son cœur pour lui tout seul mais je ne sais pas exactement comment Linux gère la répartition de la charge de calcul sur le CPU. Sur la RPi je remarque également la même ligne (aux alentours des 180 ms). Pour le moment j’utilise Raspberry pi OS avec une interface graphique, c’est plus pratique pour débugger. Bien sur, l’objectif est de faire tourner le logiciel un environnement Linux où il n’y aurait pas d’UI ou autres logiciels inutiles. Est-ce que cette ligne est due à l’OS qui fait sa tambouille en même temps? Comment m’assurer d’avoir un linux propre pour exécuter mon logiciel sur la RPi ?

Encore une fois désolé pour cette longue réponse et merci pour votre aide !

Une des contraintes que nous a donné l’ESA est que l’algorithme doit tourner intégralement sur le rover car on peut avoir plusieurs pilotes à la fois. La gestion de la priorité de pilote fait parti d’un autre projet et sors du cadre de celui-ci. Mais comme plusieurs pilotes peuvent co-exister (par exemple un sur la lune, un dans l’ISS et un sur Terre), ils doivent recevoir la même vidéo et donc le traitement est à effectuer à bord du rover.

Rien n’empêche de le faire avec mon design.

Je dis ça car en général l’aéronautique / aérospatial n’est jamais à la pointe technologique dans ce qui vole, à cause des contraintes temporels de développement et de validation mais aussi à cause de l’environnement spatial qui n’est pas très sympa avec les composants à haute performance. Et la bande passante d’envoi est aussi limitée. Et typiquement le processeur embarqué ne sera jamais celui du RPi. ;)

Du coup je suis un peu étonné de ce choix. Quelle est la demande et la contrainte à titre de curiosité ? Pourquoi avoir choisi un RPi plutôt qu’un Tegra X1 de nVidia par exemple ?

Car comme ton objectif dépend en partie de ce choix initial, tu te compliques peut être la vie même si l’objectif est atteignable.

En tout cas bonne chance. ;)

+0 -0

car j’étais extrêmement surpris que PCL n’utilise absolument pas le GPU.

Il y a 2 problèmes majeurs avec le calcul GPU :

  • le coût de transfert des données de la RAM vers la GRAM
  • tous les algos ne sont pas parallélisable (en particulier les algos d’IA, c’est pour ca par exemple que Nvidia a ajouté des Tensor Cores dans ses GPU) Ces problèmes font que ce n’est pas forcément une bonne idée de faire des calculs sur GPU (ca peut mettre être plus lent)

Héhé c’est justement un autre gros problème que l’on a actuellement. Encore une fois, nous avons une contrainte de l’ESA, une latence de maximum 500ms est acceptable pour piloter un rover, idéalement 300ms c’est mieux. Et après des mois de bataille avec GStreamer, nous avons réussi. Donc on envoie les frames en h264 avec GStreamer et la réception est également effectuée par GStreamer. Pour les afficher on utilise OpenCV dans une fenêtre Qt. Je ne suis pas la personne en charge de cette partie, si tu as des questions n’hésite pas, j’irais lui les poser.

OpenCV n’est pas trop une lib pour afficher une vidéo. C’est une lib de traitement. Pour avoir déjà fait du flux vidéo avec ffmpeg et Qt, ça se fait sans trop de problème de latence. J’avais même fait une version mobile, ça passait sans problème.

Le coût le plus important était la décompression des images par ffmpeg (ce qui était threadé). Puis j’affichais l’image directement dans le GPU comme une texture. Certaines corrections d’images, comme la déconvolution, la correction de contraste-luminosité, etc. était fait directement sur le GPU via les shaders.

Je crois même que le RPi a un décodeur h264 hardware. Vérifie que GStreamer utilise bien ça.

Un autre point a faire attention quand on utilise plusieurs libs, c’est qu’il y a parfois de conversion de données entre les libs (donc copie, allocation, etc), ce qui peut être coûteux.

Voici le graphique représentant le temps de calcul complet d’un traitement d’une frame:

Règle de base pour un graphique : tu dois faire apparaître le 0. Commencer l’axe des ordonnées a 25, ça peut être un 0 pointé dans un devoir/doc/publi.

le thread à normalement son cœur pour lui tout seul

Ca ne pourrait pas être tout simplement qu’il n’y a plus de thread dispo dans le pool et que la tâche est mise en pause quelque instant ?

Est-ce que cette ligne est due à l’OS qui fait sa tambouille en même temps?

Possible, c’est pas un OS "temps réel". (Pas sûr du terme correct)

Comment m’assurer d’avoir un linux propre pour exécuter mon logiciel sur la RPi ?

Du coup, peut être tester un linux "temps réel". (Mais je ne m’y connais pas du tout).

Dans tous les cas, ca ne sert a rien d’afficher le graph pour 10000000000 de frames. Affiches que 10–20 frames. Ajoutes d’autres infos sur le graph, comme le nombre de tâches en cours, la conso mémoire, etc. Peut être que tu trouveras une correspondance entre la perte de perfs sur certaines frames et autre chose.

+0 -0

Quelle est la demande et la contrainte à titre de curiosité ?

Sur le matériel on avait aucune contrainte à part le prix. Les seules contraintes qu’on avait étaient :

  • Développer un/des logiciels qui doivent tourner sur un rover et envoyer le flux video vers le serveur de réception
  • 500–300 ms de latence maximum

On est parti sur la RPi pour plusieurs raisons, même si j’en conviens, aujourd’hui j’aurais fait un choix différent :

  • C’est une plateforme que je connais bien, donc on s’évite la galère de configuration et on peut développer directement
  • Il fallait qu’on commande le matériel au tout début du projet, avant même de commencer le logiciel. Je n’avais jamais travaillé avant sur des points clouds donc je n’avais aucune idée des performances requises par la machine. La dernière RPi 4 avec 8Gb de RAM me semblait être un choix sur
  • Le budget était limité et les caméra stéréo, la plateforme du rover avec les moteurs en prennent déjà une bonne partie. (Oui on doit construire également un petit rover et le commander à distance pour prouver le bon fonctionnement de notre solution)

Évidemment, nous préciserons dans notre rapport et lors de la présentation que le matériel utilisé aura une grande influence sur les performances et qu’aujourd’hui nous nous tournerions plutôt vers autre chose qu’une RPi.

En tout cas bonne chance. Merci !

Le coût le plus important était la décompression des images par ffmpeg (ce qui était threadé). Puis j’affichais l’image directement dans le GPU comme une texture. Certaines corrections d’images, comme la déconvolution, la correction de contraste-luminosité, etc. était fait directement sur le GPU via les shaders.

Je vais donner ces informations à la personne en charge de la video, merci !

Je crois même que le RPi a un décodeur h264 hardware. Vérifie que GStreamer utilise bien ça.

Oui elle en a un, mais nous ne faisons qu’encoder sur la RPi, c’est le serveur de réception qui décode et qui affiche.

Règle de base pour un graphique : tu dois faire apparaître le 0. Commencer l’axe des ordonnées a 25, ça peut être un 0 pointé dans un devoir/doc/publi. Dans tous les cas, ca ne sert a rien d’afficher le graph pour 10000000000 de frames. Affiches que 10–20 frames. Ajoutes d’autres infos sur le graph, comme le nombre de tâches en cours, la conso mémoire, etc. Peut être que tu trouveras une correspondance entre la perte de perfs sur certaines frames et autre chose.

Merci, c’est noté!

Du coup, peut être tester un linux "temps réel". (Mais je ne m’y connais pas du tout).

J’ai déjà joué un peu avec FreeRTOS, je vais regarder plus en détail.

Le soucis avec cette approche est que tu ne traites pas toujours les données les plus récentes ; tu pourrais réduire la latence en traitant le dernier nuage de point reçu.

Comment ça ? Je traite les nuages de points aussi rapidement que je le peux, si je traite le dernier possible, il m’est impossible de traiter un seul nuage entièrement, ils arrivent trop vite.

Imaginons que tu arrives à traiter 10 nuages de point par seconde mais que tu en reçois 30 par seconde. Tu vas traiter le premier nuage reçu à t=0s, puis tu vas stocker celui qui arrive à t=1/30s pour traitement futur. À t=0.1s, tu auras fini de traiter ton premier nuage et tu traiteras celui que tu as stocké, qui est arrivé à t=1/30s. Ta latence est donc de 2/30 seconde (environ 67ms) + ton temps de traitement. L’autre solution est d’écraser le nuage de point à chaque fois qu’un nouveau arrive ; avec cette méthode tu traiteras à t=0.1s soit le deuxième nuage arrivé soit le troisième (en fonction du timing). Cette fois, ta latence sera entre ~0s et 1/30s (33ms).

J’aurai une question par rapport à ton projet du coup : n’as-tu pas eu de problèmes de latence ? Je n’ai pas réussi à avoir un flux vidéo sans latence en utilisant GStreamer, FFMPEG ou VLC comme clients (avec des flux non encodés) et je n’ai jamais trouvé de solution. La latence ne venait pas du processus d’émission du flux.

Héhé c’est justement un autre gros problème que l’on a actuellement. Encore une fois, nous avons une contrainte de l’ESA, une latence de maximum 500ms est acceptable pour piloter un rover, idéalement 300ms c’est mieux. Et après des mois de bataille avec GStreamer, nous avons réussi. Donc on envoie les frames en h264 avec GStreamer et la réception est également effectuée par GStreamer. Pour les afficher on utilise OpenCV dans une fenêtre Qt. Je ne suis pas la personne en charge de cette partie, si tu as des questions n’hésite pas, j’irais lui les poser.

C’est bien que vous aillez trouvé une solution. D’autres qui ont la même contrainte sont ceux qui cherche à faire du vol FPV sur des drones. Cf wifibroadcast. Raspberry Pi, flux vidéo live avec latence faible, ça ressemble vachement (sauf la partie transmission avec des émetteurs Wi-Fi qui vous intéresse probablement moins). Le blog contient des articles intéressants sur le sujet, bien que difficile à naviguer je trouve. Les forks ont des wikis intéressants. En bref, toute une communauté qui essaie de résoudre les mêmes soucis que vous.

Il semblerait y avoir un encodeur h264 hardware sur Raspberry Pi 4. Je n’ai pas suivi le tuto mais ça peut peut-être vous aider ?

Imaginons que tu arrives à traiter 10 nuages de point par seconde mais que tu en reçois 30 par seconde. Tu vas traiter le premier nuage reçu à t=0s, puis tu vas stocker celui qui arrive à t=1/30s pour traitement futur. À t=0.1s, tu auras fini de traiter ton premier nuage et tu traiteras celui que tu as stocké, qui est arrivé à t=1/30s. Ta latence est donc de 2/30 seconde (environ 67ms) + ton temps de traitement. L’autre solution est d’écraser le nuage de point à chaque fois qu’un nouveau arrive ; avec cette méthode tu traiteras à t=0.1s soit le deuxième nuage arrivé soit le troisième (en fonction du timing). Cette fois, ta latence sera entre ~0s et 1/30s (33ms).

Pour ce que j’ai compris de ses explications, il ignore les nuages de points intermédiaires, s’il n’a pas le temps de les traiter.

+0 -0

Pas compris ton message. Tu fais quoi des nuages de points que tu n’as pas traités et que tu remplaces par les données les plus récentes ?

Si tu les traites pas, que les données sont perdues et remplacées par des donnees plus recentes… alors c’est que tu les ignores. Je ne comprends pas ce que tu veux dire par "je conseille est de ne pas les ignorer".

+0 -0

Ah, oui. Dans ma compréhension de son traitement, il possède un emplacement pour un nuage de point en attente. Quand un nuage arrive et que cet emplacement est vide, il y est mis. S’il reçoit un autre nuage et que cet emplacement est pris, il ne fait rien du nouveau nuage.

Je conseille de remplacer le nuage déjà stocké par celui qui vient d’arriver (et donc d’oublier celui qui était précédemment stocké). De cette manière, il travaille sur des données plus récentes.

Imaginons que tu arrives à traiter 10 nuages de point par seconde mais que tu en reçois 30 par seconde. Tu vas traiter le premier nuage reçu à t=0s, puis tu vas stocker celui qui arrive à t=1/30s pour traitement futur. À t=0.1s, tu auras fini de traiter ton premier nuage et tu traiteras celui que tu as stocké, qui est arrivé à t=1/30s. Ta latence est donc de 2/30 seconde (environ 67ms) + ton temps de traitement. L’autre solution est d’écraser le nuage de point à chaque fois qu’un nouveau arrive ; avec cette méthode tu traiteras à t=0.1s soit le deuxième nuage arrivé soit le troisième (en fonction du timing). Cette fois, ta latence sera entre ~0s et 1/30s (33ms).

C’est exactement ce que nous faisons ! Je traite forcément le dernier nuage possible à l’instant ou le thread est libre. J’ai dû mal m’exprimer.

C’est bien que vous aillez trouvé une solution. D’autres qui ont la même contrainte sont ceux qui cherche à faire du vol FPV sur des drones. Cf wifibroadcast. Raspberry Pi, flux vidéo live avec latence faible, ça ressemble vachement (sauf la partie transmission avec des émetteurs Wi-Fi qui vous intéresse probablement moins). Le blog contient des articles intéressants sur le sujet, bien que difficile à naviguer je trouve. Les forks ont des wikis intéressants. En bref, toute une communauté qui essaie de résoudre les mêmes soucis que vous.

Il semblerait y avoir un encodeur h264 hardware sur Raspberry Pi 4. Je n’ai pas suivi le tuto mais ça peut peut-être vous aider ?

Merci beaucoup pour ces liens, c’est exactement ce dont on avait besoin!

Aujourd’hui nous avons passé notre RPi 4 sur Ubuntu 20.04 64 bits server, et nous avons doublé notre nombre de FPS pour atteindre les 25. Demain nous avons réunion avec l’ESA pour savoir si notre solution leur convient !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte