Catégorie:Nao : Différence entre versions
(→{{Rouge|Pour le challenge}}) |
|||
Ligne 319 : | Ligne 319 : | ||
{{boîte déroulante/fin}} | {{boîte déroulante/fin}} | ||
− | [[Fichier:arduinao.png|vignette|upright= | + | [[Fichier:arduinao.png|vignette|upright=2.64|Programme Arduino-Nao]] |
Version du 17 janvier 2016 à 21:29
Sommaire
Description et présentation du Projet
Le projet Nao consiste à programmer un robot pour lui faire réaliser plusieurs sortes de défis dans le but de se présenter à un concours, pour ceci on utilise le logiciel Chorégraphe pour construire un programme, puis on utilise un autre logiciel, Webots qui nous permet de simuler virtuellement les actions du robot et corriger les erreurs qui peuvent survenir, c'est ensuite que l'on peut tester ces programmes sur le robot Nao.
Utilisation de Choregraphe
Choregraphe est le logiciel de programmation de NAO. Il possède une interface assez simple et son fonctionnement est intuitif. Effectivement, pour créer un programme il "suffit" de glisser-déposer des boîtes dans la fenêtre principale du logiciel puis de les relier pour créer une séquence d'action.
Légende pour l'interface de Choregraphe:
- La fenêtre 1 est l'interface principale de Choregraphe. C'est ici que l'on va déposer les boîtes puis les relier pour créer le programme en lui-même.
- La fenêtre 2 présente le contenu du projet. Le seul fichier utile, pour notre utilisation, est "Untitled.pml". C'est dans ce fichier que sera enregistré tout le programme.
- La fenêtre 3 s'appelle "Box Librairies". Comme son nom l'indique, elle contient toutes les boîtes disponibles pour créer un programme.
- La fenêtre 4 est le Log Viewer. On verra s'afficher ici toutes les erreurs qui pourraient survenir pendant que le programme tourne sur NAO.
- La fenêtre 5 nous montre la position dans laquelle se trouve NAO. On peut également à partir de ce modèle 3D désactiver la stiffness (= rigidité) des membres de NAO ou faire bouger l'un de ceux-ci.
- La fenêtre 6 est le Video Monitor. On peut y voir, lorsqu'un NAO est connecté au logiciel, tout ce que NAO voit à l'aide de sa caméra.
- Cette barre d'outils permet, de gauche à droite:
- de se connecter à NAO
- de se déconnecter de NAO
- de lancer le programme sur NAO
- de stopper le programme en cours d’exécution sur NAO
- d'afficher les erreurs/la fenêtre de débogage
- et le rectangle avec du bleu indique la progression du chargement du programme sur NAO
- La barre 8 permet, de gauche à droite:
- de régler le son des hauts-parleurs du robot
- d'activer le mode animation (décrit plus loin)
- d'activer la vie autonome de NAO (comportement autonome inclus dans le robot)
- de mettre NAO en veille
- ou au contraire de le réveiller
- de voir le niveau de charge de la batterie
Timeline
La timeline est très pratique pour apprendre des mouvements à Nao très facilement pour cela il faut tout d'abord activer la fonction "Animation Mode" puis ouvrir un bloc de timeline, appuyer sur "Timeline editor" puis en appuyant sur les capteurs d'un bras celui ci se débloquera et on pourra le faire bouger puis en le relâchant il se bloquera de lui-même, ainsi pour les jambes ce sera les bumpers, et pour la tête les capteurs sur cette dernière.
Programme test
Voici un algorithme qui représente l'idée générale du fonctionnement du robot après la phase de programmation sur le logiciel Chorégraphe.
Avant de commencer à vouloir réaliser les défis, on décide de créer un programme où Nao exécute de multiples actions sans de but très précis si ce n'est de nous familiariser avec les blocs basiques
On se rend compte avec l'image ci-dessus que l'ajout de fonctions ou l'apport de modifications devient très dure voire impossible à cause de toutes les liaisons présente, donc pour arranger cela nous avons créé des compartiments qui nous permettrons d'inclure les fonctions existantes selon leurs actions, et la possibilité de pouvoir ajouter des fonctions beaucoup plus simplement.
On peut voir ci-dessous les différents compartiments, à gauche on a toutes les actions que nous avons programmées pour Nao ainsi qu'un switch case qui permet d'associer un mot ou une phrase à une action. A droite on peut voir une fonction qui nous permet de mettre en veille Nao ou de le remettre en marche juste en touchant sa tête qui possède trois capteurs sensoriels ainsi celui de devant permet de le "réveiller" et celui de derrière permet de le mettre en veille. Avant chaque action nous avons pris le soin de faire dire une phase "explicative" sur l'action que Nao va entreprendre ce qui permet à un utilisateur "externe" de pouvoir anticiper les actions de Nao, par exemple quand on va demander à Nao de marcher il répondra "D'accord allons nous promener".
Cherche la clé
Dans ce défi il s'agit de programmer NAO pour qu'il aille chercher une clé rouge pour ensuite la mettre dans un bac rouge. L'épreuve se situe dans une pièce fermée en équerre ce qui permet à NAO d'utiliser des repères qui pourront être placé sur les murs. Nous avions pensés mettre des affiches, mais bien vite nous nous sommes rendu compte que NAO avait beaucoup de mal à les repérer, c'est pourquoi nous avons utilisé des Naomarks (voir image ci-après): ce sont des cibles pré-enregistré par NAO et en utilisant la détection de ces Naomarks nous pouvons programmer NAO pour qu'il puisse marcher jusqu'à elles.
Ensuite pour qu'il attrape la clé nous avons créer une timeline. Mais avant cela il a fallut désactiver la stiffness des moteurs, pour que NAO puisse correctement prendre la clé sans forcer sur celle-ci et rester bloqué; pour ce faire, on ajoute quelques lignes de code au programme python de la boite:
self.motion.stiffnessInterpolation("LElbowYaw",0.0,1.0) self.motion.stiffnessInterpolation("LShoulderRoll",0.0,1.0)
Ensuite il ne restait plus qu'à la mettre dans le bac rouge, nous avons donc utilisés la reconnaissance d'image, en utilisant des images de différents angles de la boite, pour que, peu importe la localisation de NAO, il puisse la reconnaître.
Pour finir il suffit juste qu'il la dépose dans le bac, c'est pour cela qu'une simple boite en python et quelques lignes de programmes étaient amplement suffisantes.
Ci-après, les différentes parties du programme.
Programme
Explications:
- Programme principal: c'est le programme au complet. On y voit les différentes sous-partie (1er mur, 2eme...)
- 1er mur: ce morceau de programme est lancé lorsque Nao a atteint la première Naomark. Cette partie lui permet de tourner la tête pour scanner les environs et découvrir la deuxième mark.
- 2eme mur: lancé lorsque Nao atteint la deuxième mark. Cette séquence le fait ce tourner dans la direction où se trouve la clef et avancé jusqu'à ce qu'il la détecte.
- Attraper la clef: cette partie contient comme élément principale la timeline qui permet à Nao d'attraper la clef. Il y a également ici les boîtes qui lui permettent de reculer et se tourner de 180° pour se préparer à aller vers la boite.
Résultat
Pour le challenge
Pour le challenge, notre tuteur, Mr Jacquot, nous a proposé de réaliser une carte électronique à base d'Arduino qui pourrait étendre les capacités de NAO. Ceci allant du simple allumage de leds sur NAO au pilotage d'une maison domotique.
En premier lieu, nous avons décidé de faire des recherches sur le sujet pour récupérer un maximum d'informations sur les possibilités d'étendre les capacités de NAO. Nous avons appris que la prise USB derrière sa tête peut être utilisée comme moyen d'échange d'information entre le système d'exploitation de NAO et un système extérieur. Nous avons aussi trouvé des programmes exemples d'utilisation d'une carte Arduino avec NAO sur lesquels nous pouvons ainsi nous baser pour réaliser la communication entre NAO et Arduino. Nous avons également appris que l'on pouvait brancher une caméra 3D ou encore une Kinect pour offrir à NAO une vision 3D du monde qui l'entours mais cette extension des capacités de NAO est plus complexe que l'utilisation d'une carte Arduino car il y a besoin de beaucoup de connaissance mathématique (géométrie dans l'espace, coordonnées cartésiennes etc...).
Lors de nos recherches nous sommes tombés sur une vidéo démontrant l'utilisation d'une Arduino avec Nao (https://www.youtube.com/watch?v=hf_6SNGZyXQ). Dans la description de la vidéo il y a un lien qui permet de télécharger un zip contenant des programmes exemples (Choregraphe et Arduino) ainsi qu'un fichier texte expliquant la marche à suivre pour utiliser Nao avec Arduino.
Il faut donc tout d'abord installer abcdk sur Nao ce qui est simple car il suffit de lancer un programme (livré dans le zip) sur Nao et de redémarrer le robot. Ensuite, il faut lancer un programme sur la carte Arduino qui permettra d'envoyer et de recevoir des données. Ce programme est donné dans le fichier "SimpleTest.ino" dont le contenu est donné dans la suite. Celui-ci va avec le programme Choregraphe "Arduino_simple" donné ci-après.
Programme Arduino
/* * A simple program to read sensors and receive data from another device (NAO). * v0.6 */ //LED Pin int ledPin = 11; //the pin the LED is connected to //we are controlling brightness so //we use one of the PWM (pulse width // modulation pins) int inputButton1 = 2; int bLastButtonVal1 = 0==1; int bPushed = 0; int nCpt = 0; unsigned long nLastOutputMs = 0; const int nSizeSerialInputMax = 512; // a bit limited, but... char bufSerialInput[nSizeSerialInputMax+1]; int nSizeSerialInput = 0; long int anReceivedValues[16]; // max is 16 value to receive void setup() { int i; pinMode(ledPin, OUTPUT); //sets the led pin to output Serial.begin(115200); // on ArduinoBT, it's 115200 instead of 9600 // NB: with the USB one it works both with 115200 and 9600. // WARNING: if you change this value, you'll to change the one in the choregraphe behavior: in the box ArduinoCommunication: self.serial = serialtools.SerialTools( self.getParameter( "strComInfo" ), 115200, timeout=4 ); pinMode(inputButton1, INPUT); // send a small message to the user: the Arduino is running // a quick blinking for( i = 0; i < 5; ++i ) { const int nTimeMs = 400; Serial.println( "# Led flash!" ); analogWrite( ledPin, 200 ); delay(nTimeMs); analogWrite( ledPin, 0 ); delay(nTimeMs/2); } } // extract data from ascii buffer, and store it to pDataToFilled // return the number of found data // CURRENTLY: handles only numbers !!! int extractValues( const char * buf, int nLenToAnalyse, long int * pDataToFilled ) { Serial.print( "#extractValues: '" ); Serial.print( buf ); Serial.print( "', nLenToAnalyse:" ); Serial.println( nLenToAnalyse ); int nCur = 0; if( buf[nCur] == ' ' ) { for( ; buf[nCur] == ' '; ++nCur ); // skip spaces } if( buf[nCur] == '[' ) { // array of variables ++nCur; int nNbrVariable = 0; while( 1 ) { pDataToFilled[nNbrVariable] = atoi( &buf[nCur] ); // Serial.print( "# nNbrVariable:" ); // Serial.print( nNbrVariable ); // Serial.print( ", pDataToFilled[nNbrVariable]: " ); // Serial.println( pDataToFilled[nNbrVariable] ); ++nNbrVariable; for( ; buf[nCur] != ','; ++nCur ) // jump to next ',' { if( buf[nCur] == ']' || buf[nCur] == '\0'|| nCur >= nLenToAnalyse ) { break; } } if( buf[nCur] != ',' ) { break; } ++nCur; // point next value after ',' } return nNbrVariable; } // just one variable //((char*)buf)[nCur+nLenToAnalyse] = '\0'; // pour tester, mais atoi n'est pas dérangé en fait! pDataToFilled[0] = atoi( &buf[nCur] ); return 1; } // // analyse received buffer and update variable // // receive data in a specific way: // ["dataname",value]\n a pair [data,value], the value can be an integer, a float, a string, an array, an array of int, value, string, array... // #blablabla\n a comments, it will only been printed in the console. // \n can be replaced by the two char: RN // // void analyseReceivedData( char * buf ) { if( buf[0] == '#' ) { // just a comments, skipping return; } int nLen; for( nLen = 0; buf[nLen]; ++nLen ); if( buf[0] == '[' ) { // some data in the form ["data",value] const int nPosDataName = 2; int nLenDataName; int nPosComma; int nNbrData; for( nPosComma = 0; nPosComma < nLen && buf[nPosComma] != ','; ++nPosComma ); if( nPosComma >= nLen ) { return; } nLenDataName = nPosComma - 1 - nPosDataName; nNbrData = extractValues( &buf[nPosComma+1], nLen - nLenDataName - 5, anReceivedValues ); Serial.print( "# nNbrData:" ); Serial.println( nNbrData ); const char * pDataBegin = &buf[nPosDataName]; if( strncmp( pDataBegin, "Led1", nLenDataName ) == 0 && nNbrData >= 1 ) { Serial.print( "#Led1 info received:" ); Serial.println( anReceivedValues[0] ); analogWrite( ledPin, anReceivedValues[0] ); // un petit coup sur la led } } } int bPreviousWasR = false; // help to wait for \r\n void handlesSerialInput() { if( Serial.available() <= 0 ) { return; } // read the incoming byte: int nIncomingByte = Serial.read(); // say what you got: // Serial.print("# I received: "); // Serial.println(nIncomingByte, DEC); int bEndOfInput = false; if( nSizeSerialInput >= nSizeSerialInputMax ) { Serial.println( "#Too much char in input => shortened" ); bEndOfInput = true; } if( nIncomingByte == '\r' || nIncomingByte == 'R' ) { bPreviousWasR = true; } else if( ( nIncomingByte == '\n' || nIncomingByte == 'N' ) && bPreviousWasR ) { bEndOfInput = true; } else { bPreviousWasR = false; bufSerialInput[nSizeSerialInput] = nIncomingByte; ++nSizeSerialInput; } if( bEndOfInput ) { bufSerialInput[nSizeSerialInput] = '\0'; Serial.print("# I received total: "); Serial.println(bufSerialInput); analyseReceivedData( bufSerialInput ); bPreviousWasR = false; nSizeSerialInput = 0; // rst } } /* * loop() – this function will start after setup * finishes and then repeat */ void loop() { nCpt += 1; // if( nCpt > 300 ) if( millis() - nLastOutputMs > 1000 ) { // output debugging Serial.print( "#" ); Serial.print( "nLastOutputMs: " ); Serial.print( nLastOutputMs ); Serial.print( ", nCpt: " ); Serial.print( nCpt ); Serial.print( ", bLastButtonVal1: " ); Serial.print( bLastButtonVal1 ); Serial.println(""); Serial.println( "[\"Ping\",1]" ); nCpt = 0; nLastOutputMs = millis(); } bPushed = (digitalRead(inputButton1) == LOW); // read input value if( bPushed != bLastButtonVal1 ) { // button has changed state bLastButtonVal1 = bPushed; Serial.print( "[\"Button1\"," ); Serial.print( bPushed ); Serial.println( "]" ); } handlesSerialInput(); }
Cette catégorie ne contient actuellement aucune page ni fichier multimédia.