fredag den 2. maj 2014

Week 11 - Lesson 10


Date:
1/5-2014 (round 1), 2/5-2014 (round 2)

Duration of activity:
10:00 - 16:00 (round 1), 10:00 - 15:00 (round 2)

Group members participating:
Levi, Christina, Benjamin

Goal: to make experiments with the class BumperCar[1] and investigate the functions of the Arbitrator, and to use the knowledge gained to create a class SumoCar that can win in the Sumo Arena.

Investigation of behavior of touch sensor
When the bumper is pressed, the robot drives backward for one second, and then turns its wheels to respectively -180 and -360 degrees. If the bumper is kept pressed, this behaviour will be repeated over and and over, since this behavior has a higher priority in the arbitrator than the forward behaviour.
When the touch sensor is pressed, DetectWall’s takecontrol() method returns 100 to the arbitrator. This makes Detectwall’s action() method go. Action() immediately sets DetectWall’s priority to 50. This makes it possible for other methods to have a higher priority than DetectWall’s. For example, there could be a rear bumper that has priority 75, with a different avoid strategy than BumperCar’s forward bumper.

Implementation of Exit behavior:
While driving forward and pressing ESCAPE, the robot will exit behaviour immediately, as expected. While driving backward, the system does not exit immediately. There is a tiny delay from the button is pressed till the system exits: when the Escape button is pressed when the car has stopped and are standing still for 1 sec, the car actually reaches the code for turning the car (and displaying ‘Turn’ on the LCD), before exiting.
We suspect that this might have something to do with the fact that all the conditions in the while loops in the DetectWall’s action method calls the method System.currentTimeMillis() in addition to checking that it isn’t suppressed. The while loop conditions in the DriveForward’s action method only checks that it isn’t suppressed.

Source code of Arbitrator
The Arbitrator[2] calls DriveForward’s takeControl() method while DetectWall()’s trigger is true, because DetectWall() has an ‘active’ boolean that stays true giving DetectWall a priority value of 50. The first call to DetectWall().takeControl() sets the priority to 100, and activates the action() method. The next time the arbitrator calls DetectWall().takeControl() the ‘active’ boolean is true. This makes the DetectWall().takeControl() return 50. It has that priority until DetectWall().action() is done and sets ‘active’ to false, making DetectWall().takeControl() return 0. The Arbitrator keeps calling every takeControl() method while the DetectWall().action() is running.

Local thread for updating variable
To avoid that a calculation in the takeControl method takes a long time to perform, and therefore delays the whole process of starting the correct action (that has the highest priority), a local thread in the class in question, is implemented to update a variable that other parts of the class need. This variable is accessible from the takeControl method, and can hence just be used for computing some triggering condition, without going through the trouble of (and spending the time on) computing the variable itself first. When starting a thread in a class, that class need to extend the class Thread.

This is for instance the case in the DetectWall class, where the value of the distance measured from the ultrasonic sensor is used to check whether or not this class should take control. The code for this is shown below:



In the method run() the distance is being continuously sampled as often as possible because the while triggering condition is simply ‘true’. the takeControl method uses this distance to perform the calculation of whether or not the distance is smaller than 25.

Interruption of a method
When takeControl is called at first it sets its priority at 100, and activates the action method. The action method sets the priority to 50 and goes on to move the car. If the trigger is triggered again the priority is set to 100 again, and the Arbitrator suppresses the old action thread and activates a new one. This enables the car to act on the sensor input while the detectWall().action() is active.

SumoCar

The SumoCar class makes use of classes that implements the Behavior interface that has the methods takeControl(), action() and suppress().

Our final robot is shown here:



DetectWhite
Our take on the SumoCar was that it first of all should avoid the outer white circle in the arena; it does this by driving straight backwards for 1 second when it observes white color. The priority of this behavior ‘DetectWhite’ is 500.
If the car is not detecting any white color then the car is not in danger of falling of the arena (unless of course the car is pointing with it’s back towards the outer white circle; then the sensor won’t register the white color because the sensor is on the front of the car).

PushOtherCar
The next action with lower priority than to detect white color is to push another car forward. It does this by checking if something is in front of the car within approximately 20-30 cm (the distance value 25).
The pushing continues until a car is no longer registered to be in front of the car.
The pushing happens by driving the car forward with a speed on both wheels at 700 (not the speed of 400 as the standard was in the BumperCar). This higher speed was set in order to make the car more able to actually move the other car, which was more possible if the car had more forward power. The speed wasn’t set even higher, because the value of 700 was found to make the car go just so fast as it could, but still being able to register the white color on the edge of the arena when it got there, and then stop the car to back it up. Had we increased the speed to more than 700, we believe that the car sometimes wouldn’t have time to register white color and hence start the action for the DetectWhite behavior; making it drive off the arena.

FindOtherCar
Yet another action with even lower priority is to search for another car. This should have lower priority than the pushing of other cars, as a search for other cars should never happen if a car is already found. That’s why the priority for pushOtherCar is 400 and FindOtherCar is 300.
The behavior of searching for other cars ‘takes control’ if there’s nothing in front of the car in the distance of approximately 60 cm. We tried making the car search for other cars if nothing was in front of the car, by allowing it to search if the distance value measured were 255 or more (the maximum value that can be measured by the ultrasonic sensor), but because the ultrasonic signal from the sensor interferes with the arena floor and other things in the vicinity, the values measured could be between approximately 70 and 110  even if nothing was in front of it.
We found that setting the triggering conditions for the takeControl of the FindOtherCar behavior to be that ‘the distance measured should be larger or even to the distance value 60’, for the Sumo Car to function best.
This issue also had to do with the fact that we don’t know the orientation of the car at all times (we probably could have implemented this, but didn’t), which means that setting a triggering value that makes the car act well when it is placed at the edge of the arena facing inwards, probably doesn’t also make the car act well if it is placed somewhere else or placed at the same point but pointing outwards.

The action of finding other cars is pretty straightforward. First we just made the car drive around on the spot, so that it constantly would measure distance around itself, and at some point know that a car had come within the vicinity that the car could measure to be a car in front of it.
This meant that the car would, sometimes for long periods of time, just drive around itself on the spot. In order to make the car move a little around the arena while searching (to make the car less vulnerable to other cars that would easily find it if it stays in the same spot at all times), one motor was set to the speed 500, while the other motor had the standard speed of 400. In theory this would make the car drive around in circles, but not around the same spot. When testing, the difference between the two speeds of the motors should probably have been bigger, for us to actually see that the car slowly changed it’s centre of rotation.

Sensors
The light sensor was placed in front of the car, with a distance to the surface at about 0,5 cm. We tried different wheels for the car, resulting in different distances between the light sensor and the surface. We found that a distance of 1-2 mm wasn’t enough, and that 0,5 cm performed better than 1 cm.

The distance sensor was placed in ‘high’ altitude on the car; about 8-10 cm above the surface. This was necessary for the ultrasonic sensor to measure distances without too many interferences. The values for the triggering conditions mentioned earlier (the values 25 and 60) was found to work best with this described placement of the ultrasonic sensor on the car. The values should probably be ‘calibrated’ to other ones, if the sensor was placed differently.

See the picture below for placement of the light sensor and ultrasonic sensor.


Videos

A video that shows just how fast we can drive the opponent of the arena with our robot is shown here:


Another video that shows a result of a match with our robot is shown below (thanks Daniel Westergaard, for filming):

(we and the rivaling team agreed on a draw in this one).

A video that shows the effectiveness of the attached front ‘bumper’ is shown below.


A video that shows how we won over the team that ended up winning in the final is shown below:

This is how cool our robot was: we played best out of 3 with the winners after the competition ended;
- we won the first match
- the second match was draw
- the third match we won again

So in conclusion: we are the real winners!
P.S: Sumo wrestling LEGO robots was awesome fun. Ole is the sejeste forelæser. Ever.

P.P.S.: Battle Royale:


Conclusion
We created a sumobot and took part in the competition. We also completed the tasks.

References

  • [1] Bumpercar.java
  • [2] Arbitrator.java

    Ingen kommentarer:

    Send en kommentar