Pendel
C#
TAO
Rune Wilhelm Dragsnes / Student 2005
Å tegne:>Invers pendel

Mikrobalansøren

Hva
Balansor1 Balansor2
Modellering av en invers pendel

Målet med dette prosjektet var å bruke teori fra min tidligere avlagte diplomoppgave ved NTNU med studieretning teknisk kybernetikk. Jeg hadde her som oppgave å modulere, simulere og implementere en invertert pendel og en optimalisert tilstandsregulator. Ved å benytte modeller og data fra denne oppgaven til å konstruere en simulator. Ved å gjøre dette får jeg en modell som oppfører seg nært en virkelig invertert pendel, noe som også klart kommer fram når man beveger pendelen i opengl applikasjonen.

Videre satte jeg meg som mål å benytte et 3D tegne program til å konstruere pendelen, jeg regner med dette er framgangsmåten ved mange større 3D prosjekter i opengl og ønsket derfor å få kompetanse innenfor dette området. Dette er et området som jeg fant meget interessant.

Som utviklingsplattform valgte jeg å benytte C#.NET, dette ble bevist gjort da jeg tidligere har avlagt et kurs i dette språket og ønsket dermed å holde dette vedlike. Jeg så det også som en utfordring å få OpenGL til å samspille med C#.NET.

Denne oppgaven består av tre deler.

  1. Lage en matematisk modell av pendelen og en tilstandsregulator. Til sammen vil disse matematiske modellene danne grunnlaget for at den inverterte pendelen skal gi så realistiske bevegelser som mulig
  2. Tegne modellen ved hjelp av 3DS max.
  3. Lage et program i Opengl vha C#.NET som benytter seg av data levert fra matematisk modell samt den tegnede modellen.

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.

Modell

Figur 1 Modell og Regulator

Hvor

Statespace

Figur 2 Tilstandsrommodell for pendel og regulator

For å 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).

3dsmax

Figur 3 3DS max med den inverterte pendelen

I 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 http://www.tb-software.com/download.html

3DWin

Figur 4 3DWin

Modellen 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).

pendulum

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 http://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.

PendelGL1

Figur 8 Pendel lastet inn i opengl

Det 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

PendelGL2

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

  1. Innføre muligheten for å forstørre bildet
  2. Vise pendelen i forskjellige vinduer samtidig
  3. legge til tekstur på plattformen pendelen kjører på
  4. 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.

PendelGL2

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.

PendelGL4

Figur 12 Det endelige resultatet for prosjektet

Referanser

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

Vedlikehold

Skrevet juni 2005, Rune Wilhelm Dragsnes
Tilpassing til std layout, Børre Stenseth, juli2005

(Velkommen) Å tegne:>Invers pendel (Fraktal terreng)