Aujourd'hui, nous allons voir comment détecter une boule rouge avec la caméra Raspberry PI et comment commencer à pointer notre drone vers elle.

Dans des articles précédents, nous avons examiné en détail le lancement d'un drone virtuel et réel autonome. Il est temps que notre drone trouve un véritable objectif.
Le but sera, comme nous l'avons mentionné, une balle rouge.
Préparation de framboise
Nous allons écrire un programme pour le filtre sur la version Desktop de Raspbian. Depuis pour configurer le filtre on va en même temps tordre les paramètres et voir le résultat de notre triche.
Sur une clé USB distincte, nous installerons Raspbian Desktop .
Pour travailler avec Raspbian desktop, vous avez besoin d'un moniteur + clavier + souris séparé connecté à Raspberry, ce qui n'est pas très pratique. Mais vous pouvez travailler avec le bureau sans tête Raspberry et sur le réseau, via VNC.
Pour ce faire, vous avez besoin de:
- Activer VNC dans raspi-config
- Configurez le hotspot Wifi sur la framboise. Le focus avec wpa_supplicant sur la version de bureau ne passe pas, l'instruction sur la configuration des points wifi sur Raspberry se trouve ici .
- En tant que client, vous pouvez utiliser realvnc .
Pour développer un filtre en Python - mettez OpenCV:
sudo apt-get install python-opencv
Filtre HSV pour le flux vidéo
Un moyen simple et rapide de mettre en surbrillance un objet coloré dans une image consiste à transférer l'image vers l' espace colorimétrique HSV , puis à filtrer en fonction de la plage souhaitée de teinte, de saturation et de valeur à l'aide de cv2.inRange. J'ai pris cet exemple comme base.
La particularité de notre tâche est que notre balle est rouge, et si nous regardons attentivement l'échelle des tons (HUE), nous verrons que la couleur rouge est sur ses bords:

Par conséquent, si vous ne filtrez qu'une seule partie de la gamme, lorsque l'éclairage change, la balle peut «disparaître» du filtre, ce qui affectera négativement la finalité de notre drone. Par conséquent, en plus des paramètres H, S et V, nous ajouterons le drapeau d'inversion d'inversion à notre filtre - afin de pouvoir filtrer tout sauf la balle, puis inverser simplement le filtre.
Le code du programme de filtrage est indiqué ci-dessous: Mettre le filtre sur la balle ressemble à ceci:
Le calcul de la position de la balle dans l'espace
Après avoir reçu le filtre, nous pouvons trouver la balle dans l'image du filtre en utilisant la fonction de mise en évidence des contours cv2.findContours
.
Dans notre programme, nous allons parcourir tous les contours trouvés, sélectionner ceux qui ont plus de 10x10 points et choisir le plus grand d'entre eux - ce sera la balle souhaitée. Si plusieurs objets frappent la caméra - à titre indicatif, nous utilisons le plus proche, c'est-à -dire le plus gros.
Nous dessinons les informations utiles du filtre dans l'image résultante: dessinez les contours trouvés et encerclez le plus grand d'entre eux, sélectionnez le centre de la ligne (où voler) avec les lignes, dérivez le diamètre de la balle aux points et calculez la distance à celle-ci, l'angle de lacet. De plus, au centre de l'écran, j'ai ajouté un «scope» + compté et affiché la fréquence d'images - pour contrôler la vitesse de notre filtre.
Le texte complet du programme de filtrage est donné ci-dessous: Le programme de l'image de la caméra prend en compte la distance par rapport à la balle et les angles de lacet et de tangage auxquels la balle s'écarte du centre de l'image de la caméra. Ces informations nous suffisent pour viser le drone sur le ballon. De plus, nous participerons au programme d'orientation.
Paquet de détection de balle ROS
La fonctionnalité développée peut être transférée vers le système sans tête Raspberry avec ROS installé. Nous allons créer un package ROS de ballon qui remplira les fonctions suivantes:
- Lancez mavros, en nous fournissant un contrĂ´leur de vol
- Exécutez notre programme de détection de balle. Dans le programme, nous ajouterons la publication des coordonnées de la balle et des images de débogage dans les sujets ROS correspondants
- Exécutez web_video_server - un composant ROS qui nous permettra de surveiller notre filtre de l'extérieur à l'aide d'un navigateur
Avant de créer le package ROS, ajoutez les fonctionnalités suivantes à notre programme de filtrage ROS pour travailler dans l'environnement ROS:
- Lecture des paramètres de la caméra. Les paramètres dans ROS sont définis sous la forme d'un fichier yaml, qui est généralement obtenu lors de l'étalonnage de la caméra . Nous ne sommes intéressés que par les tailles d'images (largeur et hauteur), mais afin de suivre le concept ROS, nous les obtiendrons du fichier yaml.
- Obtention des paramètres de filtre spécifiés. Nous noterons les paramètres de filtre sélectionnés précédemment dans le fichier de lancement de notre package ROS.
- Publication des coordonnées de balle reçues dans le sujet ROS
/baloon_detector/twist
- Publier des images de débogage dans les rubriques ROS
/baloon_detector/image_filter
et /baloon_detector/image_result
Vous pouvez exécuter le programme pour l'exécution en utilisant le python baloon_pose_cv.py
habituel - mais il existe également un moyen plus pratique - de regrouper les fonctionnalités dont nous avons besoin dans le package ROS et de configurer son exécution automatique au démarrage du système.
Il y a beaucoup de leçons sur la création de packages ROS sur le réseau , donc je me limiterai à la liste des étapes nécessaires.
Créons le répertoire de l'espace de travail ROS pour notre package et le package ROS lui-même:
mkdir -p ~/baloon_ws/src cd ~/baloon_ws/ catkin_make source devel/setup.bash cd src catkin_create_pkg baloon std_msgs rospy
Nous mettons dans le répertoire ~ / baloon_ws / src / baloon / src les fichiers nécessaires à l'exécution de notre package:
- baloon_pose_cv.py - programme de détection de balle
- baloon_cv.launch - fichier de lancement pour lancer notre package ROS
- fe130_320_01.yaml - fichier obtenu suite à l' étalonnage de la caméra . Nous nous intéressons uniquement à la taille de l'image, mais à l'avenir, ce fichier peut être utilisé pour une analyse plus approfondie des images, la restauration de scènes 3D à partir d'une image, etc.
- baloon.service, roscore.env - ces fichiers sont utilisés pour l'exécution automatique du package ROS
Voici les textes de chacun des fichiers:
baloon_pose_cv.py - le programme principal de détection de balle baloon_cv.launch - fichier de lancement pour lancer notre package ROS <launch> <include file="$(find mavros)/launch/px4.launch"> <arg name="fcu_url" value="/dev/ttyAMA0:921600"/> <arg name="gcs_url" value="tcp-l://0.0.0.0:5760"/> </include> <node name="baloon_detector" pkg="baloon" type="baloon_pose_cv.py" output="screen"> <param name="invert" value="1"/> <param name="h1" value="7"/> <param name="h2" value="158"/> <param name="s1" value="0"/> <param name="s2" value="255"/> <param name="v1" value="0"/> <param name="v2" value="255"/> <param name="real_ballon_r" value="0.145"/> <param name="camera_info_url" value="$(find baloon)/src/fe130_320_01.yaml"/> <param name="framerate" value="40"/> </node> <node name="web_video_server" pkg="web_video_server" type="web_video_server" required="false" respawn="true" respawn_delay="5"/> </launch>
fe130_320_01.yaml - fichier d'étalonnage de la caméra image_width: 320 image_height: 240 camera_name: main_camera_optical camera_matrix: rows: 3 cols: 3 data: [251.8636348237197, 0, 161.853506252244, 0, 252.36606604425, 102.0038140308112, 0, 0, 1] distortion_model: plumb_bob distortion_coefficients: rows: 1 cols: 5 data: [-0.4424451138703088, 0.1594038086314775, 0.006694781700363117, 0.00174908936506397, 0] rectification_matrix: rows: 3 cols: 3 data: [1, 0, 0, 0, 1, 0, 0, 0, 1] projection_matrix: rows: 3 cols: 4 data: [174.0442047119141, 0, 163.822732720786, 0, 0, 175.2916412353516, 105.5565883832869, 0, 0, 0, 1, 0]
Après avoir placé les fichiers dans le répertoire baloon_ws / src / baloon / src, vous devez ajouter l'attribut "fichier exécutable" (cmod + x) aux fichiers baloon_pose_cv.py et baloon.service. Ensuite, comme premier test, nous lançons notre nœud ROS manuellement:
roslaunch baloon baloon_cv.launch
Après avoir démarré le nœud, nous pouvons observer l'image de notre filtre et de notre boule via un navigateur Web:

Et obtenez également les coordonnées de la balle détectée dans le sujet /baloon_detector/twist
:
pi@raspberry:~ $ rostopic list |grep baloon /baloon_detector/image_filter /baloon_detector/image_result /baloon_detector/twist pi@raspberry:~ $ rostopic echo /baloon_detector/twist header: seq: 1 stamp: secs: 1554730508 nsecs: 603406906 frame_id: "fcu" twist: linear: x: 6.6452559203 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.137081068334 z: -0.165806278939 ---
Il reste à ajouter le démarrage automatique de notre nœud au début de Raspberry.
Pour ce faire, créez le fichier de description du service systemd baloon.service, avec le contenu suivant:
[Unit] Description=BALOON ROS package Requires=roscore.service After=roscore.service [Service] EnvironmentFile=/home/pi/baloon_ws/src/baloon/src/roscore.env ExecStart=/opt/ros/kinetic/bin/roslaunch baloon baloon_cv.launch --wait Restart=on-abort [Install] WantedBy=multi-user.target
Le fichier fait référence à la description des variables d'environnement roscore.env:
ROS_ROOT=/opt/ros/kinetic/share/ros ROS_DISTRO=kinetic ROS_PACKAGE_PATH=/home/pi/baloon_ws/src:/opt/ros/kinetic/share ROS_PORT=11311 ROS_MASTER_URI=http://localhost:11311 CMAKE_PREFIX_PATH=/home/pi/baloon_ws/devel:/opt/ros/kinetic PATH=/opt/ros/kinetic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin LD_LIBRARY_PATH=/opt/ros/kinetic/lib PYTHONPATH=/home/pi/catkin_ws/devel/lib/python2.7/dist-packages:/opt/ros/kinetic/lib/python2.7/dist-packages ROS_IP=192.168.11.1
La connexion et le démarrage du service s'effectuent à l'aide des commandes:
sudo systemctl enable ~/baloon_ws/src/baloon/src/baloon.service sudo systemctl start baloon
Le nœud devrait maintenant démarrer automatiquement au démarrage de Raspberry.
Vous pouvez arrêter le nœud avec la commande sudo systemctl stop baloon
, annuler le démarrage automatique - sudo systemctl disable balloon
.
À la suite de nos actions, nous avons obtenu un «détecteur de balle automatique» qui est lancé lorsque le système démarre sur l'ordinateur de bord.
Dans la prochaine partie, nous procéderons au lancement final d'un drone à tête chercheuse.
Le code source des programmes est publié sur Github .