118 lines
4.9 KiB
Plaintext
118 lines
4.9 KiB
Plaintext
\b;Exercice
|
|
Télécommandez un robot, sans utiliser une \l;borne d'information\u object\exchange;, pour qu'il passe par les 6 croix bleues. Il faudra utiliser une variable \c;\l;static\u cbot\static;\n; pour communiquer directement d'un programme à un autre. Les 2 acteurs principaux de cet exercice sont:
|
|
|
|
1) Un \l;robot déménageur\u object\botgr; sans pile, donc immobile. C'est lui l'émetteur que vous devez programmer.
|
|
2) Un \l;robot d'entraînement\u object\bottr; qui attend les ordres. Ce robot est déjà programmé.
|
|
|
|
\b;Le robot récepteur
|
|
Pour commencer, il faut comprendre le programme du robot d'entraînement qui attend les ordres.
|
|
Une \l;classe\u cbot\class; \c;order\n; contient deux variables: \c;global_type\n; détermine l'ordre à effectuer (avancer ou tourner) et \c;global_param\n; détermine la distance à avancer ou l'angle de rotation:
|
|
\c;\s;\l;public\u cbot\public; \l;class\u cbot\class; order
|
|
\s;{
|
|
\s; \l;int\u cbot\int; global_type = \l;nan\u cbot\nan;;
|
|
\s; \l;float\u cbot\float; global_param;
|
|
\s;}
|
|
\n;
|
|
Une deuxième \l;classe\u cbot\class; \c;exchange\n; contient le mécanisme d'échange et de mémorisation des ordres. Il faut d'abord déclarer une variable \c;\l;static\u cbot\static;\n; appelée ici \c;global_order\n;. Cette variable contient l'ordre à effectuer. L'instruction \c;static\n; permet à tous les robots d'accéder à la même variable unique.
|
|
\c;\s;\l;public\u cbot\public; \l;class\u cbot\class; exchange
|
|
\s;{
|
|
\s; \l;static\u cbot\static; \l;private\u cbot\private; order global_order = new order;
|
|
\n;
|
|
Une première méthode \c;put\n; sera utilisée par le robot émetteur pour donner un ordre. Si l'ordre est différent de \c;\l;nan\u cbot\nan;\n;, cela signifie qu'il n'a pas encore été effectué par le robot récepteur. Dans ce cas, la méthode \c;get\n; ne fait rien et retourne \c;false\n;:
|
|
\c;\s; \l;synchronized\u cbot\synchro; \l;bool\u cbot\bool; put(order a)
|
|
\s; {
|
|
\s; if ( global_order.global_type == nan )
|
|
\s; {
|
|
\s; global_order = a;
|
|
\s; return true;
|
|
\s; }
|
|
\s; else
|
|
\s; {
|
|
\s; return false;
|
|
\s; }
|
|
\s; }
|
|
\n;
|
|
Une deuxième méthode \c;get\n; sera utilisée par le robot récepteur pour prendre connaissance d'un ordre à effectuer:
|
|
\c;\s; \l;synchronized\u cbot\synchro; order get()
|
|
\s; {
|
|
\s; return global_order;
|
|
\s; }
|
|
\n;
|
|
Une troisième méthode \c;delete\n; sera utilisée par le robot récepteur pour indiquer que l'ordre est terminé:
|
|
\c;\s; \l;synchronized\u cbot\synchro; void delete()
|
|
\s; {
|
|
\s; global_order.global_type = nan;
|
|
\s; }
|
|
\s;}
|
|
\n;
|
|
Le programme principal peut maintenant exister. La variable \c;list\n; est de type \c;exchange\n;, qui est une \l;classe\u cbot\class;. Il faut utiliser l'instruction \c;\l;new\u cbot\new;\n; pour créer immédiatement une instance.
|
|
\c;\s;\l;extern\u cbot\extern; void object::Slave3( )
|
|
\s;{
|
|
\s; exchange list = new exchange();
|
|
\s; order todo;
|
|
\n;
|
|
La première boucle \c;while\n; exécute les ordres à l'infini. La deuxième boucle \c;while\n; attend un ordre en exécutant la méthode \c;get\n; de la classe \c;exchange\n;. Dès qu'un ordre contenant une valeur différente de \c;nan\n; est reçu, la boucle est stoppée.
|
|
\c;\s; \l;while\u cbot\while; ( true )
|
|
\s; {
|
|
\s; \l;while\u cbot\while; ( true )
|
|
\s; {
|
|
\s; todo = list.get();
|
|
\s; if ( todo.global_type != nan ) break;
|
|
\s; wait(1);
|
|
\s; }
|
|
\n;
|
|
Il ne reste plus qu'à exécuter l'ordre reçu:
|
|
\c;\s; if ( todo.global_type == 1 )
|
|
\s; {
|
|
\s; move(todo.global_param);
|
|
\s; }
|
|
\s; else if ( todo.global_type == 2 )
|
|
\s; {
|
|
\s; turn(todo.global_param);
|
|
\s; }
|
|
\s; else
|
|
\s; {
|
|
\s; message("Unknown order");
|
|
\s; }
|
|
\n;
|
|
Dès que l'exécution de l'ordre est terminée, il faut appeler la méthode \c;delete\n; pour indiquer au robot émetteur qu'il peut envoyer l'ordre suivant:
|
|
\c;\s; list.delete();
|
|
\s; }
|
|
\s;}
|
|
\n;
|
|
\b;Le robot émetteur
|
|
Dans le robot émetteur, il est plus simple d'écrire une procédure \c;SendOrder\n; qui se charge d'envoyer un ordre au robot récepteur:
|
|
\c;\s;void object::SendOrder(float order, float param)
|
|
\s;{
|
|
\s; exchange list = new exchange();
|
|
\s; order todo();
|
|
\s;
|
|
\s; todo.global_type = order;
|
|
\s; todo.global_param = param;
|
|
\s;
|
|
\s; while ( list.put(todo) == false )
|
|
\s; {
|
|
\s; wait(1);
|
|
\s; }
|
|
\s;}
|
|
\n;
|
|
La boucle \c;while\n; attend qu'un éventuel ordre précédent soit terminé, ce qui arrive lorsque le robot récepteur exécute la méthode \c;delete\n;.
|
|
Le programme principal est finalement d'une simplicité enfantine:
|
|
\c;\s;extern void object::Remote4( )
|
|
\s;{
|
|
\s; SendOrder(1, 20); // move(20);
|
|
\s; SendOrder(2, 90); // turn(90);
|
|
\s; SendOrder(1, 20); // move(20);
|
|
\s; SendOrder(2, 90); // turn(90);
|
|
\s; SendOrder(1, 10); // move(10);
|
|
\s; SendOrder(2, 90); // turn(90);
|
|
\s; SendOrder(1, 10); // move(10);
|
|
\s; SendOrder(2,-90); // turn(-90);
|
|
\s; SendOrder(1, 10); // move(10);
|
|
\s;}
|
|
\n;
|
|
\key;\key help;\norm; permet de revoir ces instructions en tout temps!
|
|
|
|
\t;Voir aussi
|
|
\l;Exercice précédent\u tremote3; et \l;programmation\u cbot;.
|