... | ... | @@ -101,7 +101,7 @@ The software for the sumo wrestler LEGO car is build upon the dynamic behavioral |
|
|
|
|
|
The most important behavior is "StayInRing". According to the rules of the battle one will loose if the LEGO car drives or gets pushed off the battle area (outside the white border). In order to make the light sensor able to trigger the "StayInRing" behavior at any time, the priority of this is set to highest possible value. Even though the dynamic behavioral paradigm is used there will be no priority changes and the statical hierarchy shown in the previous figure will be kept during the lifetime of the program.
|
|
|
|
|
|
The program is made so that a calibration is required before the actual program is initiated. This copes with variations in the lighting and power level of the NXT. The threshold between black and white is determined using a weighted difference between the two calibration values as seen in the following code snippet.
|
|
|
The program is made so that a calibration is required before the actual program is initiated. This copes with variations in the lighting and power level of the NXT. The threshold between black and white is determined using a weighted difference between the two calibration values as seen in the following code snippet. Originally an average of the calibration values was used, but this caused the robot to falsely detect the edge, because the treshold was too low.
|
|
|
|
|
|
```java
|
|
|
final float alpha = 0.7f;
|
... | ... | @@ -112,6 +112,77 @@ Whenever the LEGO car is not on the border the sonar sensor is able to trigger t |
|
|
|
|
|
![How the behaviors are triggered in the battle area](https://gitlab.au.dk/rene2014/lego/raw/master/Lesson9/Images/BehavioralControlOnTrack.jpg)
|
|
|
|
|
|
#### Details of the behaviors
|
|
|
|
|
|
The implementation of the `Arbitrator` class is the one provided by [1]. The `Behavior` interface was turned into a class, and some common functionality was added, most notably `wait()` and `waitForACMovement()`:
|
|
|
|
|
|
```java
|
|
|
protected void wait(int waitTime)
|
|
|
{
|
|
|
int now = (int)System.currentTimeMillis();
|
|
|
while (!_suppressed && ((int)System.currentTimeMillis()< now + waitTime) )
|
|
|
{
|
|
|
Thread.yield();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
protected void waitForACMovement()
|
|
|
{
|
|
|
while (!_suppressed && (Motor.A.isMoving() || Motor.C.isMoving()) )
|
|
|
{
|
|
|
Thread.yield();
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
##### StayInRing
|
|
|
|
|
|
The goal of the StayInRing behavior is to keep the robot inside the ring by monitoring the lightsensors - an addition was added later for a total of two. When the robot detects an edge, it will immediatly (stayInRing has top priority when an edge is detected) drive backward, and depending one which side the edge was detected, turn to face away from the edge.
|
|
|
|
|
|
##### Search
|
|
|
|
|
|
The goal of the Search behavior is to wander around to increase the chance of detecting the opponenent. Wander would be a more correct name for this behavior, but we decided that having behaviors named "Search" and "Destroy" trumped that. The random wander algorithm is covered in the section "Added randomness".
|
|
|
|
|
|
##### Destroy
|
|
|
|
|
|
The goal of the Destroy behavior is to use the sonar to detect the opponent, and charge at the opponent when it is detected. Since it takes a while to get a measurement from the sonar sensor, reading the sensor is moved from the `takeControl()` function to another thread, so as to not block the arbitrator´s thread while taking the measurement:
|
|
|
|
|
|
```java
|
|
|
public Destroy()
|
|
|
{
|
|
|
pinger = new Thread(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
public void run() {
|
|
|
while(true)
|
|
|
{
|
|
|
distance = sonic.getDistance();
|
|
|
LCD.drawInt(distance, 5, 0, 1);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
pinger.setDaemon(true);
|
|
|
pinger.start();
|
|
|
}
|
|
|
```
|
|
|
|
|
|
When an object, assumed to be the opponent, is detected within some threshold (chosen to not detect objects outside the ring), the Destroy behavior will change its priority to be just above the priority of the Search behavior. When activated, the Destroy behavior will cause the robot to charge forward:
|
|
|
|
|
|
```java
|
|
|
@Override
|
|
|
public void action() {
|
|
|
super.action();
|
|
|
|
|
|
//charge!!!
|
|
|
Motor.A.forward();
|
|
|
Motor.C.forward();
|
|
|
wait(1000);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
We initially left out the `wait()` call. The result of that was that the first sonar measure, which did not detect an opponent would cause the control to revert to the Search behavior which was mostly not the desired behavior.
|
|
|
|
|
|
### Results
|
|
|
|
|
|
[INDSÆT BESKRIVELSE]
|
... | ... | @@ -128,7 +199,7 @@ We quickly realized that the shovel in front of the car was too poorly attached |
|
|
|
|
|
### Added randomness
|
|
|
|
|
|
Before adding randomness to the search for the opponent(s), the robot sumo wrestler would drive straight forward until the edge was detected, the backup, turn in a deterministic manner, and then drive forward again. In order to increase the chance of finding the opponent(s), randomness was added to this search. The algorith used for the random search can was as follows:
|
|
|
Before adding randomness to the search for the opponent(s), the robot sumo wrestler would drive straight forward until the edge was detected, then backup, turn in a deterministic manner, and then drive forward again. In order to increase the chance of finding the opponent(s), randomness was added to this search. The algorith used for the random search is as follows:
|
|
|
|
|
|
```java
|
|
|
@Override
|
... | ... | |