torsdag den 17. december 2009

Torsdag d. 17/12

Plan for idag:
* Få et lidt mere detalieret overblik over hvad der skal laves
* Starte arbejdet

Overblik:
Projektet kan opdeles i 3 hoved dele;
- Konstruktion af robotter
- Kodning af server delen (incl. color tracking)
- Kodning af robot software

Konstruktion af robotter:
Sidste gang fik vi eksperimenteret med hvordan robotten skulle bygges og vi fik bygget den endelige robot. Til dette punkt manger vi derfor kun at bygge 2 (eller flere) robotter magen til.

Kodning af server delen:
Som beskrevet tidligere har andre erfaret[ref] af BT stakken på OS X er for langsom til at kunne klare opgaven og at linux derfor vil være platformen severen skal køre på. Der er 2 udfordringer i denne del af projektet:
- Implementation af color tracking kode. Det skal også være muligt at bestemme orientering, måske endda en retnings vektor, med color tracking koden.
- Opstilling af kommunikations protokol imellem server og robotter, samt den rent tekniske del af BT kommunikationen.

Kodning af robot software:
...

Vi starter med at køre et parallelt forløb med udviklingen af server og robot koden. Det gør vi fordi der i starten vil være en del "udforskning" at gøre inden for de forskellige områder (specielt ved color tracking) og vi mener derfor vi kan være mere produktive hvis vi opdeler arbejdsopgaverne lidt. Det giver også mulighed for selvstændigt arbejde i juleferien.

Opdatering til Kodning af server delen:
Efter lidt research og rådgivning hos erfarne kollegaer har vi valgt at bruge OpenCV til at implementere Color Object Tracking. Det er et modent library der passer perfekt til det vi skal bruge det til og som har en god dokumentation. Der findes både en C, C++ og Python API til libraryet, hvilket gør at vi ikke skal bruge tid på at sætte os ind i et nyt sprog da vi alle har en del erfaring med Python derudover findes OpenCV til Linux og Windows (vores server skulle være på en linux box). Her er et eksempel på hvad man bl.a. kan med OpenCV, som ligger tæt op af det vi skal:
http://www.youtube.com/watch?v=Okf-EO-R4Q8&feature=player_embedded

torsdag den 10. december 2009

Lego project ideer

Torsdag den. 3. December:

Idé 1 – First Robot Shooter (FRS)

Beskrivelse

Alle mod alle

Hoved udfordringer

Udfordring

Kommentar

Sværhedsgrad

Bygning af Guns

De våben vi har kigget på kræver meget materiale og tid at bygge

M

Robot vision

Billede genkendelse og alm. webcams i Lejos. Kan man overhovedet sætte alm. webcams til? Findes der billede genkendelses frameworks / kode der kan kører på Lejos?

H

Agent software


L

One PC meany NXTs

Problems with BT comm.

L


Idé 2 – Stationary Robot Shooter

Beskrivelse

En mod alle

Hoved udfordringer

Udfordring

Kommentar

Sværhedsgrad

Bygning af et Gun

De våben vi har kigget på kræver meget materiale og tid at bygge

L

Robot vision

Billede genkendelse og alm. webcams i Lejos. Kan man overhovedet sætte alm. webcams til? Findes der billede genkendelses frameworks / kode der kan kører på Lejos?

”Eye in the sky”?

H

Agent software1

Stationær robot

L

Agent software2

Mobile robotter

L

One PC meany NXTs

Problems with BT comm.

L


Idé 3 – HammerSlammer

Hver robot har en trykfølsom plade bag på. Robotterne kører rundt på en bane og skal slå sin hammer på hinandens plade, og samtidig undgå at blive ramt. Hvis en robot bliver ramt på pladen bliver dens hastighed reduceret. Den sidste robot der kører har vundet.

Hoved udfordringer

Udfordring

Kommentar

Grad

Robot vision

Eye in the sky

H

Agent software


M

One PC many NXTs

Problems with BT comm.

M

Robot orientering

Tracking, figur form eller compass

L


Valgt ide: Idé 3

Todo liste / plan:

  • Byg robotter
  • ”Eye in the sky”: Opsætning af kamera og billede genkendelse
  • Informations protokol: Server dekoder billeder, får orientering fra compass sensor
    • Kommunikations tråd
  • Agent software: Jagt andre, undgå at blive ramt, evt. strategi (gå efter den svageste / tætteste etc.)
  • Server software: Modtag og dekode billeder, få orientering fra robotter og udsend information til robotter
  • Server operativ system: Fundet på lego blog at OS X's BT stack er langsom, linux anbefales

Brugt tid: ca 3 timer.


------------------------------------------------------------------------------


Torsdag den. 10. December:


Todo liste/plan:

  • Byg prototype robot

Idag har vi færdiggjort vores HammerSlammer®, som har en hammer (et dæk) monteret på fronten og ved hjælp af et "eye in the sky" skal lokalisere modstanderens svage punkt. Dette punkt er symboliseret med en plade, som er understøttet af to tryksensorer. Pladen er forholdsvis lille og et af vores delmål i dette projekt er, at få hammeren til at blive udløst fra den rigtige afstand i forhold til modstanderen. Dette kræver, at vi er opmærksomme på en modstanders bevægelsesretning og kan lokalisere bagenden.






Brugt tid: ca 6 timer.


torsdag den 19. november 2009

Lesson 11: Opførsel

I denne uge vil vi benytte LeJOS subsumption API´en og specifikt Bahaviour interfacet og klassen Arbitrator som bestemmer udførselsrækkefølgen.

I første omgang lagde vi BumperCar.java programmet ind på NXT´en og observerede opførslen. Bilen kører autonomt fremad så længe ingen forhindringer ses eller mærkes. Hvis takeControl() metoden i DetectWall returnerer true kaldes suppress() metoden i DriveForward og _suppressed bliver sat til true hvilket medfører at begge motorer stopper. DriveForward overtager kontrollen igen så snart DetectWall's takeControl() metode igen returnerer false. Følgende videoer viser undertrykkelsen i aktion:




Med tryksensoren trykket ind konstant vil bilen udføre sin rotate manøvre igen og igen indtil modstanden fjernes. DriveForward er altså konstant undertrykt.

Vi implementerede nu klassen Exit som skal undertrykke de andre behaviours hvis ESCAPE knappen trykkes ned. Koden ser således ud:

import lejos.nxt.Button;
import lejos.robotics.subsumption.Behavior;

class Exit implements Behavior {

public Exit() {}

public boolean takeControl() {
return Button.ESCAPE.isPressed();
}

public void suppress() {
//Since this is highest priority behavior, suppress will never be called.
}

public void action() {
System.exit(0);
}
}


Det lader til at bilen stopper med det samme uanset om bilen er i DriveForward eller DetectWall opførsel. Men hvis vi ændrer Sound.pause(20) til Sound.pause(2000) får vi følgende opførsel når ESCAPE knappen trykkes ned:

Det vi ser er, at Sound.pause(2000) blokerer for sensormålingerne inde i takeControl() metoden i 2ooo ms. så der ikke omgående bliver registeret tryk på ESCAPE eller at robotten er ved at køre ind i noget.

Vi arbejdede med implementering af tråde inde i DetectWall klassen for at forhindre forsinkelse/blokering. Med følgende løsning er takeControl() metoden ikke længere langsom og robotten reagerer igen korrekt. Koden ses her:

import lejos.nxt.SensorPort;
import lejos.nxt.Sound;
import lejos.nxt.UltrasonicSensor;

public class SonarThread extends Thread {
private UltrasonicSensor sonar;
public int distance = 0;

public SonarThread() {
sonar = new UltrasonicSensor(SensorPort.S3);
}

public void run() {
while(true) {
sonar.ping();
Sound.pause(2000);
distance = sonar.getDistance();
}
}
}

----------------------------------------------------------------------------------

import lejos.nxt.Motor;
import lejos.nxt.SensorPort;
import lejos.nxt.Sound;
import lejos.nxt.TouchSensor;
import lejos.nxt.UltrasonicSensor;
import lejos.robotics.subsumption.Behavior;

public class DetectWall implements Behavior{

public DetectWall() throws InterruptedException
{
touch = new TouchSensor(SensorPort.S1);

t = new SonarThread();
t.start();
}

public boolean takeControl()
{
return touch.isPressed() || t.distance < 25;
}

public void suppress()
{
Motor.A.stop();
Motor.C.stop();
}

public void action()
{
Motor.A.rotate(-90, true);// start Motor.A rotating backward
Motor.C.rotate(-360);// rotate C farther to make the turn
}
private TouchSensor touch;

private SonarThread t;
}


Tidsforbrug: 3 timer

torsdag den 12. november 2009

Lego lab lesson 10: Navigation

Plan for idag:
  1. Test af Blightbot (benytter TachoNavigator). Findes i noterne [1]
  2. Diskussion af, hvorledes man evt. kan navigere samtidig med at undgå objekter
  3. Navigation ved hjælp af kompas sensor.
Test af Blightbot:
Vi fandt ud af, at denne version af lejos ikke understøttede TachoNavigator og dermed goTo() metoden. Vi benytte derfor et TachoPilot(...) objekt og metoden travel(int distance). Koden ses herunder:

import lejos.nxt.*;
import lejos.robotics.navigation.*;

public class Blighbot {

public static void main(String[] args) {

TachoPilot robot = new TachoPilot(5.8f, 11.5f, Motor.C, Motor.B, false);

robot.travel(200);
robot.rotate(180);
robot.travel(100);
robot.rotate(-90);
robot.travel(100);
robot.rotate(90);
robot.travel(150);
robot.rotate(180);
robot.travel(50);
robot.rotate(90);
robot.travel(100);
}
}


Planen var, at robotten skulle vandre rundt i rummet (på Zuse's blå gulv) for til sidst at ende ved udgangspunktet. I koden ses det, at robotten efter første vandring skal rotere 180 grader, men som nedenstående video viser er dette ikke tilfældet (10 sekunder inde i filmen):



Denne række af små fejl leder til drift (større fejl) og robotten vender derfor ikke tilbage til udgangspunktet. Disse fejl kan skyldes underlaget (dårligt fæste) eller unøjagtige målinger af hjulstørrelse eller afstand mellem disse. Vi testede også robotten på et gulvtæppe, men her var drift endnu mere tydeligt.

Diskussion af, hvorledes man evt. kan navigere samtidig med at undgå objekter
En overordnet strategi for hvordan dette kan opnås; Vi kunne benytte CompassBlighBot[1] og lave compass navigationen om til et behaviour. Derudover skal der være et "obstacle avoidance" behaviour, som vha. subsumption kan undertrykke navigations behaviouret. Ideen er at robotten vil kører den rute der er defineret i navigationen samtidig med at "obstacle avoidance" parallelt med tjekker for om robotten er ved at køre ind i noget (vha. en ultrasonic sensor). Hvis robotten er på kollisionskurs skal "obstacle avoidance" behaviouret overtage styringen og guide robotten uden om forhindingen. Herefter skal navigations niveauet tage over igen. Som sagt er dette en overordnet strategi og der vil være problemer, som skal håndteres. F.eks. vi "obstacle avoidance" opførselen også flytte robotten, så robotten vil være et andet sted end hvor navigationen forventer.

Navigation ved hjælp af kompas sensor
Under denne test, havde vi en forventning om at robotten ikke ville lade sig påvirke af underlaget. Denne video viser, at robotten roterer (eller korrigerer i små hak) som ønsket og at denne løsning er mere præcis til navigation uden forhindringer:



Det ses dog i nedenstående video, at robotten påvirkes af visse objekter som kommer for tæt på. I videoen er dette illustreret ved, at robotten vandrer mod en computer:



For at give et lidt bedre billede af hvordan robotten kørte, monterede vi en tusch og kørte oven på et whiteboard. Som vi kan se fra videon påvirkes kompassen meget af omgivelserne. Den kan ikke engang køre lige ud, men trækker enten den ene eller den anden vej. Vi satte afstandene ned så robottens bane kunne være indenfor whiteboardet.



[1], Brian Bagnall, Maximum Lego NXTBuilding Robots with Java Brains, Chapter 12, Localization, p.285 - p.302.

Brugt tid: ca 3 timer.

torsdag den 5. november 2009

Lego lab lesson 9: Car that exhibits several behaviors.

Plan for idag:
  1. Afprøv programmet SoundCar.java og besvarelse af de stillede spørgsmål i ugens opgave
    beskrivelse.
  2. Tilføj ny opførsel som følger en lyskilde. Vi vil eksperimentere med denne opførsel ved at lade denne opførsel undertrykke alle andre opførsler og derefter placere den forskellige steder i hierakiet.
  3. Ombytning af opførsels niveauer: AvoidFront > FollowLight.
Afprøvning af SoundCar.java:
Vi kan aflæse på displayet, at bilen i åbne omgivelser kører ved hjælp af RandomDrive.java. Hvert 10. sekund bliver denne tråd blokeret af PlaySounds tråden som stopper bilen og afspiler en lyd. Samtidig ser vi, at RandomDrive tråden kan undertrykkes af AvoidFront tråden, hvis bilen kommer for tæt på en genstand.

Vurdering af suppress:
Vi ser i koden, at suppress() undertrykker tråde som befinder sig lavere i hierakiet. Hierakiet defineres inde i SoundCar.java, hvor vi ser at RandomDrive tråden befinder sig nederst i hierakiet (oprettet med under-niveau værdien null). RandomDrive tråden kan altså ikke undertrykke andre tråde, da den er nederst i hierarkiet. Over RandomDrive findes AvoidFront tråden som kan undertrykke RandomDrive hvis en genstand kommer for tæt på (denne afstand måles med en UltraSonicSensor). Øverst i hierakiet finder vi PlaySound tråden, som kan undertrykke de to andre tråde og gør dette hvert 10. sekund.

Suppress funktionaliteten er implementeret vha. variablen suppressCount. Denne variable holder styr på hvor mange gange et givet niveau er undertrygt af højere niveauer. En tråd får kun adgang til actuators (motorne) hvis dens suppressCount variablen er 0. F.eks. hvis robotten kører rundt grundet opførselen i RandomDrive niveauet, men kommer for tæt på en stol. AvoidFront niveauet vil opdage dette og undertrykke RandomDrive niveauet, for at fortage en undvige manøvre. RandomDrive har nu en suppressCount på 1 - AvoidFront niveauet undertrykker RandomDrive. Imens undvige manøveren bliver fortaget af AvoidFront, beslutter PlaySound niveauet sig for at spille en yndig mellodi. PlaySound niveauet undertrykker nu AvoidFront og RandomDrive niveauerne. AvoidFronts suppressCount er nu på 1 og RandomDrive's suppressCount er på 2. Når PlaySound er færdig med at spille musik, løfter den sin undertrykkelse af de nedre niveauer. AvoidFronts suppressCount er nu på 0 og kan dermed få adgang til motorne og fortsætte undvige manøvren. RandomDrive har stadigvæk en suppressCount på 1, da den stadigvæk er undertrykt af AvoidFront. Når AvoidFront løfter sin undertrykkelse vil RandomDrive igen få adgang til motorne (suppressCount på 0) og robotten vil fortsætte med at udvise denne opførsel.

"Kør mod lys" opførsel:
Vi har benyttet resultater og kode fra vores LightFollower fra sidste uge. Denne nye tråd ligger vi øverst i hierakiet og vi vil teste om suppress() virker korrekt ved, at lade bilen følge en lyskilde helt ind i en væg. Hvis dette forsøg virker, antager vi at AvoidFront tråden undertrykkes. Om PlaySound tråden undertrykkes er nemt at aflæse, da lyden ikke afspilles hvert 10. sekund.

LightFollower opførslen er baseret på følgende kode:

import lejos.nxt.LightSensor;
import lejos.nxt.SensorPort;


public class FollowLight extends Behavior {

private LightSensor lsl;
private LightSensor lsr;

private static int NORMAL_VALUE = 55;
private static int NORMAL_VALUE_BUFFER = NORMAL_VALUE+5;

public FollowLight(String name, int LCDrow, Behavior subsumedBehavior) {
super(name, LCDrow, subsumedBehavior);
lsl = new LightSensor(SensorPort.S2, true);
lsr = new LightSensor(SensorPort.S3, true);
}

public void run() {

while (true) {
int currentLeft = lsl.readValue();
int currentRight = lsr.readValue();

if (currentLeft > NORMAL_VALUE_BUFFER || currentRight > NORMAL_VALUE_BUFFER) {
suppress();
drawString("l");
drawInt(currentLeft);

forward(currentRight+30, currentLeft+30);

release();
}}}}


Resultat af "kør mod lys" opførslen placeret øverst i hierakiet:
Bilen reagerer helt som forventet. Vi kan tvinge bilen ind i en væg ved at placere en kraftig lyskilde foran UltraSonicSensoren. Så snart lyskilden fjernes, vil AvoidFront (eller PlaySound) opførslen tage over og navigere bilen væk fra væggen. Herefter tager RamdomDrive tråden så over igen. Se video:



Som det fremgår af videoen kan vi tvinge robotten ind i en væg ved at få den til at følge en lyskilde. FollowLight opførselen undertrykker nemlig AvoidFront opførselen. Bemærk dog at der bliver spillet musik imens robotten følger lyset - 00:35 inde i videoen. Dette er dog ikke pga. PlaySound niveauet ikke er undertrykt når der følges en lyskilde. Musikken starter med at spille fordi lyskilden et kort sekundt ikke bliver rettet imod lyssensorne. Det får FollowLight niveauet til at release og PlaySound niveauet får lov at spille musik. Grunden til der omgående bliver spillet musik er at PlaySound tråden har været aktiv selvom dens adgang til actuators har været blokeret af FollowLight tråden. Det vil sige PlaySound tråden er klar til at spille når den får lov. Musikken fortsætter med at spille selvom FollowLight niveauet igen overtager, da FollowLight niveauet ikke bruger eller blokerer lyd actuatoren.

Efter at have flyttet AvoidFront opførselen til det højeste niveau, optog vi den her video:


Som det kan ses, følger robotten lyset så længe ingen forhindring kan ses. Men når UltraSonicSensorn måler at der er et objekt indenfor 20 cm afstand aktiveres AvoidFront og robotten bakker.

Tidsforbrug: 3 timer

torsdag den 29. oktober 2009

Braitenberg's Vehicles (TØ 8)

Plan for idag
  1. Først vil vi implementere Vehicle 1 [2] med en light sensor. Robotten skal kunne følge en lyskilde, dvs. holde stille ved normale lysforhold og køre ved øgede lysforhold.
  2. Herefter vil vi bygger Vehicle 2b [2] med 2 lyssensorer for at se om vi kan få robotten til at følge en lyskilde.
  3. ...


Vehicle 1
Vi konstruere en robot med 1 lys sensor der reagere på øget lysforhold. Reaktionen skal være at sætte motorne igang. Under normale lysforhold skal robotten holde stille.

Vi vil bruge en initiel kalibering af lyssensoren til at bestemme hvad det normale lysforhold er og vi vil bruge en lygte til at simulere øget lysforhold. Efter som robotten kun har en lyssensor vil vi bruge en single threaded control loop. I og med vi kun har 1 lyssensor og 2 mortorer, giver vi begge mortorer samme effekt, på baggrund af input fra lyssensoren.

Effekten til mortoren er konstant 100 i dette forsøg. Control loopet ser sådan ud (se neden stående). Først læses den nuværrende lysværdi fra lyssensoren. Ud fra denne værdi bestemmer
robotten om lysforholdene er øget vha. den kaliberet lysværdi plus en margin på 5* (NORMAL_VALUE_BUFFER). Hvis den nuværrende lysværdi er højrer en den kaliberet værdi plus marginen, sætter vi begge motorer til fuld power.

*Vi fandt marginen på 5 ud fra et forsøg hvor vi obseverede hvad lyssensoren målte uden vi lyste på den (55-57) og hvad den målte når vi lyste på den (60-90).

//Start main loop
LCD.clear();
while (! Button.ESCAPE.isPressed()) {
int currentLigthValue = lightSensor.readValue();
LCD.drawInt(currentLigthValue, 4, 10, 2);
LCD.refresh();

if (currentLigthValue > NORMAL_VALUE_BUFFER) {
leftMotor.controlMotor(100, forward);
rightMotor.controlMotor(100, forward);
} else {
leftMotor.controlMotor(0, stop);
rightMotor.controlMotor(0, stop);
}

Thread.sleep(10);
}

Forsøget gik some forventet - robotten holder stille under normale lysforhold (kaliberet) og kører når vi lyser med lygten på lys sensoren.



Vehicle 2b
Vi ønsker at få robotten til at følge en lys kilde. Hvis lyskilden er lige frem foran robotten skal robotten kører lige ud. Hvis lyskilden bliver holdt til højre for robotten skal den dreje til højre.

Vi vil benytte os af en reaktionel strategi, dvs. vi sætter effekten på motoren til at være proportinel med den målte lysværdi fra lyssensoren. Vi benytter os af 2 lyssensorer til at bestemme hvilken vej der skal drejes. Eftersom vi laver effekten på motoren ligefrem proportionel med den målte lysværdi, skal vi bruge et robot design som Vehicle 2b - se tegning herunder[2].


Vores control loop kan ses herunder. Vi har nu 2 lyssensorer og derfor 2 variable til sensorværdierne (currentLeft og currentRight). I Vehicle 2b "krydses" input og motor siderne, hvilket vi har gjort ved at sensor værdien fra den venstre sensor, bestemmer effekten på højre motor og omvendt for den højre sensor. Igen har vi vores margin for normale lysforhold og en motor vil kun køre hvis sensor værdien er over denne margin. Vi har bibeholdt denne egenskab for at robotten ikke skal blive for følsom overfor environmentet.

while (! Button.ESCAPE.isPressed()) {
int currentLeft = lightSensorLeft.readValue();
int currentRight = lightSensorRight.readValue();

if (currentLeft > NORMAL_VALUE_BUFFER) {
rightMotor.controlMotor(scaleLightInput(currentLeft), forward);
} else {
rightMotor.controlMotor(0, stop);
}

if (currentRight > NORMAL_VALUE_BUFFER) {
leftMotor.controlMotor(scaleLightInput(currentRight), forward);
} else {
leftMotor.controlMotor(0, stop);
}

Thread.sleep(10);
}

Resultatet af dette forsøg kan ses her:



Som det fremgår af videoen virker denne løsning ikke optimalt. Vi kunne se på robottens opførsel at reaktionen (kør eller stop) var for hård hvilket resulterede i den "vrikkende" kørsel.

Vi ændrede lidt på vores control loop:
while (! Button.ESCAPE.isPressed()) {
int currentLeft = lightSensorLeft.readValue();
int currentRight = lightSensorRight.readValue();
if (currentLeft > NORMAL_VALUE_BUFFER || currentRight > NORMAL_VALUE_BUFFER) {
rightMotor.controlMotor(scaleLightInput(currentLeft), forward);
leftMotor.controlMotor(scaleLightInput(currentRight), forward);
} else {
leftMotor.controlMotor(0, stop);
rightMotor.controlMotor(0, stop);
}

Thread.sleep(10);
}

Vi har ændret control loopet til først at tjekke om en af lyssensorne registere en lysværdi større end vores margin. Hvis det er tilfældet giver vi motorne den målte lysværdi skaleret*. Det resulterer i at hvis vi lyser lige på begge sensorer måler begge sensorer ca. samme værdi og robotten vil kører lige ud. Lyser vi til en af siderne vi den ene sensor måle en højere værdi end den anden. Det kombineret med det "krydsede" design i Vehicle 2b resultrere i at den ene motor vil kører hurtigere end den anden, pga. forskellen i målt lysstyrke af sensorne, og robotten vil dreje til den rigtige side. Det er altså udelukkende de målte lysværdier der kontrollere robotten, hvilket passer med en Braitenbreg model.

*skalerings metoden er ganske simpel. Den addere 30 til den målte lys værdi. Vi kom frem til 30 ud fra obsevationen at de målte lysværdier ligger imellem 60 og 90 (90 er kun hvis man lyser direkte ind i en sensor fra ca. 1 cm afstand) og faktum at værdierne motorne skal have for at kører ligger imellem 60 og 100. Vores typiske målte lys værdi ligger imellem 60-70, derfor hvis vi lægger 30 til det får vi en motor effekt på 90-100, hvilket passer perfekt på den ønskede motor effekt.

Resultatet af modifikationen af control loopet ses her:



Tidsforbrug:

3 timer


Referencer
  1. P. Maes, Modeling Adaptive Autonomous Agents,
    Artificial Life Journal, C. Langton, ed., Vol. 1, No. 1 & 2, MIT Press, 1994.
  2. Tom Dean, Introduction to Machina Speculatrix and Braitenberg Vehicles
  3. Tom Dean, Notes on construction of Braitenberg's Vehicles, Chapter 1-5 of Braitenbergs book

torsdag den 1. oktober 2009

Robot Race (TØ 6 + TØ 7)

Program for torsdag 08.10:
I dag fortsætter vi med sidste uges test af ColorSensoren og vil se på andre mulige løsninger, så Alishan banen kan gennemføres hurtigst muligt. Vi har overvejet følgende løsningsmodeller:

Robot med 4 ColorSensors på række:

Idéen bag denne robot var, at de to inderste sensorer skulle kunne følge en sort linie ved at korrigere robotten svagt i den rigtige retning hvis en sort farve registreres af én af sensorerne (dvs føre sensoren væk fra det sorte). I de tilfælde hvor robottens to yderste sensorer registrerer sort (sker i forbindelse med de forskellige plateauer) skal robotten korrigere ved at stoppe den ene motor og give fuld speed på den anden for at dreje kraftigt. Når robotten registrerer en målstreg (alle 4 sensorer måler sort) skal robotten vende 180 grader og så fortsætte ned af bakken.
Vi havde svært ved at løse problemet, når robotten skulle forcere det sidste stykke af en bakke. Sensorerne kom simpelthen for højt op og registrerede derfor alle farven sort eller grøn. Det problem løste vi med en løftearm, så alle sensorer konstant kørte lige over jorden. Vi måtte til sidst sande, at denne løsning ikke var optimal til den givne opgave, da hastigheden hvormed robotten kunne navigere korrekt var for lav. Vi måtte komme frem med en specialiseret robot, som var hurtig på den givne bane og ingen andre steder. Derfor overvejede vi nedenstående robotter.
Update: ved slutningen af denne TØ fandt vi ud af sensorport 4 på vores NXT Brick ikke virkede. Dette kan være skyld i, at robotten ikke reagerede som forventet.


Robot med 1 TrykSensor:
Idé: robotten skal når den kører op af en bakke være trykket i bund. Når den når et plateau og tryksensoren frigives, skal robotten blot følge en forudbestemt kurve indtil sensoren atter er i bund. Vi kom frem til, at denne løsningsmodel ikke var holdbar da sensoren ikke ville kunne fungere på vejen ned af bakken (vil altid være trykket i bund).



Robot med 2 ColorSensors og 1 afstandsmåler som hænger langt fremme på robotten:

Idé: Skab en robot som ved hjælp af ColorSensorer følger den sorte streg på vej op og ned af bakken. Når afstandsmåleren så registrerer et fald eller en stigning, skal robotten dreje i en forudbestemt kurve. Robotten skal programmeres efter de givne omgivelser, så den drejer korrekt, dvs. højre første gang og så venstre etc.
Problem: afstandsmåleren er for følsom overfor bilen bevægelser, hvilket resulterer i svingende værider som er for svære at arbejde med. Efter diverse tests kasserede vi denne model.





Hardcoding/state:

Realiteten er, at denne konkurrence ikke kan vindes med en "tænkende robot" som udelukkende reagerer på det data den samler ind. Man kan hardcode dele af banen ind i robotten, så den følger den sorte linie v.h.a. 2 ColorSensors indtil et plateau nåes og derefter skal robotten dreje efter vores hardcodede anvisninger (dvs. uden at tage højde for sorte streger og andre omgivelser). Denne metode nåede vi ikke at afprøve.

Kode - Control loop for 4 lightsensors:

if (sensorOne.white() && sensorFour.white()) {

if (sensorTwo.white() && sensorThree.white()) {
//Continue ahead
Car.forward(power, power);
} else if (sensorTwo.black() || sensorTwo.color()) {
Car.forward(power, turnPowerMiddle);
//Turn slight right
} else if (sensorThree.black() || sensorThree.color()) {
//Turn slight left
Car.forward(turnPowerMiddle, power);
} else {
Car.stop();
}

//Edge turns
} else if (!sensorOne.white() && sensorFour.white()) {
Car.forward(power, 0);
} else if (sensorFour.white() && !sensorOne.white()) {
Car.forward(0, power);
} else if (sensorOne.black() && sensorFour.black()) {
Car.stop();
}


Kode - Test kode for Ultra sonic sensor:

final int upSlopeDistance = 23;
final int downSlopeDistance = 8;
final int upPlatformDistance = 26;
final int downPlatforDistance = 6;
UltrasonicSensor sensorDistance = new UltrasonicSensor(SensorPort.S3);

if (sensorDistance.getDistance() == upPlatformDistance) {
Car.stop();
}


Tid brugt på TØ 7: 7 timer

Program for torsdag 01.10:

I dag skal vi eksperimentere med Lightsensoren og Linefollower programmet[1] for at blive klar til at bygge vores robot til Robot Racet. Den bane vi skal køre på i racet ser sådan ud:
Målfeltet (ved gulvet) er markeret med grøn tape. Derfor får vi brug for at kunne skelne imellem 3 farver; hvid, sort og grøn. Dagens program ser derfor sådan ud:
  1. Test den udleverede BlackWhiteSensor.java[2] og LineFollowerCal.java[1]
  2. Udvid BlackWhiteSensor.java til også at kunne læse grøn
  3. Udvid koden så robotten stopper når den kommer ind i det grønne målfelt
  4. Forbedre vores kode så vi får en hurtigste tid

1 - Test af udleveret kode
Vi testede BlackWhiteSensor.java og LineFollowerCal.java (uden modifikationer)Som forventet virkede denne linefollower som den skulle. Vi bemærkede dog at denne version ocillerede mindre end den første linefollower vi testede, for et par uger siden. Vi valgte ikke at gøre mere ud af dette, så vi kunne komme igang med det interessante.

2 - Fra BlackWhiteSensor til ColorSensor
Vi forsøgte først men en hurtig implementation der samplede den grønne farve og ud fra en konstant margin, kunne udregne hvid og sort. Dette virkede dog ikke. Vi besluttede os for at ved starten af programmet skal alle 3 farver samples. [beskrivelse af upper og lower bounds]. Derudover er sersor klassen lavet så den virker med alle farver (i teorien) og ikke kun hvid, sort og grøn.


import lejos.nxt.*;

public class ColorSensor {

private LightSensor ls;
private int colorLightValue;
private int blackLightValue;
private int whiteLightValue;
private int colorLowerBound;
private int colorUpperBound;
private final int MARGIN = 5;

public ColorSensor(SensorPort p)
{
ls = new LightSensor(p, true);
// Use the light sensor as a reflection sensor
// ls.setFloodlight(true);
}

private int read(String color){

int lightValue=0;

while (Button.ENTER.isPressed());

LCD.clear();
LCD.drawString("Press ENTER", 0, 0);
LCD.drawString("to callibrate", 0, 1);
LCD.drawString(color, 0, 2);
while( !Button.ENTER.isPressed() ){
lightValue = ls.readNormalizedValue();
LCD.drawInt(lightValue, 4, 10, 2);
LCD.refresh();
}
return lightValue;
}

public void calibrate(){
blackLightValue = read("Black");
whiteLightValue = read("White");
colorLightValue = read("Color");
colorLowerBound = (blackLightValue + colorLightValue)/2;
colorUpperBound = (whiteLightValue + colorLightValue)/2;
}

public int[] getCalibration() {
int[] tmp = new int[3];
tmp[0] = blackLightValue;
tmp[1] = whiteLightValue;
tmp[2] = colorLightValue;
return tmp;
}

public void setCalibration(int[] cal) {
blackLightValue = cal[0];
whiteLightValue = cal[1];
colorLightValue = cal[2];
colorLowerBound = (blackLightValue + colorLightValue)/2;
colorUpperBound = (whiteLightValue + colorLightValue)/2;
}

public boolean black(){
return (ls.readNormalizedValue() <> colorUpperBound);
}

public boolean color(){
return ((colorLowerBound <>

3 - Make it stop please
Vi har udviddet LineFollowerCal.java så robotten vil stoppe når den ser den samplede målfelts farve.

Ved første forsøg virkede dette efter hensigten, bortset fra at robotten ikke kører helt ind i feltet.

Herfra nåede vi ikke mere i denne TØ.

4 - Optimering af kode
(Nåede vi ikke)

Tid brugt på TØ 6: 3 timer

Referencer

[1]LineFollowerCal.java
[2]BlackWhiteSensor.java

torsdag den 24. september 2009

TØ 4: Sejway - balancerende robot

Tom Ørsnes, Mark Surrow, Harald Andertun - ca 3 timer.

Denne uge har vi arbejdet med en balancerede LEGO robot, lignende Philippe Hurbain's NXTway-robot. Idéen er at den skal fungere ligesom den velkendte selvbalancerende segway.

Målet med denne lab session var først at prøve SejwayBad.java af, hvor vi gerne skulle se robotten kører meget ustabilt og drejer voldsomt frem og tilbage. Herefter skulle vi afprøve Sejwat.java, som er en forbedring af SejwayBad.java. Vi skulle gerne kunne obsevere at Sejway.java virker bedre end SejwayBad.java (bedre balance).


Vi fik downloaded de 2 kode filer, men støte derefter på et problem. Vi kunne ikke forbinde til vores NXJ, da de libraries vi bruder til kommunikere med NXJen i OS X ikke virkede. Det viste sig at en af sidste uges opdateringer til OS X satte Java til at kører 64-bit som standard, hvorfor USB og Bluetooth (hhv. usblib og bluecore) ikke længere virkede. Løsningen var at tvinge Java til at starte NXJ applikationerne (f.eks. nxjbrowse) i 32-bit. Dette tog desværre noget tid at finde ud af.

Det gøres ved at indsætte
-d32 i den sidste linie i det script man ønsker at køre. Her er et eksempel fra nxjbrowse:
java -d32 -Dnxj.home="$NXJ_HOME" -DCOMMAND_NAME="$NXJ_COMMAND" -Djava.library.path="$NXJ_BIN" -classpath "$NXJ_CP_TOOL" lejos.pc.tools.NXJBrowser "$@"

SejwayBad.java forsøg:
Problemet med denne kode er at programmet kører for langt hver vej før den skifter retning. Det 'overreagerer' hver gang, og lærer ikke af sine fejl. Efter at have overreageret burde den korrigere nogle variable så den ikke korrigerer lige så meget næste gang.

SejwayBad.java har en variable int NEUTRAL = 37. Denne variable angiver lysstyrken læst af lyssensoren når robotten står i balance (nautral). I vores tilfælde var det for lavt. Da vi kørte programmet, kunne vi aflæse på displayet en værdi ca 400. Dette resulterede i at robotten straks væltede. Så for at få SejwayBad til at virke var vi nødt til at korrigere denne værdi.

Men pga. de problemer vi havde tidligere med USB-driveren og java, valgte vi at stoppe med SejwayBad og gå videre med den bedre kode (Sejway.java) som vi fået udleveret.

Sejway.java forsøg:
Sejway.java koden er bedre af to grunde. Den første er at programmet starter med at sætte den værdi der læses fra lyssensoren, som balance punkt (i modsætning til SejwayBad.java der havde en pre defineret værdi i koden). Den anden grund er at Sejway.java forsøger at tage højde for overkorrigering ved at huske hvormeget der sidst blev korrigeret med og ændre ud fra dette, hvormeget der korrigeres.

Vi lavede et forsøg med koden uden at have ændret i det, for at se hvor længe robotten kunne holde sig oprejst. Det var muligt for den at holde sig oprejst i et par sekunder, inden den væltede.

Herefter kiggede vi på koden for at se om vi kunne forbedre dette. Vi forsøgte os med at sætte PID variablen KP ned til 10. Det gjorde vi ud fra den obsevation at robotten i første korrigerede sin balance for kraftigt i de første par iterationer og endte med at "stille" sig på lyssensoren. Vi ville derfor nedsætte styrken med hvilken robotten startede med at korrigere, så den kunne nå selv at ændre på sin korrigtions styrke.
// PID constants
final int KP = 17;

Efter nogle forsøg endte vi på 17, hvilket viste sig at være den værdi der fik robotten til at klare sig bedst. Det var det ikke en forbedring på mere end et par sekunder, robotten kunne holde sig oprejst. Herefter nåede vi ikke længere.

Reflektion:
Vi skulle måske have kigget mere på hvordan algoritmen virkede og forsøgt at arbejde med den, såvel som PID værdierne. Vi skulle også have kigget på de andre konstakter, ud over KP.

En anden ting der viste sig vigtig var hvor godt man fik placeret robotten i sit balance punkt. Ulempen her er at der i et givet forsøg ikke er nogen garenti for at vi kan placere robotten på præcis samme måde, som i forgående forsøg og dette kan påvirke vores fortolkning af den effekt, som vores ændringer i koden har givet. F.eks. er det muligt at vores ændringer i KP konstanten ikke var grunden til at vores robot klarede det (en smugle) bedre, men grunden var at vi var bedre til at placere robotten i sit balance punkt ved starten af testen. Vi havde dog ikke tid til at udforske dette, grundte den "spildte" tid på USB/Bluetooth driverne.

torsdag den 17. september 2009

TØ 3: Test af sound sensor

Vi startede med at tilslutte en NXT sound sensor til vores LEGO 9797 bil. Derefter compilede vi SonicSensorTest.java og uploadede den til Killbot. Vi havde først tænkt at lave lidt forskellige tests og udfylde en tabel med de forskellige data, men vores display opdatering virkede til at være for langsom og unøjagtig til denne manuelle aflæsning. Tabellen ses herunder:

LYDFYSISK AFSTAND/CMMÅLT AFSTAND/CMOMGIVELSE
klap1050lidt støj
klap5030lidt støj
klap10040lidt støj
klap500?
lidt støj
Ringetone50?lidt støj
Ringetone50?lidt støj

Denne lyd sensor virker meget følsom. Den registrerer lufttræk og baggrundsstøj meget nemt. Derfor valgte vi at teste den i et lille rum i Zuse, med meget lidt baggrundsstøj, for at kunne aflæse værdierne bedre. For at få et klap med samme styrke hver gang, optog vi klappet på en iPhone. Hør klappet her. Vi ville teste om et klap udført fra samme afstand ville give den forventede måling. Det tilfredsstillende resultat ses i grafen:














Dernæst testede vi Clap Controlled Car. Bilen virkede helt efter hensigten, så længe klappet var højt nok (måling på over 90).

torsdag den 10. september 2009

TØ 2: Test af Ultrasonic Sensor

Under denne uges TØ fik vi endelig Lejos til at samarbejde med vores macs. Vi brugte lidt tid på øvelsen fra sidste uge, LineFollower.java, men fokuserede hovedsageligt på NXT ultrasonic sensoren. Herunder ses en test af vores linefollower :



Med SonicSensorTest.java testede vi sensoren under forskellige forhold (bl.a. trævæg kontra gipsvæg) og opdateringshastigheder. Resultatet ses i tabellen herunder:

Fysisk afstand (cm) Killbots målte afstand (cm) Forhold
30 29-30 svag støj mod hvidt papir
20 22 -"-
10 11-12 -"-
30 30 mod plastic
20 21-22 -"-
11 11-12 -"-
30 30 mod trævæg
11.5 13 mod glas
30 30 glas
120 120 væg
254 243 gips væg
244 243 -"-

Selve brugen af sensoren begrænses naturligvis idet man ikke kan benytte den hvis man har behov for at måle afstande længere end 243-254 cm. Men for os bør det ikke være en begrænsning, da vi arbejder med forholdsvis korte afstande og de målte afstande er ganske præcise.

På korte afstande (op til 30 cm) fik vi nogle flotte og korrekte målinger selvom vi ændrede sensorens reaktionstid til 1 millisekund. Men på længere afstande bliver sensoren begrænset af tiden som lyden er om at echo tilbage og målingerne svinger for meget, hvilket begrænser brugbarheden.

Tracker: Vi arbejdede også med koden Tracker.java og Car.java, der kontrollerede bilen ved brug af Ultrasonic Sensoren. I sin originale opsætning kørte bilen kun fremad og bagud. Når den kom tæt på en forhindring bremsede den og bakkede lidt. Programmet var på dette tidspunkt ikke tilstrækkeligt intelligent til at kunne køre ud af en blind vej.

Vi pillede lidt ved de forskellige variable, og tilføjede også ny funktionalitet til programmet. I Car klassen tilføjede vi følgende metode, eftersom vi ønskede at bilen skulle dreje lidt til venstre når den havde stødt på en forhindring og været nødt til at bakke lidt.

public static void turnleft(int rightPower)
{
rightMotor.controlMotor(rightPower, forward);
}

I Tracker klassen tilføjede vi et kald til turnleft() metoden, lige efter at bilen havde bakket lidt. På denne måde drejer bilen indtil den ser en ny mulighed for at køre lige ud.

Car.backward(power, power);
LCD.drawString("Backward", 0, 6);
Car.turnleft(power);


Problemet med den blinde vej var nu løst - se video :




fredag den 4. september 2009

Vi har nu fået løst problemet og kan uploade filer til robotten (Yay!). Problemet var mangel på dokumentation for 0.85 til OS X. Det er nemlig slet ikke nødvendigt at installere USB Drivere, build lejos_nxj, opdatere .jar filer eller redigere i build scripts (og hvad vi ellers var ude i) i den nye version da USB drivere osv. er inkluderet i lejos_nxj. Det var her problemet opstod - de guides vi har brugt er outdated til 0.85, da man ved at installere Fantom USB driveren selv, tilsydenladende ødelægger lejos_nxj installationen.

Det eneste man skal er at download lejos_nxj, unzippe det og sætte 4 environment variabler:
export NXJ_HOME=din_sti_til_nxj/lejos_nxj
export DYLD_LIBRARY_PATH=${NXJ_HOME}/bin
export PATH=${NXJ_HOME}/bin:${PATH}
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home (hvis den ikke er sat)

så kan man benytte lejos_nxj/bin/nxjbrowse til at uploade. (NB: nxjconsoleviewer ser ikke ud til at virke, ihvertfald ikke på Os X)

Eclipse Plugin virker stadig ikke (over USB, BT ikke prøvet), men det har ikke top priotet.

torsdag den 3. september 2009

TØ 1: Udlevering af LEGO og installation

Vi fik udleveret vores Lego sets og fik bygget bilen vi skulle lege med. Herefter kastede vi os over at få installeret leJOS værktøjerne. Vi bruge alle Macs og det skulle vise sig ikke at være specielt nemt at få til at kører. Efter at have fulgt guides på leJOS hjemmeside og guiden i README.html uden held, kiggede vi efter andre guides. Vi har fik afprøvet en del guides, men uden held. Her er nogle af dem:
http://tucsontechnics.blogspot.com/2009/05/installing-lejos-on-macbook-pro.html
http://lejos.sourceforge.net/forum/viewtopic.php?t=1186&start=0

Selvom der ikke har været problemer med at gøre som beskrevet i de forskellige guides og vi har fået installeret en USB driver (Fantom USB Driver), er der stadig problemer med at connecte til Brick'en. Vi har brugt en debug version af pccomm.jar (lejos_nxj/lib) og det viser sig at være ham her der giver problemer:
java.lang.NoClassDefFoundError: lejos/pc/comm/NXTConnector

Vi har oprettet et indlæg på leJOS forum og er ved at få hjælp til at løse problemet. En meget mere detaljeret beskrivelse af hvad vi har gjort og problem beskrivelse findes i indlæget her:
http://lejos.sourceforge.net/forum/viewtopic.php?t=1692