1 package org.opentrafficsim.demo.trafficcontrol;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.image.BufferedImage;
6 import java.io.ByteArrayInputStream;
7 import java.io.IOException;
8 import java.net.URL;
9 import java.nio.charset.StandardCharsets;
10 import java.rmi.RemoteException;
11 import java.util.Arrays;
12 import java.util.List;
13 import java.util.Scanner;
14
15 import javax.imageio.ImageIO;
16 import javax.naming.NamingException;
17 import javax.swing.JPanel;
18 import javax.swing.JScrollPane;
19 import javax.xml.bind.DatatypeConverter;
20
21 import org.djunits.value.vdouble.scalar.Duration;
22 import org.djunits.value.vdouble.scalar.Time;
23 import org.djutils.exceptions.Throw;
24 import org.djutils.io.URLResource;
25 import org.opentrafficsim.core.dsol.AbstractOTSModel;
26 import org.opentrafficsim.core.dsol.OTSAnimator;
27 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
28 import org.opentrafficsim.core.network.NetworkException;
29 import org.opentrafficsim.demo.trafficcontrol.TrafCODDemo2.TrafCODModel;
30 import org.opentrafficsim.draw.core.OTSDrawingException;
31 import org.opentrafficsim.road.network.OTSRoadNetwork;
32 import org.opentrafficsim.road.network.factory.xml.parser.XmlNetworkLaneParser;
33 import org.opentrafficsim.swing.gui.OTSAnimationPanel;
34 import org.opentrafficsim.swing.gui.OTSSimulationApplication;
35 import org.opentrafficsim.trafficcontrol.TrafficController;
36 import org.opentrafficsim.trafficcontrol.trafcod.TrafCOD;
37 import org.opentrafficsim.xml.generated.CONTROL;
38 import org.opentrafficsim.xml.generated.CONTROL.TRAFCOD;
39 import org.opentrafficsim.xml.generated.OTS;
40
41 import nl.tudelft.simulation.dsol.SimRuntimeException;
42 import nl.tudelft.simulation.event.EventInterface;
43 import nl.tudelft.simulation.event.EventListenerInterface;
44 import nl.tudelft.simulation.event.EventType;
45
46
47
48
49
50
51
52
53
54
55
56 public class TrafCODDemo2 extends OTSSimulationApplication<TrafCODModel>
57 {
58
59 private static final long serialVersionUID = 20161118L;
60
61
62
63
64
65
66
67
68 public TrafCODDemo2(final String title, final OTSAnimationPanel panel, final TrafCODModel model) throws OTSDrawingException
69 {
70 super(model, panel);
71 }
72
73
74
75
76
77
78 public static void main(final String[] args) throws IOException
79 {
80 demo(true);
81 }
82
83
84
85
86
87
88
89
90 public static String readStringFromURL(final URL url) throws IOException
91 {
92 try (Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.toString()))
93 {
94 scanner.useDelimiter("\\A");
95 return scanner.hasNext() ? scanner.next() : "";
96 }
97 }
98
99
100
101
102
103
104 public static void demo(final boolean exitOnClose) throws IOException
105 {
106 try
107 {
108 OTSAnimator simulator = new OTSAnimator();
109 URL url = URLResource.getResource("/TrafCODDemo2/TrafCODDemo2.xml");
110 System.out.println("url is " + url);
111 String xml = readStringFromURL(url);
112 final TrafCODModel trafcodModel = new TrafCODModel(simulator, "TrafCODModel", "TrafCOD demonstration Model", xml);
113 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), trafcodModel);
114 OTSAnimationPanel animationPanel = new OTSAnimationPanel(trafcodModel.getNetwork().getExtent(),
115 new Dimension(800, 600), simulator, trafcodModel, DEFAULT_COLORER, trafcodModel.getNetwork());
116 TrafCODDemo2control/TrafCODDemo2.html#TrafCODDemo2">TrafCODDemo2 app = new TrafCODDemo2("TrafCOD demo complex crossing", animationPanel, trafcodModel);
117 app.setExitOnClose(exitOnClose);
118 }
119 catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
120 {
121 exception.printStackTrace();
122 }
123 }
124
125
126
127
128 @Override
129 protected final void addTabs()
130 {
131 JScrollPane scrollPane = new JScrollPane(getModel().getControllerDisplayPanel());
132 JPanel wrapper = new JPanel(new BorderLayout());
133 wrapper.add(scrollPane);
134 getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount() - 1,
135 getModel().getTrafCOD().getId(), wrapper);
136 }
137
138
139
140
141 public static class TrafCODModel extends AbstractOTSModel implements EventListenerInterface
142 {
143
144 private static final long serialVersionUID = 20161020L;
145
146
147 private OTSRoadNetwork network;
148
149
150 private TrafCOD trafCOD;
151
152
153 private JPanel controllerDisplayPanel = new JPanel(new BorderLayout());
154
155
156 private final String xml;
157
158
159
160
161
162
163
164 public TrafCODModel(final OTSSimulatorInterface simulator, final String shortName, final String description,
165 final String xml)
166 {
167 super(simulator, shortName, description);
168 this.xml = xml;
169 }
170
171
172 @Override
173 public void constructModel() throws SimRuntimeException
174 {
175 try
176 {
177 this.network = new OTSRoadNetwork(getShortName(), true);
178 OTS ots = XmlNetworkLaneParser.parseXML(new ByteArrayInputStream(this.xml.getBytes(StandardCharsets.UTF_8)));
179 XmlNetworkLaneParser.build(ots, this.network, getSimulator(), false);
180
181 String controllerName = "TrafCOD_complex";
182 List<CONTROL> trafficControllerList = ots.getCONTROL();
183 Throw.when(trafficControllerList.size() != 1, NetworkException.class,
184 "OTS contains wrong number of traffic controllers (should be 1, got %1)", trafficControllerList.size());
185 CONTROL controller = trafficControllerList.get(0);
186 List<TRAFCOD> trafCodList = controller.getTRAFCOD();
187 Throw.when(trafCodList.size() != 1, NetworkException.class, "Controller should contain one TRAFCOD (got %1)",
188 trafCodList.size());
189 TRAFCOD trafCod = trafCodList.get(0);
190 String programString = trafCod.getPROGRAM().getValue();
191 List<String> program = null == programString ? TrafCOD.loadTextFromURL(new URL(trafCod.getPROGRAMFILE()))
192 : Arrays.asList(programString.split("\n"));
193
194 TRAFCOD.CONSOLE.MAP mapData = trafCod.getCONSOLE().getMAP();
195 BufferedImage backgroundImage = null;
196 if (null != mapData)
197 {
198 String graphicsType = mapData.getTYPE();
199 String encoding = mapData.getENCODING();
200 String encodedData = mapData.getValue();
201 if (!"base64".contentEquals(encoding))
202 {
203 throw new RuntimeException("Unexpected image encoding: " + encoding);
204 }
205 byte[] imageBytes = DatatypeConverter.parseBase64Binary(encodedData);
206 switch (graphicsType)
207 {
208 case "PNG":
209 backgroundImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
210
211 break;
212
213 default:
214 throw new RuntimeException("Unexpected image type: " + graphicsType);
215 }
216 }
217 String objectLocationsString = trafCod.getCONSOLE().getCOORDINATES().getValue();
218 List<String> displayObjectLocations = null == objectLocationsString
219 ? TrafCOD.loadTextFromURL(new URL(trafCod.getCONSOLE().getCOORDINATESFILE()))
220 : Arrays.asList(objectLocationsString.split("\n"));
221 this.trafCOD = new TrafCOD(controllerName, program, getSimulator(), this.controllerDisplayPanel,
222 backgroundImage, displayObjectLocations);
223 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONTROLLER_EVALUATING);
224 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONTROLLER_WARNING);
225 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONFLICT_GROUP_CHANGED);
226 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_STATE_CHANGED);
227 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_VARIABLE_CREATED);
228 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_TRACED_VARIABLE_UPDATED);
229
230 addListener(this.trafCOD, TrafficController.TRAFFICCONTROL_SET_TRACING);
231
232
233
234
235
236
237
238
239
240
241
242 }
243 catch (Exception exception)
244 {
245 exception.printStackTrace();
246 }
247 }
248
249
250 @Override
251 public final OTSRoadNetwork getNetwork()
252 {
253 return this.network;
254 }
255
256
257
258
259 public final TrafCOD getTrafCOD()
260 {
261 return this.trafCOD;
262 }
263
264
265
266
267 public final JPanel getControllerDisplayPanel()
268 {
269 return this.controllerDisplayPanel;
270 }
271
272
273 @Override
274 public void notify(final EventInterface event) throws RemoteException
275 {
276 EventType type = event.getType();
277 Object[] payload = (Object[]) event.getContent();
278 if (TrafficController.TRAFFICCONTROL_CONTROLLER_EVALUATING.equals(type))
279 {
280
281 return;
282 }
283 else if (TrafficController.TRAFFICCONTROL_CONFLICT_GROUP_CHANGED.equals(type))
284 {
285 System.out.println("Conflict group changed from " + ((String) payload[1]) + " to " + ((String) payload[2]));
286 }
287 else if (TrafficController.TRAFFICCONTROL_TRACED_VARIABLE_UPDATED.equals(type))
288 {
289 System.out.println(String.format("Variable changed %s <- %d %s", payload[1], payload[4], payload[5]));
290 }
291 else if (TrafficController.TRAFFICCONTROL_CONTROLLER_WARNING.equals(type))
292 {
293 System.out.println("Warning " + payload[1]);
294 }
295 else
296 {
297 System.out.print("TrafCODDemo received event of type " + event.getType() + ", payload [");
298 String separator = "";
299 for (Object o : payload)
300 {
301 System.out.print(separator + o);
302 separator = ",";
303 }
304 System.out.println("]");
305 }
306 }
307
308 }
309
310 }