\b;Exercice
Télécommandez un robot, sans utiliser une \l;station relais\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 préhenseur\u object\botgr; sans batterie, 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;.
