Catégorie:Nao

De troyesGEII
Aller à : navigation, rechercher


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.

InterfaceChoregraphe.png

Légende pour l'interface de Choregraphe:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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
  8. 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.

Animationmode1.png Timeline1.png

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.

Algorithmenao1.png

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

programme test

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.

Essai123456789.png

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".

Essaiaction123456789.png
Essaiveille123456789.png






















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.

Naomark

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

Chercherclé1234.png ChercherClef2 (premierMur).png ChercherClef3 (deuxiemeMur).png ChercherClef4 (attraperClef).png

Explications:

  1. Programme principal: c'est le programme au complet. On y voit les différentes sous-partie (1er mur, 2eme...)
  2. 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.
  3. 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.
  4. 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();
}
Programme Arduino-Nao




















Clé USB

Pour commencer, nous allons expliquer l’utilité de la création d’une clef USB pour NAO. Nous voulions tout d’abord « personnaliser » le robot de notre département GEII. Nous avons donc pensé à mettre de LEDs de façon à écrire le sigle ‘’GEII’’ sur le torse de NAO. Aussi nous voulions pouvoir ajouter des extensions à NAO comme par exemple des modules qui lui permettraient de diriger une maison domotique.
La première étape était de réfléchir à comment nous allions mettre les LEDs sur NAO. Créer un PCB n’était pas vraiment envisageable :

  • Un PCB en dur ne pouvais pas tenir sur NAO (il n’a pas de surface suffisamment plane) ;
  • Un PCB souple aurait coûté trop cher étant donné qu’il ne nous en fallait qu’un.

Notre tuteur nous a alors aiguillé vers un matériau de fabrication pour imprimante 3D : le NinjaFlex.
Le NinjaFlex présente un très gros avantage pour nous : c’est un matériau souple. Ainsi, notre PCB souple sera « fait maison » avec du NinjaFlex.
Ce PCB a été dessiné sur un logiciel de 3D (ici FreeCAD) et transformé en fichier pour l’imprimante 3D qui l’a alors imprimé.

FREECAD.png
FREECAD MESURE.png

Mais intervient alors une autre problématique : Comment relier et faire tenir les LEDs sur le support en NinjaFlex ?
Notre tuteur nous a indiqué une possibilité : un stylo conducteur. Un stylo conducteur permet de dessiner des circuits électriques sur presque n’importe quelles surfaces, ce qui est très pratique pour nous. Il a donc fallu commander un stylo. Nous avons prix un stylo au nickel car cela était suffisant pour nous mais il existe aussi des stylos à l’argent (plus cher) qui permettent d’écrire sur plus de type de surfaces et qui de dessiner des pistes qui tiennent plus longtemps.

STYLO.jpg

Voici un essai de ce stylo sur du papier avec 1 LEDs :

ESSAI.jpg

Enfin il a fallu fabriquer la clé USB en elle-même. Celle-ci sert d’interface entre les LEDs (et autres éléments futur) et NAO. Pour faciliter les choses, nous nous sommes basé sur une carte Arduino Leonardo (microcontrôleur ATMega328U). Nous avons ajouté un module XBee sur cette clé USB pour faciliter le développement de modules d’extensions. Finalement de la carte Arduino de départ nous n’avons garder que :

  • Le microcontrôleur ATMega328U ;
  • Le quartz pour la fréquence ;
  • Le régulateur de tension 5V-3.3V (pour alimenter le module Xbee) ;
  • Les pins de sorties

Voici le schéma Eagle (comprenant le dimensionnement des composants) ainsi que notre routage de la carte (qui peut être fait autrement) :

BOTTOM.png
TOP.png


SCHEMA.png

La clé USB terminée :

CLE BOTTOM.jpg
CLE TOP.jpg

Nous n’avons pas eu la possibilité de tester/programmer la clé car le port USB de NAO ne fonctionne plus et nous avons manqué de temps pour l’essayer avec un PC.

Cette catégorie ne contient actuellement aucune page ni fichier multimédia.