Presentation av obligatoriska uppgiften trafiksimulering Ett lite större program med flera klasser Hur man designar ett system Hur man gör simuleringar 1
Valsätr ravägen Korsningen Dag hammarsköldsväg och Valsätravägen/Kungsängsleden Dag Hammarskölds väg Kungs sängslede en Korsningen är kontrollerad av ljussignaler (s1,s2,s3,s4,s5,s6) 2
Uppgiften består i att simulera en förenklad korsning! Korsningen är kontrollerad av två ljussignaler (s1,s2) 3
Vi kommer att ta upp följande... Hur gör man en simulering? Vilka förenklingar av verkligheten gör man i simuleringen? Vilka klasser behövs? Hur skall filer kopplas ihop? Hur kopplas signaler och filer? Vilka indata behövs? Vem hanterar indata? Hur går tidsstegningen till? Vilka objekt bör känna till tiden? Var samlas statistiken? Vad skall skrivas ut, när och av vem? 4
Implementation av den förenklade korsningen (trafiksystemet) Det behövs tre st filer och två st signaler för denna implementation Fordon kommer in i korsningen i en fil r0 vid E. Fordon med destination W kör in i fil r1 Fordon med destination S kör in i fil r2 Notera att filerna består av diskreta positioner, i varje sådan position finns ett fordon eller är tomt. 5
Klasser som behövs i trafiksystemet Vilka olika typer av objekt kan utkristalleras? t Jo, följande delar behövs i trafiksystemet: Vehicle: Representerar ett fordon Light: Representerar en trafiksignal Lane: Representerar en fil Dessutom behövs en klass som utgör själva trafiksystemet som består av ovan tre delar (klasser). TrafficSystem: o Tre Lane-arrayer av Vehicle o Två st Light-objekt 6
Hur gör man simuleringen? Jo, allt måste styras av en global klocka. Denna tickar ett tidssteg i taget: Vid starten för simuleringen (t=0) har hela trafiksystemet initiala värden: Inga fordon finns i systemet, trafikljusen visar grönt. I nästa steg, t=1 skall trafiksystemet stegas, dvs trafikljusen skall också stegas i deras repetitiva beteende (och kanske k slå om ljuset). Dessutom skall fordon i filerna röra sig framåt (om möjligt) och det skall kontrolleras om ett nytt fordon kommer in (föds) vid punkten E. När fordonet föds måste vi se till att fordonet kommer ihåg tiden. 7
Om det i ett givet tidssteg var grönt ljus och ett fordon lämnat systemet så skall bokföras (dvs tidsvärdet), man kan därmed beräkna hur lång tid det tog för fordonet att passera korsningen. Tidstegningen kan göras hur många ggr som helst Det finns en given klass Simulation som sköter om simuleringen och tidsstegningen av trafiksystemet. Finns att ladda ned från http://www.it.uu.se/edu/course/homepage/prog1/ht14/lessons/lektion10/ Vi kikar på klassen Simulation. Och testkör mainmetoden. 8
Klassen Simulation har en s.k. klassvariabel Så här är den deklarerad d private static int time = 0; Mainmetoden i Simulation använder den för styra den globala tiden i en tidsloop. Andra metoder i andra klasser som behöver veta den globala tiden får använda klassmetoden gettime. Ett anrop av metoden är: Simulation.getTime(); Notera att klassmetoder anropas genom att skriva klassens namn framför punkten. Jämför: Math.random() 9
Klassen Simulation tar hand om ett Exception Exekveringsfel (dvs programmet avbryts) beror ofta på att en exceptionell händelse inträffat i programmet. Man kan man låta programmet ta hand om detta på ett någorlunda kontrollerbart sätt. Att jämföra med om det uppstår ett programavbrott Vi ser att det i klassen Simulation står: try {... // I denna del kan ett Exception inträffa } catch (RuntimeException re) { // Take care of occured exceptions System.out.println("******* " + re.getmessage()); g } 10
Om det finns metoder där det kan inträffa exceptionella händelser så kan dessa kasta ifrån sig ett sådant. T.ex. så här i en metod putlast i klassen Lane. Där vi skall placera ett fordon sist i filen public void putlast(vehicle v) throws RuntimeException { // Om sista positionen i filen är ledig... // placera fordonet v där // Annars: // System.out.println("Alt: Skriv ett meddelande."); throw new RuntimeException ("Lane, putlast: position is occupied"); } Detta exception fångas upp av den metod som gör try... catch på denna händelse, dvs mainmetoden i Simulation. re.getmessage() i Simulation innehåller den text som som metoden genererat. 11
Hur gör man själva simuleringen när det gäller fordon som kommer in i korsningen vid E? Fordon måste ju komma in i korsningen med en viss frekvens (intensitet)? it t)? I en simulering kan man låta detta styras av en modell som definierar hur fordon skapas, dvs kommer in i korsningen. Modellen kan vara så här: Fordonsintensiteten är repetitiv, dvs samma mönster upprepas ínom en tidsrymd 0-59 och denna tidsrymd delas in i fyra tidsperioder, i d där period 0 gäller för tiden 0-29, period 1 för tiden 30-39, period 2 för tiden 40-49 och period 3 för tiden 50-59 59. 12
I modellen kan man definiera den sannolikhet med vilken ett fordon skapas (kommer in i korsningen) så här: Period 0, dvs tiden 0-29: Sannolikhet för ett fordon 0.2 Period 1, dvs tiden 30-39: Sannolikhet för ett fordon 0.7 Period 2, dvs tiden 40-49: Sannolikhet för ett fordon 0.9 Period 3, dvs tiden 50-59: Sannolikhet för ett fordon 0.7 En slumpgenerator (Math.random) avgör tillsammans med perioden om ett fordon dyker upp. Man kan se det som att det finns fyra olika trafikströmningsperioder. I modellen finns en intern klocka som börjar med 0 och ökar med ett tills den blir 59, därefter slår den om till 0 igen. 13
Hur simulera att bilen skall köra rakt fram eller svänga vänster? Det kan också göras med en slumpgenerator: Om ett fordon skapats (kommer in i korsningen vid E) så skall fordonet veta om att den skall svänga vänster, annars köra rakt fram. Vilket görs med en slumpgenerator när fordonet skapas. 14
En given klass VehicleGenerator skapar fordon enligt modellen beskriven på föregående sidor Klassen finns att ladda ned från http://www.it.uu.se/edu/course/homepage/prog1/ht14/lessons/lektion10/ Så det behöver ni inte bekymra er om... Vi kikar på den givna klassen VehicleGenerator Och testkör en mainmetod som använder klassen. Notera att instansvariabeln turnintensity påverkar trafikströmmen tö vad dbeträffar täff andelen som svänger eller kör rakt fram 15
period : int greentime : int clock : int Light Light( period :int, greentime : int) isgreen() : boolean step(): void; tostring() : String Ett trafikljus skall ha en periodicitet, dvs den färg trafikljuset skall visa upprepas periodiskt. Ljuset har en egen klocka som styr hur ljuset växlar. I en period skall ljuset vara grönt ett visst antal tidssteg t och rött ett visst antal tidssteg. t 16
Exempel med klassen Light : // period=5 5, varav grönt ljus 3 av 5 // Ljusets interna klocka är noll // Starta med grön ljus Light s1 = new Light(5,3); System.out.println(s1.isGreen()); // blir true s1.step(); // Klockan blir ett System.out.println(s1.isGreen()); i ()) // blir true s1.step(); // Klockan blir två System.out.println(s1.isGreen()); // blir true s1.step(); System.out.println(s1.isGreen()); // blir false s1.step(); System.out.println(s1.isGreen()); // blir false // Perioden är klar och en ny period inleds // och ljusets klocka slår om till noll s1.step(); System.out.println(s1.isGreen()); // blir true 17
Vehicle destination : char borntime : int exittime : int Vehicle( destination:char, borntime:int) getdestination() : char getborntime() : int getspenttime() : int getexittime() : int setexittime( exittime:int) : void tostring() : String Ett fordon skall ha en destination, dvs veta om den skall köra rakt fram eller svänga vänster i korsningen. Fordonet skall veta när den kom in i trafiksystemet (borntime). Den vet dessutom om när den lämnar trafiksystemet (exittime), detta gör att man kan beräkna hur länge fordonet varit i korsningen (getspenttime). 18
Exempel med klassen Vehicle: // Skapa ett fordon tiden noll. // Skall köra rakt fram i korsningen Vehicle v1 = new Vehicle('W',0); // Skapa ett annat fordon tiden 2. // Skall svänga vänster i korsningen Vehicle v2 = new Vehicle('S',2); //... // Fordonet lämnar korsningen vid tiden 15 v1.setexittime(15); // metoden spenttime returnerar 15-0 = 15 System.out.println( v1.spenttime() ); // Fordonet lämnar korsningen vid tiden 25 v2.setexittime(25); // metoden spenttime returnerar 25-2=23 System.out.println( v2.spenttime() ); 19
Klassen Lane En fil består av positioner som antingen kan innehålla ett fordon eller vara tom. Vad skall ske på en fil? Fordon kan avancera till platsen framför Fordon kan lämna från första position (dvs längst fram i filen) Fordon kan anlända till sista position Måste kunna titta på första positionen för att se om det är ett fordon som skall lämna filen Måste kunna avgöra om sista positionen är ledig 20
Lane thelane : Vehicle[]; Lane( length : int) step() : void getfirst() : Vehicle removefirst() : Vehicle lastfree() : boolean putlast( v : Vehicle); tostring() : String En fil består av en väg med fordon. Vägen är indelad i positioner där det kan finnas ett fordon eller vara tomt. När kön med bilar rör sig framåt flyttas fordonen från en position till nästa. Tips: Använd en array eller en ArrayList för att representera ett Lane-objekt 21
Exempel med klassen Lane: // Skapa en fil med plats för 5 st fordon Lane r = new Lane(5); // Skapa ett fordon tiden noll och som skall // köra rakt fram int tid=0; Vehicle v = new Vehicle('w',tid); // Placera detta fordon sist i filen // Notera, att vi vet det finns plats sist i filen r.putlast(v); // Flytta fordonet i filen fyra(tids)steg framåt for (tid=1;i<=4;i++) { r.step(); } // Nu bör fordonet vara längst fram i filen // Vi låtsas att det är grönt ljus och plockar // därför bort fordonet och bokför när fordonet // lämnar korsningen v = r.removefirst(); removefirst(); v.setexittime(tid); 22
Att diskutera Vet ett fordon om var den befinner sig? Kan ett fordon titta framför fö sig och se vad som är framför i filen? Kan ett fordon se trafikljuset? 23
Arbetsgång Börja med att skriva klassen Light och testa den. Det finns ett givet testprogram. Skriv och testa klassen Vehicle. Det finns ett givet testprogram. Skriv klassen Lane och testa den med ett givet testprogram. När dessa tre klasser är skrivna och uttestade, så kan du gå vidare i uppgiften som kommer använda de tre klasserna i ett första testsystem, se nästa sida. I och med att tre av klasserna är uttestade så behöver du inte bekymra dig om dessa, utan bara använda dem. 24
Ett första testsystem Börja med att få detta förenklade system att fungera först I denna implementation räcker det med ett Lane-objekt och ett Light-objekt Klassen TrafficSystem som har koll på detta system består alltså av: Ett Lane-objekt Ett Light-objekt Ett VehicleGenerator-objekt 25
Så här kan klassen för det första testsystemet se ut public class TrafficSystem { private VehicleGenerator vg; private Lane r1; private Light s1; // Konstruktor för TrafficSystem public TrafficSystem(VehicleGenerator vg) { this.vg = vg; this.r1 = new Lane(10); // Filen tio positioner lång this.s1 = new Light(5,3); // Perioden 5, varav 3 gröna } Fortsättning 26
// Denna metod utför ett tidssteg i systemet public void step() { /* Om grönt ljus: Om det finns ett fordon längst fram i filen, så ta bort det från filen och spara aktuell tid i detta fordon (setexittime). Spar det bortagna fordonet i en lämplig variabel för att senare kunna beräkna statistik för alla borttagna. Flytta fram fordonen en position i filen, de som går att flytta Om VehicleGeneratorn har genererat ett fordon: Placera in detta fordon sist i filen, men bara om det är ledigt där. Om det är upptaget, generera ett exception */ } // step // Andra metoder... } // TraficSystem 27
Statistik som skall beräknas i det första testsystemet Genomsnittlig tid (antal tidssteg) och maximal tid för ett fordon att passera korsningen Tips I det första testsystemet med bara en fil och trafikljus, börja med följande enkla modell: Låt filen bestå av 5 positioner och låt ljuset vara grönt hela tiden då bör värdet på spenttime för alla fordon bli 5. 28