1 package org.opentrafficsim.road.network.factory.xml.parser;
2
3 import java.awt.image.BufferedImage;
4 import java.io.ByteArrayInputStream;
5 import java.io.IOException;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8 import java.util.ArrayList;
9 import java.util.Arrays;
10 import java.util.LinkedHashMap;
11 import java.util.LinkedHashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 import javax.imageio.ImageIO;
17 import javax.xml.bind.DatatypeConverter;
18
19 import org.djunits.value.vdouble.scalar.Duration;
20 import org.djunits.value.vdouble.scalar.Length;
21 import org.opentrafficsim.core.compatibility.Compatible;
22 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
23 import org.opentrafficsim.core.gtu.RelativePosition;
24 import org.opentrafficsim.core.network.NetworkException;
25 import org.opentrafficsim.road.network.OTSRoadNetwork;
26 import org.opentrafficsim.road.network.factory.xml.utils.Transformer;
27 import org.opentrafficsim.road.network.lane.CrossSectionLink;
28 import org.opentrafficsim.road.network.lane.Lane;
29 import org.opentrafficsim.road.network.lane.object.sensor.TrafficLightSensor;
30 import org.opentrafficsim.trafficcontrol.FixedTimeController;
31 import org.opentrafficsim.trafficcontrol.FixedTimeController.SignalGroup;
32 import org.opentrafficsim.trafficcontrol.TrafficControlException;
33 import org.opentrafficsim.trafficcontrol.trafcod.TrafCOD;
34 import org.opentrafficsim.xml.generated.CONTROL;
35 import org.opentrafficsim.xml.generated.CONTROL.FIXEDTIME;
36 import org.opentrafficsim.xml.generated.CONTROL.TRAFCOD;
37 import org.opentrafficsim.xml.generated.CONTROL.TRAFCOD.CONSOLE;
38 import org.opentrafficsim.xml.generated.CONTROLTYPE;
39 import org.opentrafficsim.xml.generated.CONTROLTYPE.SIGNALGROUP;
40 import org.opentrafficsim.xml.generated.RESPONSIVECONTROLTYPE.SENSOR;
41 import org.opentrafficsim.xml.generated.RESPONSIVECONTROLTYPE.SENSOR.MULTIPLELANE;
42 import org.opentrafficsim.xml.generated.RESPONSIVECONTROLTYPE.SENSOR.MULTIPLELANE.INTERMEDIATELANES;
43 import org.opentrafficsim.xml.generated.RESPONSIVECONTROLTYPE.SENSOR.SINGLELANE;
44
45 import nl.tudelft.simulation.dsol.SimRuntimeException;
46
47
48
49
50
51
52
53
54
55 public final class ControlParser
56 {
57
58 private ControlParser()
59 {
60
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74 public static void parseControl(final OTSRoadNetwork otsNetwork, final OTSSimulatorInterface simulator,
75 final List<CONTROL> controls)
76 throws NetworkException, MalformedURLException, IOException, SimRuntimeException, TrafficControlException
77 {
78 for (CONTROL control : controls)
79 {
80
81 for (FIXEDTIME fixedTime : control.getFIXEDTIME())
82 {
83 String id = fixedTime.getID();
84 Duration cycleTime = fixedTime.getCYCLETIME();
85 Duration offset = fixedTime.getOFFSET();
86 Set<SignalGroup> signalGroups = new LinkedHashSet<>();
87 Map<String, CONTROL.FIXEDTIME.CYCLE> cycles = new LinkedHashMap<>();
88 for (CONTROL.FIXEDTIME.CYCLE cycle : fixedTime.getCYCLE())
89 {
90 cycles.put(cycle.getSIGNALGROUPID(), cycle);
91 }
92 for (SIGNALGROUP signalGroup : fixedTime.getSIGNALGROUP())
93 {
94 String signalGroupId = signalGroup.getID();
95 CONTROL.FIXEDTIME.CYCLE cycle = cycles.get(signalGroupId);
96 Duration signalGroupOffset = cycle.getOFFSET();
97 Duration preGreen = cycle.getPREGREEN() == null ? Duration.ZERO : cycle.getPREGREEN();
98 Duration green = cycle.getGREEN();
99 Duration yellow = cycle.getYELLOW();
100 List<CONTROLTYPE.SIGNALGROUP.TRAFFICLIGHT> trafficLights = signalGroup.getTRAFFICLIGHT();
101 Set<String> trafficLightIds = new LinkedHashSet<>();
102 for (CONTROLTYPE.SIGNALGROUP.TRAFFICLIGHT trafficLight : trafficLights)
103 {
104 String linkId = trafficLight.getLINK();
105 String laneId = trafficLight.getLANE();
106 String trafficLightId = trafficLight.getTRAFFICLIGHTID();
107 trafficLightIds.add(linkId + "." + laneId + "." + trafficLightId);
108 }
109 signalGroups
110 .add(new SignalGroup(signalGroupId, trafficLightIds, signalGroupOffset, preGreen, green, yellow));
111 }
112 try
113 {
114 new FixedTimeController(id, simulator, otsNetwork, cycleTime, offset, signalGroups);
115 }
116 catch (SimRuntimeException exception)
117 {
118
119 throw new RuntimeException(exception);
120 }
121 }
122
123 for (TRAFCOD trafCod : control.getTRAFCOD())
124 {
125 String controllerName = trafCod.getID();
126 String programString = trafCod.getPROGRAM().getValue();
127 List<String> program = null == programString ? TrafCOD.loadTextFromURL(new URL(trafCod.getPROGRAMFILE()))
128 : Arrays.asList(programString.split("\n"));
129
130 TRAFCOD.CONSOLE.MAP mapData = trafCod.getCONSOLE().getMAP();
131 BufferedImage backgroundImage = null;
132 if (null != mapData)
133 {
134 String graphicsType = mapData.getTYPE();
135 String encoding = mapData.getENCODING();
136 String encodedData = mapData.getValue();
137 if (!"base64".contentEquals(encoding))
138 {
139 throw new RuntimeException("Unexpected image encoding: " + encoding);
140 }
141 byte[] imageBytes = DatatypeConverter.parseBase64Binary(encodedData);
142 switch (graphicsType)
143 {
144 case "PNG":
145 backgroundImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
146
147 break;
148
149 default:
150 throw new RuntimeException("Unexpected image type: " + graphicsType);
151 }
152 }
153 CONSOLE trafCODConsole = trafCod.getCONSOLE();
154 if (trafCODConsole.getCOORDINATESFILE() != null)
155 {
156 System.out.println("coordinates file is " + trafCODConsole.getCOORDINATESFILE());
157 throw new TrafficControlException("Loading coordinates from file not implemented yet");
158 }
159 String objectLocationsString = trafCODConsole.getCOORDINATES().getValue();
160 List<String> displayObjectLocations = null == objectLocationsString
161 ? TrafCOD.loadTextFromURL(new URL(trafCod.getCONSOLE().getCOORDINATESFILE()))
162 : Arrays.asList(objectLocationsString.split("\n"));
163 TrafCOD trafCOD =
164 new TrafCOD(controllerName, program, simulator, backgroundImage, displayObjectLocations);
165 otsNetwork.addInvisibleObject(trafCOD);
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 for (SENSOR sensor : trafCod.getSENSOR())
186 {
187 if (null != sensor.getSINGLELANE())
188 {
189
190 SINGLELANE singleLaneSensor = sensor.getSINGLELANE();
191 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(singleLaneSensor.getLINK());
192 Lane lane = (Lane) link.getCrossSectionElement(singleLaneSensor.getLANE());
193 Length entryPosition =
194 Transformer.parseLengthBeginEnd(singleLaneSensor.getENTRYPOSITION(), lane.getLength());
195 Length exitPosition =
196 Transformer.parseLengthBeginEnd(singleLaneSensor.getEXITPOSITION(), lane.getLength());
197 new TrafficLightSensor(sensor.getID(), lane, entryPosition, lane, exitPosition, null,
198 RelativePosition.FRONT, RelativePosition.REAR, simulator, Compatible.EVERYTHING);
199 }
200 else
201 {
202
203 MULTIPLELANE multiLaneSensor = sensor.getMULTIPLELANE();
204 CrossSectionLink entryLink = (CrossSectionLink) otsNetwork.getLink(multiLaneSensor.getENTRYLINK());
205 Lane entryLane = (Lane) entryLink.getCrossSectionElement(multiLaneSensor.getENTRYLANE());
206 Length entryPosition =
207 Transformer.parseLengthBeginEnd(multiLaneSensor.getENTRYPOSITION(), entryLane.getLength());
208 CrossSectionLink exitLink = (CrossSectionLink) otsNetwork.getLink(multiLaneSensor.getEXITLINK());
209 Lane exitLane = (Lane) exitLink.getCrossSectionElement(multiLaneSensor.getEXITLANE());
210 Length exitPosition =
211 Transformer.parseLengthBeginEnd(multiLaneSensor.getEXITPOSITION(), exitLane.getLength());
212 List<Lane> intermediateLanes = new ArrayList<>();
213 for (INTERMEDIATELANES linkAndLane : multiLaneSensor.getINTERMEDIATELANES())
214 {
215 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(linkAndLane.getLINK());
216 intermediateLanes.add((Lane) link.getCrossSectionElement(linkAndLane.getLANE()));
217 }
218 new TrafficLightSensor(sensor.getID(), entryLane, entryPosition, exitLane, exitPosition,
219 intermediateLanes, RelativePosition.FRONT, RelativePosition.REAR, simulator,
220 Compatible.EVERYTHING);
221 }
222 }
223
224 }
225 }
226 }
227
228 }