Subsumption architecture controlling the simulated ALLEN 
========================================================

Please launch the robot simulator by run-simulator.bat
You can control the robot with arrows and the key R and the obstacle with keys A, S, W, Z
Please rotate the robot to the South-South-East (by the appraisal).

You can check how the simulator provides values to your program in Python in the following way:
Start putty and open a raw TCP connection to port 7171 on the localhost.
As a result, you get a stream of relatively readable data containing 
values monitored by sensors and odometry of the robot:
(you can stop the datastream by the mouse click or Ctrl-s and restart again by Ctrl-q)

The Bump is a tactile sensor and provides values of True or False
Sonar is a sensor that provides 12 values of the closest distance in the direction 
of 0, 30, 60, 90, ... degrees clockwise, i.e. [0] is in front, [6] is back, [9] left, [3] right
X and Y provide coordinates provided by odometry
Compass provides values from 0 to 2*np.pi; 
0 is East, np.pi is West, np.pi/2 is South, and 3*np.pi/2 North.
(we can recalculate radians to degrees by the formula: dg = 180*rad/np.pi)

You can also test control of the robot by commands written into the putty windows and 
confirmed by the Enter:
r, l, f, b, z (turn to the right, turn to left, go forward, go backward, stop)
or M 1.0 1 ("Forward" is a float while "Turn" is an integer)

Close to the connection and look into main.py, which employs allen.py.
Allen.py is a TCP client that performs the same as you have just made with putty.
allen.py provides us with two classes - Sensors and Motors, which enable us
to control the robot comfortably by the static attributes of the classes
As a result, the main.py can read the robot's value through Sensors.bump, Sensors.sonar, 
Sensors.compass, Sensors.x, and/or Sensors.y
Analogically, you can control the robot by setting:
Motors.forward = 1 (forward) or 0 (stop) or -1 (backward)
Motors.turn = -1 (to the left) or 0 (no turn) or 1 (to the right)
When we set motors, we have to call Motors.apply() to send the values to the robot,
while Sensors are updated automatically.

We build a system consisting of several agents organized in layers and employing the 
blackboard for implementation of the sumbsumption mechanisms.

At the starting point, only one agent controls motors following the
backboard variables "Forward" and "Turn." Pay attention to the fact that the default
value of the "Forward" is 1, i.e., go forward. So, when you launch run-main.bat,
the robot goes until it reaches the wall and hits it endlessly.

Now look inside the directory video and play the video behavior1.avi
Let us implement an agent (today, we follow the subsumption architecture, and we will never
modify any agent; instead, we will rather add new agents that subsume the
existing ones by influencing their mutual communication) that implements the behavior.
It resides in response to hitting the wall. So our agent must modify "Forward" 
for a particular duration. The easiest way how to do it is the following:
space(validity=0.75)["Forward"] = -1 
We apply this command when Sensors.bump is positive.
We underline that the response causes the robot goes backward and - as a result - after 
a few time (much less than 0.75s) Sensors.bump becomes negative. However, the robot still goes
backward until the validity of the "Forward" value expires.

So we add to the main:

class Behavior1(Agent):

    def init(self):
        self.attach_timer(0.1)

    def senseSelectAct(self):
        if Sensors.bump:
            space(validity=0.75)["Forward"] = -1

Behavior1()

When we return the robot to the center of the room (with the key R)
Start run-main.bat, and you should see behavior corresponding to the video behavior1.avi

Now, comment out Behavior1() to avoid starting the developed agent and 
implement Behaviour2 according to the video behavior2.avi
It can rotate while Sensors.bump is positive for a smaller period; the optimal one is 0.15s.
The code of Behavior2 resembles the code of Behavior1 a lot.

When it is running fine, uncomment also the Behavior1. 
Can you predict behavior that emerges from the parallel operation of both agents?
If you are lucky, you can observe a surprising behavior like in the video together.avi
In other words, an interaction of two elementary behaviors can create a complex behavior
that it is difficult to predict. 

Now, comment out Behavior1() again and add Behavior3, implementing escape from the room.
Behavior3 should employ Behavior2 to keep the robot on the route around walls. However,
it overcomes Behavior2's disability of crossing the door. For that, you have to employ 
Sensors.sonar and priority like space(priority=2,validity=0.5)["Turn"] = -1
In this way, Behavior3 suppresses Behavior2. MotorAgent "thinks" that data are coming from
Behavior2, but they are produced by Behavior3 that intrudes the communication among the
Behavior2 and MotorAgent.
You can also use an internal state (variables self.xy = ...). 
The system must work for any initial position of the robot.

Finally, you can add another agent that returns the robot into the room when it gets far 
enough from the doors.
