Mikrobalansøren
Modulering og simulering
Som diplomoppgave i NTNU hadde jeg som oppgave å modulere og regulere en invertert pendel. Jeg har i denne oppgaven tenkt å benytte meg av disse matematiske modellene. Ved å gjøre dette vill pendel få et tilnærmet naturlig bevegelsesmønster da alle krefter som virker på modellen er tatt med i betraktningen. Modellen av pendelen med tilstandregulatoren K er vist i figur 1. Tanken er at denne modellen skal kjøres i en separat tråd med et definert grensesnitt mot OpenGL applikasjonen. Modellen vill ha to innganger, dette er den ønskede posisjonen som pendelen vill prøve å regulere seg inn mot samt en av/på tilstand for regulatoren. Modellen vill videre gi fra seg 4 tilstander som benyttes av opengl applikasjonen til å plassere pendelen riktig i rommet. Disse tilstandene er Posisjon, hastighet, vinkel og vinkelhastighet. Figur 1 viser hele modellen med et integratortrinn, pendel, posisjonstilbakekopling og en tilstandstilbakekopling, mens figur 2 viser de beregnede verdier som skal benyttes i simulatoren.
Figur 1 Modell og RegulatorHvor
Figur 2 Tilstandsrommodell for pendel og regulatorFor å se om modell og regulator oppfører seg som tiltenkt har jeg utviklet et testprogram (ikke opengl). Kjørbar fil finner du her(.net applikasjon): PendulumEngine.zip
Ved en rekke testkjøringer av programmet ovenfor konkluderte jeg med at simulator virket. Simulatoren er laget som et separat prosjekt som lar meg gjenbruke denne senere.
Simulator kode finner du her: simulator.html
Tegning av modell
Når man utvikler applikasjoner i ett 3D Api som OpenGl finner man fort ut at det er vannskapelig å konstruerer modeller. De enkle primitivene som støttes av apiet gjør dette nemmest umulig. Jeg har derfor i denne oppgaven valgt å utforske muligheten for å benytte et 3d tegne program til å tegne modellen av den inverterte pendelen. Mitt valg av program ble 3DS Max. Nedenfor ser du et bilde fra dette programmet med pendelen ferdig tegnet (Figur 3).
Figur 3 3DS max med den inverterte pendelenI dette tegneprogrammet finnes det mange plugins som benyttes til å eksportere tegningene til forskjellige formater, jeg gjorde et søk på nettet men klarte ikke å finne gratisversjoner som konverterte til opengl format i form av *.cpp filer el. Jeg ga ettervert opp dette søket og begynte å lete etter andre programmer som importerte 3ds max filer for så å eksportere til ønsket format. Jeg kom fram til et program som heter 3DWin, dette programmet kan bla. importere filer i max format og eksportere til opengl format i *.cpp form. Cpp filen inneholder alle vertices, normaler osv. lagret i tabeller. Figur 4 viser GUI for dette programmet, en link til programmet finner du her https://www.tb-software.com/download.html
Figur 4 3DWinModellen lagret i 3DS max format og den konverterte modellen finner du her: pendulum.zip
3DS max har mange muligheter utover bare å modulere. Man kan bla ta filmsekvenser av modellen og lagre disse i kjente fil formater som avi. Den roterende pendelen på denne siden er en generert avi fil. Man kan også ta bilder av modellen fra forskjellige vinkler og lagre disse i kjente filformater (Figur 5).
Figur 5 Modell tegnet i 3DS max:Den genererte cpp filen er i c++ format, så det ble en del redigering å gjøre før denne filen kunne brukes i en C# applikasjon (valgt språk for dette prosjektet). Dette var en form for arbeid jeg fraråder andre å gjøre. Jeg anbefaler derfor å lage et prosjekt i managed c++ for deretter å importere tabellene til et C# prosjekt under .net plattformen.
OpenGL Applikasjon
Som utviklingsplattform har jeg for dette prosjektet valgt Visual studio .NET med C# som programeringspråk. OpenGL støtter i utgangspunktet ikke C#.NET, men det finnes en rekke wrappere tilgjengelig som gjør det mulig å benytte opengl. Disse verktøyene finnes på nettet i mange varianter med forskjellig kvalitet, etter en del prøving og feiling fant jeg en levert av Tao. En link til denne finne du her https://www.mono-project.com/Tao
Har valgt å først laste inn modellen for så og gjøre noen enkle transformasjoner, rotere langs alle akser + rotere hjul
Modellene som ble eksportert fra 3ds max er lagret i form av tabeller. Tabellen er organisert etter de objektene som ble dannet i tegneprogrammet, vert objekt består av 4 tabeller. Tre av tabellen beskriver henholdsvis punkt, normal og material koordinater. Videre finnes det en fjerde tabell som gjør oppslag i disse matrisene, dette gjøres for å spare minneplass.
/Første pkt koordinater public float [] MotherBoardVertices ={-1.000003f, -25.500002f, 20.272049f , ...} // første normal koordinater public float [] MotherBoardNormals ={0.000000f, 0.000000f, -1.000000f ,...} // Første tekstur koordinater public float [] MotherBoardTextures={1.000000f, 0.000000f, 0.000000f ,...} // refererer til de tre overnevnte tabellene public int [] MotherBoardIndicies ={0, 2, 3 ,0, 0, 0 ,0, 2, 3 ,...}Figur 6 Eksempel på hovedkort objektet:
Indicies tabellen er bygd opp på følgende måte. De tre første elementene i tabellen (0, 2og 3) refererer til henholdsvis pkt 0, 2 og 3 i MotherBoardVertices tabellen, mens de tre niste elementene referer til tabellen for normalene. De siste tre elementene refererer til tekstur tabellen med tekstur koordinater. Så for vert 9 element i indicies i tabellen defineres et komplett polygon, dette gjentas til man kommer til siste element i indicies tabellen.
Rutinen som tegner polygonene blir dermed som følgende:
private void DrawObject(float Normal, int Indicies, float Vertices ); { int count = Indicies.Length/9; for (int i=0;i < count;i++) { for (int ind=0; ind < 3; ind++) { int indv = Indicies[i*9+ind]; int indn = Indicies[i*9+3+ind]; Gl.glNormal3f(Normal[indn*3+0],Normal[indn*3+1],Normal[indn*3+2]); Gl.glVertex3f(Vertices[indv*3+0],Vertices[indv*3+1],Vertices[indv*3+2]); } }Figur 7 Algoritme for innlesning av objekter generert 3DWin
Resultater fra første applikasjon finner du her Kode/PendulumGL_1.zip
For å kjøre dette programmet må du laste ned følgende assembly filer Tao.Platform.Windows.zip og plassere dem i samme katalog som programmet.
Figur 6 viser skjermbildet når dette programmet kjøres.
Figur 8 Pendel lastet inn i openglDet er nå klart for å implementere simulatoren i opengl applikasjonen, simulatoren ble tidligere verifisert til å fungere som tiltenkt. Simulator prosjektet ble derfor inkludert i pendel prosjektet og startet som en separat tråd. Denne tråden har en timer som kjører modellen vert 32 ms. Dette er nødvendig da den diskrete modellen er modulert etter dette. Videre er det innført noe støy i regulatoren i form av en random generator. Dette er gjort for å tilnærmer virkeligheten i en større grad. Uten denne støyen vil regulatoren regulere seg inn til en perfekt vertikal stilling.
Rotasjonen av hjulene er også i samsvar med bevegelsen langs bakken. Rotasjonen beregnes ved at man finner omkretsen til hjulene, når så pendelen tilbakelegger en strekning lik denne omkretsen skal hjulene rotere 360 grader. Formelen som benyttes er som følgende:
Vinkel hjul = (2*pi*radius/strekning)*360
Ved hjelp av scrollbars er det mulig å rotere hele plattformen pendelen står på samt sette den ønskede posisjonen pendelen skal regulere seg inn mot. Stor endring i ønsket posisjon vil gi store utslag på pendelen. Videre er det en check boks som slår regulatoren av/på. Hvis man slår av regulatoren vil pendelen tilte uten å prøve å regulere seg til stående stilling. Slår man på regulatoren vill den straks gi fult pådrag til motorene slik at pendelen igjen regulerer seg til stående og ønsket posisjon. Det er også mulig og slå av/på lyssettingen.
Videre er det to gruppebokser som indikerer tilstandene i simulatoren. Den ene boksen forteller om data som sendes til simulatoren, dette er om regulatoren skal være på/av og den ønskede posisjonen regulatoren skal regulere seg inn mot. Videre er det en boks som viser tilstandene som genereres i simulatoren som benyttes til å tegne pendelen. Det er her flere tilstander, men de som benyttes til å tegne pendelen er vinkel og posisjon.
Figur 7 viser applikasjonen med simulator inkludert
Kjørbar fil finner du her Pendulum2.zip. Du må laste ned de samme assembly filene som tidligere, disse finner du her Tao.Platform.Windows.zip
Figur 9 Opengl og Simulator ferdig integrert
Nå som alle elementer i prosjektet er ferdig er det tid for å forbedre de visuelle effektene, har derfor valgt å implementere følgende punkter
- Innføre muligheten for å forstørre bildet
- Vise pendelen i forskjellige vinduer samtidig
- legge til tekstur på plattformen pendelen kjører på
- Lage en markør som indikerer hvilken posisjon pendelen skal regulere seg inn til
Har valgt å dele opp visningen av pendelen i tre visnings vinduer. Hovedvinduet viser pendelen fra siden, her er kameraet satt til posisjon (Zoom,0,100), retning mot punktet (0,0,50) og z aksen som opp vektor. Zoom parameteren til kameraets posisjon er knyttet til en scrollbar slik at man kan bevege possisjonen langs x-aksen og får dermed muligheten til å forminske/forstørre pendelen. Man har også to mindre vinduer, disse har henholdsvis et kamera som følger pendelen fra siden og et som er satt opp til å se pendelen ovenfra. For både hovedvinduet og det mindre som ser pendelen ovenfra har jeg brukt GLU funksjonen gluLookAt for å sette kameraposisjonen, dette viste seg å være vanskelig å gjøre det samme for følge kameraet. Jeg benyttet her vanlig matriseoperasjoner for å sette kameraposisjonen, se figur 10.
//Roterer kameraet mot klokken om x-aksen Gl.glRotatef(90,1,0,0); //Roterer kameraet med klokken om y-aksen Gl.glRotatef(-180,0,1,0); // Roterer kameraet med klokken langs z-aksen Gl.glRotatef(-10,0,0,1); // Forflytter kameraet etter pendelens bevegelser Gl.glTranslatef(-ED.X1_K*200+50,-180,-50); //Kameraet må også ta hensyn til rotasjon av platform Gl.glRotatef(-(trackBarRoatatePlatform.Value-180),0,0,1);
Figur 10 Matriseopperasjoner for å sette kameraposisjon
Metoden jeg har brukt for å sette opp de tre vinduene er bruk av ViewPort støtten til GLU. I min draw funksjon kjører jeg gjennom tre løkker, en for vært vindu som setter opp kameraposisjon og ViewPort.
Videre har jeg implementert en tekstur på plattformen til pendelen, dette ble i hovedsak gjort for å vise tydelig at det var plattformen med pendelen som roterer, og ikke bare pendelen. Koden som her ble laget innbefatter lasting av bilde fra fil samt oppsett av tekstur.
Til slutt la jeg til en enkel markør som indikerer settpunktet til regulatoren. Dette er det punktet som pendelen vill svinge seg in mot. Dette punktet er bare ment som en visuell indikasjon på at pendelen virkelig svinger seg in mot ønsket posisjon.
Kjørbar fil finner du her Pendulum.zip. Du må laste ned de samme assembly filene som tidligere, disse finner du her Tao.Platform.Windows.zip
Figur 11 viser applikasjonen med tekstur, flere vinduer, zoom og markør.
Figur 11 Skjermdump
I foregående versjon av den inverterte pendelen ble simulator data vist vha standard windows komponenter som GroupBox og Label. Skal nå erstatte denne delen med 3D tekst generert vha opengl. For gjøre dette kan man benytte funksjonen wglUseFontOutlines(...), denne genererer en displayliste med bokstaver fra valgt fonttype. Lagde videre en funksjon som parser gjennom en tekst som skal skrives og gjør riktige oppslag i displaylisten for så å presentere teksten som en 3D tekst.
Det er også gjort endringer i forbindelse med når man endrer størrelsen på formen. Endres størrelsen nå skaleres vinduene deretter.
Figur 12 viser applikasjonen med de siste endringene som nevnt ovenfor. Dette er også det endelige resultatet og min vurdering og resultater presenteres i neste avsnitt.
Figur 12 Det endelige resultatet for prosjektet
Kode
Resultater fra prosjektet finner du nedenfor.
Program finner du her: Pendulum4.zip
Modell finner du her: ModelPendulum7.zip
OpenGL wrapper finner du her: Tao.Platform.Windows.zip
Kode finner du her: OpenGL_Pendel.zip