/************************************************************************************ * Copyright (C) 2008 by Politehnica University of Bucharest and Rutgers University * All rights reserved. * Refer to LICENSE for terms and conditions of use. ***********************************************************************************/ package vnsim.applications.adaptiveTL; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Serializable; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.TreeMap; import vnsim.applications.trafficview.SimulatedCarInfo; import vnsim.core.*; import vnsim.core.events.ReceiveEvent; import vnsim.core.events.SendEvent; import vnsim.core.events.UnicastSendEvent; import vnsim.map.object.*; import vnsim.map.utils.GPSutil; import vnsim.network.RadioDev; import vnsim.vehicular.routePlan.RoutingConstants; import vnsim.vehicular.simulator.intersections.*; public class WirelessTrafficLight extends IntersectionWithTrafficLights implements Communicator{ private static final long serialVersionUID = 8724226247069906455L; public final static byte PROT_RESERVED = 0; public static final double LOW_SPEED = 5.0; // km/h public static final double MAX_QUEUE_GAP = 0.02; // km public ArrayList trafficDB = new ArrayList(); public ArrayList intersectionCars = new ArrayList(); public Integer DBmutex = new Integer(0); // public ArrayList newLightInfos; public int newCycleLength; public int phases; int lastMediumTransmission; public LinkedList receiveEvents = new LinkedList(); public TreeMap messagePeriods = new TreeMap(); boolean promiscuousMode; public static boolean adaptive = true; // public LinkedList lastHourHistory = new LinkedList(); protected boolean initialized = false; final static int CRTDIR = 0; final static int OPPDIR = 1; private final RadioDev radio = new RadioDev(this); public void init(){ for (int i = 0; i < segments.size(); i++){ DirectedRoadSegment seg = segments.get(i); seg.segmentIndex = i; seg.intersection = this; Road r1 = Globals.map.roads.get(seg.roadIndex); seg.endOfQueue = new IntersectionCarRecord[r1.laneNo + 1];//new ArrayList(r1.laneNo); seg.queueDischargeRate = new double[r1.laneNo+1]; for (int j = 0; j <= r1.laneNo; j++){ seg.endOfQueue[j] = new IntersectionCarRecord(null); seg.queueDischargeRate[j] = -1; } if (seg.isExitOnly()) continue; for (int j = 0; j < segments.size(); j++){ if (i != j && !segments.get(j).isEntryOnly()){ seg.paths.add(new IntersectionPath(this, seg, segments.get(j))); } } Intersection intersection = null; if(seg.direction) { for(int k=0; k < r1.crosses.size();k++) { if(r1.crosses.get(k).getPointIndex() > seg.pointIndex) { //that's the next cross intersection=Globals.map.allIntersections.get(r1.crosses.get(k).intersectionIndex); seg.nextwtlPointIndex = r1.crosses.get(k).getPointIndex(); break; } } } else { for(int k = r1.crosses.size()-1; k >= 0; k--) { if(r1.crosses.get(k).getPointIndex() < seg.pointIndex) { //that's the next cross intersection=Globals.map.allIntersections.get(r1.crosses.get(k).intersectionIndex); seg.nextwtlPointIndex = r1.crosses.get(k).getPointIndex(); break; } } } if (intersection == null){ seg.nextwtl = null; } if (intersection instanceof WirelessTrafficLight){ seg.nextwtl = (WirelessTrafficLight)intersection; } } } public void computeNextSignalPlan(int crtTime){ if (crtTime < 3 * Globals.MINUTE){ newCycleLength = cycleLength; for( int j = 0; j < segments.size(); j++ ) { segments.get(j).setNewLightInfo(segments.get(j).getLightInfo()); } return; } if (adaptive){ int interGreenTime = 0; interGreenTime = Globals.DEFAULT_YELLOW_TIME + Globals.DEFAULT_ALL_RED; int green=30; int time=0, j, lostTime = 0; double Y = 0, ycr = 0; int[] v = new int[segments.size()]; double[] yc = new double[segments.size()]; for( j = 0; j < segments.size(); j++ ) v[j] = 0; // CALCULATE SUM OF CRITICAL FLOW RATIOS if (Globals.map.allIntersections.size() >= 2) if(this.equals(Globals.map.allIntersections.get(1))){ v[0] = 0; } // System.out.println("%%%%%%%%%% The intersections"); // System.out.println(Globals.map.allIntersections.toString()); phases = 0; for( j = 0; j < segments.size(); j++ ) { DirectedRoadSegment seg1 = segments.get(j); if (v[j] == 1) continue; phases ++; if (!seg1.isExitOnly()){ double satflow = Globals.SATURATION_FLOW * seg1.road.laneNo; // if (segments.get(j).road.laneNo > 1) // satflow -= 300; double correction = 0; if (seg1.demand > seg1.totalVolume) correction = (double)(seg1.demand - seg1.totalVolume); yc[j] = (double)(seg1.demand + seg1.carryOver) / satflow; }else{ yc[j] = 0; } v[seg1.segmentIndex] = 1; /*if (Globals.map.roads.get(0).getName().startsWith("Iuliu")){ if (j < 2) seg1.pair = seg1.front; else{ seg1.pair = null; } }else*/{ seg1.pair = seg1.front; if (seg1.front != null) seg1.front.pair = seg1; } DirectedRoadSegment seg2 = seg1.pair; if (seg2 == null){ Y += yc[j]; continue; }else{ if (!seg2.isExitOnly()){ double satflow = Globals.SATURATION_FLOW * seg2.road.laneNo; // if (segments.get(j).road.laneNo > 1) // satflow -= 300; double correction = 0; if (seg2.demand > seg2.totalVolume) correction = (double)(seg2.demand - seg2.totalVolume); yc[seg2.segmentIndex] = (double)(seg2.demand + seg2.carryOver) / satflow; }else{ yc[seg2.segmentIndex] = 0; } } ycr = yc[j]; if (ycr < yc[seg2.segmentIndex]){ ycr = yc[seg2.segmentIndex]; yc[j] = ycr; }else{ yc[seg2.segmentIndex] = ycr; } Y += ycr; v[seg2.segmentIndex] = 1; } // CALCULATE CYCLE LENGTH WITH WEBSTER EQUATION if (Y >= 1){ newCycleLength = Globals.MAXIMUM_CYCLE_LENGTH; }else{ lostTime = (int)Math.ceil((double)segments.size() / 2) * interGreenTime; //Webster's equation newCycleLength = (int)((double)(1.5 * lostTime + 5) / (1 - Globals.Xc * Y)); // newCycleLength = (int)(2.0 * newCycleLength); if (newCycleLength > Globals.MAXIMUM_CYCLE_LENGTH || newCycleLength < 0) newCycleLength = Globals.MAXIMUM_CYCLE_LENGTH; } if (Globals.monitorWTL != null && this.equals(Globals.monitorWTL)){ Globals.pw.print(crtTime/Globals.SECOND + " "); } //COMPUTE GREEN SPLITS // newLightInfos = new ArrayList(); double extra = 0, grprop; double maxIncreaseProp = 1; int[] greens = new int[segments.size()]; double[] increaseProp = new double[segments.size()]; int count = 0, sum = 0, dec = 0; for(j=0;j maxPedestrianTime){ maxPedestrianTime = (int)seg.left.pedestrianCrossingTime; } if (seg.right != null && seg.right.pedestrianCrossingTime > maxPedestrianTime){ maxPedestrianTime = (int)seg.right.pedestrianCrossingTime; } // compare to minimum accepted green int mingreen = (int)(maxPedestrianTime + (double)Globals.MIN_WALK_LIGHT_TIME/Globals.SECOND); // System.out.println("MaxPedestrianTime [ "+j+" ] " + mingreen); increaseProp[j] = 0; if (green + interGreenTime < mingreen){ increaseProp[j] = (double)(mingreen - interGreenTime) / greens[j]; // System.out.println("Increase [ "+j+" ] " + increaseProp[j]); if (maxIncreaseProp < increaseProp[j]) maxIncreaseProp = increaseProp[j]; } } for( j = 0; j < segments.size(); j++ ) v[j] = 0; for(j=0;j 0){ greens[j] = (int)Math.round(maxIncreaseProp * greens[j]); } if ( increaseProp[j] == 0){ count ++; } sum += greens[j] + interGreenTime; v[seg1.segmentIndex] = 1; DirectedRoadSegment seg2 = seg1.pair; if (seg2 != null){ if (maxIncreaseProp > 0){ greens[seg2.segmentIndex] = (int)Math.round(maxIncreaseProp * greens[j]); } v[seg2.segmentIndex] = 1; } // System.out.println("NewGreens [ "+j+" ] " + greens[j]); } if (sum > Globals.MAXIMUM_CYCLE_LENGTH){ dec = (int)Math.ceil((double)(sum - Globals.MAXIMUM_CYCLE_LENGTH)/count); } for( j = 0; j < segments.size(); j++ ) v[j] = 0; //SET FINAL TIMING PLANS for( j = 0; j < segments.size(); j++ ) { DirectedRoadSegment seg1 = segments.get(j); if (v[j] == 1) continue; if ( increaseProp[j] == 0 && dec > 0) greens[j] -= dec; if (!seg1.isExitOnly()){ seg1.setNewLightInfo(new TrafficLightInfo(time, time + greens[j])); }else{ seg1.setNewLightInfo(new TrafficLightInfo(time, time)); } v[seg1.segmentIndex] = 1; DirectedRoadSegment seg2 = seg1.pair; if (seg2 != null){ v[seg2.segmentIndex] = 1; greens[seg2.segmentIndex] = greens[j]; if (!seg2.isExitOnly()){ seg2.setNewLightInfo(new TrafficLightInfo(time, time + greens[j])); }else{ seg2.setNewLightInfo(new TrafficLightInfo(time, time)); } } if (Globals.monitorWTL != null && this.equals(Globals.monitorWTL)){ Globals.pw.print(" " +time +" " + (time + greens[j]) +" "); } time = time + greens[j] + interGreenTime; } newCycleLength = time;//Math.ceil(extra); if (Globals.monitorWTL != null && this.equals(Globals.monitorWTL)){ Globals.pw.print(" "+newCycleLength + " s "); Globals.pw.print(" MaxInc " + maxIncreaseProp+"; \n"); Globals.pw.flush(); } }else{ newCycleLength = cycleLength; for( int j = 0; j < segments.size(); j++ ) { segments.get(j).setNewLightInfo(segments.get(j).getLightInfo()); } } } public void extendGreen(int t, int secs, DirectedRoadSegment segment){ Globals.pw.print("Green Extension\t"); TrafficLightInfo tli = segment.getLightInfo(); if (secs > (tli.greenEnd - tli.greenStart)/2) secs = (tli.greenEnd - tli.greenStart)/2; for(int j = 0; j < segments.size(); j++ ) { DirectedRoadSegment seg = segments.get(j); tli = seg.getLightInfo(); if (t < tli.yellowStart) seg.setLightInfo(new TrafficLightInfo(tli.greenStart + secs, tli.greenEnd + secs)); if (seg.equals(segment)) seg.setLightInfo(new TrafficLightInfo(tli.greenStart, tli.greenEnd + secs)); tli = seg.getLightInfo(); Globals.pw.print(" " +tli.greenStart +" " + tli.greenEnd +" "); } cycleLength += secs; Globals.pw.println(" "+cycleLength + " s"); Globals.pw.flush(); } int changeTime = -1; public void step(int crtTime){ if (!initialized){ initialized = true; init(); } //recommend speeds to cars // scheduleSingleSendEvent(1, Globals.PROT_TL_FEEDBACK); if (crtTime % (10 * Globals.SECOND) == 0){ for (int k = 0; k < this.segments.size(); k++) { DirectedRoadSegment seg = segments.get(k); seg.recordQueueSize(); } /*//broadcast feedback if (Engine.simulationType == RoutingConstants.DYNAMIC_CITY_ROUTE) { scheduleSingleSendEvent(0, Globals.PROT_TL_FEEDBACK); }*/ } // compute the next cycle signal plan with 2 seconds before switching if (crtTime == lastCycleStartTime + cycleLength * Globals.SECOND - 2 * Globals.SECOND){ if (Globals.monitorWTL != null && this.equals(Globals.monitorWTL)){ Globals.pw.println("\n"+crtTime/Globals.SECOND + "s ) WTL"); } int dem = 0, vol = 0; double stops = 0; for (int k = 0; k < this.segments.size(); k++) { DirectedRoadSegment seg = segments.get(k); dem = seg.computeDemand(Globals.ANALYSIS_PERIOD); vol = seg.computeVolume(Globals.ANALYSIS_PERIOD); stops = seg.noOfStops; int analysisPeriod = Globals.ANALYSIS_PERIOD; if (Globals.ANALYSIS_PERIOD < crtTime){ analysisPeriod = crtTime; } // if (dem > vol){ seg.carryOver += (int)((double)(dem - vol) * (double)(cycleLength * Globals.SECOND) / analysisPeriod); if (seg.carryOver < 0) seg.carryOver = 0; // }else{ // seg.carryOver -= (int)((double)(dem - vol) * (double)(cycleLength * Globals.SECOND) / analysisPeriod); // } Point px = seg.road.points.get(seg.pointIndex); double qs = seg.get95thQueueSize(); if (Globals.monitorWTL != null && this.equals(Globals.monitorWTL)){ Globals.pw.println(" "+ seg.segmentIndex + "" + " dem: "+seg.demand + " carry: "+seg.carryOver+" vol: " + seg.totalVolume + " stops: " + seg.noOfStops + " avgQueue: " + qs ); Globals.pw.flush(); } if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ /*if (segments.get(2).road.getName().startsWith("Iuliu")){ if (k == 0) Globals.demo.st.setDemand("sw", vol, dem, true); if (k == 2) Globals.demo.st.setDemand("se", vol, dem, true); if (k == 1) Globals.demo.st.setDemand("ne", vol, dem, true); if (k == 3) Globals.demo.st.setDemand("nw", vol, dem, true); } if (segments.get(1).road.getName().startsWith("Dr T")){ if (k == 0) Globals.demo.st.setDemand("sw", vol, dem, true); if (k == 2) Globals.demo.st.setDemand("se", vol, dem, true); if (k == 1) Globals.demo.st.setDemand("ne", vol, dem, true); if (k == 3) Globals.demo.st.setDemand("nw", vol, dem, true); }*/ } } computeNextSignalPlan(crtTime); } boolean debug = false; if (crtTime == lastCycleStartTime + cycleLength * Globals.SECOND){ debug = true; lastCycleStartTime = crtTime; cycleLength = newCycleLength; for( int j = 0; j < segments.size(); j++ ) { segments.get(j).setLightInfo(segments.get(j).getNewLightInfo()); } } int thisSec = (int) (crtTime / (Globals.executionFPS)); int aux = thisSec - (lastCycleStartTime / Globals.SECOND); synchronized (this) { boolean b = false; if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ Globals.demo.st.cycle.setText("Cycle: " + cycleLength + " s"); } for (int k = 0; k < this.segments.size(); k++) { TrafficLightInfo info = segments.get(k).getLightInfo(); int color = info.getColor(aux); if (color != currentColor.get(k) ){ currentColor.set(k, color); int dem = 0, vol = 0; double stops = 0; if (segments.get(k).pair != null && segments.get(k).pair.getLightInfo().getColor(aux-1) == Globals.GREEN && adaptive){ int i = segments.get(k).paths.indexOf(new IntersectionPath(segments.get(k), segments.get(k).pair)); if (i!= -1 && color == Globals.YELLOW){ int secsEx = segments.get(k).leftSignalExtension(); if (secsEx > 0){ System.out.println("Extension"); extendGreen(aux, secsEx, segments.get(k)); continue; } } } segments.get(k).changePhase(null,crtTime, color); if (!segments.get(k).isExitOnly()){ DirectedRoadSegment seg = segments.get(k); dem = seg.computeDemand(Globals.ANALYSIS_PERIOD); vol = seg.computeVolume(Globals.ANALYSIS_PERIOD); stops = seg.noOfStops; } b = true; if (segments.get(k).pair != null){ int i = segments.get(k).paths.indexOf(new IntersectionPath(segments.get(k), segments.get(k).pair)); if (i!= -1 && color == Globals.YELLOW){ IntersectionPhaseStatistics ips= segments.get(k).paths.get(i).getLastGreenPhase(); // if (ips!= null) // System.out.println(crtTime + ") gap ["+segments.get(k)+" "+segments.get(k).front+"] "+ ips.avgGap); } } if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ /*if (segments.get(2).road.getName().startsWith("Iuliu")){ if (k == 0) Globals.demo.st.setDemand("sw", vol, dem, true); if (k == 2) Globals.demo.st.setDemand("se", vol, dem, true); if (k == 1) Globals.demo.st.setDemand("ne", vol, dem, true); if (k == 3) Globals.demo.st.setDemand("nw", vol, dem, true); } if (segments.get(0).road.getName().startsWith("Dr T")){ if (k == 0) Globals.demo.st.setDemand("sw", vol, dem, true); if (k == 2) Globals.demo.st.setDemand("se", vol, dem, true); if (k == 1) Globals.demo.st.setDemand("ne", vol, dem, true); if (k == 3) Globals.demo.st.setDemand("nw", vol, dem, true); }*/ } } if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ int x; x = info.greenEnd - aux; if (x < 0) x = 0; if (aux < info.greenStart) x = info.greenEnd - info.greenStart; // // if (segments.get(2).road.getName().startsWith("Iuliu")){ // if (k == 0) // Globals.demo.st.phase2.setText("Green sw: " + x +" s"); // if (k == 2) // Globals.demo.st.phase1.setText("Green se: " + x +" s"); // if (k == 1) // Globals.demo.st.phase3.setText("Green ne: " + x +" s"); // if (k == 3) // Globals.demo.st.phase4.setText("Green nw: " + x +" s"); // } // if (segments.get(0).road.getName().startsWith("Dr T")){ // if (k == 0) // Globals.demo.st.phase2.setText("Green sw: " + x +" s"); // if (k == 2) // Globals.demo.st.phase1.setText("Green se: " + x +" s"); // if (k == 1) // Globals.demo.st.phase3.setText("Green ne: " + x +" s"); // } } } if (b){ changeTime = crtTime; } if (debug){ } if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ Globals.demo.st.repaint(); } //debug /* if (Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this) && changeTime != -1 && crtTime == changeTime + 200){ prevSec = (int) ((changeTime - 11) / (Globals.executionFPS)); aux = prevSec % this.totalTime; for (int k = 0; k < this.segments.size(); k++) { if (!segments.get(k).isExitOnly()){ TrafficLightInfo info = this.lightInfos.get(k); Road r = Globals.map.roads.get(segments.get(k).roadIndex); int l = segments.get(k).pointIndex; if (segments.get(k).direction) l++; else l--; if (info.getColor(aux) == 1) System.out.print("Red "); if (info.getColor(aux) == 2) System.out.print("Yellow "); if (info.getColor(aux) == 3) System.out.print("Green "); int n = 0; for (int i=0; i < segments.get(k).paths.size();i++){ IntersectionPath ip = segments.get(k).paths.get(i); IntersectionPhaseStatistics ips = ip.lastHourHistory.getLast(); if (changeTime <= ips.phaseStartFrame ){ ips = ip.lastHourHistory.get(ip.lastHourHistory.size() - 2); } n += ips.getCarsNo(); } Road road = Globals.map.roads.get(segments.get(k).roadIndex); Point p0 = road.points.get(segments.get(k).pointIndex); if (segments.get(k).cars != null) for (int i = 1; i < segments.get(k).cars.size(); i ++){ SimulatedCarInfo sc1 = segments.get(k).cars.get(i-1).car; SimulatedCarInfo sc2 = segments.get(k).cars.get(i-1).car; Point p1 = road.points.get(sc1.getPointIdx()); Point p2 = road.points.get(sc2.getPointIdx()); if (Math.pow(p1.getDistance() - p0.getDistance(),2) > Math.pow(p2.getDistance() - p0.getDistance(),2)) throw new RuntimeException(); } System.out.println(segments.get(k).roadIndex+"; "+r.getName() + " [" + l +"] : " + n); } } System.out.println(" --------- /"+ crtTime); System.out.flush(); }*/ } } public void onReceive(byte[] bytesReceived, Serializable message, Communicator sender) { int j, k = 0; ByteArrayInputStream byteStream = new ByteArrayInputStream(bytesReceived); byte numberOfRecords, recordsRead = 0; byte[] b = new byte[Globals.NONAGG_RECORD_SIZE]; int offset; byte protocol = (byte)byteStream.read(); switch (protocol){ case Globals.PROT_NEIGHBOR_DISCOVERY: numberOfRecords = 1; break; case Globals.PROT_SETOFCARS: numberOfRecords = (byte)byteStream.read(); break; default: return; } if (numberOfRecords == -1) return; int comState = (byte)byteStream.read(); DirectedRoadSegment messageSegment = null; boolean sendToNeighborWTL = false; offset = 2; while (recordsRead < numberOfRecords){ int n = byteStream.read(b, 0, Globals.NONAGG_RECORD_SIZE); if (n == -1 || n < Globals.NONAGG_RECORD_SIZE){ break; } offset += Globals.NONAGG_RECORD_SIZE; recordsRead ++; SimulatedCarInfo sc = new SimulatedCarInfo(); sc.wrap(b); Engine e = Globals.engine; if (Globals.engine.startedWithGUI && Globals.demo.mv.currentIntersection != null && Globals.demo.mv.currentIntersection.equals(this)){ j = 0; } IntersectionCarRecord icr = new IntersectionCarRecord(sc); int i = trafficDB.indexOf(icr); // update car if (i != -1){ IntersectionCarRecord old = trafficDB.get(i); DirectedRoadSegment oldseg = null; DirectedRoadSegment seg = null; if (old.getCar().getTimestamp() >= sc.getTimestamp() ) continue; if (!(sender instanceof WirelessTrafficLight)){ old.learnedFromWTL = false; } if (old.isPassed()){ if (recordsRead == 1 && comState == CRTDIR){ for (j=0; j=2 && Globals.map.allIntersections.get(1).equals(this)){ messageSegment = seg; } messageSegment = seg; sendToNeighborWTL = true; } icr.setPassed(true); trafficDB.set(i,icr); } } break; } } if (j == segments.size()){ System.out.println("WTL" + this.toString() + ": car not on my segments: " +sc); synchronized(DBmutex){ trafficDB.remove(i); } return; } } // new car else{ DirectedRoadSegment seg = null; for (j=0; j 0.15){ icr.increaseDemand(); } } // if (recordsRead == 1 && comState == OPPDIR){ // //first car // messageSegment = seg; // sendToNeighborWTL = true; // } }else{ if (recordsRead == 1 && comState == CRTDIR){ messageSegment = seg; sendToNeighborWTL = true; } } break; } } } } // Got stack overflow when 2 traffic lights at the end of a segment // route are sending messages to each other //if (sendToNeighborWTL && messageSegment.nextwtl != null){ // messageSegment.nextwtl.onReceive(bytesReceived, this); //} } public byte[] prepareMessage(int messageType) { byte[] bytesToSend = null; if (messageType == Globals.PROT_TL_FEEDBACK){ ByteBuffer bb = ByteBuffer.allocate(Globals.TL_FEEDBACK_SIZE); bb.put(Globals.PROT_TL_FEEDBACK); bb.putShort((short)cycleLength); int thisSec = (int) (Globals.engine.crtTime / (Globals.SECOND)); int aux = thisSec - (lastCycleStartTime / Globals.SECOND); bb.put((byte)segments.size()); for (int k = 0; k < this.segments.size(); k++) { Road rx = Globals.map.roads.get(segments.get(k).roadIndex); Point px = rx.points.get(segments.get(k).pointIndex); bb.putShort((short)segments.get(k).roadIndex); bb.putShort((short)segments.get(k).pointIndex); if (segments.get(k).direction == true) bb.put((byte)1); else bb.put((byte)0); TrafficLightInfo info = segments.get(k).getLightInfo(); int color = info.getColor(aux); bb.put((byte)color); int remaining = -1; if (color == Globals.GREEN){ remaining = info.greenEnd - aux; } if (color == Globals.RED){ if (aux < info.greenStart) remaining = info.greenStart - aux; else{ remaining = info.greenStart + (cycleLength - aux); // remaining = - remaining; } } bb.putShort((short)remaining); bb.putShort((short)(cycleLength - (info.greenEnd - info.greenStart))); for (int i = 1; i < segments.get(k).endOfQueue.length;i++){ IntersectionCarRecord icr = segments.get(k).endOfQueue[i]; if (icr.car == null){ bb.putDouble(0); }else{ Road r = Globals.map.roads.get(icr.car.getRoadIdx()); Point p = r.points.get(icr.car.getPointIdx()); double distance = p.getDistance() - px.getDistance(); if (distance < 0) distance = - distance; bb.putDouble(distance); } } } bytesToSend = bb.array(); } return bytesToSend; } public int getLastMediumTransmition() { return lastMediumTransmission; } public void setLastMediumTransmition(int lastMediumTransmission) { this.lastMediumTransmission = lastMediumTransmission; } public boolean mediumAvailable(int crtTime){ int fps = Globals.engine.fps; if (crtTime - lastMediumTransmission >= Globals.WIRELESS_TRANSMISSION_FRAMES) return true; return false; } public boolean isPeriodicalMessage(int messageType){ return (messageType >= 0); } public int getPeriod(int messageType){ try{ return messagePeriods.get(new Integer(messageType)).intValue(); }catch(Exception e){ return -1; } } public boolean isPromiscuousMode() { return promiscuousMode; } public void setPromiscuousMode(boolean promiscuousMode) { this.promiscuousMode = promiscuousMode; } /** * delay of the new event (in frames) * @return the identifier of the new message type */ public int scheduleSingleSendEvent(int delay, int messageType){ Engine engine = Globals.engine; int newType = PROT_RESERVED; if (messageType != -1) newType = Globals.PROT_TL_FEEDBACK; // if (singleMessageNo < MIN_NEG_INT) singleMessageNo = -1; engine.schedEvent(new SendEvent(engine.crtTime + delay, this, newType)); return newType; } @Override public String toString() { String s = "[ "; for (int i = 0; i < segments.size(); i++){ if (i > 0 && segments.get(i-1).road.getName().equals(segments.get(i).road.getName())){ continue; } s += segments.get(i).road.getName().trim()+" "; } s += "]"; return s; } public short getRoadIdx(){ return (short)segments.get(0).roadIndex; } public short getPointIdx(){ return (short)segments.get(0).pointIndex; } public RadioDev getRadio(){ return radio; } public ReceiveEvent getReceiveEventForTime(int t){ int i = receiveEvents.indexOf(new ReceiveEvent(t, null, null, null, 0)); if (i == -1) return null; return receiveEvents.get(i); } public void addReceiveEventForTime(ReceiveEvent re){ receiveEvents.add(re); } public void removeReceiveEventForTime(int t){ int i = receiveEvents.indexOf(new ReceiveEvent(t, null, null, null, 0)); if (i == -1) return; receiveEvents.remove(i); } }