Thursday, November 25, 2010

Lab Exercise 10

Date:
18/11 2010

Duration of activity:
3 hours

Group members participating:
Frederik, Christian & Lasse

Goals:
To investigate the leJOS API "subsumption" architecture by using a BumperCar-example as a starting point. 

Plan:
1. Get the sample running and observe the behaviour
2. Do experiments with the BumperCar sample code
3. Implement a new behaviour called Exit, which shall exit the program


Results:

1. Running the sample
We reused the construction of the car from the last lab session equipped with two motors. Furthermore we needed to mount a bump sensor and an ultrasonic sensor on the car because they are used by the DetectWall behaviour in the BumperCar sample. We though chose to mount two bump sensors to achive a better detection of bumps in front of the car. An image of the car is seen below:



When running the sample the overall behaviour was as expected; the car drives forward until an obstacle is detected by the ultra sonic sensor (within 25 cm) or the bump sensors, the car then backs of and rotates, and continues to drive forward. Before doing experiments with the sample code we decided to make it possible to exit the program when pressing the escape button - we just made as a thread listening for the button press, this was not the actual Exit behaviour implementation. This was done because the building structure of the car made it difficult the access the battery, which was necessary remove in order to exit the application (we later found out that a program can be terminated by pressing the enter and escape buttons simultaneously).

2. Experiments
When keeping the bump sensor pressed the DetectWall behaviour suppresses the DriveForward because the takeControl() method of DetectWall yields true when the bump sensor is pressed. When looking at the Arbitrator class it is seen that the list of behaviours is traversed and the highest index gets the highest priority and lower prioritized behaviours are supressed as seen below:




3. Exit behaviour
The escape code made in point 1 was removed to ensure that only the new Exit behaviour reacts to escape button presses. The exit behaviour was implemented with highest priority and when running the code we noticed that when the DetectWall behaviour has control the program is blocked i.e. it is not possible to poll the exit button until the rotation is finished. This is caused both by the Motor.A.rotate(-180, true); and Motor.C.rotate(-360); statements but the Sound.pause(20); statement also has a little influence. When increasing the Sound.pause parameter to 2000 ms a delay of 2 sec is added which causes the Arbitrator to block the takeControl() checks which is seen in the code example above.


The code for the exit behaviour is seen in the Exit class in the file BumperCar.java[1]


Because the DetectWall class is no longer the highest prioritized class we added some handling to its supress() method which stops the motors if they are running. We noticed that the action method of DetectWall had different behaviour for the two rotate-calls to the motors as seen below:
The true parameter is 'immediate return' which causes the method call to return right after it is called. This must not be done for the call to motor C because that would have caused that the action method returned right after it is called and thereby not getting enough time to back off.


To make the takeControl() in DetectWall more responsive we made a Thread which handles the reading of the sonar sensor and writes to a shared variable. This variable is then read by the takeControl() method and thereby avoiding the delay which previous was in the method, this is illustrated below:





To make sure that the routine stops if it is suppressed during the sleep period we made an action thread for DetectWall which performs the back off action; moves backwards for a second and then rotates. If the thread is interrupted during sleep (by a suppression) the thread returns and thereby ignores the rotation. This implementation sadly didn't work out because of some threading problems that we didn't manage to solve.

Conclusion:
We have seen that it is possible to improve the performance of a certain behaviour by moving the sampling of a particular sensor into a separate thread. This is because the sensor reading lasts a certain amount of time and thereby blocking the main program if the reading isn't performed in a separate thread. Generally a lot of tweaking can be done using the subsumption architecture by means of moving time consuming parts to threads and thereby making the program more responsive.


References: