Aller au contenu


Photo
- - - - -

Comment détecter des codes Aruco avec Vigibot ?

code aruco

3 réponses à ce sujet

#1 Hayrpey

Hayrpey

    Nouveau membre

  • Membres
  • 4 messages

Posté 14 mars 2022 - 04:35

TUTO Tag Aruco

 

Avant de commencer ce tuto si ce n’est pas encore fait il faut installer Vigibot sur votre Raspberry en suivant ce tuto.

 

Aller dans le flux de configuration matériel en cliquant sur l’engrenage :

engrenage vigibot.png

Cliquer sur « config effective » puis sur « CAMERAS » puis « 0 » puis « SOURCE » et remplacez-le « 0 » par 5

vigibot cam.png

Cliquer sur enregistrer (en bas de la fenêtre)

 

     

oubli enregistrer.png

 

Pour vérifier que tout fonctionne prendre un Tag Aruco 6x6 (voir l’exemple en dessous) et si vous avez la même chose que sur cette image c’est que la détection de Tag Aruco est bien installée.

 

code detecter.png

 

 

code aruco.png

 

Nous allons voir comment modifier le type de Tag que l'on détecte.

 

Il faut tout d'abord connaitre la taille du Tag Aruco.

 

Pour calculer la taille de votre Tag Aruco voici comment compter :

Regarder le nombre de carré blanc sur un côté. Attention ne pas compter la bordure noire !

 

compter code.png

 

Dans cette exemple vous pouvez voir qu'il y a 6 carrés, il s'agit d'un Tag Aruco 6x6.

Pour détecter d'autre type de Tag Aruco installez d’abord un client SSH comme PuTTY (pour windows).

 

Connecter sur PuTTY, pour cela vous pouvez trouver votre adresse IP sur vigibot en passant votre sourie sur l’icône de votre robot et regarder l’adresse IP après « LAN ». Ensuite sur PuTTY dans "Host Name" écrivez @pi puis votre adresse IP. Appuyez sur « Open », si vous avez un message d’alerte appuyez sur « Accept ».

Un mot de passe va vous être demandé, il s’agit normalement de « raspberry ».

putty demarage.png

 

Taper ce code pour changer de fichier (clique droit de la sourie pour coller) :

cd /usr/local/vigiclient/opencv

Appuyer sur « Entrer », si vous avez une erreur c’est que vous avez surement oublié l’espace entre « cd » et « /usr/….. » ou que vous avez mal recopié la ligne de code.

 

Taper :

sudo nano aruco/main.cpp

Vous allez obtenir ça :

lancement sudo.png

 

Il faut maintenant trouver cette ligne de code (utiliser les flèches pour vous déplacer):

Ptr<Dictionary> dictionary = getPredefineDictionary(DICT_6X6_50);

Descendez, vous allez la voir rapidement.

 

Vous pouvez changer "DICT_6X6_50" par la dimension de votre Tag Aruco en remplaçant uniquement le "6X6".

Lorsque vous avez fini, fermer le fichier avec CTRL + X puis appuyer sur Y et sur Entrer.

 

Il faut relancer le nouveau programme, pour cela mettre cette ligne de code :

sudo ./make.sh

L'ordinateur va compiler le code, vous n'avez qu'à attendre qu'il s'arrête.

Aller sur Vigibot et mettre votre robot sur veille.

veille.png

Attendre 5 secondes puis remettre le robot en marche (cliquer sur l’écran suffit).

Mettre maintenant votre Tag Aruco devant la caméra pour voir s’il le détecte.

 

Si oui bravo vous pouvez détecter n'importe quel Tag Aruco !

 

Si non retourner sur PuTTY, il y a surement une erreur dans la compilation.


  • Mike118 et RobertMok aiment ceci

#2 Hayrpey

Hayrpey

    Nouveau membre

  • Membres
  • 4 messages

Posté 04 avril 2022 - 05:43

TUTO Tag Aruco et UART

Pour ce tuto vous devez d’abord faire celui du haut afin de pouvoir avoir la base du code.

Allumer PuTTY puis écrivez (pour coller faites un clic droit):

sudo passwd root

 

 

On va vous demander d’écrire un nouveau mot de passe afin de se connecter avec root pour avoir tous les droits sur votre Raspberry (si vous ne voyez pas le mot de passe s’écrire c’est normal)

Écrire :

su

 

 

Rentrer le mot de passe que vous venez d’ajouter.

Image1.png

Écrire ces lignes pour ne plus être connecté à Vigibot puis reboot la Raspberry:

systemctl disable vigiclient
reboot

 

Se reconnecter puis écrire :

su

 

 

(il faut remettre le même mot de passe)

Écrire :

cd /usr/local/vigiclient/opencv
nano aruco/main.cpp

 

En dessous des include ajouter :

#include <string>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>

 

Image2.png

Après:

Ptr<Dictionary> dictionary = getPredefinedDictionary(DICT_6X6_50);

 

 

Image3.png

Écrire :

 

  int serial_port = open("/dev/ttyAMA0", O_RDWR);
  struct termios tty;
  tty.c_cflag &= ~PARENB;
  tty.c_cflag &= ~CSTOPB; 
  tty.c_cflag &= ~CSIZE; 
  tty.c_cflag |= CS8; 
  tty.c_cflag &= ~CRTSCTS; 
  tty.c_cflag |= CREAD | CLOCAL; 
  tty.c_lflag &= ~ICANON;
  tty.c_lflag &= ~ECHO; 
  tty.c_lflag &= ~ECHOE; 
  tty.c_lflag &= ~ECHONL;
  tty.c_lflag &= ~ISIG; 
  tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
  tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
  tty.c_oflag &= ~OPOST; 
  tty.c_oflag &= ~ONLCR;
  tty.c_cc[VTIME] = 10;
  tty.c_cc[VMIN] = 0;
  cfsetispeed(&tty, B9600);
  cfsetospeed(&tty, B9600);

 

Aller dans la boucle while et mettez cette ligne en commentaire avec // ;

drawAxis(image, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.05);

 

 

Image4.png

Cela permet d’afficher les vecteurs lorsque nous somme connecter à Vigibot, ici ça ne nous sert donc à rien.

A coter du for ajouter une accolade {

Image5.png

 En dessous écrire :

    string c11 = to_string(corners[0][0].x) + " ";
    string c12 = to_string(corners[0][0].y) + " ";
    string c21 = to_string(corners[0][1].x) + " ";
    string c22 = to_string(corners[0][1].y) + " ";
    string c31 = to_string(corners[0][2].x) + " ";
    string c32 = to_string(corners[0][2].y) + " ";
    string c41 = to_string(corners[0][3].x) + " ";
    string c42 = to_string(corners[0][3].y) ;

 

Pour calculer les coordonnées des coins du Tag Aruco.

Pour afficher ces coordonnées il faut toutes les écrire sur une seule ligne :

string msg = "id " + to_string(i) + " = " + to_string(ids[i]) + "/ " + "X1 "+c11+ "Y1 "+c12+ "X2 "+c21+ "Y2 "+c22+ "X3 "+c31+ "Y3 "+c32+ "X4 "+c41+ "Y4 "+c42 + "\n\r";

 

 

En dessous écrire :

    int n = msg.length();
    char char_array[n + 1];
    strcpy(char_array, msg.c_str());
    write(serial_port, char_array, n);
}

 

Attention à ne pas oublier l’accolade à la fin.

En dessous mettre en commentaire :

writeModem(fd, telemetryFrame);

 

 

et

fwrite(image.data, size, 1, stdout);

 

Sinon vous on ne voit rien sur le port Série.

Image6.png

Faites CTRL + X afin d’enregistrer et fermer.

Pour que le programme compile faites :

./make.sh 

 

 

Maintenant connecter votre Raspberry à votre ordinateur (ou à un Arduino par exemple)

Attention si vous souhaiter vous connecter à un Arduino il vous faut un convertisseur de niveau logique sinon vous aller cramer votre Raspberry.

Pour se connecter à l’ordinateur il vous faut un convertisseur usb uart.

Brancher 3 fils au convertisseur, un sur Tx, un sur Rx et un sur Gnd.

Brancher le fil Rx sur le Tx, le fil Tx sur le Rx et le Gnd sur le Gnd (Ground) sur la Raspberry

Image7.png

Brancher le tout à votre PC en USB.

Il faut trouver sur quel port se trouve la connexion.

Si vous avez l’IDE Arduino aller dans Outils puis Port.

Sinon dans la barre de recherche de Windows chercher gestionnaire de périphériques puis cliquer sur ports, le numéro se trouve à coter de COM (ici COM9)

Image8.png

Ouvrez à nouveau PuTTY (sans fermer l’autre fenêtre) en faisant clic droit sur l’icône du logiciel puis cliquer sur PuTTY.

Cliquer sur Serial.

Image9.png

Rentrer le numéro de votre port dans Serial line.

Cliquer sur Open, si une fenêtre noire s’affiche c’est que ça c’est bien ouvert.

Retourner sur la première fenêtre de PuTTY et écrire :

aruco/bin

 

 

Image10.png

Maintenant mettez un Tag Aruco devant votre caméra et regarder ce qui se passe sur le moniteur série.

Si rien ne s’affiche c’est que vous avez oublié quelque chose, relisez bien votre code ou que le Tag Aruco n’est pas de la bonne dimension (ici 6X6).

Image11.png

Faire CTRL + C pour arrêter le code.

Ce code permet d’afficher les coordonnées des 4 coins du Tag Aruco, nous allons voir maintenant pour calculer les longueurs du Tag Aruco et la position de son centre.

Revenir sur le code avec nano aruco/main.cpp

Mettre cette ligne en commentaire :

//string msg = "id " + to_string(i) + " = " + to_string(ids[i]) + "/" + c11+ c12+ "|" + c21+ c22+ "|" + c31+ c32+ "|" + c41+ c42 + "\n\r";

 

 

Au dessus écrire :

    string coordcentrex = to_string((corners[0][0].x+corners[0][1].x+corners[0][2].x+corners[0][3].x)/4);
    string coordcentrey = to_string((corners[0][0].y+corners[0][1].y+corners[0][2].y+corners[0][3].y)/4);

    string dist1 = to_string(sqrt(pow(corners[0][0].x-corners[0][1].x,2)+pow(corners[0][0].y-corners[0][1].y,2)));
    string dist2 = to_string(sqrt(pow(corners[0][1].x-corners[0][2].x,2)+pow(corners[0][1].y-corners[0][2].y,2)));
    string dist3 = to_string(sqrt(pow(corners[0][2].x-corners[0][3].x,2)+pow(corners[0][2].y-corners[0][3].y,2)));
    string dist4 = to_string(sqrt(pow(corners[0][3].x-corners[0][0].x,2)+pow(corners[0][3].y-corners[0][0].y,2)));

 

En dessous écrire :

    string msg1 = "id " + to_string(i) + " = " + to_string(ids[i]) + "/ " +"x_centre : "+coordcentrex+" y_centre : "+ coordcentrey + "\n\r";
    string msg2 = "distance 1 : " + dist1 + " / distance 2 : " + dist2 + " / distance 3 : " + dist3 + " / distance 4 : " + dist4 + "\n\r\n";
    string msg = msg1+msg2;

 

Sauvegarder et fermer avec CTRL + X

Faites ./make.sh puis aruco/bin

Remettre un Tag Aruco devant la caméra et regarder le moniteur série.

Si tout marche vous pouvez maintenant envoyer des données de votre Raspberry vers un autre système. Mais si vous voulez un système plus optimisé pour ensuite utiliser ces données sur un Arduino par exemple il faut envoyer les données autrement.

 


  • Mike118 aime ceci

#3 Hayrpey

Hayrpey

    Nouveau membre

  • Membres
  • 4 messages

Posté 29 juin 2022 - 02:30

Tuto UART 2

Avec le code fais précédemment nous envoyons des données mais on peut difficilement les traités par la suite. Nous allons donc voir comment faire.

Tout d’abord aller dans le programme main.cpp sur la Raspberry :

cd /usr/local/vigiclient/opencv
nano aruco/main.cpp

Nous allons créer un union de structure afin de convertir facilement les octets en entier ou tout autres type de variable. Pour cela taper sous les include :

union TESTR{
  struct{
    uint8_t id;
    struct{
      uint16_t x;
      uint16_t y;
    } coord;
    uint16_t sumbytes;
  } aruco;
  uint8_t bytes[7];
} testr;

 Image1.png

 

L’union permet de faire la conversion entre ici le numéro du tag Aruco et les bytes qui sont ensuite envoyés à l’Arduino. Si vous voulez modifier cette union par la suite il faut faire attention à la valeur dans bytes[7]. Il s’agit du nombre d’octets contenu dans la structure. Lorsque l’on met uint8_t on envoie 1 octet mais si vous mettez uint16_t cela envoi 2 octets. Vous pouvez trouver sur internet le nombre d’octets par type pour faire le compte.

Ensuite nous allons créer une nouvelle fonction afin de remplacer celle qu’utilise vigibot :

Taper :

void writeModemTest(int fd, TESTR &testr) {
 for(int i = 0; i < sizeof(testr.bytes); i++)
  serialPutchar(fd, testr.bytes[i]);
}

Puis taper en dessous (nous verrons à quoi cela servira plus tard):

int posex;
int posey;

Nous allons maintenant revenir dans le for pour pouvoir remplacer l’ancien programme.

 Vous pouvez mettre en commentaire tout ce qu’il y a dans le for car nous n’en auront plus besoin (ne supprimer rien car vous pourrez vous en servir pour retrouver les formules).

Au début tapez :

testr.aruco.id=ids[i];

Afin d’obtenir l’id du tag Aruco.
Nous allons maintenant calculer les coordonnées du centre du Tag Aruco :

    posex = (corners[0][0].x+corners[0][1].x+corners[0][2].x+corners[0][3].x)/4;
    testr.aruco.coord.x = posex;
    posey = (corners[0][0].y+corners[0][1].y+corners[0][2].y+corners[0][3].y)/4;
    testr.aruco.coord.y= posey;

Nous avons désormais calculé toutes nos valeurs, il faut maintenant les envoyer, il faut d’abord ajouter une variable de test pour savoir si nous avons bien tout envoyer :

    int sumbytes=0;
    for(int j=0; j<sizeof(testr.bytes)-3;j++){
      sumbytes=sumbytes+testr.bytes[j];
    }
    testr.aruco.sumbytes=sumbytes;

Maintenant nous pouvons enfin envoyer des données. Pour commencer il faut envoyer un caractère pour débuter l’envoie :

serialPutchar(serial_port, 'a');

Pour envoyer tout ce qu’il y a dans l’union il suffit de faire :

writeModemTest(serial_port, testr);

Nous pouvons maintenant enregistrer le programme et le compiler (ne pas le lancer tout de suite).

Il faut maintenant ouvrir l’IDE Arduino afin de programmer la carte Arduino. Attention ici j’utilise une Arduino due il peut donc y avoir quelque différence car j’utilise le Rx et Tx 3 de l’Arduino donc je dois mettre 3 devant Serial si vous programmez sur une arduino classique il ne faut pas le mettre. Au début du programme il faut copier/coller le même union afin de faire la conversion dans l’autre sens :

 

Image2.png

 

Maintenant dans le loop il suffit de copier ceci :

  if (Serial3.available() >= 8) {
    SerialUSB.print("nouveau tour \n");
    int donnee = Serial3.read();
    int sumbytes=0;
   
    if (donnee=='a'){
      for(uint8_t i=0; i<7; i++) {
          testr.bytes[i] = Serial3.read();
          }
      for(int j=0; j<sizeof(testr.bytes)-3;j++){
          sumbytes=sumbytes+testr.bytes[j];
          }
    if (sumbytes==testr.aruco.sumbytes){
   
    SerialUSB.print("Id: ");
    SerialUSB.println(testr.aruco.id);
    SerialUSB.print("Coordonnée: ");
    SerialUSB.print(testr.aruco.coord.x);
    SerialUSB.print(" ");
    SerialUSB.println(testr.aruco.coord.y);
    SerialUSB.print("\n");

Serial.available() doit être supérieur à 8 car on envoie un octet supplémentaire pour démarrer la lecture. Ensuite on test lorsque l’on lit l’octet de démarrage (ici ‘a’). Puis on calcul la somme des octets lu, si ça correspond à celui envoyé alors on peut afficher ce que l’on a lu.

Vous pouvez maintenant lancer le compiler le code sur votre Arduino et le lancer sur votre Raspberry avec :

aruco/bin

Si vous obtenez ceci alors votre programme fonctionne:

Image3.png

 

 


  • Melmet et Mike118 aiment ceci

#4 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 934 messages
  • Gender:Male
  • Location:Anglet
  • Interests:Robotique, Entrepreneuriat, Innovation, Programmation, Résolution de problème, Recherche de solutions, Mécanique, Electronique, Créer, Concevoir

Posté 29 juin 2022 - 07:42

Petites remarques en passant : 

Tu fais un checksum pour vérifier l'intégrité de ta trame avec la variable sumbytes sur 2 octets alors que tu pourrais le faire avec un seul octet. 

Dommage d'avoir fait la structure aruco contenant aussi ton checksum, en général on sépare les données de ce qui est là pour contrôler les données. 
La logique voudrait que tu fasse une structure Aruco qui ne contienne que l'id et la position x et y. 
Après tu peux faire une structe " Trame "  qui contient : L'octet de démarrage de trame, une structure aruco, le checksum, en plus ça te permettre de simplifier l'envois des donnée en utilisant uniquement la ligne : " writeModemTest(serial_port, testr); " 

 

Sans avoir besoin de faire : " serialPutchar(serial_port, 'a');" car le 'a' sera déjà présent dans testr dans ce cas. =) 

Ensuite dernier point qui est à vérifier, quand on utilise des structures et des unions en bas niveau comme ça il est recommandé de bien ranger les données dans le bon ordre pour que ça rentre bien dans les case mémoire...
Si un jour vous rencontrez un problème d'une information qui se retrouve pas dans la bonne case mémoire ou autre ça peut être du au fait de comment sont organisée vos données... Dans une structure normalement une variable sur 4 octets doit commencer à une adresse multiple de 4, une variable sur 2 octets à une adresse en multiple de 2 etc ... pour être bien rangée correctement dans les tableaux d'octets ... sinon il est possible que le compilateur saute quelque cases mémoire et les remplisse de 0 pour pouvoir respecter la bonne organisation ...  Après si de toutes façon c'est fait pareil des deux côtés ça pose pas de problème, mais en analysant les données vous pouvez vous rendre compte que vous envoyez plus d'octets que nécessaires avec certains octets mis à 0 qui n'ont pas d'utilités en terme de contenu de données  ... Mais bon cette discussion mériterait éventuellement son propre sujet ;) 

 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 




Répondre à ce sujet



  


0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users