Denne blog bruges af Kim Munk Petersen (20063667), Andreas Koefoed-Hansen (20062154) og Tim Rasmussen (20061947) som dagbog i forbindelse med kurset Embedded Systems/Legolab på Århus Universitet.

onsdag den 20. januar 2010

Projekt - 7

Dato:
20-01-2010

Antal timer brugt:
4 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  • Implementere LineFollower
  • Rette blogindlæg
Planen:
Vi vil i dag forsøge at tilføje en ny behavior til Legwayen. Som beskrevet i de tidligere blogindlæg, bruger vi leJOS' subsumption framework hvilket gør det nemt at tilføje nye behaviors. Den nye behavior vi vil tilføje er en Line-follower således at vores Legway bliver i stand til at følge linjen på gulvet i Legolab, ligesom ved øvelsesgang 1 [1] og 4 [2].
Herefter vil vi rette de hidtil skrevne blogindlæg samt uddybe mangelfulde forklaringer mm.

Processen:
Vi mener at Legwayen har mulighed for at følge linjen på gulvet i Legolab idet vi ved at den er i stand til at balancere, køre ligeud og dreje uden problemer. Et mindre problem kan være at den for at holde balancen kører lidt frem og tilbage hvilket kan forsage at den kommer til at køre for langt frem i et skarpt sving og dermed kommer uden for banen. Dette problem er mindre udtalt ved lave hastigheder og vi starter derfor med at implementere en funktion der gør os i stand til at styre farten af Legwayen. I øjeblikket er farten ved ligeudkørsel hardcoded ind i programmet og det er altså denne vi vil have flyttet ud i en variabel så den kan ændres. Herved opnår vi også en mere generisk løsning der gør det let at implementere en analog styring af Legwayen, selvom vi ikke har planer om at implementere dette. Legwayens acceleration er bestemt af en eksponentialfunktion som forklaret i forrige blogindlæg, og metoden setMaxSpeed sætter derfor den maksimalt opnåelige fart ved henholdsvis kørsel frem og tilbage ifølge to parametre der gives med.

public void setMaxSpeed(double maxFowradSpeed, double maxBackwardSpeed) {
  this.maxForwardSpeed = maxFowradSpeed;
  this.maxBackwardSpeed = maxBackwardSpeed;
}


De to fields maxForwardSpeed og maxBackwardSpeed bruges nu i metoden runDriveState på følgende måde:

if (driveState == CtrlParam.FORWARDS)
  setTiltAngle(maxForwardSpeed - maxForwardSpeed * Math.exp(-damp));
else if (driveState == CtrlParam.BACKWARDS)
  setTiltAngle(-maxBackwardSpeed + maxBackwardSpeed * Math.exp(-damp));

Efterhånden som det andet led i kaldet til setTiltAngle går mod nul, sættes tilt-vinklen til maxForwadSpeed hvis Legwayen kører fremad og -maxBackwardSpeed hvis den bakker.

Efter vi implementerede setMaxSpeed-metoden i CtrlParam-klassen, flyttede vi også konstanterne STATIONARY, FORWARDS og BACKWARDS samt metoden runDriveState() fra BalanceController til CtrlParam idet vi ikke mener at det er BalanceControllerens ansvarsområde at få Legwayen til at køre frem og tilbage, men derimod blot at holde balancen.

Opførslen til at følge linjen er implementeret i klassen FollowLine der implementerer Behavior. Vi har valgt at den skal ligge lavest i behavior-hierarkiet, dvs. have den mindste prioritet. Den skal ikke ligge over AvoidFront idet der godt kan være en forhinding på en bane. Her giver det så god mening at Legwayen vender om og kører den anden vej. Den skal heller ikke ligge over BTDriver idet det er svært at detektere hvornår den er på en bane med en sort linje den kan følge, og dermed supresse Bluetooth-forbindensen. Nedenstående diagram viser Legwayens aktuelle behavior-hierarki.





I øjeblikket bruger Legwayen to ud af de fire sensorporte som NXT'en stiller til rådighed. De to sidste sensorporte kan derfor bruges til lyssensorer. Ved at bruge to lyssensorer i modsætning til én, får vi ikke en bang-bang controller [3], som er karakteriseret ved to tilstande, men derimod en controller med fire tilstande. Disse fire tilstande udgøres af mulige farvekombinationer som de to lyssensorer kan se, dvs. hvid/hvid, sort/sort, sort/hvid og hvid/sort. Ulempen ved at bruge en enkelt lyssensor er at robotten hele tiden skal holde sig på den ene side af linjen. Den har ingen mulighed for at opdage det hvis den ved et uheld krydser linjen, idet sensoren går fra sort til hvid uanset hvilken side af linjen den havner på, og kan derfor ikke finde tilbage til linjen igen. Ved at bruge to lyssensorer ved robotten til hver en tid på hvilken side af den sorte streg den befinder sig ved at se på hvilken sensor der sidst så den sorte linje. Da Legwayen er ustabil af natur hvorved den let kan komme til at krydse linjen, besluttede vi fra begyndelsen at bruge to lyssensorer.

Der er flere måder at lave styringen på. Vi lavede den således at robotten altid kører langsomt fremad og så korrigerer retningen ved at bremse hjulet der sidder i den retning den ønsker at dreje til. Skemaet herunder forklarer hvad robotten skal gøre alt efter hvilken af de fire førnævnte tilstande den er i.




Til at starte med placerede vi lyssensorerne mellem hjulene under robottens tyngdepunkt som vist på billedet herunder. Vi placerede dem således at de sidder på hver deres side af linjen, men stadig så tæt som muligt for at robotten hurtigst muligt registrerer når den kører skævt ift. linjen.




Da vi testede denne konfiguration viste det sig at robotten ikke var i stand til at følge linjen på gulvet. Den kørte meget fra side til side, nogle gange så meget at den vendte en halv omgang og begyndte at følge linjen i den forkerte retning. Problemet løste vi ved at flytte lyssensorerne længere frem. Herved får robotten mere feedback når den drejer idet sensorerne bevæger sig mere. Et eksempel herpå kan ses på nedestående illustration hvor lyssensorerne er placeret midt under robotten på den øverste serie af billeder hvorimod de er rykket lidt fremad på den nederste serie af billeder. Billederne illustrerer robotten og banen set oppefra, og hvad der sker når robotten kommer til et sving med henholdsvis den ene og den anden placering af lyssensorerne. Der er ingen forskel på de to tilfælde når robotten kører parallelt med stregen, men i sving har robotten nemmere ved at navigere når sensorerne sidder fremme idet den hurtigere finder den rigtige retning og ikke kommer helt på tværs af stregen som den ellers ville gøre (vist på øverste højre billede).




Vores eneste bekymring ved at placere lyssensorerne et stykke foran robotten er at de under acceleration løftes fra underlaget idet robotten tilter bagud, hvilket kan gøre at de muligvis ikke kan "se" farven på underlaget. Omvendt kan de under deceleration komme til at røre underlaget hvilket kan få robotten til at "snuble". Det første tilfælde viste sig ikke at være et problem i praksis og det andet tilfælde var kun et problem når Legwayen kører op af en stejl skråning. Dette problem ville givetvis kunne løses ved at rykke sensorerne en smule længere ind under robotten, og evt. ved at sætte en begrænsning i programmet på hvor skarpt robotten må dreje, for at undgå at den kommer helt på tværs af linjen. Dette når vi desværre ikke at eksperimentere med inden præsentation i morgen.

I det følgende beskriver vi kort implementeringen af opførslen. Idet FollowLine implementerer Behavior, har den metoderne action(), takeControl() og suppress(). TakeControl-metode returnerer altid true således at den bliver aktiv hvis ingen anden behavior ønsker kontrollen, hvilket giver god mening idet den har lavest prioritet. Suppress-metoden sætter en boolean isSuppresed til true. Denne bruges i action-metoden til at afgøre hvornår den skal stoppe med at følge linjen. Så snart Legwayen kommer for tæt på en mur eller der oprettes forbindelse til den via Bluetooth, vil henholdsvis AvoidFront eller LegwayDriver få arbitratoren til at supresse FollowLine og dermed sætte isSuppressed-flaget hvorefter den stopper sin action-metode så den opførsel der suppressede den kan blive afviklet. I starten af action-metoden tændes lyssensorernes floodlight og de slukkes lige inden action-metoden returnerer. Herved kan vi se på robotten om FollowLine-opførslen er aktiv eller ej.

Idet det egentlig mål med robotten var at få den til at balancere, kan man mene det er dumt at den afvikler FollowLine-opførslen pr. default, antaget af kriterierne for højere-prioritets opførsler ikke er opfyldt hvilket de typisk ikke er når robotten stares. Af den grund udvidede vi FollowLine-opførslen med en boolean isEnabled som angiver om den må udføres eller ej. Denne boolean starter med værdien false og kan kun sættes til true via PC-programmet der også bruges til at styre Legwayen. Det betyder at robotten ikke har nogen opførsel der ønsker kontrollen lige efter den er startet op hvorfor den blot står og balancerer. På samme måde gjorde vi det også muligt at aktivere og deaktivere AvoidFront-opførslen via Bluetooth så erfarne "chauffører" ikke risikerer at robotten pludseligt overtager styringen. Herunder ses et snapshot af det nye PC-program til styring af Legwayen. Desuden udskrives bitmasken nu også i tekstfeltet i midten således at vi kan kontrollere at de rigtige kommandoer bliver afsendt til Legwayen.




Afslutningsvis navngav og flyttede vi nogle "magiske" konstanter, som før var hardcoded ind i Legway'ens program, op i toppen af deres respektive klasse. Et eksempel herpå er konstanten der afgør hvornår Legwayen er væltet. Denne er nu defineret i BalanceController som følgende, således at koden bliver mere overskuelig og let kan justeres hvis vi skulle få brug for det.
private static final int FALL_ERROR = 8000; // constant for determining when Legway has fallen
Afrunding:
Projektforløbet er nu ved at være slut og vi når derfor ikke at implementere flere features på vores Legway. For at give et overblik over vores endelige softwarearkitektur, har vi lavet et UML-diagram som vist herunder. For at gøre det simpelt, har vi ikke inkluderet leJOS-klasser og interfaces såsom Behavior, Arbitrator, Motor og diverse sensorer. Derudover har vi kun skrevet de væsentligste metoder og fields i klasserne. Vi har illustreret hvilke klasser der ligger på NXT'en og hvilken der ligger på PC'en der bruges til at styre Legwayen via Bluetooth.

Mange af klasserne vist i UML-diagrammet er beskrevet i de forgående blogindlæg. Nogle af klasserne er dog ikke beskrevet, hvilket vi derfor kort gør i det følgende. Klassen Legway på NXT'en er hovedklassen forstået på den måde at den indeholder main-metoden som er programmets entry point. Den starter BalanceControlleren og tilføjer behaviors til arbitratoren som herefter også startes. Klassen Car implementerer nogle metoder der kan bruges til at få robotten til at køre frem/tilbage, dreje og stoppe. CtrlParam indeholder kontrolparametre der angiver robottens kinetiske tilstand, såsom drive-state, damp og motor-offsets.

Konklusion:

Det lykkedes os at få implementeret en ny behavior til Legwayen således at den nu er i stand til at følge en linje. Selvom vi som nævnt tidligere har implementeret samme opførsel ved to af øvelsesgangene, var det lidt sværere denne gang fordi vi skulle tage højde for Legwayens ustabilitet. Ved at få den til at køre langsomt minimerede vi ustabiliteten og ved at bruge to lyssensorer sørgede vi for at den kan finde tilbage til linjen hvis den kommer til at krydse den.
Efter præsentationen i morgen begynder vi at lave den endelige konklusion på projektet. 


Referencer:
  1. NXT Programming, Lesson 1, http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson1.dir/Lesson.html
  2. NXT Programming, Lesson 4, http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson4.dir/Lesson.html
  3. Bang-bang control, http://en.wikipedia.org/wiki/Bang-bang_control

Ingen kommentarer:

Send en kommentar

Faste læsere