Vous avez dans cette rubrique l'ensemble des corrections issues des travaux pratiques proposés dans l'étude précédente.
Le premier TP nous permet d'utiliser les deux moteurs du robot ainsi que les quatres boutons présents sur la brique. Nous allons commencer par quelques mouvements simples. Voici les fonctionnalités attendues une fois que le programme est en cours d'exécution :
package robot; import lejos.nxt.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); public Piloter() { Button.ENTER.addButtonListener(this); Button.LEFT.addButtonListener(this); Button.RIGHT.addButtonListener(this); } public static void main(String[] args) { new Piloter(); Button.ESCAPE.waitForPressAndRelease(); } public void buttonPressed(Button bouton) { if (bouton == Button.ENTER) robot.avancer(); if (bouton == Button.RIGHT) robot.tournerADroite(); if (bouton == Button.LEFT) robot.tournerAGauche(); } public void buttonReleased(Button bouton) { } }
package robot; import lejos.nxt.*; public class Robot { private Motor droite = Motor.A; private Motor gauche = Motor.C; void avancer() { droite.forward(); gauche.forward(); } void tournerADroite() { gauche.resetTachoCount(); gauche.setSpeed(200); droite.setSpeed(400); while (gauche.getTachoCount() < 360); gauche.setSpeed(360); droite.setSpeed(360); } void tournerAGauche() { droite.resetTachoCount(); droite.setSpeed(200); gauche.setSpeed(400); while (droite.getTachoCount() < 360); droite.setSpeed(360); gauche.setSpeed(360); } }
Le deuxième TP est une variante du premier. Il serait intéressant de pouvoir arrêter les mouvements du robot sans pour cela quitter impérativement le programme. Je propose donc de nous reservir du bouton de validation pour arrêter le robot. Ainsi le bouton de validation devient l'équivalent d'une bascule :
package robot; import lejos.nxt.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); private boolean bouge; public Piloter() { Button.ENTER.addButtonListener(this); Button.LEFT.addButtonListener(this); Button.RIGHT.addButtonListener(this); } public static void main(String[] args) { new Piloter(); Button.ESCAPE.waitForPressAndRelease(); } public void buttonPressed(Button bouton) { if (bouton == Button.ENTER) { bouge = !bouge; if (bouge) robot.avancer(); else robot.arreter(); } if (bouton == Button.RIGHT && bouge) robot.tournerADroite(); if (bouton == Button.LEFT && bouge) robot.tournerAGauche(); } public void buttonReleased(Button bouton) { } }
package robot; import lejos.nxt.*; public class Robot { private Motor droite = Motor.A; private Motor gauche = Motor.C; void avancer() { droite.forward(); gauche.forward(); } void arreter() { droite.stop(); gauche.stop(); } void tournerADroite() { gauche.resetTachoCount(); gauche.setSpeed(200); droite.setSpeed(400); while (gauche.getTachoCount() < 360); gauche.setSpeed(360); droite.setSpeed(360); } void tournerAGauche() { droite.resetTachoCount(); droite.setSpeed(200); gauche.setSpeed(400); while (droite.getTachoCount() < 360); droite.setSpeed(360); gauche.setSpeed(360); } }
Lorsque le robot s'approche d'un obstacle comme le mur de la salle par exemple, il serait souhaitable de le faire ralentir dans un premier temps et de l'arrêter ensuite au contact du mur. Il pourrait alors reculer légèrement pour le dégager du mur.
Pour tester cette fonctionnalité, je vous propose dans un premier temps de ne plus vous préoccuper de faire tourner le robot à droite ou à gauche ou même de faire la demande de l'arrêt. Tenez-vous en uniquement à l'avance du robot avec précausion. Voici d'ailleurs la procédure à suivre :
package robot; import lejos.nxt.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); public Piloter() { Button.ENTER.addButtonListener(this); } public static void main(String[] args) { new Piloter(); Button.ESCAPE.waitForPressAndRelease(); } public void buttonPressed(Button bouton) { robot.avancerPrudemment(); robot.reculerLegerement(); } public void buttonReleased(Button bouton) { } }
package robot; import lejos.nxt.*; public class Robot { private Motor droite = Motor.A; private Motor gauche = Motor.C; private UltrasonicSensor ultraSon = new UltrasonicSensor(SensorPort.S1); private TouchSensor finDeCourse = new TouchSensor(SensorPort.S3); void avancer() { droite.forward(); gauche.forward(); } void avancer(int vitesse) { droite.setSpeed(vitesse); gauche.setSpeed(vitesse); if (!droite.isMoving()) avancer(); } void avancerPrudemment() { avancer(); while (!finDeCourse.isPressed()) { int distance = ultraSon.getDistance(); LCD.drawInt(distance, 5, 0, 0); if (distance <= 40) avancer(200); } arreter(); } void reculerLegerement() { droite.rotate(-360, true); gauche.rotate(-360); } void arreter() { droite.stop(); gauche.stop(); } void tournerADroite() { gauche.resetTachoCount(); gauche.setSpeed(200); droite.setSpeed(400); while (gauche.getTachoCount() < 360); gauche.setSpeed(360); droite.setSpeed(360); } void tournerAGauche() { droite.resetTachoCount(); droite.setSpeed(200); gauche.setSpeed(400); while (droite.getTachoCount() < 360); droite.setSpeed(360); gauche.setSpeed(360); } }
Nous allons reprendre toutes les fonctionnalités précédentes en rajoutant juste un ralentissement progressif au lieu de proposer une vitesse de ralentissement unique à l'approche de l'obstacle. Nous en profiterons également pour prévoir un demi-tour complet du robot après qu'il ait reculé de l'obstacle.
package robot; import lejos.nxt.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); public Piloter() { Button.ENTER.addButtonListener(this); } public static void main(String[] args) { new Piloter(); Button.ESCAPE.waitForPressAndRelease(); } public void buttonPressed(Button bouton) { robot.avancerPrudemment(); robot.reculerLegerement(); robot.demiTour(); } public void buttonReleased(Button bouton) { } }
package robot; import lejos.nxt.*; public class Robot { private Motor droite = Motor.A; private Motor gauche = Motor.C; private UltrasonicSensor ultraSon = new UltrasonicSensor(SensorPort.S1); private TouchSensor finDeCourse = new TouchSensor(SensorPort.S3); void avancer() { droite.forward(); gauche.forward(); } void avancer(int vitesse) { droite.setSpeed(vitesse); gauche.setSpeed(vitesse); if (!droite.isMoving()) avancer(); } void avancerPrudemment() { avancer(); while (!finDeCourse.isPressed()) { int distance = ultraSon.getDistance(); LCD.drawInt(distance, 5, 0, 0); if (distance >= 60) avancer(360); if (distance < 60 && distance > 30) avancer(4*distance); if (distance <= 30) avancer(120); } arreter(); } void reculerLegerement() { droite.rotate(-360, true); gauche.rotate(-360); } void demiTour() { droite.rotate(1000, true); gauche.rotate(-1000); } void arreter() { droite.stop(); gauche.stop(); } void tournerADroite() { gauche.resetTachoCount(); gauche.setSpeed(200); droite.setSpeed(400); while (gauche.getTachoCount() < 360); gauche.setSpeed(360); droite.setSpeed(360); } void tournerAGauche() { droite.resetTachoCount(); droite.setSpeed(200); gauche.setSpeed(400); while (droite.getTachoCount() < 360); droite.setSpeed(360); gauche.setSpeed(360); } }
Nous allons faire une fusion de tous les TPs précédents. Nous désirons ainsi que notre robot puisse avancer, tourner à gauche et à droite, s'arrêter. Toutefois, lorsque le robot en en mouvement, il faudrait "en même temps" qu'il soit capable de détecter les obstacles et de réagir en conséquence, c'est-à-dire de ralentir progressivement, faire demi-tour en cas de contact et de repartir comme si de rien n'était.
package robot; import lejos.nxt.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); private boolean bouge; public Piloter() { Button.ENTER.addButtonListener(this); Button.LEFT.addButtonListener(this); Button.RIGHT.addButtonListener(this); } public static void main(String[] args) { new Piloter(); Button.ESCAPE.waitForPressAndRelease(); } public void buttonPressed(Button bouton) { if (bouton == Button.ENTER) { bouge = !bouge; if (bouge) robot.avancer(); else robot.arreter(); } if (bouton == Button.RIGHT && bouge) robot.tournerADroite(); if (bouton == Button.LEFT && bouge) robot.tournerAGauche(); } public void buttonReleased(Button bouton) { } }
package robot; import lejos.nxt.*; public class Robot { private Motor droite = Motor.A; private Motor gauche = Motor.C; private UltrasonicSensor ultraSon = new UltrasonicSensor(SensorPort.S1); private TouchSensor finDeCourse = new TouchSensor(SensorPort.S3); private boolean faireAvancer; void demarrer() { droite.forward(); gauche.forward(); } void avancer() { faireAvancer = true; new Thread(new Runnable() { public void run() { demarrer(); avancerPrudemment(); } }).start(); } void avancer(int vitesse) { droite.setSpeed(vitesse); gauche.setSpeed(vitesse); } void avancerPrudemment() { while (faireAvancer) { while (!finDeCourse.isPressed() && faireAvancer) { int distance = ultraSon.getDistance(); LCD.drawInt(distance, 5, 0, 0); if (distance >= 60) avancer(360); if (distance < 60 && distance > 30) avancer(4*distance); if (distance <= 30) avancer(120); } if (faireAvancer) { arreter(); reculerLegerement(); demiTour(); demarrer(); } } } void reculerLegerement() { droite.rotate(-360, true); gauche.rotate(-360); } void demiTour() { droite.rotate(1000, true); gauche.rotate(-1000); } void arreter() { droite.stop(); gauche.stop(); } void tournerADroite() { faireAvancer = false; gauche.stop(); droite.rotate(360); avancer(); } void tournerAGauche() { faireAvancer = false; droite.stop(); gauche.rotate(360); avancer(); } }
Nous finissons notre étude en reprenant exactement les fonctionnalités précédentes, mais le robot cette fois-ci sera piloté à distance et non plus par les boutons de la brique.
package robot; import java.awt.event.ActionEvent; import java.io.*; import javax.swing.*; import lejos.pc.comm.*; public class Distante extends JFrame { private JToolBar outils = new JToolBar(); private NXTConnector connexion; private DataOutputStream requete; private int commande; private final int QUITTER = 0; private final int AVANCER = 1; private final int GAUCHE = 2; private final int DROITE = 3; private final int ARRETER = 4; public Distante() { super( ); seConnecter(); add(outils); outils.add(new AbstractAction( ) { public void actionPerformed(ActionEvent e) { try { requete.writeInt(QUITTER); requete.flush(); } catch (IOException ex) { setTitle( ); } } }); outils.add(new AbstractAction( ) { public void actionPerformed(ActionEvent e) { try { requete.writeInt(AVANCER); requete.flush(); } catch (IOException ex) { setTitle( ); } } }); outils.add(new AbstractAction( ) { public void actionPerformed(ActionEvent e) { try { requete.writeInt(GAUCHE); requete.flush(); } catch (IOException ex) { setTitle( ); } } }); outils.add(new AbstractAction( ) { public void actionPerformed(ActionEvent e) { try { requete.writeInt(DROITE); requete.flush(); } catch (IOException ex) { setTitle( ); } } }); outils.add(new AbstractAction( ) { public void actionPerformed(ActionEvent e) { try { requete.writeInt(ARRETER); requete.flush(); } catch (IOException ex) { setTitle( ); } } }); pack(); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } private void seConnecter() { connexion = new NXTConnector(); if (connexion.connectTo(1234)) requete = connexion.getDataOut(); else System.err.println( ); } public static void main(String[] args) { new Distante(); } }
package robot; import java.io.*; import lejos.nxt.*; import lejos.nxt.comm.*; public class Piloter implements ButtonListener { private Robot robot = new Robot(); private NXTConnection connexion; private DataInputStream requete; private int commande; private final int QUITTER = 0; private final int AVANCER = 1; private final int GAUCHE = 2; private final int DROITE = 3; private final int ARRETER = 4; public Piloter() { Button.ESCAPE.addButtonListener(this); LCD.drawString( , 0, 1); connexion = Bluetooth.waitForConnection(); requete = connexion.openDataInputStream(); LCD.drawString( , 0, 1); commander(); } public static void main(String[] args) { new Piloter(); } private void commander() { try { do { commande = requete.readInt(); LCD.drawInt(commande, 3, 0, 2); switch (commande) { case AVANCER : robot.avancer(); break; case GAUCHE : robot.tournerAGauche(); break; case DROITE : robot.tournerADroite(); break; case ARRETER : robot.arreter(); break; } } while (commande!=QUITTER); requete.close(); connexion.close(); LCD.drawString( , 0, 1); } catch (IOException ex) { LCD.drawString( , 0, 1); } } public void buttonPressed(Button bouton) { System.exit(0); } public void buttonReleased(Button bouton) { } }