Robocup
Sammanfattning RoboCup är ett världsmästerskap i Artificiell Intelligens, en utav grenarna i RoboCup är fotboll där lag av robotar tävlar mot varandra. I det här fördjupningsarbetet har jag valt att koncentrera mig på ett lag som heter Dutch Nao Team för att undersöka hur de löst problemen för att kunna få robotar att spela fotboll.
Innehåll Sammanfattning... 3 Syfte... 5 Bakgrund... 5 Ligor... 5 Dutch Nao Team... 6 Roboten Nao... 6 Game Controller... 7 Uppbyggnad/Faser... 8 BallFound... 8 BallNotFound... 8 Kick... 8 BallApproaching... 8 InGoalArea... 9 Unpenalized... 9 ReturnField... 9 Percept... 9 Bolligenkänning... 9 Måligenkänning... 9 Diskussion... 11 Bilaga Måligenkänningsalgoritm... 12 Referenser... 15
Syfte Att göra robotar som kan spela fotboll är inte bara nöjesprojekt utan kan förbättra förståelse för hur man kan lösa problem för robotprogrammering i allmänhet, i en värld där allt mer sköts automatiserat och med visioner om robotarbetare för att lösa våra vardagliga problem så hjälper fotbollsrobotarna oss att lära oss mer om hur man kan lösa problem som objektigenkänning. Syftet med fördjupningsuppgiften är att få en fördjupad förståelse av hur man kan lösa problem inom Artificiell Intelligens genom att studera programmeringskoden från ett lag som tävlar i fotbollscupen RoboCup. Bakgrund RoboCup startades 1997 med syftet att förbättra forskningen av robotteknik, artificiell intelligens och öka samarbetet mellan forskare från hela världen. Officiellt så har man sagt att målet med cupen är att vid år 2050 så ska ett lag av humanoida robotar vinna över mänskliga världsmästarna i fotboll. (www.robocup.org, 2011) Ligor På RoboCup kan man tävla inom de olika grenarna fotboll, räddning och hemservice. Fotbollscupen har fem stycken ligor, där man kan tävla med robotar av olika storlekar men det finns även en liga för simulerade fotbollsrobotar där man kan följa matchen på en datorskärm. Small size i small size-ligan tävlar två lag med sex robotar i varje lag med robotar som får vara högst 18 cm i diameter och 15 cm hög och man spelar med en orange golfboll. Ligan fokuserar på problem med hur robotarna samarbetar med varandra i en dynamisk miljö med en hybrid av centraliserat/distribuerat system. Robotarna identifieras alltså av två stycken kameror som är kopplad till en dator som i sin tur skickar robotarnas och bollarnas position och id till lagens datorer som sedan skickar ut kommandon till robotarna. Middle size Robotarna i middle-size-ligan får inte vara större än 50 cm i diameter och spelar i lag av 6 robotar. Till skillnad från small size-ligan så sköts all sensorisk percept individuellt på robotarna som sedan kan kommunicera över trådlöst nätverk. I middle size-ligan lägger man fokus på självständighet för planering och perception och hur man ska använda det för att samarbeta.
Simulation Simulationsligan består av två stycken ligor, 2D och 3D. I ligorna spelar oberoende simulerade agenter mot varandra, fokus läggs på artificiell intelligens och lagstrategi. Humanoid Till skillnad från small och middle size-ligorna som spelas av robotar på hjul så finns humanoidligan där man behöver lösa problem som att kunna gå, springa och sparka bollen medans de håller koll på balansen, visuell perception av bollen, andra spelare, planen och sin egen position. Ligan är uppdelad i tre stycken underligor: Kid size, teen size och adult size som motsvarar robotarnas storleksrestriktioner. Standard platform I standard platformligan får alla lag använda sig utav identiska robotar, därför behöver lagen inte tänka på att hårdvarumässigt göra en optimal robot utan koncentrerar sig endast på mjukvaruutvecklingen. På så sätt så har alla lag samma förutsättningar och det lag med bäst kod vinner. I standard platformligan används den humanoida roboten Nao från robotutvecklaren Alderaban. Dutch Nao Team Jag har valt att följa laget Dutch Nao Team som tävlar i standard platformligan och har ännu inte vunnit någon pallplats i RoboCup. Lagets källkod är skrivet i programmeringsspråket Python och är öppen för alla läsa. Med en lätt läsbar och lättillgänglig kod gjorde att jag valde laget snarare än att välja ett lag som vunnit cupen. Roboten Nao Roboten Nao är roboten som används i standard platformligan, roboten görs av det franska företaget Aldebaran Robotics och är en 57 cm hög, 5,2 kg tung humanoid robot. Den kan ta emot percept via sina 2 kameror, 4 mikrofoner, sonar avståndsmätare och 2 st. IR-mottagare. Beroende på användning så klarar batteriet av att köra Nao självständigt upp till 1,5 timmar. Man kan styra Nao med antingen programvaran Choregraphe som är skapad specifikt för Nao, eller med något utav programmeringsspråken C++ eller Python.
Game Controller Likt riktiga fotbollsmatcher så har RoboCup domare som blåser av matchen och utvisar spelare. För att kunna ge robotarna information om matchens tillstånd så har domarna en game controller. Matchtillståndet sänds via nätverk och innehåller information som tid, poäng och bestraffningar. En operatör kontrollerar game controllerns mjukvara för att uppdatera de beslut som huvuddomaren tar i matchtillståndet. En match är uppdelad i tillstånden Initial, Ready, Set, Playing, Penalized och Finished. Dessa tillstånd bestäms av operatören av Game Controllern. Vid tillståndet Initial så får robotarna inte röra på sig utöver att ställa sig upp. I Ready-tillståndet så ska robotarna gå in på planen och positionera sig för avspark. I matchtillståndet så finns information om vilket lag som kommer att göra avsparken. Om någon robot inte lyckats positionera sig på en godkänd position så kan domaren förflytta roboten till en godkänd position, detta görs under Settillståndet där robotarna inte får röra på sig. När alla robotar har en godkänd startposition så blåser huvuddomaren i en visselpipa och matchtillståndet ändras till Playing. När något lag gör mål så ändras tillståndet till Ready igen och det blir avspark. Om någon robot bryter mot en regel så får den individuella roboten tillståndet Penalized och ställs av planen, standardutvisningen är 30 sekunder. När domaren blåser av för halvlek/matchslut så ändras tillståndet till Finished, där stannar robotarna. Fördelarna med en Game Controller och matchtillstånd är att robotarna kan agera mer självständigt genom att själva gå ut på planen och positionera sig. I och med att robotarna även får information om utvisningar och poängställning så kan robotarna utveckla strategier utefter den informationen.
Uppbyggnad/Faser Dutch Nao Teams källkod är skriven i programmeringsspråket Python, koden är uppbyggd för att roboten ska agera olika utefter matchens tillstånd som bestäms av Game Controllern och efter spelfaser som är specifika situationer under matchen och bestäms av vad roboten kan observera. För varje fas så finns villkor och om ett villkor uppfylls så agerar roboten därefter. T ex om bollen är tillräckligt nära för att kunna sparka på den under fasen BallFound så går roboten in i Kick-fasen. Man valde det här tillvägagångssättet för att huvudproblemet, att spela fotboll, går att bryta ner till delproblem man kan lösa lokalt och självständigt. Nedan så görs några korta förklaringar för faserna. BallFound BallFound-fasen kallar på funktionen findball som tar en bild och söker igenom den efter bollens position och returnerar ett x- och y-värde för positionen. Om bollen är tillräckligt nära så går den in i Kick-fasen, annars så börjar roboten röra sig mot bollens riktning. Om bollen försvunnit ur synhåll så går man över till BallNotFound-fasen. BallNotFound Om bollens position är okänd så skannar den av området genom att vrida på huvudet. Om den inte kan hitta bollen ändå så börjar den cirkulera tills den hittar bollen. När bollen är upphittad så går den över till BallFound-fasen. Kick Kick-fasen tillkallas när en spelare är tillräckligt nära bollen, då skannar spelaren efter motståndarmålet. Om spelaren hittar motståndarmålet så sparkar spelaren bollen mot målet. Om man istället hittar sitt eget lags mål kollar undersöks åt vilket håll målet är, om man har målet på sin vänstra sida så sparkar spelaren bollen åt höger och tvärtom. Om målet är rakt framför spelaren så gör den en klackspark. Efter en lyckad spark så går spelaren över till BallNotFound-fasen. BallApproaching BallApproaching-fasen är en fas som endast målvakten har. Om bollen rör sig i hög hastighet mot målvakten i en specifik riktning så kommer målvakten beroende på riktningen att välja hur den ska agera, slänga sig eller förflytta sig åt höger eller vänster.
InGoalArea InGoalArea gäller också endast målvakten. När bollen är i straffområdet så kommer målvakten att gå mot den, sparka den och gå tillbaka till sin originalposition. Unpenalized När en spelare blir unpenalized, alltså inte längre utvisad så går den in i unpenalized-fasen. Eftersom man får börja på sidlinjen så börjar spelaren gå två meter in på planen och går över till ReturnField-fasen. ReturnField ReturnField kan endast nås från Unpenalized-fasen och går ut på att medans den går börja söka efter bollen. Percept Bildhanteringen av percepten sköts med hjälp av OpenCV, ett programvarubibliotek inom datorseende och bildanalys som ursprungligen utvecklades av Intel. Bolligenkänning Boll- och måligenkänningen är baserade på färgfilter. Innan en match behövs färgintervall sättas för den röda bollen, det gula samt det blå målet. Intervallen används sedan för att filtrera bilderna som tas av Nao och resulterar i en gråskalig bild. Pixlarna har då intensitetsvärden där det lägsta möjliga värdet är svart och det högsta möjliga är vitt, när spelaren sedan söker efter bollen så undersöker man ifall bildens ljusaste pixels intensitetsvärde når över ett tröskelvärde. Om så är fallet så antar man att det är bollen. När bollen väl har hittats så behöver spelaren räkna ut dess position, eftersom den sett bollen på en tvådimensionell bild så är det svårt att avgöra var den är i en tredimensionell värld. Detta görs med hjälp av kamerans position och orientering när bilden togs. Måligenkänning Ett mål känns igen genom dess två stolpar, bilden söks då igenom efter rektanglar som är långa och breda nog att kunna vara en stolpe. Tröskelhöjden för att vara en stolpe är 20 stycken pixlar hög. Måligenkänningen görs genom denna algoritm (baserad på källkoden som finns i Bilaga 1):
- Skapa en dictionary av vertikala linjer. - Gå igenom en vertikal rad av pixlar i taget, sök igenom vart tionde pixel från och med tionde pixeln upp till maxhöjden av bilden. - Om en pixel är sann, alltså har ett värde över tröskeln på 70 på gråskalan så går man tillbaka nio pixlar. - Sök därefter igenom en pixel i taget tills man hittar en sann pixel. - Räkna från den sanna pixeln fram till tjugo (tröskelhöjden för en stolpe) sanna pixlar i rad eller fram tills en falsk pixel hittas. - Om en falsk pixel hittas så fortsätter genomsökningen från där den var när den fann den sanna pixeln. Klumpen av sanna pixlar den hittade nådde med andra ord inte upp till tröskelhöjden på 20 pixlar som krävs för att det ska vara en stolpe. - Om den istället hittar 20 stycken sanna pixlar i rad så görs en likadan sökning fast från bildens maxhöjd-10 och nedåt. - Memorera de sanna start- och slutpixlarna i dictionaryn som skapades i början med x- värdet som nyckel. Gruppera de vertikala linjerna: - Loopa igenom värdena i dictionaryn från vänster till höger. - Om någon av staplarna av sanna pixlar ligger bredvid varandra i x-led och längden på dom inte skiljer mer än 50 %, sätt ihop dom till en grupp. - Om en grupp hittats och är stor nog, kom ihåg den och sök efter fler grupper. - Returnera de största grupperna. De är med andra ord stolparna för målet.
Diskussion Dutch Nao Team har en mycket lättläst kod med gott om kommentarer vilket har gjort det lätt för mig att förstå hur de tänker och få en djupare förståelse för hur de löser sina problem. Det skulle vara intressant att jämföra deras lösningar med andra lag som presterat bättre i tävlingar och se vad som är skillnaden och vad som skulle kunna göras bättre. Även om det i nuläget inte ser ut som att det kommer vara någon större risk att något mänskligt fotbollslag överhuvudtaget skulle kunna förlora mot ett lag robotar framöver så har robotforskningen gjort mycket imponerande framsteg sedan första RoboCup 97 och en vacker dag så är det inte en omöjlighet att vi har robotar som räddar människor från katastrofer och olyckor, släcker bränder och hjälper oss i våra hem. På så sätt gör RoboCupdeltagarna ett starkt jobb att trycka på utvecklingen av artificiell intelligens till sin spets och samarbeta världen över men även ett sätt att få studenter att få en inspark i robotforskning. Fördjupningsarbetet har ökat mitt intresse för robotar starkt och är något jag skulle kunna tänka mig att undersöka vidare, då det går att simulera robotar på datorer så man kan göra egen kod och testa även om man inte har någon robot.
Bilaga Måligenkänningsalgoritm threshold = 70 # threshold for the grayscale (width, height) = (160,120) # resolution of the input images #######################ALGORITHMICDIVISION####################### # Form a dict of vertical lines. lines = {} for x in range(width): for y in range(10,height,10): if (image[y,x] > threshold): ry = y - 9 while(image[ry,x] <= 70): ry = ry + 1 checker = False for checky in range(ry, min(ry + 20, height)): if (image[checky,x] <= 70): break if (checky == ry+19): checker = True if (checker): for by in range(height-10,0,-10): if (image[by,x] > threshold): bry = by + 9 while(image[bry,x] <= 70): bry = bry - 1 checker = False for checky in range(max(bry-20,0), bry): if (image[checky,x] <= 70): break if (checky == bry-19): checker = True if (checker): lines[x] = (ry, bry) break break #######################ALGORITHMICDIVISION####################### # Group the veritcal lines together. sortedlines = sorted(lines.keys()) currentblob = 'empty' upperline = 0 underline = 0
# initiate top two maximum values Max = None NotQuiteAsMax = None posmax = None posnotquiteasmax = None for i in range(len(lines)-1): if (currentblob == 'empty'): currentblob = 'full' underline = sortedlines[i] left = sortedlines[i] right = sortedlines[i+1] (lefttop,leftbot) = lines[left] (righttop,rightbot) = lines[right] if (((right - left) == 1) and not((leftbot<righttop) or (rightbot<lefttop))): upperline = sortedlines[i+1] else: if ((upperline - underline) > 3): pos = (upperline + underline)/2 dif = upperline - underline if (dif > NotQuiteAsMax): if (dif > Max): posnotquiteasmax = posmax NotQuiteAsMax = Max posmax = pos Max = dif else: posnotquiteasmax = pos NotQuiteAsMax = dif currentblob = 'empty' if ((upperline - underline) > 3): pos = (upperline + underline)/2 dif = upperline - underline if (dif > NotQuiteAsMax): if (dif > Max): posnotquiteasmax = posmax NotQuiteAsMax = Max posmax = pos Max = dif else: posnotquiteasmax = pos NotQuiteAsMax = dif #######################ALGORITHMICDIVISION####################### # return angles to the found positions tupplepart1 = None
if posnotquiteasmax: tupplepart1 = calcxangle(posnotquiteasmax) + yawhead tupplepart2 = None if posmax: tupplepart2 = calcxangle(posmax) + yawhead if tupplepart1 or tupplepart2: return (tupplepart2, tupplepart1) # (closest, furthest) # return the angles
Referenser ten Velthuis, Duncan (2011) Dutch Nao Team Technical Report 2011. hämtat från: www.dutchnaoteam.nl/wp-content/uploads/2011/10/technicalreport.pdf ten Velthuis, Duncan (2011) Dutch Nao Team Team Description Paper for RoboCup 2011. Hämtat från: www.dutchnaoteam.nl/wp-content/uploads/2012/01/qualificationdutchnaoteam2012.pdf Petters, Sebastian (2009) Usage of Referee / Game Controller Software in the RoboCup Humanoid League. Hämtat från: www.dribblers.de/gc/ Alderaban Robotics - http://www.aldebaran-robotics.com