Start

Förstasidan
Statistik

Social robot

Robotens syn
Modell/simulator
Levande modell


Arduino

Starta upp Arduino
DCcduino UNO
Pro Mini

Raspberry pi

Om Raspberry

Pic32

Om Pic32
Konstruktionen
Praktisk kom-igång
Starta upp UBW32
Installera MPLAB
Rinnande ljus
Stegmotor
Display
RS232 Pic32 - terminal
Luffarschack

Servo

Överblick
Isärmonterat servo
Styrning av servo
Mini Maestro
Bygga ett servo

Elektronik

Open Collector
Kontaktstuds
Drivsteg på utgångarna
Halleffektsensor/switch
MLX90316 (halleffekt)
Pulsbreddsmodulering

Open CV

Om OpenCV

Matematik

Linjär algebra
Olinjär länkmekanism

Robotens syn
Stereoseende
robotsyn Poängen med 2 ögon är ju som bekant att vi får ett djupseende, stereoseende. På så vis kan vi avgöra vilka föremål som är nära och vilka som är långt ifrån oss. Stereosynen och avståndsbedömningen är främst en finess som fungerar bra på korta avstånd, dvs ungefär lagom för att fungera utmärkt med våra händer. På längre avstånd avtar förmågan att bedöma djupet. Vi använder då istället vår kunskap om föremåls storlek - känslan - för att avgöra var föremål befinner sig djupledes.
Den rörelse vi människor gör med våra ögon för att fokusera på ett föremål kan man kalla konvergensrörelse. Denna mekanism hos människan är en optisk reflex som sker omedvetet. Ögonen justerar sig individuellt och tittar på samma objekt i samma punkt; det objekt vi vill fokusera på. I teorin behöver inte ögonen fokusera i samma punkt för att få nödvändig data för att se djup (se längre ner om att kalkylera djup med fixerade ögon). Men att ögonen fokuserar i samma punkt innebär att ögonen i princip ser samma bild vilket kraftigt förenklar bearbetningen av informationen.

En inte helt oviktig detalj här är att ögonen kan röra sig individuellt i sidled. Men i höjdled rör sig båda ögon, på en frisk människa, parallellt. Det är extremt svårt, för att inte säga omöjligt, att röra bara ett öga uppåt och låta det andra titta rakt fram. ogonhallareMen varför skulle ögonen kunna göra dessa rörelser? Det behövs inte till något. Vet vi detta kan man också skala bort en del matematik och mekanik, då båda ögon alltid rör sig parallellt upp eller ner.

Jag tänker mig att denna justering av ögonen (kameramodulerna) kan ske på 2 sätt.

Ögonens konvergensvinklar
Trigonometrisk kalkyl, 2D-exempel (ovanifrån)
Flytta objektet som skall fokuseras (upp | ner | vänster | höger) och snurra på robotens huvud (moturs | medurs) med pilarna. Vinklarna som räknas ut är respektiva ögas konvergensvinkel, dvs de vinklar ögonen har för att fokusera objektet.

Data


Uträkning av viklarna gör jag på följande sätt
konvergensrorelser Om man namnger vinklarna som jag gjort här till höger så blir allting mycket lättare. Tyvär verkar det inte finnas någon textfunktion inbyggt i det javascript canvas -objekt som skapar ovanstående interaktiva skiss annars hade jag lagt in beteckningarna där.

Hursomhelst. Det är V1 och V2 som är intressanta att räkna ut givet att vi vet D (längd) och vinklarna VD samt VO. Vi vet också de fixa statiska avstånden till ögonen D1 och D2.

Cosinussatsen
cosinussatsen Först måste jag räkna ut längderna på C1F och C2F. Det gör jag med cosinussatsen. Därefter kan jag t.ex. använda sinunssatsen för att få ut vinklarna jag önskar.
a2 = b2+c2+2bc*COS(alfa)

Det betyder alltså applicerat på detta:
C1F=SQRT(D12+D2+2*D1*D*COS(180-VO))     respektive
C2F=SQRT(D22+D2+2*D2*D*COS(VO))

Sinussatsen
sinussatsen Därefter kan jag räkna ut V1 och V2 med hjälp av sinussatsen.

VDC2F=sin-1(D2*SIN(VO)/C2F)
V2=180-Vo-VDC2F
V2=180-Vo-sin-1(D2*SIN(VO)/C2F)

Anledningen till att jag räknar ut VDC2F först och sedan utnyttjar att summan av triangelns vinklar är 180 grader beror på att V2 resp. V1 ibland blir trubbiga. Det blir aldrig VDC1F eller VDC2F, eller låt säga sannolikt väldigt sällan. Återkommer till det. När V1 eller V2 blir trubbiga (större än 90 grader) så uppstår en flertydighet som resulterar i att man får fel vinkel. Studera bilden här nedan till höger. När vinkeln B blir större än 90 grader får man tillbaka en vinkel som är mindre än 90 grader (!?). Väldigt olustigt och ologiskt innan myntet trillar ner.

sinussatsen flertydighet För att vinklarna VDC1F eller VDC2F skall bli trubbiga måste man tvinga roboten att fokusera på ett föremål som mycket närmare än ögonavståndet. Så nära kommer inte kamerorna kunna fokusera ändå. Det är alltså hållbart att lita till att dessa vinklar alltid är spetsiga.

Linjär algebra rockar mer än 2D-trigonometri
Okej, ovanstående exempel var bara en kul grej. I verkligheten rör vi (och robotarna) oss i 3 dimensioner. Så därför har jag snickra ihop en 3D-modell med hjälp av linjär algebra. Här finns en ännu mer levande robotmodell men det är fortfarande bara exempel gjorda med javascript.


Hitta vektorn
Bilderna från ögonen skall analyseras så att roboten kan hitta ansikten och räkna ut fokusvektorer till de olika ansiktena. Poängen med att lagra vektorer till ansikten i rummet är att roboten snabbt kan fokusera dessa och att matematiken blir enkel.

Analysera inkommande bilder
Eftersom ögonen betraktar världen från lite olika perspektiv fångar de som bekant 2 olika bilder. Tittar man lite närmare på dessa bilder kan man konstatera att skillnaden mellan bilderna är beroende av djupet i bilderna. Säg att vi betraktar en solnedgång (man ska helst inte titta in i en sol, men detta är bara teori) där vi har ett konstigt träd med en spiral på toppen i förgrunden.
Vi kommer då att få in ovanstående 2 bilder i hjärnan. Solen som ligger väldigt bort i horisonten hamnar på samma ställe i båda ögon medans trädet i förgrunden hamnar på olika ställen.

Skulle vi lägga bilderna ovanpå varandra ser det ut ungefär som ovan. Träden hamnar på olika plats medans solen hamnar på samma plats. Lite pedagogisk geometri över detta gör eventuellt situationen mer lättbegriplig.

Vi fokuserar långt fram mot horisonten. Båda ögonen stirrar i prinip rakt fram och placerar samtidigt solen i centrum av ögonen. Detta samtidigt som trädet ligger nära och förutsätter ett helt annat fokus för att hamna i centrum.

Expriment för tvivlande
Du kan göra ett expriment för att övertyga dig att det verkligen är exakt såhär. Ställ dig ca 15 meter framför ett träd. Sedan håller du en pinne ca 20 cm mitt framför ögonen med handen. Håll hela tiden pinnen mitt framför ögonen samtidigt som du har trädet i bakgrunden.

Fokusera först på pinnen och fundera över vad du ser. Därefter flyttar du fokus till trädet längre bak och funderar över var du ser. Resultatet blir ungefär som nedan.

När du fokuserar på pinnen kommer pinnen synas skarpt och du kommer uppleva suddiga träd på vardera sidan om pinnen.


När du fokuserar på trädet kommer trädet synas skarpt i mitten och du kommer se suddiga pinner på vardera sidan om trädet.


Okej, låt säga vi övertygat oss själva att det är på detta vis. Hur kan man använda detta för att knacka kod som räknar ut avståndsvektorn? Saker och ting börjar klara här. Låt oss titta lite på indata vi har att jobba med.

Utdata från ansiktsdetektering
Kameramodulernas är kopplade till var sin processor som i allt väsentligt kör en algoritm för ansiktsdetektering. Jag tänker använda mig av opencv, som är färdig öppen källkod som innehåller redan optimerade versioner av de mest kända algoritmerna. Det är ju lite onödigt att uppfinna hjulet på nytt, speciellt som det troligtvis blivit ett mycket sämre hjul.

Utdata från opencv - för att göra en lång historia kort som finns beskriven på annat ställe på denna webbsida - är typiskt en lista med rektanglar. Dessa rektanglar är i själva verket detekterade ansikten, dvs det algoritmen tror är ett ansikte (att känna igen detta ansikte är ett senare problem).

Åtminståne i teorin bör båda kameramoduler detektera samma ansikten då det - bortsett från lite olika perspektiv på världen - kör exakt samma mjukvara. Vi borde alltså få data som ser ut ungefär som nedan. En större rektangel borde föreställa ett ansikte närmare oss och en mindre representerar ett ansikte längre bort.

Dvs, det ser troligtvis ut som nedan.


Man kan ju då fråga sig, vilket säkert du också gör, följande fråga: Okej, vi har ett antal rektanglar som indata. Om det bara finns en rektangel så representerar denna rektangel samma ansikte. Men om det finns flera personer i robotens blickfång, hur vet man då vilka rektanglar som hör ihop och inte - ifall man inte känner igen ansiktena? Jag klurade lite på detta och kom fram till att det finns en mycket enkel lösning. Jag påstår att det helt sonika är så att rektanglar med ungefär samma storlek är samma ansikte. Och, rektanglarna kommer att ha olika storlek då det inte rymms så många personer i robotens blickfång. När det gäller ansikten långt bort så spelar avståndet mindre roll. Begrunda bilden ovan t.ex. där vi stirrade mot solen i horisonten. Ansikten långt bort är inget fokuseringsproblem. Det är bara ansikten nära roboten som blir intressanta att fokusera på - och här borde storleken kunna fungera som sorteringsfunktion eftersom det inte rymms så många ansikten nära roboten. Utöver detta får roboten kanske sortera ansikten efter hur det förekommer från höger till vänster. Mer om detta längre ner.

Räkna på avståndet
Hur ser matematiken ut om vi vill räkna på avståndet? Ponera att vi fokuserar den röda rektangeln; båda ögon har vinklat sig för att fokusera dessa. Om vi vet respektive ögas vinkel, en vinkel som faktiskt är samma för båda ögon om huvudet är vänt mot objektet ifråga, då kan vi räkna ut avståndet med nedanstående matematik som för enkelhetens skull utgår ifrån att den horisontella vinkeln (höjdled) är liten.
Studerar man formeln för avståndet, C x Tan(x) / 2, inser man snabbt att det krävs väldigt exakt vinkelmätning för att få fram exakt avstånd. I praktiken kommer detta vara mycket svårt. Roboten kommer få gissa lite och sedan skapa ett medelvärde.

Djupberäkning med fixerade kameror
Lite kuriosa. Det är möjligt att skapa ett stereoseende utan att ögonen (kamerorna) rör på sig - dvs är fixerade och tittar parallellt rakt fram.

stereosyn perspektiv Matematiken bakom kallas triangulering. Man behöver veta kamerornas brännvidd, avståndet mellan de två kamerorna. Sedan behöver man en punkt i objektet (P) som man kan känna igen i båda bilderna. Denna punkt hamnar då i Pv respektive Ph i bilderna (se övre bilden). Vektorerna Zv och Zh är alltså de framåtriktade kamerornas riktning. Ur dessa bilder måste datorn sedan plocka fram Xv1 och Xh1 som är avstånden från origo på C1 och C2 till punkterna Pv respektive Ph (se nedre bild).

När så är gjort kan avståndet till P enkelt räknas ut enligt:

D = bf/(xh1+xv1)

En sådan här statisk setup med 2 stycken kameror används på många håll inom robotiken. Nu stereosyn matematikbygger jag ett robothuvud där båda ögon är rörliga så denna lösning är inget jag kommer grotta djupare i. Men teorin bakom hur djup beräknas med fixa kameror kan till viss del användas även för rörliga, jag återkommer till det längre ner.

Fokalavstånd (f) - vad är det?
Du har kanske sett en skiss över en kamera eller ett mänskligt öga i någon bok. Fokalavståndet är då avståndet från linsen till bildsensorn.
fokalavstånd
Jag kommer inte bry mig om något absolut fokalavstånd utan jag är bara intresserad av sambanden. Fokalavståndet kommer ligga inbakat i exprimentellt framställda konstanter i ekvationerna.





Robot och elektronik -sidan byter namn till electro.st

Senast läst 13:28:28 20/7 2017 Texten uppdaterad 17/9 2014
footer sign