IMA5 2018/2019 P22 : Différence entre versions
(→Réalisation du Projet) |
(→Conclusion) |
||
(151 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
__TOC__ | __TOC__ | ||
<br style="clear: both;"/> | <br style="clear: both;"/> | ||
+ | |||
+ | =Démonstration= | ||
+ | |||
+ | <center><include iframe src="https://www.youtube.com/embed/JEo3ZkRbA1g" width="680px" height="420px" frameborder="0" scrolling="yes"/></center> | ||
=Présentation générale= | =Présentation générale= | ||
Ligne 437 : | Ligne 441 : | ||
<center><include iframe src="https://www.youtube.com/embed/FRN0uHV3LK4" width="480px" height="320px" frameborder="0" scrolling="yes"/></center> | <center><include iframe src="https://www.youtube.com/embed/FRN0uHV3LK4" width="480px" height="320px" frameborder="0" scrolling="yes"/></center> | ||
− | ===Semaine 15=== | + | ==Semaine 15== |
+ | La semaine 11 et la semaine 12 sont pour les vacances de Noël, la semaine 13 et la semaine 14 sont pour les modules transversaux, donc nous recommencons notre projet à partir de la dernière semaine des modules transversaux. | ||
+ | |||
+ | Pendant cette semaine, nous avons pris un rendez-vous avec monsieur Pekpe, pour discuter les travaux en suite. Pour l'instant, nous pouvons recevoir tous les données de capteurs, mais elles sont en mauvaise format, comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_s15_1.png | center | 800px]] | ||
+ | |||
+ | Nous voulons les tranformer à un format plus facile à lire, ligne par ligne. Donc nous avons implémenté un petit code, pour changer le virgule à le retour, et puis l'enregistrer à un fichier de 'txt'. Le code est comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_s15_2.png | center | 600px]] | ||
+ | |||
+ | Le résultat après le traitement est comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_s15_3.png | left | 350px]][[Fichier:P22_s15_4.png | 350px]][[Fichier:P22_s15_5.png | 350px]] | ||
+ | |||
+ | Nous ne sommes pas intéressés par toutes les données, nous devons choisir des données relatives à la vitesse. | ||
+ | |||
+ | Et nous avons trouvé: | ||
+ | |||
+ | 'SpeedChanged_speedX': 0.1320406198501587 # Vitesse par rapport au nord (lorsque le drone se déplace vers le nord, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 | ||
+ | 'SpeedChanged_speedY': 0.014817928895354271 # Vitesse par rapport à l'est (lorsque le drone se déplace vers l'est, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 | ||
+ | 'SpeedChanged_speedZ': -0.006148712709546089 # Vitesse sur l'axe z (lorsque le drone descend, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 | ||
+ | 'moveByEnd_dX': 0.9047849178314209 # Distance parcourue dans l'axe avant (en m) # ardrone3.xml - 1081 | ||
+ | 'moveByEnd_dY': -0.0011207163333892822 # Distance parcourue dans l'axe droit (en m) # ardrone3.xml - 1081 | ||
+ | 'moveByEnd_dZ': -0.010766029357910156 # Distance parcourue dans l'axe descendant (en m) # ardrone3.xml - 1081 | ||
+ | |||
+ | L'explication de la fonction se trouve dans les deux fichiers suivants: | ||
+ | https://github.com/amymcgovern/pyparrot/blob/master/pyparrot/commandsandsensors/ardrone3.xml | ||
+ | https://github.com/amymcgovern/pyparrot/blob/master/pyparrot/commandsandsensors/common.xml | ||
+ | |||
+ | Mais le problème est que chaque fois que nous voulons que la valeur renvoyée par le capteur soit renvoyée, nous devons appeler la fonction bebop.sensors.sensors_dict une fois. Donc on ne peut pas obtenir les informations en temps réel. | ||
+ | Par conséquent, nous ne pouvons qu'abandonner cette méthode et réutiliser bebop_autonomy. | ||
+ | |||
+ | ==Semiane 16== | ||
+ | Cette semaine, nous avons fait un petit rendez-vous avec Monsieur Pekpe. Pour l'instant, nous pouvons reçu certaines données viennent de tous les capteurs, incluent la vitesse changée par rapport au nord, à l'est et sur l'axe z, et aussi la vitesse de rotation changée sur 3 axes (pitch, yaw, roll). Mais il n'y pas de vitesse en temps réel. Pour nous, nous pouvons réguler la distance et la radian, mais nous ne pouvons pas réguler la vitesse et la vitesse de rotation directement. Monsieur Pekpe nous a donné des idées, nous pouvons utiliser la méthod qui s'appelle 'Moyenne mobile' pour calculer la vitesse et la vitesse accélérée. Pour faire ça, la première étape est connaître c'est quoi 'Moyenne mobile'. | ||
+ | |||
+ | '''Moyenne mobile'''[https://fr.wikipedia.org/wiki/Moyenne_mobile] | ||
+ | |||
+ | On sais que pour calculer la vitesse, on peut utiliser le temps d'échantillon, divisé par la distance parcourue. Et pour la vitesse accélérée, on peut utiliser le temps d'échantillon, divisé par la différence entre la vitesse parcourue. | ||
+ | |||
+ | [[Fichier:P22_16_1.png | center | 100px ]] | ||
+ | |||
+ | Comme il y a de bruit dans le signal original, il faut tout d'abord faire le filtre, et puis faire la moyenne mobile. Monsieur Pekpe nous a dit, c'est mieux de faire la visualisation de ces courbes. Et comme notre programme est implémenté par python, nous avons cherché un biliothèque qui s'appelle 'Matplotlib' pour les graphiques. | ||
+ | |||
+ | [[Fichier:P22_16_2.png | center | 300px]] | ||
+ | |||
+ | '''Matplotlib'''[https://matplotlib.org/] | ||
+ | |||
+ | Matplotlib est une bibliothèque de traçage Python 2D qui produit des images de qualité publication dans divers formats de copie papier et environnements interactifs sur toutes les plateformes. | ||
+ | |||
+ | Et il y a aussi une autre question, c'est comment obtenir la vitesse sur 3 axes en temps réel. | ||
+ | |||
+ | ==Semaine 17== | ||
+ | Pendant la semaine dernière, nous avons essayé d'obtenir la vitesse de drones, mais il ne peut pas être arrivé avec pyparrot. Nous avons re-configuré notre environnement de travail pendant le week-end. | ||
+ | |||
+ | N'oublie pas de faire: | ||
+ | |||
+ | source ~/bebop_ws/devel/setup.bash | ||
+ | |||
+ | Ensuite, créer notre propre espace de travail. Situé dans bebop_ws/src. On a fait: | ||
+ | |||
+ | catkin_create_pkg [nom de notre espace de travail] std_msgs rospy nav_mgs roslib sensor_msgs | ||
+ | |||
+ | roscore est une collection de noeuds et le lancer est un prérequis pour l’utilisation d’un système basé ROS. | ||
+ | Il est nécessaire d’avoir roscore de lancé afin d’avoir une communication entre les noeuds ROS. On le lance dans le terminal avec la commande roscore. | ||
+ | |||
+ | Si on utilise la commande roslaunch, il lance automatiquement roscore s’il détecte qu’il n’est pas déjà en cours d’execution. | ||
+ | |||
+ | Roscore met alors en place : | ||
+ | |||
+ | -un ROS Master | ||
+ | -un serveur de parametre ros | ||
+ | -un noeud d’identification ROS. | ||
+ | |||
+ | Après cela il faut lancer le driver bebop autonomy en tant que noeud. | ||
+ | L’exécutable du noeud se nomme bebop_driver_node et se situe dans bebop_driver. | ||
+ | Il est recommandé d’executer le noeud dans son son espace avec sa configuration par défaut. | ||
+ | Le driver est accompagné d’un fichier executable bebop_driver/launch/bebop_node.launch | ||
+ | La procédure d’execution est la suivante : | ||
+ | |||
+ | $ roslaunch bebop_driver bebop_node.launch | ||
+ | |||
+ | Le roscore utilise un terminal pour la mise en place des différents paramètres. | ||
+ | Le bebop_node.launch utilise également un terminal pour la communication entre les différents noeuds. | ||
+ | On ouvre alors un troisième terminal où on tapera direcrement les instructions de commande. | ||
+ | |||
+ | En premier lieu, nous avons cherché le nom du topic sur lequel nous pouvons récupérer les informations. Pour cela nous avons lancé roslaunch et dans un second terminal nous avons lancé la commande : | ||
+ | |||
+ | rostopic list | ||
+ | |||
+ | Nous avons reçu ceci : | ||
+ | |||
+ | [[Fichier:P22_17_1.png | center | 400px]] | ||
+ | |||
+ | |||
+ | De dont, il y a un topic qui s'appelle '''/bebop/odom''', il est un standrad ROS topic, et son tpye de message est '''nav_msgs/Odometry''' | ||
+ | |||
+ | Le pilote intègre les estimations de la vitesse d'inertie visuelle rapportées par le microprogramme de Bebop pour calculer l’odométrie. Ce message contient à la fois la position et la vélocité du Bebop dans un cadre odometery aligné ENU, également appelé odom. Ce nom de trame est configurable (voir Paramètres du pilote). La convention de trame cooridnate est conforme à ROS REP 103 (types de messages standard ROS (i.e Twist, Odometery) - REP 103). Veuillez noter que l’odométrie étant calculée à partir des États Bebop (voir États (alias Navdata)), le taux de mise à jour est limité à 5 Hz. | ||
+ | |||
+ | Après afficher tous les informations de '''/bebop/odom''', nous avons utilisé la commande ci-dessous : | ||
+ | |||
+ | $ rostopic echo /bebop/odom | ||
+ | |||
+ | Et nous avons reçu ceci: | ||
+ | |||
+ | [[Fichier:P22_17_2.png | center | 800px]] | ||
+ | |||
+ | |||
+ | On peut voir qu'il y a deux partie de données, une partie de position et une autre partie de twist. Les messages de type '''geometry_msgs/Twist''' sont publiblié à '''cmd_vel''' topic. L’effet de chaque champ du message sur le mouvement de Bebop est décrit ci-dessous: | ||
+ | |||
+ | linear.x (+) Traduire en avant | ||
+ | linear.x (-) Traduire en arrière | ||
+ | linear.y (+) Traduire à gauche | ||
+ | linear.y (-) Traduire à droite | ||
+ | linear.z (+) Monter | ||
+ | linear.y (-) Descendre | ||
+ | angular.z (+) Tourner dans le sens antihoraire | ||
+ | angular.z (-) Le sens des aiguilles d'une montre | ||
+ | |||
+ | - Les parties '''linear.x''' et '''linear.y''' de ce message définissent respectivement les angles de tangage et de roulis du Bebop et contrôlent par conséquent ses accélérations vers l'avant et latérales. | ||
+ | |||
+ | - La partie '''linear.z''' de ce message contrôle la vitesse verticale du Bebop. La vitesse résultante en m/s | ||
+ | |||
+ | - La composante '''angular.z''' de ce message contrôle la vitesse de rotation du Bebop (autour de l'axe z). | ||
+ | |||
+ | Après ceci nous avons donc pu commencer à écrire notre code python pour récupérer les données[https://answers.ros.org/question/250143/subscribing-to-a-topic-with-python/]. Afin de le réaliser, nous nous sommes inspiré de ce code : | ||
+ | |||
+ | [[Fichier:P22_17_5.png | center | 600px]] | ||
+ | |||
+ | Notre code est donc le suivant : | ||
+ | |||
+ | [[Fichier:P22_17_3.png | center | 600px]] | ||
+ | |||
+ | En executant ce programme, nous recuperons ceci : | ||
+ | |||
+ | [[Fichier:P22_17_4.png | center | 600px]] | ||
+ | |||
+ | Pour traiter des données plus facilement, on a implémenté de code comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_17_6.png | center | 300px]] | ||
+ | |||
+ | Ce code réalise de transformer des données au format 'csv', il peut être ouvert par Excel, c'est facile de l'écrire et de le lire. Le tableau après le traitement est comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_17_7.png | center | 300px]] | ||
+ | |||
+ | |||
+ | Les valeurs du topic Odometry qui sont récupérées appartiennent à l'intervalle [-1;1]. C'est la pourcentage, avec le changement comme ci-dessous: | ||
+ | |||
+ | roll_degree = linear.y * max_tilt_angle | ||
+ | pitch_degree = linear.x * max_tilt_angle | ||
+ | ver_vel_m_per_s = linear.z * max_vert_speed | ||
+ | rot_vel_deg_per_s = angular.z * max_rot_speed | ||
+ | |||
+ | Avec l'angle max et la vitesse max, on peut obtenir la degrée de roll et la degrée de pitch, la vitesse de verticale et la vitesse de rotation( sur l'axe Z). | ||
+ | |||
+ | Nous avons trouvé les données du pourcentage, ensuite nous avons cherché les données du maximum. | ||
+ | |||
+ | Les paramètres ROS suivants modifient les paramètres de Bebop. Ils peuvent être modifiés pendant l'exécution à l'aide de l'interface graphique de reconfiguration dynamique. | ||
+ | |||
+ | http://wiki.ros.org/dynamic_reconfigure#dynamic_reconfigure.2BAC8-groovy.reconfigure_gui | ||
+ | |||
+ | Liste tous les nœuds reconfigurables: | ||
+ | |||
+ | rosrun dynamic_reconfigure dynparam list | ||
+ | |||
+ | Nous avons trouvé 4 sujets: | ||
+ | |||
+ | /bebop/bebop_driver | ||
+ | /bebop/image_raw/compressed | ||
+ | /bebop/image_raw/compressedDepth | ||
+ | /bebop/image_raw/theora | ||
+ | |||
+ | Les données relatives au vol devraient être sur /bebop_driver. | ||
+ | |||
+ | Après, récupère la configuration d'un noeud reconfigurable: | ||
+ | |||
+ | rosrun dynamic_reconfigure dynparam get /bebop/bebop_driver > read.txt | ||
+ | |||
+ | Nous pouvons voir: | ||
+ | |||
+ | [[Fichier:P22_read_config.png | center | 800px]] | ||
+ | |||
+ | Nous pouvons trouver: | ||
+ | |||
+ | 'PilotingSettingsMaxTiltCurrent': 20.0 | ||
+ | 'SpeedSettingsMaxVerticalSpeedCurrent': 1.0 | ||
+ | 'SpeedSettingsMaxRotationSpeedCurrent': 100.0 | ||
+ | |||
+ | Pour trouver la fréquence de publication du sujet: | ||
+ | |||
+ | rostopic hz /bebop/odom | ||
+ | |||
+ | Nous avons trouvé: | ||
+ | [[Fichier:P22_freq_cap.png | center | 300px]] | ||
+ | |||
+ | La fréquence de moyenne:f=5Hz. | ||
+ | |||
+ | Avec des informations ci-dessus, on peut faire la traitement de données. Nous voulons réaliser affichager de courbe de la vitesse (la vitesse verticale en m/s et la vitesse de rotation en degree/s). | ||
+ | |||
+ | Nous avons utiliser trois bibliothèque, '''csv''' est pour traiter des données en format csv, '''matplotlib.pyplot''' est pour dessiner les courbes, '''numpy''' est pour mathématique. | ||
+ | |||
+ | import csv | ||
+ | import matplotlib.pyplot as plt | ||
+ | import numpy as np | ||
+ | |||
+ | Et puis, nous avons ouvert le fichier qu'on a crée un certain moment avant et lu toutes les données ligne par ligne, on a crée 4 lists vides, comme nous avons 4 type de données, et puis on a met chaque données dans son list, et à la fin, on a fait un changement de chaque données à son valeur réel, parce que dans Bebop_autonomy, toutes les données sont en pourcentage, donc il faut multiplier avec son valeur maximal. Le code est comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_code_1.png | center | 600px]] | ||
+ | |||
+ | Et après, nous avons crée deux graph, sur chaque graph, il y a deux courbes, le premier graph est la relation entre le temps et la degrée, le deuxième graph est la relation entre le temps et la vitesse. Le code et comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_code_2.png | center | 500px]] | ||
+ | |||
+ | Avec les données qu'on a obtenu, après lancer le programme qu'on a implémenté, le résultat sont comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_deg_1.png | center | 300px]] | ||
+ | [[Fichier:P22_vit_1.png | center | 300px]] | ||
+ | |||
+ | Avec la visualisation, on peut voir très claire le changement et la perturbation de vitesse. | ||
+ | |||
+ | Ensuite, nous avons testé les commandes de pilotage: | ||
+ | |||
+ | $ rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}' | ||
+ | |||
+ | ==Semaine 18== | ||
+ | |||
+ | Cette semaine nous avons testé les commandes pour piloter: | ||
+ | |||
+ | Pour voir le vitesse d'avancer, on a fait 0.15 pour le valeur linear de x(en pourcentage): | ||
+ | |||
+ | Car linear.x répresente l'angle pas la vitesse, nous avons utilisé rostopic echo /bebop/states/ardrone3/PilotingState/SpeedChanged/speedX pour montrer la vraie vitesse comme indiqué ci-dessous | ||
+ | |||
+ | [[Fichier:P22_speed_X.png | center | 800px]] | ||
+ | |||
+ | Pour voir la vitesse d'augmenter, on a fait 0.2 pour la valeur linear de z(en pourcentage): | ||
+ | |||
+ | Nous pouvons voir la vraie vitesse: lin_z = 1 * msg.twist.twist.linear.z comme indiqué ci-dessous | ||
+ | |||
+ | [[Fichier:P22_speed_Z.png | center | 800px]] | ||
+ | |||
+ | Mais quand nous avons testé la rotation, le valeur de retour du capteur msg.twist.twist.angular.z est toujours 0. Nous ne savons pas la raison exacte. | ||
+ | |||
+ | Donc, nous avons utilisé rostopic echo /bebop/states/ardrone3/PilotingState/AttitudeChanged/yaw pour montrer l'angle(Ici c'est radian mais pas degré). | ||
+ | |||
+ | Chaque angle du drone a une valeur correspondante entre -3.14 et +3.14 (c'est à dire, chaque 1 radian répresente 57.32 degrés). | ||
+ | |||
+ | Calculez la différence entre les deux données adjacentes, puis divisez par l'intervalle de temps(environ 5Hz, l'intervalle est 0.2s). | ||
+ | |||
+ | De cette façon, nous pouvons calculer la vitesse de rotation angulaire(degré/s). | ||
+ | |||
+ | [[Fichier:P22_speed_rotation.png | center | 800px]] | ||
+ | |||
+ | Nous avons constaté que ces données réelles sont très proches de nos valeurs définies. Certaines valeurs trop élevées seront ajustées. En fin, il aura une tendance à être stable. | ||
+ | |||
+ | Nous pensons que le drone a une fonction de réparer automatiquement les erreurs. | ||
+ | |||
+ | Afin de faire régulation de la vitesse, nous avons une question: le PID est-il nécessaire? Comme on peut voir qu'à la fin, toutes les vitesse vont devenir la valeur qu'on a conseigné, la courbe est en première ordre. Après le temps de réponse, la vitesse est pseudo-stable, avec un petit peu de perturbation. Mais en fait, cette perturbation est normale et obligatoire, parce que quand il y a du vent ou d'autre chose, le drone change sa position, pour rentrer sa position initiale, il faut avoir une vitesse supplémentaire. Si on fait la correction de cette perturbation, la position de drone va changer, il ne peut plus rentrer la position initiale et puis il va perdu de stabilité. Et pour le vol stable, le drone peut correcter leur perturbation lui-même, pendant une durée très courte. Donc pour réguler la vitesse, nous pensons que c'est pas necessaire de faire un PID. | ||
+ | |||
+ | Nous avons une réunion avec Monsieur Gérald pendant le matin du mercredi, on lui a proposé trois questions. Le première question est comme nous n'arrivons jamais d'obtenir les valeurs de la vitesse de rotation par ROS Node, il nous a conseillé d'essayer de ROS Nodlet ou utiliser autre topic pour obtenir l'angle de rotation, et puis faire un petit calcul, par ce méthode, on peut obtenir la vitesse de rotation réel, et puis comparer avec la valeur qu'on a consigné. Il y a un delai par ce méthode, mais comme note fréquence est 5Hz, ça veut dire que l'intervalle du temps de changement est 0.2 seconde, donc un petit delai n'est pas grave. Et la deuxième question est comme j'ai écrit au-dessus, il y a déjà un PID dans le drone, pour réguler la vitesse, est-ce que c'est nécessaire d'ajouter un autre PID. La réponse est neutre, comme il a déjà un PID dans le drone, mais on ne sais pas les coefficients Kp,Ki,Kd de ce drone, si on veut faire un contrôlleur, il faut avoir les coefficients qui est plus grand que ses propres, si non le PID ajouté sera à rien, il ne fonctionne pas pour diminuer le temps de réponse. En même temps, il faut faire attention de la saturation, il faut éviter l'oscillation grave. Et la dernière question est pour l'instant, nous avons implèmenté un script pour réguler la vitesse, mais comme nous avons mis que '''latch=Ture''', tous les commandes lance qu'une fois, il ne peut pas lancer permanent, sauf qu'avec une boucle. Mais il a aussi un point négatif avec la boucle, c'est tous les commandes faut attendre par la queue, jusqu'à la fin de la commande dernière. Il nous a conseillé de utiliser un '''Publisher''' pour prendre la place de boucle. | ||
+ | |||
+ | * Supplément: Avec Monsieur Gérald, nous avons testé le nodelet pour voir les valeurs de Twist. Mais pas reussi, toujours 0 pour les valeurs. Habituellement, afin de fermer le noeud, nous choisirons d'utiliser une méthode de jugement comme while not rospy.is_shutdown(). Mais le problème actuel est que nous avons intégré toutes les fonctions dans un seul fichier et qu'une fois que nous faisons "shutdown comme ctrl+c", le programme entier est tué. Ajouter un "Publisher" avec tous les paramètres 0 est un bon moyen de survoler le drone.(Il doit savoir comment mettre à jour son statut.) | ||
+ | |||
+ | * Un autre supplément: Active le "verrouillage(latching)" sur une connexion. Lorsqu'une connexion est verrouillée, le dernier message publié est enregistré et envoyé automatiquement aux futurs abonnés(Subscribers) qui se connectent. Ceci est utile pour passer lentement à des données statiques telles qu'une carte. Notez que s'il existe plusieurs éditeurs(Publishers) sur le même sujet, instanciés dans le même nœud, alors seul le dernier message publié de ce nœud sera envoyé, par opposition au dernier message publié de chaque éditeur sur ce sujet unique. | ||
+ | |||
+ | Selon le mécanisme de fonctionnement de ROS, on sais que "Node" est le terme ROS pour un exécutable connecté au réseau ROS. Ici, nous allons créer les noeuds '''Publisher''' qui diffusera en permanence un message, et les noeuds '''Subscriber''' qui recevra le message. | ||
+ | |||
+ | Tout d'abord, il faut importer '''rospy''' si on veut créer un noeud. | ||
+ | |||
+ | import rospy | ||
+ | |||
+ | Et puis on a importé des | ||
+ | |||
+ | from std_msgs.msg import Empty | ||
+ | from geometry_msgs.msg import Twist | ||
+ | |||
+ | Donc on peut utiliser les types de message de '''std_msgs/Empty''' et '''geometry_msgs/Twist''' pour diffuser. | ||
+ | |||
+ | Les Publihsers pour décoller, atterrir, trouner et s'élever sont comme ci-dessous : | ||
+ | |||
+ | [[Fichier:P22_18_1.png | center | 500px]] | ||
+ | |||
+ | |||
+ | Cette section de code ci-dessous définit l'interface du locuteur avec le reste des ROS. | ||
+ | |||
+ | pub = rospy.Publisher("bebop/takeoff", Empty, queue_size=1, latch=True ) | ||
+ | pub = rospy.Publisher("bebop/land", Empty, queue_size=1, latch=True ) | ||
+ | pub = rospy.Publisher("bebop/cmd_vel", Twist, queue_size=1, latch=True) | ||
+ | pub = rospy.Publisher("bebop/cmd_vel", Twist, queue_size=1, latch=True) | ||
+ | |||
+ | pub = rospy.Publisher ("bebop/takeoff", Empty, queue_size=1, latch=True) déclare que notre noeud est en cours de publication dans la rubrique chatter à l'aide du type de message Empty. La chaîne ici est en fait la classe std_msgs.msg.Empty. L'argument queue_size est Nouveau dans ROS Hydro et limite le nombre de messages en file d'attente si un abonné ne les reçoit pas assez rapidement. Dans les anciennes distributions ROS, omettez simplement l'argument. | ||
+ | |||
+ | * Supplément: Ici, nous avons mis queue_size=1, parce que c'est une approche valable si nous voulons nous assurer qu’une nouvelle valeur publiée empêchera toujours d’abandonner les valeurs plus anciennes non encore envoyées. Pour un capteur qui ne se soucie que de la dernière mesure. N'envoyez jamais de mesures plus anciennes s'il en existe une nouvelle. | ||
+ | |||
+ | La ligne suivante, rospy.init_node (NAME, ...), est très importante car elle indique à Rospy le nom de notre noeud. Tant que Rospy n'aura pas cette information, il ne pourra pas commencer à communiquer avec le maître ROS. Dans ce cas, notre noeud prendra le nom de locuteur. anonymous = True garantit que notre noeud a un nom unique en ajoutant des nombres aléatoires à la fin de NAME. | ||
+ | |||
+ | rospy.init_node('réguler_la_vitesse', anonymous=True) | ||
+ | |||
+ | REMARQUE: le nom doit être un nom de base, c’est-à-dire qu’il ne peut contenir aucune barre oblique "/". | ||
+ | |||
+ | |||
+ | Et puis, nous voulons prendre de données(la valeur de vitesse consigné) et le lire vient de clavier, donc nous avons implémenté une interface, taper de valeur consigné dans la boîte de dialogue, et puis faire valider, et ensuite faire un jugement pour identifier ce sonts des chiffre efficace ou pas(dans une intervalle validée), si oui, il appele de fonction qu'on lui a demandé. | ||
+ | |||
+ | [[Fichier:P22_18_3.png | center | 500px]] | ||
+ | |||
+ | Il y a une boucle dans chaque fonction | ||
+ | |||
+ | i = 0 | ||
+ | while i < 50: | ||
+ | up(float_input) | ||
+ | i += 1 | ||
+ | sleep(0.2) | ||
+ | |||
+ | La paramètre '''i''' est pour compter, quand cette fonction est appelé, si est même si la vitesse est validé, cette boucle va lancer. Elle va lancer jusqu'à 50 fois, chaque fois durée 0.2 secondes(grace à la frequence est égale 5Hz),ça veut dire que la durée totale de cette boucle est égale 10 secondes. Pendant ces 10 secondes, le drone peut lancer successivement, il ne peut pas s'arrêter, sauf que une commande d'atterrir est reçu. Après il finira cette boucle, il peut lancer la commande suivante, sinon les commandes suivantes attendent dans la queue. | ||
+ | |||
+ | Nous utilisons également while not rospy.is_shutdown() pour faire une boucle au lieu de compter | ||
+ | |||
+ | while not rospy.is_shutdown(): | ||
+ | up(float_input) | ||
+ | |||
+ | Notre interface est comme ci-dessous: | ||
+ | |||
+ | [[Fichier:P22_interface.jpg | center | 600px]] | ||
+ | |||
+ | |||
+ | Afin d’obtenir les données renvoyées par le capteur et consigner la vitesse de l'axe Z et la vitesse de rotation du drone lors de l’utilisation de l’interface en même temps, nous avons implémenté 3 fonctions de CALLBACK, ces fonctions peuvent être appelé indépendamment dans le Subscriber. | ||
+ | |||
+ | Tout d'abord, on a importé des | ||
+ | |||
+ | from nav_msgs.msg import Odometry | ||
+ | from bebop_msgs.msg import Ardrone3PilotingStateSpeedChanged | ||
+ | from bebop_msgs.msg import Ardrone3PilotingStateAttitudeChanged | ||
+ | |||
+ | Donc on peut utiliser les types de message de '''nav_msgs/Odometry''', '''bebop_msgs/Ardrone3PilotingStateSpeedChanged''' et '''bebop_msgs/Ardrone3PilotingStateAttitudeChanged''' pour recevoir. | ||
+ | |||
+ | Les trois fonctions de CALLBACK sont comme ci-dessous : | ||
+ | |||
+ | [[Fichier:P22_18_5.png | center | 500px]] | ||
+ | |||
+ | Dans les fonctions de CALLBACK, il y a une ligne de | ||
+ | |||
+ | rospy.loginfo('LES INFO' % les_info) | ||
+ | |||
+ | qui effectue une triple tâche: les messages sont imprimés à l'écran, il est écrit dans le fichier journal du noeud, et il est écrit dans rosout. rosout est pratique pour le débogage: vous pouvez extraire des messages en utilisant rqt_console au lieu de devoir chercher la fenêtre de la console avec la sortie de votre noeud. | ||
+ | |||
+ | Et dans chaque fonction de CALLBACK, la dernière ligne est comme ça : | ||
+ | |||
+ | input_to_file_lin_z([lin_z]) | ||
+ | input_to_file_speed_xyz(speed_xyz) | ||
+ | input_to_file_ang_yaw([ang_yaw]) | ||
+ | |||
+ | '''input_to_file''' est une fonction pour importer toutes les données de capteur à un fichier en format csv, par ce méthode la, c'est plus simple de voir la tendance de courbe de vitesse, la fonction est comme ci-dessous : | ||
+ | |||
+ | [[Fichier:P22_18_7.png | center | 400px]] | ||
+ | |||
+ | |||
+ | Le code de listener.py est similaire à talker.py, sauf que nous avons introduit un nouveau mécanisme basé sur le rappel pour l’abonnement aux messages. | ||
+ | |||
+ | [[Fichier:P22_18_6.png | center | 800px]] | ||
+ | |||
+ | Cela déclare que notre noeud est abonné au sujet de discussion qui est de type std_msgs/msg. Lorsque de nouveaux messages sont reçus, le rappel est appelé avec le message comme premier argument. | ||
+ | |||
+ | Nous avons également modifié quelque peu l'appel à | ||
+ | |||
+ | rospy.init_node (). | ||
+ | |||
+ | Nous avons ajouté l'argument mot | ||
+ | |||
+ | anonymous = True. | ||
+ | |||
+ | Le ROS nécessite que chaque noeud ait un nom unique. Si un nœud portant le même nom apparaît, il remplace le précédent. C’est pour que les nœuds défectueux puissent facilement être renvoyés du réseau. L'indicateur anonymous = True indique à rospy de générer un nom unique pour le nœud afin que plusieurs noeuds listener.py puissent s'exécuter facilement. | ||
+ | |||
+ | Le dernier ajout | ||
+ | |||
+ | rospy.spin () | ||
+ | |||
+ | empêche simplement votre noeud de sortir jusqu'à ce que le noeud soit fermé. Contrairement à roscpp, rospy.spin () n’affecte pas les fonctions de rappel des abonnés, car celles-ci ont leurs propres threads. | ||
+ | |||
+ | Après nous avons récupéré les données, nous avons dessiné la courbe. | ||
+ | |||
+ | L'angle sur l'axe Z est comme ci-dessous : | ||
+ | |||
+ | [[Fichier:P22_18_8.png | center | 400px]] | ||
+ | |||
+ | Tout d'abord il n'y a pas de changement, et puis on a mis la vitesse de rotation égale à 20 degree/s, on peut voir que la vitesse change très rapidement, le temps de réponse est trop petit, et pendant la processus de rotation, la vitesse est très stable, elle est égale à le valeur de la pente. | ||
+ | |||
+ | Même si nous avons utilisé deux topic différents pour réguler la vitesse verticale sur l'axe Z, on peut voir que les deux façons est pseudo la même chose, sauf que tous les données est inverse. | ||
+ | |||
+ | Le premier graph est dessiné par les données qui reviennent de '''bebop_msgs/Ardrone3PilotingStateSpeedChanged''' | ||
+ | |||
+ | [[Fichier:P22_18_9.png | center | 400px]] | ||
+ | |||
+ | Le deuxième graph est dessiné par les données qui reviennent de '''nav_msgs/Odometry''' | ||
+ | |||
+ | [[Fichier:P22_18_10.png | center | 400px]] | ||
+ | |||
+ | Le premier changement subit de situation est la commande de décoller, et le dernier changement subit de situation est la commande d'atterrir, une unité égale 0.2 secondes. Entre la décollage et l'atterrissage, nous avons demandé augmenter l'altitude du drone par 0.25 m/s, durée 10 secondes. On peut voir que le temps de réponse est seulement 0.4 secondes, c'est assez rapide pour un drone, donc on pense que ce n'est pas nécessaire d'ajouter un supplémentaire contrôleur PID. | ||
+ | |||
+ | ==Semaine 19== | ||
+ | |||
+ | Comme l'objectif pour faire Tp dans la salle C305, on doit limiter le vol du drone. Nous devons considérer de la taille de la zone disponible pour le vol. | ||
+ | |||
+ | Nous avons defini le hauteur de vol maximale à 2m. rosrun dynamic_reconfigure dynparam set /bebop/bebop_driver PilotingSettingsMaxAltitudeCurrent 2.0 (in m) Ici, l'altitude indiquée est l'altitude au-dessus du point de décollage. C'est une valeur relative, pas une valeur réelle. | ||
+ | |||
+ | Pour la gamme de vol, tout d'abord, nous avons defini à 5m pour tester. rosrun dynamic_reconfigure dynparam set /bebop/bebop_driver PilotingSettingsMaxDistanceValue 5.0 (in m) | ||
+ | |||
+ | En même temps, pour valider la définition de la gamme de vol, nous devons définir le valeur de PilotingSettingsNoFlyOverMaxDistanceShouldnotflyover comme 1. De cette façon, le drone ne peut pas voler plus que la limite. | ||
+ | |||
+ | Il marche bien pour la hauteur maximale de vol est fixée à deux mètres au-dessus du point de décollage. | ||
+ | |||
+ | Et nous avons testé les limites du déplacement horizontal aussi. Nous avons trouvé qu'il y a une valeur minimale de 10 pour la valeur de PilotingSettingsMaxDistanceValue. | ||
+ | |||
+ | [[Fichier:limit_distance.png | center | 1000px]] | ||
+ | |||
+ | Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 11, la valeur reçu = 11 ; Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 10.5, la valeur reçu = 10.5; Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 9.9, la valeur reçu = 10. Nous ne pouvons pas définir une valeur qui est moins 10, c'est à dire, il est irréaliste de vouloir définir une portée de trois ou cinq mètres. Logiquement, ce n’est pas d’une valeur adaptée pour voler à l’intérieur, si vous voulez lancer une commande à l'intérieur, vous devez faire 100% attention. | ||
+ | |||
+ | Et pour le temps reste, nous avons cherché la façon pour améliorer la boucle, et nous avons ecrit le rapport et le PPT. | ||
+ | |||
+ | =Conclusion= | ||
+ | En ce qui concerne le résumé, ce projet est une application proposée par l'enseignant et utilisée pour l'enseignement en salle. Grâce à ce projet, nous avons découvert les systèmes ROS et certaines interfaces liées aux drones. Afin de contrôler le drone, nous avons finalement choisi bebop_autonomy, le pilote basé sur l’ARDroneSDK3 officiel de Parrot. Compréhension approfondie du mécanisme de communication du noeud ROS, puis utilisation de la bibliothèque d'interface Rospy Python sur ROS pour créer leur propre programme d'interface de contrôle. Nous sommes très heureux de participer à ce nouveau projet de développement au cours duquel nous avons pris beaucoup de détours, mais nous avons résolu de nombreux problèmes. Nous avons non seulement amélioré nos performances, mais nous avons également laissé une expérience pertinente aux futurs développeurs. | ||
=Documents Rendus= | =Documents Rendus= | ||
Ligne 443 : | Ligne 865 : | ||
[[Fichier: Présentation_Intermédiaire_P22.pdf ]] | [[Fichier: Présentation_Intermédiaire_P22.pdf ]] | ||
+ | |||
+ | [[Fichier: Rapport_Final_P22.pdf ]] | ||
+ | |||
+ | [[Fichier: Présentation_Final_P22.pdf ]] | ||
+ | |||
+ | [[Fichier: boutton_vitesse_file.zip ]] |
Version actuelle datée du 28 février 2019 à 15:59
Sommaire
Démonstration
Présentation générale
Description
Le but de notre projet est réaliser le commande en position d'un drone Parrot Bebop 2.
Pour réaliser ce projet, nous avons à notre disposition le drone Parrot Bebop 2. Nous testons donc d'abord le drone volant, nous utilisons la manette de pilotage ou de l'application smartphone FreeFlight Pro pour le contrôler.La fonctionnalité cible étant une application payante, afin de mieux comprendre le thème de notre projet, nous avons regardé une vidéo sur le Web qui présentait la fonctionnalité ‘follow me’ de bebop.
Notre projet se concentre sur la détection d'images et l'analyse de l'environnement à l'aide d'un capteur d'image situé au bas du drone (à cause de la perte du signal de GPS dans la salle), permettant au drone d'atteindre un vol stable et de suivre la cible, avec rejet de perturbations.Le développement des applications pourra se faire sous Linux en passant par ROS, Robot Operating System, grâce à Matlab Simulink ou une application sous le langage Python.
Une démarche de prospection et de recherche bibliographique doit être entreprise sur tous ces outils en début de projet.
Afin de mettre en œuvre ce projet, nous soumettons un rapport à monsieur Komi Midzodzi PEKPE après avoir terminé nos travaux chaque jour, où nous montrons nos progrès et choisissons les mesures à prendre en conséquence.
Objectifs
Les objectifs peuvent être divisés en trois phases:
- D'abord nous devons assurer que le perroquet peut voler de façon stable.
- Nous concevons l'itinéraire de vol et le réaliser.
- Utiliser la technologie de traitement d'image pour effectuer le suivi des objets spécifiés. Peut-être nous pouvons mettre en œuvre une variété de fonctions de suivi.
Préparation du projet
Cahier des charges
Choix techniques : matériel et logiciel
- Parrot Bobop 2
- Un PC linux avec une installation de ROS Kinetic
- ROS Kinetic Kame vise principalement la version Ubuntu 16.04 (Xenial), bien que d'autres systèmes Linux, ainsi que Mac OS X, Android et Windows, soient pris en charge à des degrés divers.
- Driver ROS <<Bebop_autonomy>>:
- Bebop_autonomy est un pilote ROS pour drone Parrot Bebop, basé sur l’ARDroneSDK3 officiel de Parrot.
- SDK Parrot:
- Le SDK Parrot nous aide à connecter, contrôler, recevoir des flux vidéo, enregistrer et télécharger des fichiers multimédias (photos et vidéos), envoyer et lire des plans de vol, des mises à jour et plus encore. Le SDK est principalement écrit en C, qui fournit une base de données pour les systèmes UNIX, ANDROID et IOS. Il est également livré avec un simulateur de drone appelé SPHINX qui nous aide à tester votre application avant de piloter le drone pour garantir la sécurité du vol.
- SIMULINK®
- Le pack de support Simulink® pour PARROT® Minidrones nous permet de concevoir et de construire des algorithmes de contrôle de vol pour les minidrones PARROT. Nous pouvons déployer des algorithmes sans fil via Bluetooth® Low Energy. Les algorithmes peuvent accéder aux capteurs embarqués, tels que les capteurs à ultrasons, les accéléromètres, les gyroscopes et les capteurs de pression d'air, ainsi qu'à la caméra orientée vers le bas.
- PYTHON
Liste des tâches à effectuer
- Découverte, prise en main et pilotage du drone
- Recherche/Documentation sur les différents composants du drone
- Recherche/Documentation pour définir quels outils nous allons choisir
- Stabilisation du drone
- Gérer le traitement d'images
- Suivre la cible
- Réalisation d'un rapport final exploitable afin que les personnes souhaitant travailler sur ce projet puissent ajouter eux même ce qu'ils souhaitent, et mettre en avant leurs connaissances et compétences
Calendrier prévisionnel
Réalisation du Projet
Semaine 1
Durant la première semaine, nous nous sommes entretenues avec monsieur Komi Midzodzi PEKPE à mieux définir le contexte du projet et leurs attentes quant à ce projet. Nous avons ensuite effectué des recherches générales sur le drone pour connaître ses capacités et être plus familier avec les différents capteurs qu'il possède ainsi que des recherches sur les différentes technologies/logiciels utilisables avec le drone pour préparer le développement futur.
L'opération du drone
- Nous avons commencé à prendre en main le drone en effectuant des premiers vols en utilisant FlightFree Pro (une application iOS/Android) proposée par Parrot et de la manette pilotage.
Recherche du drone
- Une caméra verticale qui permet le maintien d’un point fixe.
- Un capteur ultrason qui analyse l'altitude de vol jusqu'à 5 mètres.
- Un gyroscope 3 axes qui permet de calculer l’angle d’inclinaison de l’appareil.
- Un magnétomètre 3 axes qui donne la possibilité de définir la position du drone, à l’image d’une boussole.
- Un GPS et un GLONASS pour la géolocalisation du drone et aide à mesurer la vitesse de drone pour plus de stabilité à haute altitude.
- Un capteur de pression qui permet de mesurer la pression et de calculer l'altitude de vol lorsque celle-ci dépasse les 5 mètres.
- Un accéléromètre qui permet de mesurer l’orientation du drone sur 3 axes et sa vitesse linéaire.
Recherche des technologies/logiciels
ROS
ROS (Robot Operating System) fournit des bibliothèques et des outils pour aider les développeurs de logiciels à créer des applications robotiques. Il fournit une abstraction matérielle, des pilotes de périphérique, des bibliothèques, des visualiseurs, la transmission de messages, la gestion des packages, etc. ROS est sous licence Open Source, BSD.
Nous avons choisi ROS Kinetic comme l’environnement pour développer notre projet. Et puis nous l’avons installé sur mon PC, comme l’ordinateur dans la salle C303 a une version d’Ubuntu 14.04, ce n’est pas possible d’installer ROS Kinetic sur lui.
Après nous l’avons installé, nous faisions de test.
Nous avons exécuté la commande suivante dans terminal:
$ roscore
Et puis nous avons ouvert un nouveau terminal et avons exécuté la commande suivante pour ouvrir la petite fenêtre tortue :
$ rosrun turtlesim turtlesim_node
Et en suite nous avons ouvert un nouveau terminal, exécuté la commande suivante pour ouvrir la fenêtre de contrôle de la tortue, utilisez les touches fléchées pour contrôler le mouvement de la tortue :
$ rosrun turtlesim turtle_teleop_key
A la fin, nous avons sélectionné la fenêtre de contrôle et appuyez sur les touches fléchées pour voir la tortue dans la petite fenêtre de la tortue.
Et puis nous avons ouvert un nouveau terminal, exécuté la commande suivante, nous pouvons voir l'interface graphique de ROS, montrant la relation entre les nœuds
$ rosrun rqt_graph rqt_graph
À ce stade, le test est terminé, indiquant que l'installation de ROS ne pose aucun problème.
Vous pouvez trouver de plus d'information ici : http://wiki.ros.org/
Driver ROS <<Bebop_autonomy>>
Bebop_autonomy est un pilote ROS pour les drones Parrot Bebop 1.0 et 2.0 (quadricoptères), basé sur ARDroneSDK3 officiel de Parrot . Ça peut être utilisé pour lancer le pilote, envoyer de commandes à Bebop, lecture de Bebop, configuration de Bebop et du pilote.
Pour l'installation, des conditions pré-requis sont comme ci-dessous:
- ROS Indigo , Jade ou Kinetic (uniquement testé sur Ubuntu )
- Paquets Ubuntu: build-esstential, python-rosdep,python-catkin-tools
- Connaissance élémentaire de la création de packages ROS
Et puis on utilise ce commande pour l'installer:
$ sudo apt-get install build-essential python-rosdep python-catkin-tools
Pour compiler à partir de la source, vous devez cloner le code source dans un catkin espace de travail nouveau ou existant , utiliser rosdep pour installer des dépendances et enfin compiler l'espace de travail à l'aide de catkin . Les commandes suivantes illustrent cette procédure dans un catkin espace de travail nouvellement créé .
# Create and initialize the workspace $ mkdir -p ~/bebop_ws/src && cd ~/bebop_ws $ catkin init $ git clone https://github.com/AutonomyLab/bebop_autonomy.git src/bebop_autonomy # Update rosdep database and install dependencies (including parrot_arsdk) $ rosdep update $ rosdep install --from-paths src -i # Build the workspace $ catkin build
Pour plus d'information : https://bebop-autonomy.readthedocs.io/en/latest/index.html
Semaine 2
SDK Parrot
Le SDK vous aidera à vous connecter, à piloter, à recevoir des flux, à enregistrer et à télécharger des médias (photo et vidéo), à envoyer et à lire des plans de vol sur pilote automatique et à mettre à jour votre drone. Vous pouvez l'utiliser sur les Spider Rolling, Cargos, Mambo, Swing, Sumo Jumping, Evo Sumo, Bebop Drone, Bebop 2, Bebop 2 Power, Disco, Bluegrass, SkyController et SkyController 2.
FreeFlight Pro utilise ce SDK.
Ce SDK est principalement écrit en C, il fournit des bibliothèques pour le système Unix, Android et iOS.
Il est également livré avec un simulateur de drone appelé Sphinx, conçu pour vous aider à tester votre application avant de voler avec votre drone actuel.
UNIX BUILD Linux: testé sur Ubuntu 14.04
La commande permettant de créer la plate-forme SDK pour Unix est la suivante:
$ ./build.sh -p arsdk-native -t build-sdk -j
La sortie sera dans <SDK>/out/Unix-base/staging/usr/
Les tâches disponibles sont:
$ build-sdk (Construire un sdk natif) $ build-sample (Construire tous les échantillons natifs) $ build-sample-SAMPLE_NAME (exemple de compilation d'und sdk pour SAMPLE_NAME)
Lancer les échantillons:
Pour exécuter les exemples, vous devez ajouter le dossier <SDK>/out/arsdk-native/staging/usr/lib à la variable d'environnement LD_LIBRARY_PATH. Cela peut être effectué à l'aide du script <SDK> /out/Unix-base/staging/native-wrapper.sh.
Ce script peut être utilisé des deux manières suivantes:
- En tant que script shell pour appeler un seul échantillon:
$ ./out/arsdk-native/staging/native-wrapper.sh ./out/arsdk-native/staging/usr/bin/BebopSample
Ou si vous avez un ordinateur MacOs:
$ ./out/arsdk-native/staging/native-darwin-wrapper.sh ./out/arsdk-native/staging/usr/bin/BebopSample
- En tant que script source permettant de définir les variables d'environnement PATH et LD_LIBRARY_PATH:
$ source ./out/arsdk-native/staging/native-wrapper.sh.
Après avoir recherché ce script, vous pouvez appeler directement les échantillons par leur nom sans indiquer de chemin complet, car le dossier <SDK>/out/arsdk-native/staging/usr/bin sera ajouté à votre chemin.
Pour plus d'informqtion : https://developer.parrot.com/docs/SDK3/#general-information
SIMULINK®
PARROT Minidrones Support de Simulink pour concevoir, simuler et déployer des algorithmes pour piloter PARROT Minidrones.
Le pack d'assistance Simulink ® pour PARROT ® Minidrones vous permet de concevoir et de construire des algorithmes de contrôle de vol pour les minidrones PARROT. Vous pouvez déployer des algorithmes sans fil via Bluetooth ® Low Energy. Les algorithmes peuvent accéder aux capteurs intégrés, tels que les capteurs à ultrasons, accéléromètre, gyroscope et pression atmosphérique, ainsi qu'à la caméra orientée vers le bas.
Les outils complémentaires Simulink offrent des fonctionnalités supplémentaires. Aerospace Blockset ™ comprend un exemple utilisant les minidrones PARROT. L'exemple vous permet de modéliser des équations de mouvement à 6 DOF et de simuler le comportement d'un aéronef dans diverses conditions de vol et environnementales. Simulink Coder ™ vous permet d’enregistrer des données de vol sur le minidrone et d’accéder au code C généré à partir de modèles Simulink.
Vous pouvez ajouter des exemples de modèles et d'algorithmes existants pour améliorer les contrôleurs de vol prédéfinis ou commencer à partir de zéro et développer de nouveaux algorithmes de contrôle de vol.
Pour plus d'information : https://ww2.mathworks.cn/hardware-support/parrot-minidrones.html
Semaine 3
Pyparrot
Pyparrot est conçu pour programmer les drones Parrot Minidrone et Parrot Bebop (1 ou 2) à l’aide de Python. Cette interface a été développée pour enseigner aux enfants de tous âges (K-20) les concepts STEM (programmation, mathématiques, etc.) en leur permettant de programmer un drone pour qu'il vole de manière autonome.
Installation, démarrage rapide, documentation, FAQ ou plus d'information : https://pyparrot.readthedocs.io/en/latest/
Des problèmes
Il y avait un problème de la connexion entre l'ordinateur et le drone, la machine virtuelle ne pouvait pas appeler le wifi. Parce que la carte réseau sans fil ne peut pas être ajoutée dans la machine virtuelle VMware. Le lien d'internet entre la machine virtuelle et le windows est par la méthode NAT. En faite, il y a trois méthode pour accéder à l'internet pour la machine virtuelle :
- NAT
- Host-only
- Bridge
Mais seulement la méthode Bridge permet à la machine virtuelle d’avoir différentes adresses IP indépendantes de l’hôte, tout en conservant le même segment de réseau que l’hôte, ce qui permet d’ajouter toutes les machines virtuelles au réseau local de l’hôte local, qui fait partie du réseau local. L'ajout à d'autres hôtes n'est pas différent. Du point de vue de la technologie réseau, cela revient à ajouter un commutateur virtuel à l’hôte frontal, puis à ce que l’hôte et toutes les machines virtuelles partagent le commutateur ou tout simplement à comprendre qu’il est amélioré sur l’hôte pour lui faire passer un commutateur (bien sûr, un commutateur virtuel). ) pour l'hôte hôte et les autres machines virtuelles du segment de réseau.
Après une configuration difficile, la connexion réseau de la machine virtuelle est devenue Bridge, mais la connection entre le drone et le Linux n'a pas encore réussi. Donc nous avons donc décidé d'installer le système d'ubuntu 16.04 et tous les logiciels/travaux environnements sur la base de Windows 10.
Après, on va essayer à faire la connexion et puis contrôler le drone.
Semaine 4
Après une semaine d’installation et de débogage fastidieux, nous avons finalement terminé la connexion entre drone et linux.
Ils peuvent communiquer normalement et transmettre certains flux d'informations.
Semaine 5
Ces dernières semaines, nous avons travaillé à la construction de l'environnement de travail, à l'installation et aux tests du logiciel, à la connexion entre le drone et la console (ordinateur), à la recherche de méthode possible pouvant être appelées et lues sur capteur d'image du fond du drone, mais n'a pas réussi à appeler le capteur d'image au fond du drone. Qu'il s'agisse de l'outil de développement officiel SDK ou de tout autre outil de développement secondaire open source sur Internet, il n'y a aucun moyen d'appeler le capteur.
Après avoir discuté avec professeur, nous avons appris que le drone dispose de deux Linux, la caméra frontale est sous le premier Linux mais tous les capteurs appartiennent au deuxième système Linux. L'instructeur a suggéré que nous ne devrions pas envisager d'appeler la caméra inférieure pour le moment, en commençant par la tâche consistant à utiliser l'ordinateur pour contrôler le décollage / l'atterrissage / la stabilité du drone.
Pour atteindre cet objectif, nous avons utilisé python comme langage de programmation.
Tout d'abord, nous avons utilisé le Python3 (Nous avons utilisé le https://www.anaconda.com/download/ installer et le gestionnaire de paquets pour python) et Untangle Package (utilisé pour analyser les fichiers xml dans le SDK parrot)
Et ensuite, pour la connexion Wifi, nous avons installé le logiciel zeroconf.
A la fin, nous avons installé une bibliothèque https://github.com/amymcgovern/pyparrot pour les drones de python.
Logiciels requis:
- Python 3: Nous avons utilisé le https://www.anaconda.com/download/ :: installer et le gestionnaire de paquets pour python. Notez que lorsque nous installons anaconda, installez également l’option Visual Studio.
- Démêler le paquet: Utilisé pour analyser les fichiers XML dans le SDK de Parrot
pip install untangle
- Vision: Si vous avez l'intention de traiter les fichiers de la caméra, vous devez installer opencv, puis ffmpeg ou VLC. J'ai installé ffmpeg en utilisant brew pour le mac mais apt-get sur linux devrait également fonctionner. Pour VLC, vous DEVEZ installer le programme `VLC <https://www.videolan.org/vlc/index.html`_ (et pas seulement la bibliothèque en python). Il doit être à la version 3.0.1 ou supérieure. (Pas encore finir cette étape )
- Connexion Wifi: zeroconf Pour installer le logiciel zeroconf, procédez comme suit:
pip install zeroconf
- Connexion BLE: pybluez (notez que ceci est UNIQUEMENT pour le support sans caméra!) Ceci est UNIQUEMENT supporté sur Linux. Pour installer le logiciel BLE, procédez comme suit:
sudo apt-get install bluetooth sudo apt-get install bluez sudo apt-get install python-bluez
- Notez qu'il est également possible que vous deviez installer bluepy (si ce n’est pas déjà fait). Ces commandes devraient le faire:
sudo apt-get install python-pip libglib2.0-dev sudo pip install bluepy sudo apt-get update
Installation à partir de la source:
- Commencez par télécharger pyparrot en clonant le référentiel à l’adresse https://github.com/amymcgovern/pyparrot. Les instructions correspondantes sont décrites ci-dessous.
git clone https://github.com/amymcgovern/pyparrot cd pyparrot
Assurez-vous d'installer les autres packages nécessaires (wifi ou BLE, vision, etc.) comme spécifié ci-dessus.
Installation à partir de Pip:
pip install pyparrot
Assurez-vous d'installer les autres packages nécessaires (wifi ou BLE, vision, etc.) comme spécifié ci-dessus.
Quelques commandes Bebop:
Bebop (drone_type = "Bebop2")
Crée un objet Bebop avec un argument optionnel drone_type pouvant être utilisé pour créer un objet bebop one ou bebop 2. La valeur par défaut est Bebop 2.
connect (num_retries)
Connectez-vous aux services wifi du Bebop. Cela effectue une poignée de main. Cela peut prendre plusieurs secondes pour s'assurer que la connexion fonctionne. Vous pouvez spécifier un nombre maximal de nouvelles tentatives. Retourne true si la connexion est réussie ou False sinon.
disconnect ()
Déconnecte de la connexion wifi.
safe_takeoff (timeout)
C'est la méthode recommandée pour le décollage. Il envoie une commande puis vérifie les capteurs (via l'état de vol) pour s'assurer que le bebop est en train de décoller. Ensuite, il attend que le bebop vole ou flotte pour revenir. Il expirera et reviendra si le temps dépasse les secondes.
safe_land (timeout)
C'est la méthode recommandée pour atterrir le bebop. Envoie des commandes jusqu'à ce que le bebop ait réellement atteint l'état atterri. Il expirera et reviendra si le temps dépasse les secondes.
smart_sleep (secondes)
Ceci dort le nombre de secondes (qui peut être une virgule flottante) mais est activé pour toutes les notifications wifi.
ask_for_state_update ()
Ceci envoie une demande au bebop pour renvoyer TOUS les états. Les données sont renvoyées assez rapidement mais pas instantanément. Le bebop a déjà une fréquence de rafraîchissement du capteur de 10Hz, mais tous les capteurs ne sont pas envoyés automatiquement. Si vous recherchez un capteur spécifique qui n’est pas envoyé automatiquement, vous pouvez l’appeler, mais je ne recommande pas de l’envoyer encore et encore. La plupart des capteurs dont vous avez besoin doivent être envoyés à la fréquence 10Hz ou comme un événement appelé déclenchant ce capteur.
fly_direct(roll, pitch, yaw, vertical_movement, duration)
Faites voler le bebop directement en utilisant les mouvements de roulis, de tangage, de lacet et de verticalité spécifiés. Les commandes sont répétées pendant des secondes. Chaque valeur va de -100 à 100 et correspond essentiellement à un pourcentage et à une direction de max_tilt (pour le roulis / la hauteur) ou de max_vertical_speed (pour le mouvement vertical).
Ensuite, nous avons créé un fichier de type python(test.py) pour tester quelques commandes pour contrôler le drone.
Nous avons constaté que l'exécution des instructions n'était pas toujours bonne, bien qu'il n'y eût aucun problème de décollage et d'atterrissage.
Par exemple, en supposant que nous ayons fermé les portes et les fenêtres de la salle C305 pour nous assurer que le vent ne soit pas dérangé, nous voulons que le drone décolle et puis vole droit à une distance défini, et puis atterrit, il ne peut pas le faire. Il va altérer lui-même (on peut le voit clairement dans le vidéo après, il vole droit et puis il rentre, enfin, il a atterri le long de la barre oblique et n'a pas atterri en ligne droite), plutôt que de pouvoir se stabiliser sur une coordonnée. Une vidéo du test est enregistrée ici:
Et puis on a testé le même code pour deuxième fois, il vole comme ça : il vole pour une distance plus longe qu’on l’a définie.
Et les résultats montrent que le capteur est problématique aussi. Pour ce résultat, nous voulons le tester dans un autre environnement. Comme le vol du bebop2 est causé par le vent descendant de quatre hélices, le sol n’est pas plat ou les objets environnants peuvent avoir un impact. Nous pensons toujours qu'il peut y avoir des facteurs d'interférence inconnus dans la zone de test. Dans cette salle, le drone est également difficile à contrôler/stabiliser même si on utilise APP FreeFlight Pro (Lorsque nous ne faisons rien, le drone volera librement et sera incontrôlé).
Semaine 6
Afin de comprendre la cause de ce problème, nous avons effectué une recherche sur Internet. Nous pensons que le champ magnétique de la classe C305 interfère avec certaines performances du capteur du drone. Comme il y a beaucoup de robots et d'ordinateurs dans la salle C305 et qu'il y a des correctifs métalliques sur le site expérimental, ceux-ci peuvent avoir un impact sur l'étalonnage géomagnétique du bebop2, ce qui empêche le bebop2 de planer ou de voler comme prévu.
Afin de vérifier notre hypothèse, nous avons exécuté notre code dans le hall d'entrée de Polytech (environnement intérieur) et sur l'herbe à l'extérieur de Polytech (environnement extérieur).
On peut voir clairement dans ce vidéo, sur l'herbe à l'extérieur de Polytech (environnement extérieur), notre drone peut décoller, et puis voler droit à une distance défini, enfin atterrir, il peut régulièrement effectuer cette série de tâches sans autre action que l'exécution de code.
Et ensuite, on a testé le code pour le décoller, faire une pause et atterrir dans le hall d’entrée de Polytech, le drone marche bien, sans arrêté sans action surprenante.
Semaine 7
Nous avons installé opencv pour le traitement des images. (partie des travaux non terminée de semaine5)
Pourquoi ce problème se produit-il? Parce que quand compiler opencv, l’interface de python est ouvert. Si la compilation réussit, le fichier de bibliothèque partagée cv2.so sera généré sous Linux. Pour l'importer correctement, il faut mettre cv2.so dans le chemin ou python peut trouver le package ou modifier la variable d'environnement PYTHONPATH pour inclure le chemin où cv2.so existe. Pour résoudre ce problème, nous avons recherché les informations pertinentes, puis ajouté la ligne suivante à la fin du fichier .bashrc ouvert: export PYTHONPATH = "/home/parrotbebop2/anaconda3/lib/python3.5/site-packages:$PYTHONPATH"
Après, on va le rester:
Mais pour ffmpeg, bien que ce soit déjà la dernière version de ubuntu16.04, cela ne semble pas être suffisant.
Maintenant, c'est la version 2.8
Peut-être je dois mettre à niveau ffmpeg vers la version 3.4, nous allons l'essayer ensuite. Notre plan suivant: Après finir les préparations, nous allons tester la sortie vidéo du drone et essayer à trouver des moyens de traiter l’image.
Semaine 8
La semaine dernière, nous n’avons pas réussi à utiliser l’OpenCV pour accéder aux photos et vidéos de camera horizontal avec ffmpeg en version 2.8, cela ne semble pas être suffisant pour l’OpenCV en version 3.2.
Nous avons démonté ffmpeg en version 2.8, et puis nous avons réinstallé la version 3.4, qui est plus haute. Et puis, nous avons essayé d’accéder aux photos et vidéos de camera horizontal en utilisant OpenCV, le résultat était bon.
Nous avons codé un petit programme en utilisant python, dans le travail environnement de ROS, utilisant la bibliothèque graphique de l’OpenCV.
Ce programme réalise les fonctions de connecter avec le drone lui-même, si la télécommunication entre le drone et l’ordinateur n’a aucun de problème, il va démarrer le camera horizontal, pour retourner des vidéos à l’ordinateur.
Après notre ordinateur reçoit des vidéos, il va mettre chaque frame de vidéo dans un fichier, en format ‘png’, et mettre la propriété de vidéo dans un document en format ‘sdp’ en même temps.
Si tous les process avant sont réussi, le drone va décoller, son altitude n’est pas supérieure à 5m, et rester en l’air dans une position pour un instant (ça peut être modifié), et puis il va avancer pour une distance avec la vitesse maximale de 1m/s, et puis il reste dans une position pour un instant, après il va reculer la même distance qu’il est avancé, et reste l’air pour un instant.
A la fin, il va descendre, arrêter de mettre des photos, atteindre le camera horizontal, retourner le pourcentage d’électricité reste du batterie et disconnecter avec l’ordinateur.
Les codes sont comme ci-dessous
Les images sont enregistrées dans un dossier.
Pour réaliser la fonction ‘Suivi’, nous voulons faire de traitement d’image avec les photos qu’on sauvegarde. Nous avons fait de recherche de l’algorithme pour traiter des images.
Notre idée est faire la comparaison de deux photos, identifier les éléments similaires entre les deux, et puis trouver de notre objectif. Nous voulons utiliser un algorithme qui s’appelle SIFT (La scale-invariant feature transform).
C'est quoi la SIFT
La scale-invariant feature transform (SIFT), que l'on peut traduire par « transformation de caractéristiques visuelles invariante à l'échelle », est un algorithme utilisé dans le domaine de la vision par ordinateur pour détecter et identifier les éléments similaires entre différentes images numériques (éléments de paysages, objets, personnes, etc.). Il a été développé en 1999 par le chercheur David Lowe.
Pourquoi la SIFT
Pour identifier les éléments similaires entre les deux photos, tout d'abord de détecter sur l'image des zones circulaires « intéressantes », centrées autour d'un point-clé et de rayon déterminé appelé facteur d'échelle. Celles-ci sont caractérisées par leur unité visuelle et correspondent en général à des éléments distincts sur l'image. Sur chacune d'elles, on détermine une orientation intrinsèque qui sert de base à la construction d'un histogramme des orientations locales des contours, habilement pondéré, seuillé et normalisé pour plus de stabilité. C'est cet histogramme qui sous la forme d'un vecteur à 128 dimensions (ou valeurs) constitue le descripteur SIFT du point-clé, et l'ensemble des descripteurs d'une image établissent ainsi une véritable signature numérique du contenu de celle-ci.
Ces descripteurs présentent l'avantage d'être invariants à l'orientation et à la résolution de l'image, et peu sensibles à son exposition, à sa netteté ainsi qu'au point de vue 3D. Ils possèdent ainsi des propriétés similaires à celles des neurones du Cortex visuel primaire qui permettent la détection d'objet en intégrant les composantes de base comme les formes, la couleur ainsi que le mouvement.
Semaine 9
Puisque la version correspondante n'est pas trouvée à l'aide de pip, on a téléchargé le package d'installation, le décompressé et le placé dans le chemin correspondant (sous site-packages).
Comment faire les commandes CMake?
$ cd <opencv_build_directory> $ cmake -DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules <opencv_source_directory> $ make -j5
Normalement, opencv sera construit dans <opencv_build_directory> avec tous les modules du référentiel opencv_contrib. On ne peut pas installer plusieurs packages différents dans le même environnement. Comme tous les packages utilisent le même espace de noms (cv2), il faut désinstaller le package précédent.
Semaine 10
Le but de notre projet est réalisé la commande en position d'un drone Parrot Bebop 2.
Comme un drone peut décoller, atterrir, avancer, reculer, pivoter, basculer et prendre des photographies aériennes, nous espérons mettre en œuvre un contrôle cinématique du drone. Il peut s'agir d'un contrôle de la position spatiale du drone, d'un contrôle basé sur le traitement d'image ou d'un contrôle de vitesse du drone. Il existe de nombreuses possibilités pour ce contrôle de la cinématique, nous étudions les fonctionnalités qui nous intéressent et essayons de mettre en œuvre cette fonction.
Dans la première moitié de nos études, nous avons mené des recherches sur le contrôle de la position spatiale des drones sur la base du traitement des images. Nous étions à l'origine prêts à implémenter l'algorithme en python, cependant, étant donné que l'image doivent être modélisées après le traitement par cette méthode, la position du drone peut être contrôlée avec précision, ce qui prend trop de temps et ne peut pas être appliqué à un apprentissage ultérieur. Donc, pour les travails ensuite, nous sommes plus intéressants à contrôler et réguler la vitesse de ce drone par une interface.
Pour la seconde moitié du travail, nous serons plus intéressés par le contrôle de la vitesse de rotation du drone.
Notre professeur nous a suggéré de créer d’abord une interface d’exploitation afin que nous puissions contrôler nos drones en temps réel à l’aide des boutons sur l’interface. Nous avons donc ajouté une interface sur la base de l'original et nous pouvons la contrôler en temps réel via des boutons.
Pour l’instant, nous avons déjà réussi de contrôler ce drone pour décoller et atterrir.
Nous mettons actuellement en œuvre l'utilisation de boutons pour contrôler la vitesse de rotation de drone et contrôler la distance de vol de drone. Nous devons mettre certaines conditions limitées, par exemple, la hauteur maximum, la vitesse de rotation limite, la vitesse de voler maximum, pour garantir la sécurité dans le cas de l’utiliser dans une salle. Nous avons utilisé trois axes comme ci-dessous comme des variables à réguler :
Une démonstration de contrôler de drone par notre interface. Il a réalisé de décoller, atterrir, voler à gauche, voler à droite, avancer, reculer, tourner en rad, augmenter, descendre, connecter et déconnecter.
Semaine 15
La semaine 11 et la semaine 12 sont pour les vacances de Noël, la semaine 13 et la semaine 14 sont pour les modules transversaux, donc nous recommencons notre projet à partir de la dernière semaine des modules transversaux.
Pendant cette semaine, nous avons pris un rendez-vous avec monsieur Pekpe, pour discuter les travaux en suite. Pour l'instant, nous pouvons recevoir tous les données de capteurs, mais elles sont en mauvaise format, comme ci-dessous:
Nous voulons les tranformer à un format plus facile à lire, ligne par ligne. Donc nous avons implémenté un petit code, pour changer le virgule à le retour, et puis l'enregistrer à un fichier de 'txt'. Le code est comme ci-dessous:
Le résultat après le traitement est comme ci-dessous:
Nous ne sommes pas intéressés par toutes les données, nous devons choisir des données relatives à la vitesse.
Et nous avons trouvé:
'SpeedChanged_speedX': 0.1320406198501587 # Vitesse par rapport au nord (lorsque le drone se déplace vers le nord, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 'SpeedChanged_speedY': 0.014817928895354271 # Vitesse par rapport à l'est (lorsque le drone se déplace vers l'est, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 'SpeedChanged_speedZ': -0.006148712709546089 # Vitesse sur l'axe z (lorsque le drone descend, la vitesse est> 0) (en m/s) # ardrone3.xml - 835 'moveByEnd_dX': 0.9047849178314209 # Distance parcourue dans l'axe avant (en m) # ardrone3.xml - 1081 'moveByEnd_dY': -0.0011207163333892822 # Distance parcourue dans l'axe droit (en m) # ardrone3.xml - 1081 'moveByEnd_dZ': -0.010766029357910156 # Distance parcourue dans l'axe descendant (en m) # ardrone3.xml - 1081
L'explication de la fonction se trouve dans les deux fichiers suivants:
https://github.com/amymcgovern/pyparrot/blob/master/pyparrot/commandsandsensors/ardrone3.xml https://github.com/amymcgovern/pyparrot/blob/master/pyparrot/commandsandsensors/common.xml
Mais le problème est que chaque fois que nous voulons que la valeur renvoyée par le capteur soit renvoyée, nous devons appeler la fonction bebop.sensors.sensors_dict une fois. Donc on ne peut pas obtenir les informations en temps réel. Par conséquent, nous ne pouvons qu'abandonner cette méthode et réutiliser bebop_autonomy.
Semiane 16
Cette semaine, nous avons fait un petit rendez-vous avec Monsieur Pekpe. Pour l'instant, nous pouvons reçu certaines données viennent de tous les capteurs, incluent la vitesse changée par rapport au nord, à l'est et sur l'axe z, et aussi la vitesse de rotation changée sur 3 axes (pitch, yaw, roll). Mais il n'y pas de vitesse en temps réel. Pour nous, nous pouvons réguler la distance et la radian, mais nous ne pouvons pas réguler la vitesse et la vitesse de rotation directement. Monsieur Pekpe nous a donné des idées, nous pouvons utiliser la méthod qui s'appelle 'Moyenne mobile' pour calculer la vitesse et la vitesse accélérée. Pour faire ça, la première étape est connaître c'est quoi 'Moyenne mobile'.
Moyenne mobile[1]
On sais que pour calculer la vitesse, on peut utiliser le temps d'échantillon, divisé par la distance parcourue. Et pour la vitesse accélérée, on peut utiliser le temps d'échantillon, divisé par la différence entre la vitesse parcourue.
Comme il y a de bruit dans le signal original, il faut tout d'abord faire le filtre, et puis faire la moyenne mobile. Monsieur Pekpe nous a dit, c'est mieux de faire la visualisation de ces courbes. Et comme notre programme est implémenté par python, nous avons cherché un biliothèque qui s'appelle 'Matplotlib' pour les graphiques.
Matplotlib[2]
Matplotlib est une bibliothèque de traçage Python 2D qui produit des images de qualité publication dans divers formats de copie papier et environnements interactifs sur toutes les plateformes.
Et il y a aussi une autre question, c'est comment obtenir la vitesse sur 3 axes en temps réel.
Semaine 17
Pendant la semaine dernière, nous avons essayé d'obtenir la vitesse de drones, mais il ne peut pas être arrivé avec pyparrot. Nous avons re-configuré notre environnement de travail pendant le week-end.
N'oublie pas de faire:
source ~/bebop_ws/devel/setup.bash
Ensuite, créer notre propre espace de travail. Situé dans bebop_ws/src. On a fait:
catkin_create_pkg [nom de notre espace de travail] std_msgs rospy nav_mgs roslib sensor_msgs
roscore est une collection de noeuds et le lancer est un prérequis pour l’utilisation d’un système basé ROS. Il est nécessaire d’avoir roscore de lancé afin d’avoir une communication entre les noeuds ROS. On le lance dans le terminal avec la commande roscore.
Si on utilise la commande roslaunch, il lance automatiquement roscore s’il détecte qu’il n’est pas déjà en cours d’execution.
Roscore met alors en place :
-un ROS Master -un serveur de parametre ros -un noeud d’identification ROS.
Après cela il faut lancer le driver bebop autonomy en tant que noeud. L’exécutable du noeud se nomme bebop_driver_node et se situe dans bebop_driver. Il est recommandé d’executer le noeud dans son son espace avec sa configuration par défaut. Le driver est accompagné d’un fichier executable bebop_driver/launch/bebop_node.launch La procédure d’execution est la suivante :
$ roslaunch bebop_driver bebop_node.launch
Le roscore utilise un terminal pour la mise en place des différents paramètres. Le bebop_node.launch utilise également un terminal pour la communication entre les différents noeuds. On ouvre alors un troisième terminal où on tapera direcrement les instructions de commande.
En premier lieu, nous avons cherché le nom du topic sur lequel nous pouvons récupérer les informations. Pour cela nous avons lancé roslaunch et dans un second terminal nous avons lancé la commande :
rostopic list
Nous avons reçu ceci :
De dont, il y a un topic qui s'appelle /bebop/odom, il est un standrad ROS topic, et son tpye de message est nav_msgs/Odometry
Le pilote intègre les estimations de la vitesse d'inertie visuelle rapportées par le microprogramme de Bebop pour calculer l’odométrie. Ce message contient à la fois la position et la vélocité du Bebop dans un cadre odometery aligné ENU, également appelé odom. Ce nom de trame est configurable (voir Paramètres du pilote). La convention de trame cooridnate est conforme à ROS REP 103 (types de messages standard ROS (i.e Twist, Odometery) - REP 103). Veuillez noter que l’odométrie étant calculée à partir des États Bebop (voir États (alias Navdata)), le taux de mise à jour est limité à 5 Hz.
Après afficher tous les informations de /bebop/odom, nous avons utilisé la commande ci-dessous :
$ rostopic echo /bebop/odom
Et nous avons reçu ceci:
On peut voir qu'il y a deux partie de données, une partie de position et une autre partie de twist. Les messages de type geometry_msgs/Twist sont publiblié à cmd_vel topic. L’effet de chaque champ du message sur le mouvement de Bebop est décrit ci-dessous:
linear.x (+) Traduire en avant linear.x (-) Traduire en arrière linear.y (+) Traduire à gauche linear.y (-) Traduire à droite linear.z (+) Monter linear.y (-) Descendre angular.z (+) Tourner dans le sens antihoraire angular.z (-) Le sens des aiguilles d'une montre
- Les parties linear.x et linear.y de ce message définissent respectivement les angles de tangage et de roulis du Bebop et contrôlent par conséquent ses accélérations vers l'avant et latérales.
- La partie linear.z de ce message contrôle la vitesse verticale du Bebop. La vitesse résultante en m/s
- La composante angular.z de ce message contrôle la vitesse de rotation du Bebop (autour de l'axe z).
Après ceci nous avons donc pu commencer à écrire notre code python pour récupérer les données[3]. Afin de le réaliser, nous nous sommes inspiré de ce code :
Notre code est donc le suivant :
En executant ce programme, nous recuperons ceci :
Pour traiter des données plus facilement, on a implémenté de code comme ci-dessous:
Ce code réalise de transformer des données au format 'csv', il peut être ouvert par Excel, c'est facile de l'écrire et de le lire. Le tableau après le traitement est comme ci-dessous:
Les valeurs du topic Odometry qui sont récupérées appartiennent à l'intervalle [-1;1]. C'est la pourcentage, avec le changement comme ci-dessous:
roll_degree = linear.y * max_tilt_angle pitch_degree = linear.x * max_tilt_angle ver_vel_m_per_s = linear.z * max_vert_speed rot_vel_deg_per_s = angular.z * max_rot_speed
Avec l'angle max et la vitesse max, on peut obtenir la degrée de roll et la degrée de pitch, la vitesse de verticale et la vitesse de rotation( sur l'axe Z).
Nous avons trouvé les données du pourcentage, ensuite nous avons cherché les données du maximum.
Les paramètres ROS suivants modifient les paramètres de Bebop. Ils peuvent être modifiés pendant l'exécution à l'aide de l'interface graphique de reconfiguration dynamique.
http://wiki.ros.org/dynamic_reconfigure#dynamic_reconfigure.2BAC8-groovy.reconfigure_gui
Liste tous les nœuds reconfigurables:
rosrun dynamic_reconfigure dynparam list
Nous avons trouvé 4 sujets:
/bebop/bebop_driver /bebop/image_raw/compressed /bebop/image_raw/compressedDepth /bebop/image_raw/theora
Les données relatives au vol devraient être sur /bebop_driver.
Après, récupère la configuration d'un noeud reconfigurable:
rosrun dynamic_reconfigure dynparam get /bebop/bebop_driver > read.txt
Nous pouvons voir:
Nous pouvons trouver:
'PilotingSettingsMaxTiltCurrent': 20.0 'SpeedSettingsMaxVerticalSpeedCurrent': 1.0 'SpeedSettingsMaxRotationSpeedCurrent': 100.0
Pour trouver la fréquence de publication du sujet:
rostopic hz /bebop/odom
Nous avons trouvé:
La fréquence de moyenne:f=5Hz.
Avec des informations ci-dessus, on peut faire la traitement de données. Nous voulons réaliser affichager de courbe de la vitesse (la vitesse verticale en m/s et la vitesse de rotation en degree/s).
Nous avons utiliser trois bibliothèque, csv est pour traiter des données en format csv, matplotlib.pyplot est pour dessiner les courbes, numpy est pour mathématique.
import csv import matplotlib.pyplot as plt import numpy as np
Et puis, nous avons ouvert le fichier qu'on a crée un certain moment avant et lu toutes les données ligne par ligne, on a crée 4 lists vides, comme nous avons 4 type de données, et puis on a met chaque données dans son list, et à la fin, on a fait un changement de chaque données à son valeur réel, parce que dans Bebop_autonomy, toutes les données sont en pourcentage, donc il faut multiplier avec son valeur maximal. Le code est comme ci-dessous:
Et après, nous avons crée deux graph, sur chaque graph, il y a deux courbes, le premier graph est la relation entre le temps et la degrée, le deuxième graph est la relation entre le temps et la vitesse. Le code et comme ci-dessous:
Avec les données qu'on a obtenu, après lancer le programme qu'on a implémenté, le résultat sont comme ci-dessous:
Avec la visualisation, on peut voir très claire le changement et la perturbation de vitesse.
Ensuite, nous avons testé les commandes de pilotage:
$ rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}'
Semaine 18
Cette semaine nous avons testé les commandes pour piloter:
Pour voir le vitesse d'avancer, on a fait 0.15 pour le valeur linear de x(en pourcentage):
Car linear.x répresente l'angle pas la vitesse, nous avons utilisé rostopic echo /bebop/states/ardrone3/PilotingState/SpeedChanged/speedX pour montrer la vraie vitesse comme indiqué ci-dessous
Pour voir la vitesse d'augmenter, on a fait 0.2 pour la valeur linear de z(en pourcentage):
Nous pouvons voir la vraie vitesse: lin_z = 1 * msg.twist.twist.linear.z comme indiqué ci-dessous
Mais quand nous avons testé la rotation, le valeur de retour du capteur msg.twist.twist.angular.z est toujours 0. Nous ne savons pas la raison exacte.
Donc, nous avons utilisé rostopic echo /bebop/states/ardrone3/PilotingState/AttitudeChanged/yaw pour montrer l'angle(Ici c'est radian mais pas degré).
Chaque angle du drone a une valeur correspondante entre -3.14 et +3.14 (c'est à dire, chaque 1 radian répresente 57.32 degrés).
Calculez la différence entre les deux données adjacentes, puis divisez par l'intervalle de temps(environ 5Hz, l'intervalle est 0.2s).
De cette façon, nous pouvons calculer la vitesse de rotation angulaire(degré/s).
Nous avons constaté que ces données réelles sont très proches de nos valeurs définies. Certaines valeurs trop élevées seront ajustées. En fin, il aura une tendance à être stable.
Nous pensons que le drone a une fonction de réparer automatiquement les erreurs.
Afin de faire régulation de la vitesse, nous avons une question: le PID est-il nécessaire? Comme on peut voir qu'à la fin, toutes les vitesse vont devenir la valeur qu'on a conseigné, la courbe est en première ordre. Après le temps de réponse, la vitesse est pseudo-stable, avec un petit peu de perturbation. Mais en fait, cette perturbation est normale et obligatoire, parce que quand il y a du vent ou d'autre chose, le drone change sa position, pour rentrer sa position initiale, il faut avoir une vitesse supplémentaire. Si on fait la correction de cette perturbation, la position de drone va changer, il ne peut plus rentrer la position initiale et puis il va perdu de stabilité. Et pour le vol stable, le drone peut correcter leur perturbation lui-même, pendant une durée très courte. Donc pour réguler la vitesse, nous pensons que c'est pas necessaire de faire un PID.
Nous avons une réunion avec Monsieur Gérald pendant le matin du mercredi, on lui a proposé trois questions. Le première question est comme nous n'arrivons jamais d'obtenir les valeurs de la vitesse de rotation par ROS Node, il nous a conseillé d'essayer de ROS Nodlet ou utiliser autre topic pour obtenir l'angle de rotation, et puis faire un petit calcul, par ce méthode, on peut obtenir la vitesse de rotation réel, et puis comparer avec la valeur qu'on a consigné. Il y a un delai par ce méthode, mais comme note fréquence est 5Hz, ça veut dire que l'intervalle du temps de changement est 0.2 seconde, donc un petit delai n'est pas grave. Et la deuxième question est comme j'ai écrit au-dessus, il y a déjà un PID dans le drone, pour réguler la vitesse, est-ce que c'est nécessaire d'ajouter un autre PID. La réponse est neutre, comme il a déjà un PID dans le drone, mais on ne sais pas les coefficients Kp,Ki,Kd de ce drone, si on veut faire un contrôlleur, il faut avoir les coefficients qui est plus grand que ses propres, si non le PID ajouté sera à rien, il ne fonctionne pas pour diminuer le temps de réponse. En même temps, il faut faire attention de la saturation, il faut éviter l'oscillation grave. Et la dernière question est pour l'instant, nous avons implèmenté un script pour réguler la vitesse, mais comme nous avons mis que latch=Ture, tous les commandes lance qu'une fois, il ne peut pas lancer permanent, sauf qu'avec une boucle. Mais il a aussi un point négatif avec la boucle, c'est tous les commandes faut attendre par la queue, jusqu'à la fin de la commande dernière. Il nous a conseillé de utiliser un Publisher pour prendre la place de boucle.
- Supplément: Avec Monsieur Gérald, nous avons testé le nodelet pour voir les valeurs de Twist. Mais pas reussi, toujours 0 pour les valeurs. Habituellement, afin de fermer le noeud, nous choisirons d'utiliser une méthode de jugement comme while not rospy.is_shutdown(). Mais le problème actuel est que nous avons intégré toutes les fonctions dans un seul fichier et qu'une fois que nous faisons "shutdown comme ctrl+c", le programme entier est tué. Ajouter un "Publisher" avec tous les paramètres 0 est un bon moyen de survoler le drone.(Il doit savoir comment mettre à jour son statut.)
- Un autre supplément: Active le "verrouillage(latching)" sur une connexion. Lorsqu'une connexion est verrouillée, le dernier message publié est enregistré et envoyé automatiquement aux futurs abonnés(Subscribers) qui se connectent. Ceci est utile pour passer lentement à des données statiques telles qu'une carte. Notez que s'il existe plusieurs éditeurs(Publishers) sur le même sujet, instanciés dans le même nœud, alors seul le dernier message publié de ce nœud sera envoyé, par opposition au dernier message publié de chaque éditeur sur ce sujet unique.
Selon le mécanisme de fonctionnement de ROS, on sais que "Node" est le terme ROS pour un exécutable connecté au réseau ROS. Ici, nous allons créer les noeuds Publisher qui diffusera en permanence un message, et les noeuds Subscriber qui recevra le message.
Tout d'abord, il faut importer rospy si on veut créer un noeud.
import rospy
Et puis on a importé des
from std_msgs.msg import Empty from geometry_msgs.msg import Twist
Donc on peut utiliser les types de message de std_msgs/Empty et geometry_msgs/Twist pour diffuser.
Les Publihsers pour décoller, atterrir, trouner et s'élever sont comme ci-dessous :
Cette section de code ci-dessous définit l'interface du locuteur avec le reste des ROS.
pub = rospy.Publisher("bebop/takeoff", Empty, queue_size=1, latch=True ) pub = rospy.Publisher("bebop/land", Empty, queue_size=1, latch=True ) pub = rospy.Publisher("bebop/cmd_vel", Twist, queue_size=1, latch=True) pub = rospy.Publisher("bebop/cmd_vel", Twist, queue_size=1, latch=True)
pub = rospy.Publisher ("bebop/takeoff", Empty, queue_size=1, latch=True) déclare que notre noeud est en cours de publication dans la rubrique chatter à l'aide du type de message Empty. La chaîne ici est en fait la classe std_msgs.msg.Empty. L'argument queue_size est Nouveau dans ROS Hydro et limite le nombre de messages en file d'attente si un abonné ne les reçoit pas assez rapidement. Dans les anciennes distributions ROS, omettez simplement l'argument.
- Supplément: Ici, nous avons mis queue_size=1, parce que c'est une approche valable si nous voulons nous assurer qu’une nouvelle valeur publiée empêchera toujours d’abandonner les valeurs plus anciennes non encore envoyées. Pour un capteur qui ne se soucie que de la dernière mesure. N'envoyez jamais de mesures plus anciennes s'il en existe une nouvelle.
La ligne suivante, rospy.init_node (NAME, ...), est très importante car elle indique à Rospy le nom de notre noeud. Tant que Rospy n'aura pas cette information, il ne pourra pas commencer à communiquer avec le maître ROS. Dans ce cas, notre noeud prendra le nom de locuteur. anonymous = True garantit que notre noeud a un nom unique en ajoutant des nombres aléatoires à la fin de NAME.
rospy.init_node('réguler_la_vitesse', anonymous=True)
REMARQUE: le nom doit être un nom de base, c’est-à-dire qu’il ne peut contenir aucune barre oblique "/".
Et puis, nous voulons prendre de données(la valeur de vitesse consigné) et le lire vient de clavier, donc nous avons implémenté une interface, taper de valeur consigné dans la boîte de dialogue, et puis faire valider, et ensuite faire un jugement pour identifier ce sonts des chiffre efficace ou pas(dans une intervalle validée), si oui, il appele de fonction qu'on lui a demandé.
Il y a une boucle dans chaque fonction
i = 0 while i < 50: up(float_input) i += 1 sleep(0.2)
La paramètre i est pour compter, quand cette fonction est appelé, si est même si la vitesse est validé, cette boucle va lancer. Elle va lancer jusqu'à 50 fois, chaque fois durée 0.2 secondes(grace à la frequence est égale 5Hz),ça veut dire que la durée totale de cette boucle est égale 10 secondes. Pendant ces 10 secondes, le drone peut lancer successivement, il ne peut pas s'arrêter, sauf que une commande d'atterrir est reçu. Après il finira cette boucle, il peut lancer la commande suivante, sinon les commandes suivantes attendent dans la queue.
Nous utilisons également while not rospy.is_shutdown() pour faire une boucle au lieu de compter
while not rospy.is_shutdown(): up(float_input)
Notre interface est comme ci-dessous:
Afin d’obtenir les données renvoyées par le capteur et consigner la vitesse de l'axe Z et la vitesse de rotation du drone lors de l’utilisation de l’interface en même temps, nous avons implémenté 3 fonctions de CALLBACK, ces fonctions peuvent être appelé indépendamment dans le Subscriber.
Tout d'abord, on a importé des
from nav_msgs.msg import Odometry from bebop_msgs.msg import Ardrone3PilotingStateSpeedChanged from bebop_msgs.msg import Ardrone3PilotingStateAttitudeChanged
Donc on peut utiliser les types de message de nav_msgs/Odometry, bebop_msgs/Ardrone3PilotingStateSpeedChanged et bebop_msgs/Ardrone3PilotingStateAttitudeChanged pour recevoir.
Les trois fonctions de CALLBACK sont comme ci-dessous :
Dans les fonctions de CALLBACK, il y a une ligne de
rospy.loginfo('LES INFO' % les_info)
qui effectue une triple tâche: les messages sont imprimés à l'écran, il est écrit dans le fichier journal du noeud, et il est écrit dans rosout. rosout est pratique pour le débogage: vous pouvez extraire des messages en utilisant rqt_console au lieu de devoir chercher la fenêtre de la console avec la sortie de votre noeud.
Et dans chaque fonction de CALLBACK, la dernière ligne est comme ça :
input_to_file_lin_z([lin_z]) input_to_file_speed_xyz(speed_xyz) input_to_file_ang_yaw([ang_yaw])
input_to_file est une fonction pour importer toutes les données de capteur à un fichier en format csv, par ce méthode la, c'est plus simple de voir la tendance de courbe de vitesse, la fonction est comme ci-dessous :
Le code de listener.py est similaire à talker.py, sauf que nous avons introduit un nouveau mécanisme basé sur le rappel pour l’abonnement aux messages.
Cela déclare que notre noeud est abonné au sujet de discussion qui est de type std_msgs/msg. Lorsque de nouveaux messages sont reçus, le rappel est appelé avec le message comme premier argument.
Nous avons également modifié quelque peu l'appel à
rospy.init_node ().
Nous avons ajouté l'argument mot
anonymous = True.
Le ROS nécessite que chaque noeud ait un nom unique. Si un nœud portant le même nom apparaît, il remplace le précédent. C’est pour que les nœuds défectueux puissent facilement être renvoyés du réseau. L'indicateur anonymous = True indique à rospy de générer un nom unique pour le nœud afin que plusieurs noeuds listener.py puissent s'exécuter facilement.
Le dernier ajout
rospy.spin ()
empêche simplement votre noeud de sortir jusqu'à ce que le noeud soit fermé. Contrairement à roscpp, rospy.spin () n’affecte pas les fonctions de rappel des abonnés, car celles-ci ont leurs propres threads.
Après nous avons récupéré les données, nous avons dessiné la courbe.
L'angle sur l'axe Z est comme ci-dessous :
Tout d'abord il n'y a pas de changement, et puis on a mis la vitesse de rotation égale à 20 degree/s, on peut voir que la vitesse change très rapidement, le temps de réponse est trop petit, et pendant la processus de rotation, la vitesse est très stable, elle est égale à le valeur de la pente.
Même si nous avons utilisé deux topic différents pour réguler la vitesse verticale sur l'axe Z, on peut voir que les deux façons est pseudo la même chose, sauf que tous les données est inverse.
Le premier graph est dessiné par les données qui reviennent de bebop_msgs/Ardrone3PilotingStateSpeedChanged
Le deuxième graph est dessiné par les données qui reviennent de nav_msgs/Odometry
Le premier changement subit de situation est la commande de décoller, et le dernier changement subit de situation est la commande d'atterrir, une unité égale 0.2 secondes. Entre la décollage et l'atterrissage, nous avons demandé augmenter l'altitude du drone par 0.25 m/s, durée 10 secondes. On peut voir que le temps de réponse est seulement 0.4 secondes, c'est assez rapide pour un drone, donc on pense que ce n'est pas nécessaire d'ajouter un supplémentaire contrôleur PID.
Semaine 19
Comme l'objectif pour faire Tp dans la salle C305, on doit limiter le vol du drone. Nous devons considérer de la taille de la zone disponible pour le vol.
Nous avons defini le hauteur de vol maximale à 2m. rosrun dynamic_reconfigure dynparam set /bebop/bebop_driver PilotingSettingsMaxAltitudeCurrent 2.0 (in m) Ici, l'altitude indiquée est l'altitude au-dessus du point de décollage. C'est une valeur relative, pas une valeur réelle.
Pour la gamme de vol, tout d'abord, nous avons defini à 5m pour tester. rosrun dynamic_reconfigure dynparam set /bebop/bebop_driver PilotingSettingsMaxDistanceValue 5.0 (in m)
En même temps, pour valider la définition de la gamme de vol, nous devons définir le valeur de PilotingSettingsNoFlyOverMaxDistanceShouldnotflyover comme 1. De cette façon, le drone ne peut pas voler plus que la limite.
Il marche bien pour la hauteur maximale de vol est fixée à deux mètres au-dessus du point de décollage.
Et nous avons testé les limites du déplacement horizontal aussi. Nous avons trouvé qu'il y a une valeur minimale de 10 pour la valeur de PilotingSettingsMaxDistanceValue.
Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 11, la valeur reçu = 11 ; Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 10.5, la valeur reçu = 10.5; Si on a mis la valeur de PilotingSettingsMaxDistanceValue = 9.9, la valeur reçu = 10. Nous ne pouvons pas définir une valeur qui est moins 10, c'est à dire, il est irréaliste de vouloir définir une portée de trois ou cinq mètres. Logiquement, ce n’est pas d’une valeur adaptée pour voler à l’intérieur, si vous voulez lancer une commande à l'intérieur, vous devez faire 100% attention.
Et pour le temps reste, nous avons cherché la façon pour améliorer la boucle, et nous avons ecrit le rapport et le PPT.
Conclusion
En ce qui concerne le résumé, ce projet est une application proposée par l'enseignant et utilisée pour l'enseignement en salle. Grâce à ce projet, nous avons découvert les systèmes ROS et certaines interfaces liées aux drones. Afin de contrôler le drone, nous avons finalement choisi bebop_autonomy, le pilote basé sur l’ARDroneSDK3 officiel de Parrot. Compréhension approfondie du mécanisme de communication du noeud ROS, puis utilisation de la bibliothèque d'interface Rospy Python sur ROS pour créer leur propre programme d'interface de contrôle. Nous sommes très heureux de participer à ce nouveau projet de développement au cours duquel nous avons pris beaucoup de détours, mais nous avons résolu de nombreux problèmes. Nous avons non seulement amélioré nos performances, mais nous avons également laissé une expérience pertinente aux futurs développeurs.
Documents Rendus
Fichier:Rapport Intermédiaire P22.pdf
Fichier:Présentation Intermédiaire P22.pdf