Dernière modification : 01/12/2022 à 09:16
Le but de la séance est de réaliser un Robot capable de suivre une ligne. La détection de la ligne et le contrôle associé se feront dans une tâche temps réel, libérant des ressources pour permettre au Robot de faire d’autres tâches (arrêt d’urgence, par exemple).
À l’issue de ce premier exercice, votre robot pourra suivre la ligne.
Construire un Robot mobile simple avec un moteur indépendant pour chaque roues.
On peut s’inspirer du modèle proposé ici : https://perso.esiee.fr/~hamouchr/IN4R21/8547UserGuideFrench_PDF.pdf
Il faudra remplacer le troisième moteur (inutile) par un système permettant de fixer le capteur de lignes. Voir le modèle déjà construit.
La classe NXTLineLeader.java permet de gérer le capteur de ligne. Malheureusement elle n’est pas inclus dans le .jar des classes standard fournies avec le projet LejosRT (basé sur une version ancienne de Lejos).
Télécharger le code source de la classe NXTLineLeader.java
wget dajam.fr/v2/Teachings/\ EIG-2201/src/NXTLineLeader.java
Vous ne toucherez pas au contenu de ce fichier, gardez le simplement avec vos autres fichiers sources dans le même répertoire de travail.
Dans un fichier SimpleLineLeader.java ajouter une classe SimpleLineLeader avec une méthode main() qui instancie un objet NXTLineLeader :
NXTLineLeader captLine = new NXTLineLeader(SensorPort.S1);
(remplacez S1 par le numéro du port sur lequel vous avez branché le détecteur de ligne).
Le détecteur de ligne est composé de huit détecteurs photosensibles capables de distinguer deux couleurs. Ici nos couleurs seront blanc et noir.
La méthode getResult() d’une instance de NXTLineLeader renvoie un entier dont les huit bits de poids fort codent l’état des huit capteurs. Pour le suivi de ligne on ne va s’intéresser qu’aux bits 2 à 5 (on laisse de coté les bits 0,1,6,8 pour se concentrer sur ceux qui sont au milieu du capteur).
Huit cas sont alors à considérer par rapport aux valeurs de ces quatre bits centraux :
Pour isoler uniquement les 4 bits qui nous intéressent, on fera ce qu’on appelle un masque grâce à l’opération :
value & 0x3C
0x3C
étant la représentation héxadécimale d’un nombre dont les deux premiers bits sont à 0, puis les 4 suivant à 1 puis les autres à 0.
On obtient alors un entier avec les bits 0 et 1 à 0, les bits 2,3,4,5 avec les valeurs renvoyées par le capteurs et les bits suivants à 0.
Il nous reste encore à décaler les bits vers la droite de deux positions, avec l’opérateur >>>2
Ce qui nous donne le squelette de code :
int value = capteur.getResult(); switch( (value&0x3C) >>>2 ){ case 0x?? : // 1100 case 0x?? : // 1110 ... //tourne à gauche break; case 0x?? : // 1000 ... // tourne fort à gauche break; ... // cas symétriques case 0x00 : // 0000 ... // stop ! default : ... // va tout droit }
int value = capteur.getResult();
switch( (value&0x3C) >>>2 ){
case 0x?? : // 1100
case 0x?? : // 1110
... //tourne à gauche
break;
case 0x?? : // 1000
... // tourne fort à gauche
break;
... // cas symétriques
case 0x00 : // 0000
... // stop !
default :
... // va tout droit
}
Pour pouvoir écrire l’algorithme de contrôle, il ne reste plus qu’à déterminer les différentes vitesses. Ceci se fait par une étude physique du robot et l’application de vos futurs cours d’automatique. Ici on vous donne une manière empirique de les calculer, que vous pourrez ajuster au besoin :
Soit une vitesse de base de 200 (par exemple) qu’on note vb
On peut maintenant presque passer au test sur le circuit (paillasse “prof”). En effet, le détecteur de ligne nécessite d’être calibrer pour fonctionner correctement. Cela se fait avec un programme qui va lire le capteur lorsqu’il est au dessus d’une surface blanche, puis de nouveau lorsqu’il est au dessus d’une surface noire. Le programme sera à lancer sur le robot avant chaque test car les valeurs du capteur dépendent de la luminosité ambiante et d’autres facteurs qui changent avec le temps.
wget dajam.fr/v2/Teachings/\ EIG-2201/src/Calibrate.java
public class MyRTClass extends RealtimeThread{ public MyRTClass(int priority, long periodMillis) { super( new PriorityParameters(priority), new PeriodicParameters(new RelativeTime(periodMillis,0)) ); } private Motor leftM = Motor.C; private Motor rightM = Motor.A; // ... add any sensor you want to use @Override public void run(){ // any oneshot computation needed at launch goes here // TODO while (true){ waitForNextPeriod(); // the code for the control goes here // TODO }// end while }// end run() }// end class()
public class MyRTClass extends RealtimeThread{
public MyRTClass(int priority, long periodMillis)
{
super(
new PriorityParameters(priority),
new PeriodicParameters(new RelativeTime(periodMillis,0))
);
}
private Motor leftM = Motor.C;
private Motor rightM = Motor.A;
// ... add any sensor you want to use
@Override
public void run(){
// any oneshot computation needed at launch goes here
// TODO
while (true){
waitForNextPeriod();
// the code for the control goes here
// TODO
}// end while
}// end run()
}// end class()
public class RTLauncher{ public static void main(String[] args){ // if needed // while (!RConsole.isOpen()){ // RConsole.open(); // } RTLineLeader rt_ll = new RTLineLeader(...); rt_ll.start(); try{ rt_ll.join(); }catch(InterruptedException e){ // RConsole.println("ie in launcher"); } } }
public class RTLauncher{
public static void main(String[] args){
// if needed
// while (!RConsole.isOpen()){
// RConsole.open();
// }
RTLineLeader rt_ll = new RTLineLeader(...);
rt_ll.start();
try{
rt_ll.join();
}catch(InterruptedException e){
// RConsole.println("ie in launcher");
}
}
}
Les priorités autorisées pour les threads temps réel sont de 11 à 28.
Ajouter sur votre robot un bouton capteur de touché.
Ajouter une classe temps réel (sur le même modèle que RTLineLeader) nommée RTPullEvent. Cette classe modèlise une tâche qui teste périodiquement si le boutton est appuyé (méthode isPressed()). Si c’est le cas, elle arrète les moteur.
Proposez une solution plus élégante en ajoutant un paramètre mode dans la classe RTLineLeader et les setter/getter associés. La tâche RTPullEvent se contentra d’appeller la méthode setMode() pour arreter le robot.