Presentation av obligatoriska uppgiften trafiksimulering Ett större program med flera klasser Hur man designar ett system Hur man gör simuleringar 1
Korsningen Dag hammarsköldsväg och Vårdsätravägen/Kungsängsleden Dag Hammarsköldsväg Polacksbacken Kungsängsleden Vårdsätravägen 2
Vårdsätravägen Korsningen Dag Hammarsköldsväg och Vårdsätravägen/Kungsängsleden Dag Hammarskölds väg Kungsängsleden Korsningen är kontrollerad av ljussignaler (s1,s2,s3,s4,s5,s6) 3
Uppgiften består i att simulera en förenklad korsning! Korsningen är kontrollerad av två ljussignaler (s1,s2) 4
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 (trafik)filerna kopplas ihop? Hur kopplas signaler och (trafik)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? 5
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 lane vid E. Fordon med destination W kör in i fil lanewest Fordon med destination S kör in i fil lanesouth Notera att filerna består av diskreta positioner, i varje sådan position finns ett fordon eller är tomt. 6
Klasser som behövs i trafiksystemet Vilka olika typer av objekt kan utkristalleras? 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 + en kö av inkommande fordon vid E + en variabel som samlar på sig data som man kan beräkna statistik från 7
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 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. 8
Om det i ett givet tidssteg var grönt ljus och ett fordon lämnat systemet så skall det 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 (driver) simuleringen och tidsstegningen av trafiksystemet. Finns att ladda ned från http://www.it.uu.se/edu/course/homepage/prog1/ht16/lessons/le10/tostudents/simulation.java Vi kikar på klassen Simulation. Den innehåller en mainmetod som sköter simuleringen, vi testkör den. 9
Vi ser i mainmetoden i klassen Simulation att det skapas ett TrafficSystem-objekt TrafficSystem tf = new TrafficSystem(); Att TrafficSystem har följande metoder: step() print() printstatistics() ty mainmetoden anropar dessa metoder. 10
Klassen Simulation har en s.k. klassvariabel Så här är den deklarerad 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() 11
Klassen Simulation tar hand om ett Exception Exekveringsfel (dvs programmet avbryts) beror på att ett fel har inträffat i programmet. Man kan man låta programmet ta hand om detta på ett någorlunda kontrollerbart sätt, istället för att 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()); re.printstacktrace(); } 12
Om det finns metoder där det kan inträffa fel 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 i try-blocket i mainmetoden i Simulation. re.getmessage() i Simulation innehåller den text som som metoden putlast genererat. 13
Hur gör man själva simuleringen när det gäller fordon som kommer in i korsningen vid E? Dvs hur genereras/produceras fordonen? Fordon måste ju komma in i korsningen med en viss frekvens (intensitet). 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 inom en tidsrymd ex.vis. 0-49 och denna tidsrymd kan delas in i ett antal tidsperioder, där varje tidsperiod är en del av tidsrymden 0-49. Exvis kan man ha två perioder: period 0 gäller för tiden 0-29, period 1 för tiden 30-49. 14
Hur gör man själva simuleringen när det gäller fordon som kommer in i korsningen vid E? Dvs hur genereras/produceras fordonen? Fordon måste ju komma in i korsningen med en viss frekvens (intensitet). I en simulering kan man låta detta styras av en modell som definierar hur fordon skapas, dvs kommer in i korsningen. I modellen kan man definiera den sannolikhet med vilken ett fordon skapas (kommer in i korsningen) Vi låter en variabel definiera sannolikheten. 15
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. 16
Sammantaget är modellen så här: Fordonsintensiteten är repetitiv, dvs samma mönster upprepas inom en tidsrymd 0-N (49) och denna tidsrymd delas in i ett antal tidsperioder. Exvis så här: Två st tidsperioder där period 0 gäller för tiden 0-29, period 1 för tiden 30-49. Om vi dessutom låter dessa båda sannolikheter bero på vilken period det är kan det se ut så här: Period time Arrival prob Turn prob 0 0-29 0.7 0.5 1 30-49 0.8 0.7 Styrs av java s Math.random() Man kan se det som att det finns två olika trafikströmningsperioder. I modellen finns en intern klocka som börjar med 0 och ökar med ett tills den blir 49, därefter slår den om till 0 igen. 17
En given klass VehicleGenerator skapar fordon enligt givna sannolikheter som modellen beskriven på föregående sidor Klassen finns att ladda ned från http://www.it.uu.se/edu/course/homepage/prog1/ht16/lessons/le10/tostudents/vehiclegenerator.java 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 instansvariabelrna turningprobabilities och arrivalprobalities påverkar trafikströmmen vad beträffar andelen som svänger eller kör rakt fram: Vi kikar på detta i step-metoden. 18
period : int greentime : int clock : int Light Instansvariabler Light( period :int, greentime : int) isgreen() : boolean step(): void; tostring() : String Ett trafikljus skall ha tre instansvariabler. (1) En periodicitet, dvs den färg trafikljuset skall visa upprepas periodiskt. (2) Ljuset har en egen klocka som styr hur ljuset växlar. (3) I en period skall ljuset vara grönt ett visst antal tidssteg och rött ett visst antal tidssteg. 19
Exempel med klassen Light : // period=5, varav grönt ljus 3 av 5 // Ljusets interna klocka är noll // Starta med grönt ljus Light s1 = new Light(5,3); System.out.println(s1.isGreen()); // blir true s1.step(); // Klockan blir ett System.out.println(s1.isGreen()); // 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 20
Vehicle destination : char borntime : int Instansvariabler Vehicle(destination:char) getdestination() : char gettime() : int tostring() : String Ett fordon skall ha en destination, dvs veta om den skall köra rakt fram eller svänga vänster i korsningen. Vid skapandet av en Vehicle skall det anges om fordonet skall svänga eller inte. Fordonet skall veta när den kom in i trafiksystemet (borntime) genom att konstruktorn anropar metoden för att få veta den globala klockan (Simulation.getTime()), dvs instansvariabeln borntime sätts till värdet av Simulation.getTime() 21
Exempel med klassen Vehicle: // Sätt den globala klockan till tiden noll. Simulation.setTime(0); // Skapa ett fordon som vid den tiden och // som skall köra rakt fram (västerut) i korsningen Vehicle v1 = new Vehicle('W'); // Sätt den globala klockan till tiden 1. Simulation.setTime(1); // Skapa ett fordon som vid den tiden och // som skall svänga vänster (söderut) i korningen Vehicle v2 = new Vehicle('S'); System.out.println(v1.getTime()); // 0 System.out.println(v1.getDestination()); // W 22
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 23
Lane thelane : Vehicle[] Lane( length : int) step() : void getfirst() : Vehicle removefirst() : Vehicle lastfree() : boolean putlast( v : Vehicle) tostring() : String Instansvariabel 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. 24
Exempel med klassen Lane: // Sätt den globala klockan till noll int time=0; Simulation.setTime(time); // Skapa en fil med plats för 5 st fordon Lane r = new Lane(5); // Skapa ett fordon vid tiden noll som skall köra rakt fram Vehicle v = new Vehicle('w'); // Placera detta fordon sist i filen // Notera, att vi vet att det finns plats sist i filen r.putlast(v); // Flytta fordonet i filen fyra(tids)steg framåt for (time=1;time<=4;time++) { Simulation.setTime(time); r.step(); } // Nu bör fordonet vara längst fram i filen // Vi låtsas att det är grönt ljus, tar därför bort fordonet. v = r.removefirst(); // Beräkna hur länge fordonet har legat i filen int spenttime = time - v.gettime(); // 5 25
Givna saker på kurswebben Vi kikar på kurswebben där finns Hela uppgiften beskriven i ett separat dokument Dokumentation (JavaDoc) av klasserna Light, Vehicle och Lane De färdiga klasserna Simulation VehicleGenerator Kodskal för: Light Vehicle Lane TrafficSystem 26
Att diskutera Vet ett fordon om var den befinner sig? Kan ett fordon titta framför sig och se vad som är framför i filen? Kan ett fordon se trafikljuset? 27
Arbetsgång Börja med att skriva klassen Light och testa den. Skriv och testa klassen Vehicle Skriv klassen Lane och testa den. 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 de tre av klasserna är uttestade så behöver du inte bekymra dig om dessa, utan bara använda dem. 28
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 29
Så här kan klassen TrafficSystem för det första testsystemet se ut i en version 0 där det hela tiden är grönt ljus public class TrafficSystem { private VehicleGenerator vg; private Lane [] lanewest; private Light lightwest; // Konstruktor för TrafficSystem public TrafficSystem() { // Konstruera VehicleGenerator-objektet this.vg = new VehicleGenerator(); // Filen tio positioner lång this.lanewest = new Lane(10); // Perioden 5, varav 5 gröna, dvs hela tiden grönt ljus int lightperiod=5, greentime=5; this.lightwest = new Light(lightPeriod,grenTime); } Fortsättning 30
Metoden step i klassen TrafficSystem // 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 Flytta fram alla fordonen en position i filen, dvs lanewest.step anropas Om VehicleGeneratorn vg genererar ett fordon dvs vg.step() har returnerat ett Vehicle-objekt: Placera in detta fordon sist i filen, men bara om det är ledigt där. Annars om det är upptaget, varna för detta i så fall. (anrop av lanewest.putlast) Stega trafikljuset */ } // slut på metoden step //... Andra metoder i TrafficSystem 31
Utskrifter Metoden print i klassen TrafficSystem skall skriva ut alla de värden som gör att vi kan se vad som händer i systemet. Metoden skall skriva ut ljusets värden och filens värden i varje tidssteg Exempelvis så här med ett trafikljus och EN fil tio lång: W Light: period=5,green=5,internaltime=4(g) <W WW > Trafikljusets värden Filens värden Ett trafikljus betecknat W, med perioden 5, gröntid=5, vars interna klocka är 4 och ljuset visar Grönt därav (G). Filen visas som <W WW > dvs tio positioner, det finns fordon i 1:a, 8:e och 9:e positionen. Alla dessa fordon skall köra rakt fram, därav värdet W. 32
Version 1 av det första testsystemet där det är omväxlande grönt och rött ljus Ändra delar av konstruktorn i TrafficSystem enligt: // Perioden 5, varav 3 gröna (och 2 röda) int lightperiod=5, greentime=3; this.lightwest = new Light(lightPeriod,grenTime); Testa att systemet i denna version fungerar Utmana systemet genom att ändra till // Perioden 5, varav 2 gröna (och 3 röda) int lightperiod=5, greentime=2; this.lightwest = new Light(lightPeriod,grenTime); Testa systemet Utmana systemet ytterligare genom att ändra till // Perioden 5, varav 1 grön (och 4 röda) int lightperiod=5, greentime=1; this.lightwest = new Light(lightPeriod,grenTime); Testa systemet 33
Statistik som skall beräknas i det första testsystemet När du ser att det första testsystemet fungerar, bygg på det med att beräkna statistik. Data för statistiken fås genom att varje gång ett fordon lämnar korsningen beräknas hur länge fordonet varit i korsning. Bl.a. genomsnittlig tid för fordon och maximal tid för ett fordon att passera korsningen. Använd klassen Measurements för att samla på mätvärden så att man kan beräkna denna statistik. Det innebär att trafiksystemet i det första testsystemet innehåller en instansvariabel som är ett Measurementsobjekt. Statitik skall beräknas och skrivas ut av metoden printstatistics i klassen TrafficSystem. Tips: I version 0 är filen10 lång och ljuset är grönt hela tiden, då bör alla fordon vara i filen 10 st tidssteg. Det är ett exempel på den statistik som skall beräknas av metoden printstatistics i klassen TrafficSystem. Det blir då enkelt att bekräfta att den statistik som beräknas blir korrekt. 34
Det fullständiga programmet Tre filer och en inkommande kö av skapade bilar vid pkt E. Denna kö kan lösas som en ArrayList av Vehicle. Filerna är av fix längd. Två st trafikljus som har fixa data. Tips: Börja med en förenkling där båda ljusen är gröna hela tiden, så att du ser att det blir ett flöde av fordon genom hela systemet i filerna och utan några som helst hinder. 35
Statistik från en körning av det fullständiga programmet: genomsnittliga och maximala tider (antal tidssteg) för fordon att passera ljussignalen lightwest respektive lightsouth, andel tidssteg som kön framför vardera signalen varit längre än längden på lanewest och lanesouth dvs den tid som fildelningen vid X varit blockerad av kö (för att beräkna detta behöver man räkna antal tidssteg som det ej gick att lägga ett fordon i lanewest resp lanesouth därför att sista positionen var upptagen) andel tidssteg som det funnits fordon i kön vid entrypunkten (E). Samla tiderna för fordon som lämnar systemet i två Measurements-objekt ett för vardera utgång, för att ta fram statistiken 36
Notera uppgiften finns beskriven till fullo på http://www.it.uu.se/edu/course/homepage/prog1/ht16/lessons/le10/ I synnerhet i dokumentet: http://www.it.uu.se/edu/course/homepage/prog1/ht16/lessons/le10/ou5.pdf 37