zteel created page: Week11 sumo wrestling robots authored by Troels Fleischer Skov Jensen's avatar Troels Fleischer Skov Jensen
...@@ -21,11 +21,11 @@ to try different sensor configurations, robot designs and behaviors to decide wh ...@@ -21,11 +21,11 @@ to try different sensor configurations, robot designs and behaviors to decide wh
### Goal ### Goal
To study the sample *bumpercar*[REF] from the leJOS NXJ distribution and how it implements behavioral control. To study the sample *Bumpercar*[3] from the leJOS NXJ distribution and how it implements behavioral control.
### Plan ### Plan
Use the *Express bot*[REF] mounted with a bumper and a ultrasonic sensor, to do the experiments. Use the *Express bot*[5] mounted with a bumper and a ultrasonic sensor, to do the experiments.
### Result ### Result
...@@ -33,6 +33,8 @@ Use the *Express bot*[REF] mounted with a bumper and a ultrasonic sensor, to do ...@@ -33,6 +33,8 @@ Use the *Express bot*[REF] mounted with a bumper and a ultrasonic sensor, to do
Image 1: Image of BumperCar Image 1: Image of BumperCar
The modified version of *Bumpercar* can be found on our GitLab[4]
#### Touch sensor continually pressed #### Touch sensor continually pressed
When the touch sensor is pressed continuously the robot stays in the detect wall behavior, where it first drives a little backwards, followed by turning a little to the right. This is done with the *RegulatedMotor*, where a non blocking command is sent to the left motor, commanding the motor to turn 180 degrees backwards, and a blocking command to the right motor commanding it to turn 360 degrees backwards. When the touch sensor is pressed continuously the robot stays in the detect wall behavior, where it first drives a little backwards, followed by turning a little to the right. This is done with the *RegulatedMotor*, where a non blocking command is sent to the left motor, commanding the motor to turn 180 degrees backwards, and a blocking command to the right motor commanding it to turn 360 degrees backwards.
...@@ -48,14 +50,16 @@ We want a behavior that if the ESCAPE button is pressed, System.Exit(0) is calle ...@@ -48,14 +50,16 @@ We want a behavior that if the ESCAPE button is pressed, System.Exit(0) is calle
When the escape button is pressed, the robot takes the following action: When the escape button is pressed, the robot takes the following action:
```java ```java
public void action() { public void action() {
LCD.drawString("Now exiting...", 0, 0); LCD.drawString("Now exiting...", 0, 0);
BumperCar.leftMotor.stop(); BumperCar.leftMotor.stop();
BumperCar.rightMotor.stop(); BumperCar.rightMotor.stop();
System.exit(0); System.exit(0);
} }
``` ```
Which simply stops the motors and exits the system if the ESCAPE button is pressed.
In detect wall we have added a proper suppression so that the escape behavior can take precedence. In detect wall we have added a proper suppression so that the escape behavior can take precedence.
##### Observation of the behavior ##### Observation of the behavior
...@@ -71,14 +75,14 @@ Getting the distance takes a little time, which goes against the contract of a b ...@@ -71,14 +75,14 @@ Getting the distance takes a little time, which goes against the contract of a b
```java ```java
_ping = new Thread(new Runnable(){ _ping = new Thread(new Runnable(){
public void run() { public void run() {
while (true) { while (true) {
sonar.ping(); sonar.ping();
_distance = sonar.getDistance(); _distance = sonar.getDistance();
Delay.msDelay(20); Delay.msDelay(20);
} }
}}); }});
_ping.start(); _ping.start();
``` ```
...@@ -89,79 +93,131 @@ To get the robot to move backwards for one second before turning, the following ...@@ -89,79 +93,131 @@ To get the robot to move backwards for one second before turning, the following
```java ```java
BumperCar.leftMotor.backward(); BumperCar.leftMotor.backward();
BumperCar.rightMotor.backwart(); BumperCar.rightMotor.backwart();
Delay.msDelay(1000); Delay.msDelay(1000);
``` ```
#### Making call interruptible #### Making call interruptible
A problem with the implementation of Detect Wall is that both delay and the last rotate is blocking calls, meaning that we cannot do anything new. This have been solved by making small methods that do the same, but we have use some busy waiting instead, where we do checks if it should start from the beginning or if it has been suppressed. A problem with the implementation of Detect Wall is that both delay and the last rotate is blocking calls, meaning that we cannot do anything new. This have been solved by making small methods that do the same, but we have use some busy waiting instead, where we do checks if it should start from the beginning or if it has been suppressed.
```java
// The backwards method returns if it has been interrupted
public boolean bwd() {
long time = System.currentTimeMillis();
BumperCar.leftMotor.backward();
BumperCar.rightMotor.backward();
while (System.currentTimeMillis() < time + 1000) {
if (_suppressed) {_suppressed = false; return true;}
if (takeControl()){ return true; }
}
BumperCar.leftMotor.stop();
BumperCar.rightMotor.stop();
return false;
}
private void turn() {
BumperCar.rightMotor.resetTachoCount();
BumperCar.rightMotor.backward();
BumperCar.leftMotor.backward();
while (BumperCar.rightMotor.getTachoCount() > -180) {
if (_suppressed) {_suppressed = false; return;}
if(takeControl()){ action(); return; }
}
BumperCar.leftMotor.stop();
BumperCar.rightMotor.backward();
while (BumperCar.rightMotor.getTachoCount() > -360) {
if (_suppressed) {_suppressed = false; return;}
if(takeControl()){ action(); return; }
}
}
```
Here we use lower level methods to run the motors, giving us more control of what is done while the robot is doing the call.
### Conclusion ### Conclusion
We have gained knowledge about the built in arbitrator and the behavioal interface. We have gained knowledge about the built in arbitrator and the behavioral interface.
## Dynamic priority
The prioritizing of behaviors can either be dynamic or fixed. Krink[2] looks at autonomous robots as simple animals, which is a good abstraction if we want a dynamic behavior, we however have not found a fitting usage of this in our design and have gone with a simple fixed behavior priority queue.
The dynamic arbitrator[6], takes a behavior[7], that instead of returning a simple boolean value, returns an integer representing how much motivation it has to run i.e. its priority, which makes the dynamic prioritising possible.
Because we do not need dynamic behavior, we have chosen to do our implementation of our sumo wrestler robot with the leJOS behavior interface and arbitrator.
## Sumo Wrestler Robot ## Sumo Wrestler Robot
### Building the robot ### Initial construction of the robot
The main purpose of the robot should be not to lose. To achieve this we got the following general idea for building our robot which was to have as many useful and different sensors as possible. This should reduce the chance that our opponent could trick our robot into doing something unintended to a minimum. One of the first things we realized was that we could have multiple touch sensors connected to the same port, which fit our idea nicely. The main purpose of the robot should be not to lose. To achieve this we got the following general idea for building our robot which was to have as many useful and different sensors as possible. This should reduce the chance that our opponent could trick our robot into doing something unintended to a minimum. One of the first things we realized was that we could have multiple touch sensors connected to the same port, using cables for RCX sensors, which fit our idea nicely.
The original building plan for the robot was to build a big wall around the robot to protect against whatever unpredictable thing our opponent would do. Among these we wanted to prevent another robot to drive something below our robot and lift it from the floor. The original building plan for the robot was to build a big wall around the robot to protect against whatever unpredictable thing our opponent would do. Among these we wanted to prevent another robot to drive something below our robot and lift it from the floor.
Behind each wall we wanted 2 touch sensors one in each end for a total of 8. The idea here was that we could use the ultrasonic sensor to detect the direction of an opponent, and use the touch sensor to detect when the robot was right next to our robot. By having touch sensor all the way around our robot and only try to push the opponent’s robot when they are pressed, we should be able to avoid the case where the opponent's robot drops something and our robot using the ultrasonic sensor interprets the dropped item as the opponent's robots, since that item probably won’t be heavy enough to push in the touch sensors. Behind each wall we wanted 2 touch sensors one in each end for a total of 8. The idea here was that we could use the ultrasonic sensor to detect the direction of an opponent, and use the touch sensor to detect when the robot was right next to our robot. By having touch sensor all the way around our robot and only try to push the opponent’s robot when they are pressed, we should be able to avoid the case where the opponent's robot drops something and our robot using the ultrasonic sensor interprets the dropped item as the opponent's robots, since that item probably won’t be heavy enough to push in the touch sensors.
To detect the white edge of the arena plate, we wanted 2 light sensors in front connect to one port and 2 light sensor in the back to another port. To detect the white edge of the arena plate, we wanted 2 light sensors in front connected to one port and 2 light sensor in the back to another port.
We wanted to use the ultrasonic sensor to find our opponent without having turn the car, the best way to do that was to place the ultrasonic sensor on a motor so it could be rotated independently. We wanted to use the ultrasonic sensor to find our opponent without having turn the car, the best way to do that was to place the ultrasonic sensor on a motor so it could be rotated independently.
![small_IMAG0691](http://gitlab.au.dk/uploads/lego-group-3/lego/c4aedf3d8a/small_IMAG0691.jpg) ![small_IMAG0691](http://gitlab.au.dk/uploads/lego-group-3/lego/c4aedf3d8a/small_IMAG0691.jpg)
Image 2: Image of partial build original idea Image 2: Image of partial build original idea
So we started building our robot, but we didn’t get that far before we checked the weight and discovered it was way too heavy and so we had to cut down on a lot of things. We started building our robot, but we didn’t get that far before we checked the weight and discovered it was way too heavy and so we had to cut down on a lot of things.
After cutting down we had only small walls and no walls behind the robot, we also cut the light sensor behind the robot plus some other small optimizations and we managed to get below 1 kg. After cutting down we had only small walls and no walls behind the robot, we also cut the light sensor behind the robot plus some other small optimizations and we managed to get below 1 kg.
![small_IMAG0692](http://gitlab.au.dk/uploads/lego-group-3/lego/a6438303cf/small_IMAG0692.jpg) ![small_IMAG0692](http://gitlab.au.dk/uploads/lego-group-3/lego/a6438303cf/small_IMAG0692.jpg)
Image 2: Image of ultrasonic version of the robot. Image 2: Image of ultrasonic version of the robot.
We however found that the motor mounted ultrasonic sensor was simply too slow. It took about one second to do the entire reading of forward and 45 degrees left and right. Meaning that the guess of the position of the other robot always will be way too outdated, so we could not use the guess to anything constructive. One second is a lot of time in a lego sumo match. By discarding the motor and the ultrasonic sensor, we suddenly had a bit more weight to play with, so we could remount our back wall with touch sensors. And because we no longer needed a sensor port for the ultrasonic sensor, we were able to separate the front wall from the three other walls. ### Programming the robot
With this design we however have another problem. We only know if have something in front of us, which is what we want, or if we have been touch on one of the three sides we do not want. Question is if we can distinguish the walls from each other by small differences in the raw value from the touch sensors. #### Ultrasonic Behavior
As distance readings, from the ultrasonic sensor, blocks the thread, we implemented this behavior in a separate thread. The *Behavior* class could then request the latest reading. Using the *NXTRegulatedMotor* class, we pointed the ultrasonic sensor forward, then 45 degrees to the right and finally 45 degrees to the left. Using distance values, from the three angles, we estimated turned the robot in the direction with the shortest distance.
We however found that the motor mounted ultrasonic sensor was simply too slow. It took about one second to do the entire reading of forward and 45 degrees left and right. Meaning that the guess of the position of the other robot always will be way too outdated, so we could not use the guess for anything constructive. One second is a lot of time in a lego sumo match.
### Programming the robot Because of the disappointing results, we chose not to use the ultrasonic sensor.
#### Bumpers
By discarding the motor and the ultrasonic sensor, we suddenly had a bit more weight to play with, so we could remount our back wall with touch sensors. And because we no longer needed a sensor port for the ultrasonic sensor, we were able to separate the front wall from the three other walls.
####MAYBE>>? With this design we however have another problem. We only know if have something in front of us, which is what we want, or if we have been touched on one of the three sides we do not want. Question is if we can distinguish the walls from each other by small differences in the raw value from the touch sensors. This will be possible if the sensors are inaccurate, but precise.
The prioritising of behaviors can either be dynamic or fixed. Krink[REF!] looks at autonomous robots as simple animals, which is a good abstraction if we want a dynamic behavior, we however have not found a fitting usage of this in our design and have gone with a simple fixed behavior priority queue. We tested all the unused touch sensors in LegoLab, and found the the raw value returned by SensorPort.readRawValue() ranged in 181-185 with readings from the individual sensor being fairly consistent. We were able to pair touch sensors to get raw values of 98, 99 and 100. It was possible to get readings of +/- 3, but most readings of the paired sensors were the same. Although detecting which bumper is pressed using the raw values, may sometimes be imprecise, it is still better than random guessing.
// we edited robot again, image of new look We have found that we are surprisingly good at detecting which sensors have been activated. Before testing we considered using an average value over the latest measurements, an idea we discarded, because our experiments showed it was unnecessary. We even considered connecting the front bumper to the side and rear bumpers, in order to free up a sensor port. We ended up keeping them separate, as adding another sensor would push the robot above the weight requirement.
#### Motor speed
// ref behaviour # Conclusion
We have been very limited by the weight limitation, because of our vast amounts of sensors and especially the rcx cables. We have found that a motor mounted ultrasonic sensor is simply too slow to use in a sumo fight, a solution could have been to use two ultrasonic sensors, but we did not have weight or sensor ports to spare. Most interestingly is our experience with using multiple touch sensors connected to the same port through rcx cables. It was surprising how well we could distinguish the sensors solely because of small differences in the measured raw value.
# References
/* delete: [1], Exercise description - http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson10.dir/Lesson.html
general idea
ultrasonic rotating on motor = look at opponent, turn to face
8 bumpers around the car = detect if hit (ultrasonic knows direction)
need to check length to object (in case ultra sonic is look at a dropped item, it
should rotate to find where the attack came from)
2 light sensor in front to detect white line when driving forward
2 light sensor in back to detect white line when driving backwards
*/
[2], Thiemo Krink(in prep.). Motivation Networks - http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson10.dir/Krink.pdf
[3], leJOS Bumpercar sample - $LEJOS_HOME/samples/src/org/lejos/sample/bumpercar/bumpercar.java
/* maybe just forget about this [4], Modified Lejos Bumpercar sample -
//experiment two ultrasonic sensors look at each other https://gitlab.au.dk/lego-group-3/lego/blob/master/Week9/BumperCar.java
// no effect, using one robot (probably only one of the sensors sending at a time)
*/
[5], Express Robot Building Guide -
http://www.nxtprograms.com/9797/express-bot/index.html
[6], Dynamic arbitrator -
http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson10.dir/Arbitrator.java
[7], Dynamic behavior -
http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson10.dir/Behavior.java
# Conclusion
# References
[1], description - link [1], description - link
* // remember using / referencing to litteratur for higher grade than 7 * // remember using / referencing to litteratur for higher grade than 7