... | ... | @@ -14,259 +14,200 @@ Our goal is to get experience with behavior based programming and use this knowl |
|
|
|
|
|
## **Plan**
|
|
|
|
|
|
Start by reading the leJOS tutorial on behavior programming [1].
|
|
|
Other than that we plan to follow the [9th lesson plan](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson9.dir/Lesson.html) and start by implementing a BumperCar followed by a sumo wrestling car.
|
|
|
We planned to follow the [9th lesson plan](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson9.dir/Lesson.html), starting out by implementing a BumperCar followed by a sumo wrestling car. Since this week’s lesson plan looked fairly well-structured (as opposed to lesson plan 8), we planned to go by our usual protocol and have specific roles: Since Camilla and Nicolai met up a few hours before the rest of the group, we had Camilla be in charge of the coding while Nicolai took notes. Emil and Ida were then to take care of testing and building. The role distribution quickly became muddled, however, due to theoretical discussions and separation of the group into two halves (see the section on motivation functions).
|
|
|
|
|
|
As this week’s lesson plan looks pretty structured, we plan to have fairly specific roles. [TODO indsæt roller]
|
|
|
Camilla would not be able to participate in our second session, on Friday the 13th, so only three people would be available. We planned on having one or two people coding, depending on whether or not we would decide to test out alternative approaches, and one or two people working on (re-)construction and reinforcement of the robot as well as testing of the functionality of the robot’s physical aspects.
|
|
|
|
|
|
May 12: Camilla a’ codin’, Nicola ‘a notin’. Hvad lavede Ida og Emil?
|
|
|
|
|
|
May 13: Nicolai bygger og re-inforcer, Nicolai og Ida programmerer og eksperimenterer sammen, Ida tager noter, Emil programmerer og eksperimenterer (og tager vist også noter)
|
|
|
|
|
|
## **Results**
|
|
|
|
|
|
Robot was rebuild as base car + bumper + ultrasonic sensor
|
|
|
|
|
|
### Intro
|
|
|
|
|
|
The implementations for the Bumper Car exercises and for the exercises on motivation functions can be found in BumperCar.java and MotivatedBumperCar.java, respectively. For the sumo wrestling exercise we have added behaviors to MotivatedBumperCar.java.
|
|
|
## **Result****s**
|
|
|
|
|
|
### Preliminary exercises
|
|
|
|
|
|
#### BumperCar
|
|
|
|
|
|
##### Arbiter investigation
|
|
|
|
|
|
Press the touch sensor and keep it pressed. What happends ? Explain.
|
|
|
|
|
|
It drives backwards a bit and turns left (backs up the right wheel) to get clear of the obstacle
|
|
|
|
|
|
This happens as soon as we press the touch sensor -> the arbiter changes behaviors emidiately (properbly calls supress method of basic drive farward behavior)
|
|
|
|
|
|
Note: Only 1 touch sensor is implemented in code
|
|
|
|
|
|
Implement a third behavior, Exit. Is the Exit behavior activated immediately when pressed during other behaviors?
|
|
|
|
|
|
We did exit, created new class Exit, implementing behavior
|
|
|
|
|
|
[Insert code example]
|
|
|
|
|
|
We didn’t implement suppress, because it should never be suppressed. We also put its suppress trigger into DetectWall, as it should be able to suppress all other behaviors
|
|
|
|
|
|
The action() method of DetectWall was changed to accommodate immediate return when suppressed. This seems correct, as the higher priority is exit and therefore it is not desired that the robot ends its backwards turn, but that it stops immediately.
|
|
|
|
|
|
DetectWall.action() will abort as this method is constantly called again when bumper is pressed and will terminate after only two short statements if it is suppressed.
|
|
|
|
|
|
After implementing Exit, the DetectWall behavior behaved strangely. It would only drive backwards when the bumper was pressed continuously, and would immediately return to driving forward when releasing the bumper, as opposed to finishing a backwards turn.
|
|
|
|
|
|
We fixed this by locking the backwards turn in a loop that breaks only when the turn is done, or when the behavior has been suppressed. This way, the drive is not interrupted by DriveForward, but will still be stopped if a higher priority behavior, like Exit, is triggered.
|
|
|
|
|
|
Is takeControl of DriveForward called when the triggering condition of DetectWall is true?
|
|
|
|
|
|
It is not, as the Arbiter has a separate thread, that runs backwards through the given list of behaviors and breaks if one behavior want controls. Thereby the DriveForward.takecontrol() will not be called when the DetectWall.takecontrol() returns true;
|
|
|
|
|
|
Make variable with updating thread for ultrasonic sensor
|
|
|
|
|
|
We made a local thread which constantly updates the ultrasonicsensor variable and stores it in a variable. The DetectWall then asks the thread for the newest variable in its takeControl() (of BODY AND SOUL!!!)
|
|
|
|
|
|
NB: Der står "To avoid the pause in the takeControl method of DetectWall **a local thread in DetectWall** could be implemented that sample the ultrasonic sensor e.g. every 20 msec and stores the result in a variable distance accessible to takeControl."
|
|
|
|
|
|
… men vi har lavet en klasse, der gør det. Det skal enten ændres eller bemærkes og begrundes i rapporten.
|
|
|
|
|
|
DetectWall moving backwwards 1 second before turning
|
|
|
|
|
|
We changed the rotations of 180/360 degrees of the two wheels using tacho counter to instead drive backwards for 1 second with a while loop using system.currenttimemilis
|
|
|
|
|
|
DetectWall interrupting when touch sensor pressed during turn
|
|
|
|
|
|
We tried a solution where our blocking while loop [Insert !supressed code] also checks whether the touch sensor is pressed, and in that case, breaks. This implementation relies on the Arbitrator happening to call takeControl after the loop breaks, and before the touch sensor is no longer pressed.
|
|
|
As our robot currently was wearing all the gear for track climbing we started out by removing a lot of LEGO and taking it back to the [express bot base car](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson9.dir/ExpressBot.pdf) that we have used a lot of times. Afterwards we added two touch sensors with a bumper and an ultrasonic sensor to the base car robot. The rebuilt robot can be seen in Figure 1.
|
|
|
|
|
|
Using beep sound to know when the ation method of DetectWall has been called, so that we can check that our implementation works as intended.
|
|
|
![bumperCar build](https://gitlab.au.dk/LEGO/lego-kode/blob/master/week12/img/IMG_2372.JPG)
|
|
|
|
|
|
It doesn’t work D:
|
|
|
*Figure 1: Base car robot with touch sensor bumper and ultrasonic sensor.*
|
|
|
|
|
|
[TODO: Emil talk about potential thread solution]
|
|
|
#### BumperCar investigations
|
|
|
|
|
|
NOTES til det:
|
|
|
##### Touch sensor test
|
|
|
|
|
|
Tried putting all the ultrasounds sensor functionality in a thread shared by the PursuitEnemy behavior and the FlipEnemy behavior, where they both call getDistance. Initially it was meant for only the FlipEnemy behavior where it should sample distances over a set time (eg. 1 second) and then take the minimal distance in the array, but this didn’t work. When it was extracted from FlipEnemy it seemed obvious to give it to PursuitEnemy, but this behavior didn’t need the sampling. This wouldn’t be too bad though, since that behavior doesn’t need to look for an enemy more than a few times every second. We never got to the point where the sampling worked, but we made a solution that continuously ran over 50 elements in an FIFO array and took the minimal distance. The ultrasound sensor has a downtime of around 15-20 ms for every ping and 50 elements would [TODO Nicolai and Ida didnt consider the downtime, and called Thread.sleep(20) as another sampling time - to investigate: What happens if you call a method on a sleeping thread? The thread that calls the method aren’t sleeping, so it can process the method even if the runnable is sleeping?] be taking the minimum of the distances the last 1 second. This would make it lift the fork more than once at a sighting of an enemy (which is still a problem since we need to lift our enemy and keep it high and not raise it further (or what??)).
|
|
|
After rebuilding the robot, we uploaded the leJOS sample program **_BumperCar.java_** [3] and after checking that the correct sensor ports were used we ran the program and played arround with the touch sensors.
|
|
|
We observed that when the touch sensors are pressed the robot immediately breaks out of the behavior for driving forward and starts backing up, before doing a small backwards left turn. This further means that the arbiter used to control the different behaviors of the *BumperCar* must be suppressing the basic drive forward behavior and thereby letting the wall detecting behavior take over.
|
|
|
|
|
|
#### Motivation functions
|
|
|
|
|
|
Split the work - Camilla & Ida on motivation functions, Nicolai and Emil on sumo
|
|
|
|
|
|
If the touch sensor is pressed again while the robot is turning, it should reactivate its action() method, i.e. start over on its evasive behavior.
|
|
|
|
|
|
overvejelser:
|
|
|
|
|
|
* difference from priorities to motivation: we can incorporate state (e.g. "performing evasive turn") into mapping function
|
|
|
|
|
|
* how to be able to stop action and start over: run action in separate thread and wait for it to return, unless…?
|
|
|
|
|
|
* issue: we can’t interrupt an ongoing action
|
|
|
|
|
|
do:
|
|
|
|
|
|
* make interface Bheavior of our own ("first")
|
|
|
|
|
|
* motivation as "percentage" (0 to 100) (noted in Behavior, as part of “first”)
|
|
|
|
|
|
In Arbitrator ("second"):
|
|
|
|
|
|
We loop from the highest priority behavior and check if its motivation (currentMovation) is greater than the one currently registered as highest (highestMotivation). If yes, we update the value of highestMotivation and set the highestMotivated variable to the behavior currently being checked. Since we begin from the behavior with the highest priority and only update it if the value currently being checked is greater (not equal), we are also ensured that ties between behaviors are resolved so that the highest prioritized wins.
|
|
|
|
|
|
"Third":
|
|
|
|
|
|
Class names are prefixed with "motivated"
|
|
|
During the experimentation with the wall detection behavior we realized that only one of the touch sensors were used by the *BumperCar* program. We decided not to change this, as we, at the moment, just needed to test the program behavior and not have a fully functional robot.
|
|
|
|
|
|
DetectWall:
|
|
|
##### Additional behavior
|
|
|
|
|
|
* for ultrasonic sensor: map from 0-255 range to 0-100 range - distance 255 corresponds to 0 motivation, distance 0 corresponds to 100 motivation (we will never get here as the bumper is further in front - might consider making 100 motivation correspond to the distance from the bumper end to the ultrasonic sensor end)
|
|
|
Our next task was to implement a new and higher prioritized behavior, *Exit*, that stopped the program execution when the Escape button were pressed.
|
|
|
|
|
|
overvejelser:
|
|
|
We started out by creating a new class within the *BumperCar.java* file, as this was the example set by leJOS and aded the behavior of stopping whenever the Escape button were pressed and we therefore wanted to take control. We decided that the *suppress*-method should not do anything as there were no behavior with higher priority than this. The resulting code of the Exit behavior class can be seen in Code Snippet 1.
|
|
|
|
|
|
* move mapping calculations to separate class (like old Update class)
|
|
|
```java
|
|
|
|
|
|
→ DONE (SensorContact)
|
|
|
class Exit implements Behavior
|
|
|
{
|
|
|
@Override
|
|
|
public boolean takeControl() {
|
|
|
return Button.ESCAPE.isDown();
|
|
|
}
|
|
|
|
|
|
* active-variable is set if evasive action is in progress
|
|
|
@Override
|
|
|
public void action() {
|
|
|
Car.stop();
|
|
|
System.exit(0);
|
|
|
}
|
|
|
|
|
|
* if active is set and motivation is less than 50 |new touch is registered|, set motivation to 50. The variable active makes sure that if the sensor is still pressed, the likelihood that the evasive behavior is overruled is less than if it was not still pressed (understood by looking at Ole’s implementation).
|
|
|
@Override
|
|
|
public void suppress() {
|
|
|
// should never be supressed
|
|
|
}
|
|
|
}
|
|
|
|
|
|
NOTE: Because the other half of the group was still working on the robot (rebuilding and testing tiny code things), we did not test the things implemented in the exercises on motivation. We expect to use them in the sumo robot though, so it will be tested there.
|
|
|
```
|
|
|
|
|
|
TODO: Discuss choices of motivation values
|
|
|
*Code Snippet 1: The Exit behavior class with no implementation of the suppress method*
|
|
|
|
|
|
### Sumo wrestler
|
|
|
Even though we chose not to implement *suppress()* we knew that this was not the best practise, as it now wasn’t possible to add a new behavior with even higher priority than *Exit*. Again we however chose to follow leJOS’ poor coding example for the sake of consistency.
|
|
|
|
|
|
TODO: (kort) intro
|
|
|
After implementing the *Exit* behavior we had to make sure that it could be used by the *BumperCar* program. Therefore we added the behavior to the *BumperCar* programs behavior list, and began adding a suppress method for the *DetectWall* behavior, that leJOS had ignored. To do this, we however had to change the *action*-method of the *DetectWall* behavior to ensure that it would return immediately after *suppress()* were called. This decision seemed correct as it is not desired that the robot finish backing away from the wall before stopping if the Escape button has been pressed. This means that the *action*-method of *DetectWall *will now terminate after only two short statements if the *suppressed-*method is called as seen in Code Snippet 2.
|
|
|
|
|
|
#### Construction
|
|
|
```java
|
|
|
|
|
|
We thought of several ideas to enhance our sumo bot.
|
|
|
public void suppress()
|
|
|
{
|
|
|
_suppressed = true; //Standard Lejos design pattern for suppressing
|
|
|
}
|
|
|
|
|
|
Forklift - Vertical third motor attached with a forklift, that combined with the ultrasonic or touch sensor can lift the other robot when we detect they are in front of us
|
|
|
public void action()
|
|
|
{
|
|
|
_suppressed = false;
|
|
|
BumperCar.leftMotor.rotate(-180, true); *// start Motor.A rotating backward*
|
|
|
BumperCar.rightMotor.rotate(-360, true); *// rotate C farther to make the turn*
|
|
|
|
|
|
Nicolai’s additional idea (with regards from Ida): try to flip robot in front; but if we register that we accidentally lifted the other robot, we will instead try to drive it to the edge
|
|
|
if(_suppressed){
|
|
|
|
|
|
Side/rear guards - Big plates mounted to the side near the floor, to guard against opposing forklifts from sides or rear.
|
|
|
Thread.yield();
|
|
|
|
|
|
We considered using the third motor for a third motorized back wheel, to give us more pushing power, but we figured this would be against the rules as the robot had to be based on the Express bot.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
![sumo build](https://gitlab.au.dk/LEGO/lego-kode/raw/master/week12/img/build.PNG)
|
|
|
```
|
|
|
|
|
|
*Figure TODO: The robot rebuilt with a third motor for a fork and with side and rear guards to protect from being swept up by other robots*
|
|
|
*Code Snippet 2: The suppress- and action-methods of the DetectWall behavior that enables suppressing DetectWall.*
|
|
|
|
|
|
TODO fredag:
|
|
|
After implementing *Exit*, the *DetectWall* behavior behaved strangely. It would only drive backwards when the bumper was pressed continuously, and would immediately return to driving forward when releasing the bumper, as opposed to finishing a full backwards turn.
|
|
|
|
|
|
* make robot work as it is when we leave on Thursday:
|
|
|
We fixed this by locking the backwards turn in a loop that breaks only when the turn is done, or when the behavior has been suppressed as seen in Code Snippet 3. This way, the drive is not interrupted by the *DriveForward* behavior, but will still be stopped if a higher priority behavior, like *Exit*, wants to take over.
|
|
|
|
|
|
* test durability of side/rear guards
|
|
|
```java
|
|
|
|
|
|
* test ability to stay within lines; make difficult tests!
|
|
|
public void action()
|
|
|
{
|
|
|
_suppressed = false;
|
|
|
BumperCar.leftMotor.rotate(-180, true); *// start Motor.A rotating backward*
|
|
|
BumperCar.rightMotor.rotate(-360, true); *// rotate C farther to make the turn*
|
|
|
while(!_suppressed){
|
|
|
if(BumperCar.rightMotor.getRotationSpeed() >= 0) { *//motor is not backing up*
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
* implement remaining behavior (NB: Perhaps lowest behavior should not be a simple cruise behavior, but a waiting behavior, or a more sophisticated cruise behavior - going straight doesn’t seem to be the most clever choice)
|
|
|
```
|
|
|
|
|
|
COULD BE NICE:
|
|
|
*Code Snippet 3: Action-method of DetectWall that finishes but can be immediately suppressed.*
|
|
|
|
|
|
* use bumper to sense if being pushed from behind; could then react by either pushing back or evading, perhaps depending on how close to edge (theoretical note: would make use of the ability to include additional behaviors)
|
|
|
##### Arbiters call sequence
|
|
|
|
|
|
* implement alternative Eye of The Tiger kamikaze bot
|
|
|
The next task was to investigate whether the leJOS **_Arbitrator.java_** [5] called *takeControl()* of behaviors if one with a higher priority wantet to take control. By looking into the code of the *Arbiter* class we found that it starts up a monitor thread that has the responsibility of monitoring which behaviors wants to take control. It does this by going through the arbitrators list of behaviors from the one with the highest priority to the lowest each time calling the *takeControl*-method and if this call returns true it breaks the loop and starts over. Thereby the *DriveForward.takeControl()* will not be called when the *DetectWall.takeControl()* returns true.
|
|
|
|
|
|
#### Implementation
|
|
|
##### Design pattern for takeControl()
|
|
|
|
|
|
Done:
|
|
|
In the leJOS tutorial on behavioral programming [1], LeJOS has specified a specific design pattern for behaviors that basically states, that *takeControl()* should return without spending time, *suppress()* should just update a variable, and *action()* should be aborted as soon as possible when the suppressed-variable is true. This design pattern is not complied by the *DetectWall* behavior as it uses the ultrasonic sensors *ping- *and *getDistance*-methods that should be separated by at least 20 milliseconds. Therefore *takeControl()* doesn’t return right away and therefore doesn’t comply with the design pattern.
|
|
|
|
|
|
* implemented AvoidEdge behavior (motivation 100 on detection of edge)
|
|
|
To solve this issue we added an **_Updater_**** **class to the *BumperCar.java* file and used an instance of this class in the *DetectWall* behavior. The *Updater* would, given an ultrasonic sensor, keep pinging it and updating a local variable. Whenever the *takeControl-*method of *DetectecWall* was called it should just ask the updater-variable with the last measured distance was and use this number. This would return much faster than 20 ms and therefore better comply with the design pattern.
|
|
|
|
|
|
* our own arbitrator and motivatedcar do not work - we use Ole’s and see if we have time to figure out what’s wrong with our own implementation later
|
|
|
We chose to implement a separate thread class rather than have a local one, as done by LeJOS’ *Arbitrator*, as we expected that we could reuse the *Updater* class for other sensor-updaters.
|
|
|
|
|
|
* robot turns too much (values -360 for one wheel, -1300 for other wheel); sometimes drives backwards off edge
|
|
|
##### Moving further backwards
|
|
|
|
|
|
* → implementation that turns on the spot. Works OK. Will optimize later if desired.
|
|
|
The next task was to change the behavior of *DetectWall* such that it backs up for 1 second before turning when it encounters a wall. This was done by adding two statements in the beginning of the *action*-method, telling both motors to go backwards. Then a while loop was added to loop for one second unless the *_suppressed*-variable became true. This was done to ensure that the method was still suppressable in as short time as possible.
|
|
|
|
|
|
* Next: Implement detection of other robot and go to it. After that: Implement detection of other robot and try to flip it.
|
|
|
We also changed the turning part such that it only turned and didn’t back up to separate the code as much as possible. We however forgot to stop the left motors backwards motion as we started the rights tacho-counter turn, which resulted in the robot going backwards without turning over and over again when pressing bumper. We therefore stopped the left motors motion after the one second of backing was done as can be seen together with the other changes in Code Snippet 4. This time it worked perfectly.
|
|
|
|
|
|
* On detection and following of other robot:
|
|
|
```java
|
|
|
|
|
|
* How to test? Make robot go faster if it sees an enemy - that way we can tell that it has detected its enemy. Implement behavior Drive that only drives with speed 60 - makes it very obvious when the robot switches to PursueEnemy (where we set speed to 400)
|
|
|
public void action()
|
|
|
{
|
|
|
_suppressed = false;
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
BumperCar.leftMotor.backward();
|
|
|
BumperCar.rightMotor.backward();
|
|
|
|
|
|
while(System.currentTimeMillis() < startTime + 1000) {
|
|
|
if(_suppressed){
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
BumperCar.rightMotor.rotate(-180, true); *// rotate C farther to make a turn*
|
|
|
|
|
|
* Don’t try to make it follow the enemy - simply go faster straight ahead if enemy is within vision
|
|
|
BumperCar.leftMotor.stop(); *// need to stop leftmotor to turn*
|
|
|
while(!_suppressed){
|
|
|
if(BumperCar.rightMotor.getRotationSpeed() >= 0) { *//motor is not backing up*
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
* Overvejelse: We let avoiding the edge outweigh enemy detection, as crossing of the edge leads to losing the match with much higher certainty than not pursuing an enemy. Perhaps we should even stop for a second when losing track of the enemy, so as to minimize the risk of being lured to the edge (or would stopping make us more vulnerable to attacks?).
|
|
|
```
|
|
|
|
|
|
* Using distance 30 cm for detection; have not tested other distances
|
|
|
*Code Snippet 4: The action-method of DetectWall that now backs up for one second before turning - still respecting the fast-suppress design pattern.*
|
|
|
|
|
|
* On detection and flipping other robot
|
|
|
##### Interrupt *DetectWall*s behavior by itself
|
|
|
|
|
|
* Change base speed to 200
|
|
|
The next task was to change the behavior of *DetectWall* such that it reinitiated the backup whenever the bumper was pressed during the *action*-method.
|
|
|
|
|
|
* Use tacho counter to make sure that we don’t flip forklift "all over the place" like when Frej was almost strangled in a previous lesson
|
|
|
We discussed several ways of doing this:
|
|
|
|
|
|
* Make test program for testing flip: FlipTest
|
|
|
* having a separate thread that performed the behavior which could then be interrupted by the *action-*method if another touch were measured.
|
|
|
|
|
|
* NB: Robot must not begin to chase because it is seeing its own forklift (should not happen, as pursue has lower priority)
|
|
|
* checking whether the touch sensors were pressed during execution and breaking if this was the case
|
|
|
|
|
|
* First test: -30 rotation on flip motor (motorport A, FlipMotor). Looks okay.
|
|
|
[TODO: Er der nogle løsningsforslag som ikke er med i dette afsnit? Noterne var ikke udførlige grundet vores diskussion her. Læs lige grundigt og tænk tilbage /Camilla]
|
|
|
|
|
|
* Note: Use of motivation functions would be nice: Could lower motivation for flipping after a flip has been performed, such that the robot would rather push the other robot by running into it again
|
|
|
[TODO: Tanke: vi snakkede om at trykke på igen og at holde trykket nede = forskel - skal det med i det her afsnit, da vi snakker om det i næste? /Camilla]
|
|
|
|
|
|
* Implement so that on suppress or loss of sight of enemy makes the forklift go back down
|
|
|
We spent a lot of time discussing these solutions. All of them had pros and cons, and we had a hard time choosing. The solution with adding checks for touch sensor presses seemed like the easiest, but we didn’t know how to stop during the first second of backing up and we worried about the program timing as it relied on the *touch.isPressed()* to return true long enough for the arbitrator to call *takeControl()* on *DetectWall* again.
|
|
|
|
|
|
* Sometimes robot sees (bogus?) far distances even if something is very close in front of it → forklift flips out [VIDEO]
|
|
|
The thread solution seemed ok, but were hard to grasp and implement.
|
|
|
|
|
|
* → make update thread to keep track of distance over a timeslice
|
|
|
DIT NOT WORK OUT!
|
|
|
[TODO: mere ræsonnement omkring thread-løsning. Emil - tænkte det var et job for dig /Camilla]
|
|
|
|
|
|
* Note: Can FlipEnemy be suppressed in between setting ForkLifted to true and flipping the fork? What happens then?
|
|
|
[TODO: nævn potentiel thread-løsning - ref. ned til beskrivelse af lignende problem med FlipEnemy i sumo-implementation … Jeg kan ikke lave reference /Camilla]
|
|
|
|
|
|
TODO: Video fra Nicolai (fucked up fork reactions)
|
|
|
We decided to go with a simple solution of adding a *touch.isPressed()* check to our last while loop (the one that lets the robot turn). Even though this solution doesn’t restart the *DetectWall.action()* if it encounters a touch on the bumper while backing up, it seemed like a reasonable solution.
|
|
|
|
|
|
#### Further ideas
|
|
|
We added a *beep* sound to the beginning of the *action*-method to clearly indicate that the *action*-method had been restarted. This would make it easy for us to test if the *action()* started over before turning if the touch sensors were pressed.
|
|
|
|
|
|
IDEAS
|
|
|
We ended up concluding that the LeJOS Arbitrator is not implemented to ease interruption of behaviors with the same priority as the one that is running, which in case of this implementation is whether the behavior should in fact be restarted before it has ended.
|
|
|
|
|
|
* If registrering push (i.e. if using touch sensors) while reading white, back fast away from white.
|
|
|
#### Division of work
|
|
|
|
|
|
* Incorporate random movement in drive (perhaps by using motivational functions and having a turn behavior that randomly gets high motivation) so that we don’t go so much towards the edge
|
|
|
At this point, we had already spent a few hours and decided to divide the remaining work between the group members to avoid spending too much time before getting cracking on the important part of the lab session, namely building a sumo wrestler that would win the next day.
|
|
|
|
|
|
* Implement search for enemy
|
|
|
We split the group in half, having Camilla and Ida experiment with dynamically prioritized behaviors via motivation functions, while Nicolai and Emil began work on our sumo wrestler.
|
|
|
|
|
|
Note: The strategy that we initially discussed was to make a purely defensive robot (with two bumpers), which would perhaps push aggressively back if it registered running into something.
|
|
|
|
|
|
Note (regarding sepearate thread for vision): if sampling over an entire second, we would get a perhaps undersirable delay (shorter sampling timeslices would help with this)
|
|
|
|
|
|
#### Insights from the sumo tournaments
|
|
|
|
|
|
Note: From the tournament, we saw that it might be useful to include a "this is taking too long"-behavior that changes strategy to avoid a draw (on the other hand, we would need to make sure not to risk
|
|
|
|
|
|
Note: Our forklift didn’t work as intended, but helped to disrupt the driving of the others + it also helped by getting stuck in the floor, enabling the robot to stand firm in pushing battles
|
|
|
|
|
|
TODO: Videoer fra Nicolai (kampe)
|
|
|
|
|
|
## **Conclusion**
|
|
|
|
|
|
TODO:
|
|
|
|
|
|
* hvad fik vi ud af de indledende øvelser?
|
|
|
|
|
|
* konklusion på sumoarbejdet
|
|
|
|
|
|
* indsigter fra sumoturnering
|
|
|
|
|
|
## **References**
|
|
|
|
|
|
[1] [LeJOS tutorual on behavior programming ](http://www.lejos.org/nxt/nxj/tutorial/Behaviors/BehaviorProgramming.htm)
|
|
|
|
|
|
[2] Thiemo Krink(in prep.), [Motivation Networks - A Biological Model for Autonomous Agent Control](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson9.dir/Krink.pdf)
|
|
|
#### Motivation functions
|
|
|
|
|
|
NB! Lav ikke nedenstående om til links - det fucker op!
|
|
|
The task with Thiemo Krink’s motivation functions [2] was to consider and test whether such functions can help solve the problem of how to reactivate the *action*-method when the touch sensor is pressed again while the robot is turning, i.e. start over on its evasive behavior.
|
|
|
|
|
|
[TODO-nummer] [BumperCar.java](https://gitlab.au.dk/LEGO/lego-kode/blob/master/src/Lesson9programs/BumperCar.java) containing classes for the Bumper Car exercises
|
|
|
Before starting to reimplement the leJOS behavior framework, we discussed the use of motivation functions in behavior programming compared to priority based behavior programming. This discussion produced the following thoughts:
|
|
|
|
|
|
[TODO-nummer] MotivatedBumperCar.java](https://gitlab.au.dk/LEGO/lego-kode/blob/master/src/Lesson9programs/MotivatedBumperCar.java) containing classes for the sumo exercise, and for the exercises on motivational functions
|
|
|
As priorities are static there are no way of using the fact that a given behavior is currently in use. Therefore it is not possible to incorporate the fact that even though one is currently avoiding a wall it is desired to restart the behavior is another wall turns up during the evasion of the last. This can however be done with motivation functions as the returned motivation from *takeControl()* can be increased when the behavior is currently executing, and thereby making the arbitrator choose to reactivate the behavior due to the higher motivation - i.e. it is possible to incorporate a state into motivation functions that cannot be used by prioritized behaviors.
|
|
|
|
|
|
[TODO-nummer] Our implementation of the [Arbitrator](https://gitlab.au.dk/LEGO/lego-kode/blob/master/src/Lesson9programs/Arbitrator.java) interface, using motivational functions
|
|
|
After considering how motivation functions could help us solve the problem of restarting a currently performing behavior, we began re-implementing the **_BumperCar.java _**[3] interface and implementing our own versions of the **_Behavior.java_** [4] and **_Arbitrator.java _**[5] interfaces.
|
|
|
|
|
|
[TODO-nummer] Our implementation of the [Behavior](https://gitlab.au.dk/LEGO/lego-kode/blob/master/src/Lesson9programs/Behavior.java) interface, using motivational functions
|
|
|
We started out by changing the *Behavior *interface so that the *takeControl*-method returns an integer value instead of a boolean. We considered which range of numbers would be appropriate for a behavior to return, and concluded that a motivation between 0 and 10 was too narrow if more behaviors were added and therefore settled on a range from 0 to 100 (analogous to a sort of motivation percentage). This change can be found in our new interface, **_Behavior.java _**[6].
|
|
|
|
|
|
The next thing we had to do was change the arbitrator to account for the new return value of *takeControl().* The changes are implemented in **_Arbitrator.java_** [7]. In this class we simply find the behavior with the highest current motivation instead of finding the one with highest priority that wan |
|
|
\ No newline at end of file |