Bygga en robotarm för Science Olympiad (12 / 14 steg)
Steg 12: P.3, kod: omvänd kinematik och annan kod bitar
Först, vi ansåg inklusive omvända kinematiska beräkningar i vår Objective-C kod, men detta visade sig vara en dålig idé eftersom det finns massor av beräkningar att göra vid initiering, och efter de är gjort en gång, det finns ingen anledning att upprepa dem igen. Det faktum att objekt inte flytta runt är ju grunden för vår kontrollsystem. I stället vi hårdkoda vinklar.
En mycket viktig del av koden är en metod som kommer att sakta ner på armen som det att närma sig sin destination, i stället för knuffande det hela vägen och hoppas det inte börjar svänga (kanske i en perfekt värld med perfekta servon).
Först, vi Pausar körning för en liten tid att låta servo att flytta till vinkeln vi ge dem (första gången denna metod kallas, servo vilja inte ännu vara i rörelse):
[NSThread sleepForTimeInterval:0.03];
Nästa, vi jämför servo är nuvarande kantiga position till önskad slutposition - om det har nära nog (som vi definierat vara 2 grader), då anger du variabeln som lagrar den aktuella rotationsvinkel lika till önskad slutposition (du får se till detta är meningsfullt i en stund):
om (abs(targetAngle-angle) < = 2) {vinkel = targetAngle;}
Nu, beräkna en tiondel skillnaden mellan den aktuella rotationsvinkel och mål - om aktuella vinkeln är lika med vinkeln mål, då återgår noll:
dubbel diff = (targetAngle - vinkel) * 0.1;
Nu flytta servo till nuvarande kantiga position plus en tiondel skillnaden - om aktuella vinkeln är lika med vinkeln mål, detta kommer att orsaka servo att flytta hela vägen till målet vinkel:
[själv moveActualTo:(angle + diff)];
Se video beskrivningen nedan för att få en bättre förståelse för hur någon varför detta sker. Du kan hitta här koden i metoden calculateChange i Motor.m, som fästas som en del av en zip-fil i nästa steg.
Den första versionen av vår kod används endast elektromagneten (detta är vad vi tog till regionals - videon togs runt 06: 00 dag, efter en all-nighter att få det att fungera!) och såg ut ungefär så här:
YouTube video Beskrivning:
"Detta är den första fullständiga testet av våra robotarm för Massachusetts Science Olympiad. Vi hade en av koordinaterna fel i vårt program (Ja, det visade sig vara en programvaruproblem - mycket bättre än en slumpmässig "MOSFET inte aktivera" glitch!), så det inte gick att plocka upp en av spikarna, men vi fick den fast i tid för händelsen regionala senare samma dag och vann en jordskredsseger!
Ett av de problem vi hade tidigare (och många av lagen hade vid regionals) oscillerande servon och servon som rör alltför snabbt och svinga armen i oförutsägbara vägar. För att åtgärda detta, skrev vi en algoritm som saktar ner servon när de närmar sin slutdestination genom att ge dem en kontinuerlig ström av koordinater som är exponentiellt närmare och närmare mål vinkeln till servo är inom några delta, vanligtvis en eller två grader, i denna vinkel och nära nog för att bara gå direkt dit. Varje iteration beräknas genom att hitta en tiondel av den vinkel som servo återstår att resa för att slutföra steget. Istället för att använda rekursion har metoden vinkel-beräkning av kalla sig tills steget är klar, använde vilket är det självklara valet, vi en NSTimer i en egen tråd för att undvika att behöva lägga till förseningar i vårt program att hänga beräkningarna med servon (servon gå mycket långsammare än datorn kan spotta ut vinklar).
Anledningen till att vi använda exponentiell förruttnelse snarare än bara avtog linjär rörelse är att armen i huvudsak fungerar som en dämpad Harmonisk oscillator (om vi antar att den proportionella termen i servo är inre PID-regulator dominerar runt börvärdet, vilket verkar passa vad jag observerade när armen oscillerande), så om vi kör det linjärt, det kommer att börja med några inledande kinetisk energi när den är på resmålet och svänga runt det snarare än komma till ett stopp. Den enda lösningen (om vi insisterar på att köra det linjärt) är att bromsa armen för att minska amplituden av svängningen tills vi anser det acceptabelt, vilket inte är önskvärt när man betraktar detta som en begränsad konkurrens. Istället, om vi tvingar det till nästa vinkel med i ett exponentiellt ruttnande mönster, det bör komma det med väldigt lite rörelseenergi, med fel orsakade endast av faktumet att vi ger det diskreta data.
Varje position som servon måste nå beräknas använda omvänd kinematik och därefter justeras individuellt med hjälp av vårt program manuellt läge vara så korrekt som möjligt. En av de saker vi arbetar med för nästa månad är realtid inverse kinematic kontroll som gör det möjligt att flytta den arm slutet effektor i någon exakt väg som vi väljer, i stället för bara flytta servon till varje vinkel en i taget som vi gör nu.
Även om vi bara har en elektromagnet, och inte en universell gripdon eller klo, som man kan plocka upp föremål (vilket tvingade oss att lämna hälften av spelplanen orörda), automatisk kontroll innebär att denna arm kan plocka upp föremål snabbt och utan mänskliga fel, så att vi framgångsrikt placera 100% av objekt vi siktar på att placera varje gång vi kör armen."