1 package org.opentrafficsim.demo.conflict;
2
3 import java.net.URL;
4 import java.rmi.RemoteException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import javax.naming.NamingException;
13 import javax.swing.SwingUtilities;
14
15 import org.djunits.unit.AccelerationUnit;
16 import org.djunits.unit.DurationUnit;
17 import org.djunits.unit.FrequencyUnit;
18 import org.djunits.unit.LengthUnit;
19 import org.djunits.unit.SpeedUnit;
20 import org.djunits.unit.TimeUnit;
21 import org.djunits.value.vdouble.scalar.Acceleration;
22 import org.djunits.value.vdouble.scalar.Duration;
23 import org.djunits.value.vdouble.scalar.Frequency;
24 import org.djunits.value.vdouble.scalar.Length;
25 import org.djunits.value.vdouble.scalar.Speed;
26 import org.djunits.value.vdouble.scalar.Time;
27 import org.opentrafficsim.base.modelproperties.Property;
28 import org.opentrafficsim.base.modelproperties.PropertyException;
29 import org.opentrafficsim.core.distributions.Generator;
30 import org.opentrafficsim.core.distributions.ProbabilityException;
31 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
32 import org.opentrafficsim.core.dsol.OTSModelInterface;
33 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
34 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
35 import org.opentrafficsim.core.gtu.GTUCharacteristics;
36 import org.opentrafficsim.core.gtu.GTUDirectionality;
37 import org.opentrafficsim.core.gtu.GTUException;
38 import org.opentrafficsim.core.gtu.GTUType;
39 import org.opentrafficsim.core.gtu.animation.GTUColorer;
40 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
41 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
42 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
43 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
44 import org.opentrafficsim.core.idgenerator.IdGenerator;
45 import org.opentrafficsim.core.network.Node;
46 import org.opentrafficsim.core.network.OTSLink;
47 import org.opentrafficsim.core.network.OTSNetwork;
48 import org.opentrafficsim.core.network.route.Route;
49 import org.opentrafficsim.road.animation.AnimationToggles;
50 import org.opentrafficsim.road.gtu.animation.DefaultSwitchableGTUColorer;
51 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
52 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
53 import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
54 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
55 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristics;
56 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristicsGenerator;
57 import org.opentrafficsim.road.gtu.lane.RoadGTUTypes;
58 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectBusStopPerception;
59 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
61 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
62 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationBusStop;
63 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
64 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveBusStop;
65 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
66 import org.opentrafficsim.road.gtu.lane.tactical.pt.BusSchedule;
67 import org.opentrafficsim.road.gtu.lane.tactical.util.ConflictUtil;
68 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
69 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
70 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
71 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
72 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
73 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
74 import org.opentrafficsim.road.network.lane.CrossSectionLink;
75 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
76 import org.opentrafficsim.road.network.lane.Lane;
77 import org.opentrafficsim.road.network.lane.conflict.ConflictBuilder;
78 import org.opentrafficsim.road.network.lane.object.BusStop;
79 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
80 import org.opentrafficsim.simulationengine.OTSSimulationException;
81
82 import nl.tudelft.simulation.dsol.SimRuntimeException;
83 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
84 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
85 import nl.tudelft.simulation.jstats.streams.StreamInterface;
86 import nl.tudelft.simulation.language.io.URLResource;
87
88
89
90
91
92
93
94
95
96
97
98 public class BusStreetDemo extends AbstractWrappableAnimation
99 {
100
101
102 private static final long serialVersionUID = 20161211L;
103
104
105 @Override
106 protected final OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
107 {
108 return new BusStreetModel();
109 }
110
111
112 @Override
113 protected final void addAnimationToggles()
114 {
115 AnimationToggles.setTextAnimationTogglesFull(this);
116 this.hideAnimationClass(OTSLink.class);
117 }
118
119
120 @Override
121 public final String shortName()
122 {
123 return "Bus street demonstration";
124 }
125
126
127 @Override
128 public final String description()
129 {
130 return "Bus street demonstration";
131 }
132
133
134
135
136 class BusStreetModel implements OTSModelInterface
137 {
138
139
140 private static final long serialVersionUID = 20161211L;
141
142
143 private OTSNetwork network;
144
145
146 private OTSDEVSSimulatorInterface simulator;
147
148
149 private GTUColorer gtuColorer;
150
151
152 @Override
153 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> arg0)
154 throws SimRuntimeException, RemoteException
155 {
156 this.gtuColorer = new DefaultSwitchableGTUColorer();
157 this.simulator = (OTSDEVSSimulatorInterface) arg0;
158 Map<String, StreamInterface> streams = new HashMap<>();
159 streams.put("generation", new MersenneTwister(100L));
160 this.simulator.getReplication().setStreams(streams);
161 try
162 {
163 URL url = URLResource.getResource("/conflict/BusStreet.xml");
164 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser(this.simulator);
165 this.network = nlp.build(url);
166 ConflictBuilder.buildConflicts(this.network, GTUType.ALL, this.simulator,
167 new ConflictBuilder.FixedWidthGenerator(new Length(2.0, LengthUnit.SI)));
168
169
170 Lane lane = ((CrossSectionLink) this.network.getLink("B1B2")).getLanes().get(0);
171 BusStop stop = new BusStop("Cafe Boszicht.1", lane, lane.getLength(), "Cafe Boszicht", this.simulator);
172 Set<String> lines1 = new HashSet<>();
173 lines1.add("1");
174 stop.setLines(lines1);
175
176 lane = ((CrossSectionLink) this.network.getLink("C1C2")).getLanes().get(0);
177 stop = new BusStop("Cafe Boszicht.2", lane, lane.getLength(), "Cafe Boszicht", this.simulator);
178 Set<String> lines2 = new HashSet<>();
179 lines2.add("2");
180 stop.setLines(lines2);
181
182 lane = ((CrossSectionLink) this.network.getLink("EF")).getLanes().get(0);
183 stop = new BusStop("Herberg De Deugd", lane, new Length(75.0, LengthUnit.SI), "Herberg De Deugd",
184 this.simulator);
185 stop.setLines(lines1);
186
187 lane = ((CrossSectionLink) this.network.getLink("FG")).getLanes().get(1);
188 stop = new BusStop("De Vleeshoeve", lane, new Length(75.0, LengthUnit.SI), "De Vleeshoeve", this.simulator);
189 Set<String> lines12 = new HashSet<>();
190 lines12.add("1");
191 lines12.add("2");
192 stop.setLines(lines12);
193
194 lane = ((CrossSectionLink) this.network.getLink("GH")).getLanes().get(2);
195 stop = new BusStop("Kippenboerderij De Scharrelaar", lane, new Length(50.0, LengthUnit.SI),
196 "Kippenboerderij De Scharrelaar", this.simulator);
197 stop.setLines(lines2);
198
199 lane = ((CrossSectionLink) this.network.getLink("I1I2")).getLanes().get(0);
200 stop = new BusStop("Dorpshuys", lane, lane.getLength(), "Dorpshuys", this.simulator);
201 stop.setLines(lines1);
202
203 lane = ((CrossSectionLink) this.network.getLink("K1K2")).getLanes().get(0);
204 stop = new BusStop("De verkeerde afslag", lane, lane.getLength(), "De verkeerde afslag", this.simulator);
205 stop.setLines(lines12);
206
207 makeGenerator();
208
209 }
210 catch (Exception exception)
211 {
212 exception.printStackTrace();
213 }
214 }
215
216
217 @Override
218 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
219 {
220 return this.simulator;
221 }
222
223
224 @Override
225 public OTSNetwork getNetwork()
226 {
227 return this.network;
228 }
229
230
231
232
233
234
235
236
237 private void makeGenerator() throws GTUException, SimRuntimeException, ProbabilityException, ParameterException
238 {
239 Lane lane = ((CrossSectionLink) this.network.getLink("AB")).getLanes().get(0);
240 String id = lane.getId();
241 Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
242 initialLongitudinalPositions
243 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
244 Generator<Duration> headwayGenerator =
245 new HeadwayGenerator(new Frequency(800, FrequencyUnit.PER_HOUR), this.simulator);
246 LaneBasedGTUCharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(this.simulator,
247 new double[] { 0.9, 0.06, 0.04 }, initialLongitudinalPositions, this.network);
248 RoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
249 new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO,
250 new Time(Double.MAX_VALUE, TimeUnit.BASE_SECOND), this.gtuColorer, characteristicsGenerator,
251 initialLongitudinalPositions, this.network, roomChecker);
252 }
253
254 }
255
256
257
258
259
260
261 public static void main(final String[] args) throws SimRuntimeException
262 {
263 SwingUtilities.invokeLater(new Runnable()
264 {
265 @Override
266 public void run()
267 {
268 try
269 {
270 BusStreetDemo animation = new BusStreetDemo();
271
272 animation.buildAnimator(Time.ZERO, Duration.ZERO, new Duration(60.0, DurationUnit.MINUTE),
273 new ArrayList<Property<?>>(), null, true);
274
275 }
276 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
277 {
278 exception.printStackTrace();
279 }
280 }
281 });
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295 private class HeadwayGenerator implements Generator<Duration>
296 {
297
298
299 private final Frequency demand;
300
301
302 private final OTSSimulatorInterface simulator;
303
304
305
306
307
308 HeadwayGenerator(final Frequency demand, final OTSSimulatorInterface simulator)
309 {
310 this.demand = demand;
311 this.simulator = simulator;
312 }
313
314
315 @Override
316 public Duration draw() throws ProbabilityException, ParameterException
317 {
318 try
319 {
320 return new Duration(
321 -Math.log(this.simulator.getReplication().getStream("generation").nextDouble()) / this.demand.si,
322 DurationUnit.SI);
323 }
324 catch (RemoteException exception)
325 {
326 throw new ProbabilityException("Could not draw for Probability.", exception);
327 }
328 }
329
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343 public class CharacteristicsGenerator implements LaneBasedGTUCharacteristicsGenerator
344 {
345
346
347 private final OTSDEVSSimulatorInterface simulator;
348
349
350 private final double[] probabilities;
351
352
353 private final Set<DirectedLanePosition> initialLongitudinalPositions;
354
355
356 private final OTSNetwork network;
357
358
359 private final IdGenerator idGenerator = new IdGenerator("");
360
361
362 private final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> plannerFactory;
363
364
365 private final Route carRouteN;
366
367
368 private final Route carRouteO;
369
370
371 private final List<Node> busNodes1;
372
373
374 private final List<Node> busNodes2;
375
376
377 private final Duration shortDwellTime = new Duration(15.0, DurationUnit.SI);
378
379
380 private final Duration longDwellTime = new Duration(60.0, DurationUnit.SI);
381
382
383
384
385
386
387
388 public CharacteristicsGenerator(final OTSDEVSSimulatorInterface simulator, final double[] probabilities,
389 final Set<DirectedLanePosition> initialLongitudinalPositions, final OTSNetwork network)
390 {
391 this.simulator = simulator;
392 this.probabilities = probabilities;
393 this.initialLongitudinalPositions = initialLongitudinalPositions;
394 this.network = network;
395 List<Node> carNodesN = new ArrayList<>();
396 carNodesN.add(network.getNode("A"));
397 carNodesN.add(network.getNode("B"));
398 carNodesN.add(network.getNode("C"));
399 carNodesN.add(network.getNode("D"));
400 carNodesN.add(network.getNode("E"));
401 carNodesN.add(network.getNode("F"));
402 carNodesN.add(network.getNode("G"));
403 carNodesN.add(network.getNode("H"));
404 carNodesN.add(network.getNode("I"));
405 carNodesN.add(network.getNode("J"));
406 carNodesN.add(network.getNode("K"));
407 carNodesN.add(network.getNode("L"));
408 carNodesN.add(network.getNode("M"));
409 List<Node> carNodesO = new ArrayList<>(carNodesN);
410 carNodesN.add(network.getNode("N"));
411 carNodesO.add(network.getNode("O"));
412 this.carRouteN = new Route("carN", carNodesN);
413 this.carRouteO = new Route("carO", carNodesO);
414 this.busNodes1 = new ArrayList<>();
415 this.busNodes1.add(network.getNode("A"));
416 this.busNodes1.add(network.getNode("B"));
417 this.busNodes1.add(network.getNode("B1"));
418 this.busNodes1.add(network.getNode("B2"));
419 this.busNodes1.add(network.getNode("D"));
420 this.busNodes1.add(network.getNode("E"));
421 this.busNodes1.add(network.getNode("F"));
422 this.busNodes1.add(network.getNode("G"));
423 this.busNodes1.add(network.getNode("H"));
424 this.busNodes1.add(network.getNode("I"));
425 this.busNodes1.add(network.getNode("I1"));
426 this.busNodes1.add(network.getNode("I2"));
427 this.busNodes1.add(network.getNode("J"));
428 this.busNodes1.add(network.getNode("K"));
429 this.busNodes1.add(network.getNode("K1"));
430 this.busNodes1.add(network.getNode("K2"));
431 this.busNodes1.add(network.getNode("L"));
432 this.busNodes1.add(network.getNode("M"));
433 this.busNodes1.add(network.getNode("N"));
434
435 this.busNodes2 = new ArrayList<>();
436 this.busNodes2.add(network.getNode("A"));
437 this.busNodes2.add(network.getNode("B"));
438 this.busNodes2.add(network.getNode("C"));
439 this.busNodes2.add(network.getNode("C1"));
440 this.busNodes2.add(network.getNode("C2"));
441 this.busNodes2.add(network.getNode("E"));
442 this.busNodes2.add(network.getNode("F"));
443 this.busNodes2.add(network.getNode("G"));
444 this.busNodes2.add(network.getNode("H"));
445 this.busNodes2.add(network.getNode("I"));
446 this.busNodes2.add(network.getNode("J"));
447 this.busNodes2.add(network.getNode("K"));
448 this.busNodes2.add(network.getNode("K1"));
449 this.busNodes2.add(network.getNode("K2"));
450 this.busNodes2.add(network.getNode("K3"));
451 this.busNodes2.add(network.getNode("L"));
452 this.busNodes2.add(network.getNode("M"));
453 this.busNodes2.add(network.getNode("O"));
454
455 this.plannerFactory = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactoryCarBus(),
456 new BehavioralCharacteristicsFactoryCarBus());
457 }
458
459
460 @Override
461 public LaneBasedGTUCharacteristics draw() throws ProbabilityException, ParameterException, GTUException
462 {
463
464 double r = this.simulator.getReplication().getStream("generation").nextDouble();
465 int classNum = r < this.probabilities[0] ? 0 : r < this.probabilities[0] + this.probabilities[1] ? 1 : 2;
466 r = this.simulator.getReplication().getStream("generation").nextDouble();
467 GTUType gtuType;
468 Length length;
469 Length width;
470 Speed maximumSpeed;
471 Route route;
472 switch (classNum)
473 {
474 case 0:
475 {
476 gtuType = new GTUType("CAR", RoadGTUTypes.CAR);
477 length = new Length(4.0, LengthUnit.SI);
478 width = new Length(1.8, LengthUnit.SI);
479 maximumSpeed = new Speed(200.0, SpeedUnit.KM_PER_HOUR);
480 route = r < 0.5 ? this.carRouteN : this.carRouteO;
481 break;
482 }
483 case 1:
484 {
485 gtuType = new GTUType("BUS1", RoadGTUTypes.SCHEDULED_BUS);
486 length = new Length(8.0, LengthUnit.SI);
487 width = new Length(2.0, LengthUnit.SI);
488 maximumSpeed = new Speed(100.0, SpeedUnit.KM_PER_HOUR);
489 BusSchedule schedule =
490 new BusSchedule("bus1." + this.simulator.getSimulatorTime().getTime(), this.busNodes1, "1");
491 Time now = this.simulator.getSimulatorTime().getTime();
492 schedule.addBusStop("Cafe Boszicht.1", now.plus(new Duration(70.0, DurationUnit.SI)), this.longDwellTime,
493 true);
494 schedule.addBusStop("Herberg De Deugd", now.plus(new Duration(100.0, DurationUnit.SI)), this.shortDwellTime,
495 false);
496 schedule.addBusStop("De Vleeshoeve", now.plus(new Duration(120.0, DurationUnit.SI)), this.shortDwellTime,
497 false);
498 schedule.addBusStop("Dorpshuys", now.plus(new Duration(200.0, DurationUnit.SI)), this.longDwellTime, true);
499 schedule.addBusStop("De verkeerde afslag", now.plus(new Duration(270.0, DurationUnit.SI)),
500 this.longDwellTime, true);
501 route = schedule;
502 break;
503 }
504 case 2:
505 {
506 gtuType = new GTUType("BUS2", RoadGTUTypes.SCHEDULED_BUS);
507 length = new Length(12.0, LengthUnit.SI);
508 width = new Length(2.0, LengthUnit.SI);
509 maximumSpeed = new Speed(100.0, SpeedUnit.KM_PER_HOUR);
510 BusSchedule schedule =
511 new BusSchedule("bus2." + this.simulator.getSimulatorTime().getTime(), this.busNodes2, "2");
512 Time now = this.simulator.getSimulatorTime().getTime();
513 schedule.addBusStop("Cafe Boszicht.2", now.plus(new Duration(80.0, DurationUnit.SI)), this.longDwellTime,
514 true);
515 schedule.addBusStop("De Vleeshoeve", now.plus(new Duration(110.0, DurationUnit.SI)), this.shortDwellTime,
516 false);
517 schedule.addBusStop("Kippenboerderij De Scharrelaar", now.plus(new Duration(180.0, DurationUnit.SI)),
518 this.longDwellTime, false);
519 schedule.addBusStop("De verkeerde afslag", now.plus(new Duration(260.0, DurationUnit.SI)),
520 this.longDwellTime, true);
521 route = schedule;
522 break;
523 }
524 default:
525 throw new RuntimeException("Reaching default of switch case.");
526 }
527
528 GTUCharacteristics gtuCharacteristics = new GTUCharacteristics(gtuType, this.idGenerator, length, width,
529 maximumSpeed, this.simulator, this.network);
530
531 return new LaneBasedGTUCharacteristics(gtuCharacteristics, this.plannerFactory, route,
532 new Speed(50.0, SpeedUnit.KM_PER_HOUR), this.initialLongitudinalPositions);
533 }
534
535
536 @Override
537 public OTSDEVSSimulatorInterface getSimulator() throws ProbabilityException
538 {
539 return this.simulator;
540 }
541
542 }
543
544
545
546
547
548
549
550
551
552
553
554
555 private class LMRSFactoryCarBus implements LaneBasedTacticalPlannerFactory<LMRS>
556 {
557
558
559 LMRSFactoryCarBus()
560 {
561 }
562
563
564 @Override
565 public final BehavioralCharacteristics getDefaultBehavioralCharacteristics()
566 {
567 BehavioralCharacteristics behavioralCharacteristics = new BehavioralCharacteristics();
568 behavioralCharacteristics.setDefaultParameters(ParameterTypes.class);
569 behavioralCharacteristics.setDefaultParameters(LmrsParameters.class);
570 behavioralCharacteristics.setDefaultParameters(ConflictUtil.class);
571 behavioralCharacteristics.setDefaultParameters(AbstractIDM.class);
572 return behavioralCharacteristics;
573 }
574
575
576 @Override
577 public final LMRS create(final LaneBasedGTU gtu) throws GTUException
578 {
579 DefaultLMRSPerceptionFactory pFac = new DefaultLMRSPerceptionFactory();
580 LMRS lmrs = new LMRS(new IDMPlus(), gtu, pFac.generatePerception(gtu), Synchronization.PASSIVE);
581 lmrs.setDefaultIncentives();
582 if (gtu.getGTUType().isOfType(RoadGTUTypes.SCHEDULED_BUS))
583 {
584 lmrs.addMandatoryIncentive(new IncentiveBusStop());
585 lmrs.addAccelerationIncentive(new AccelerationBusStop());
586 lmrs.getPerception().addPerceptionCategory(new DirectBusStopPerception(lmrs.getPerception()));
587 }
588 return lmrs;
589 }
590
591 }
592
593
594
595
596
597
598
599
600
601
602
603
604 private class BehavioralCharacteristicsFactoryCarBus implements BehavioralCharacteristicsFactory
605 {
606
607
608 BehavioralCharacteristicsFactoryCarBus()
609 {
610 }
611
612
613 @Override
614 public void setValues(final BehavioralCharacteristics defaultCharacteristics, final GTUType gtuType)
615 throws ParameterException
616 {
617
618 defaultCharacteristics.setParameter(ParameterTypes.LOOKAHEAD, new Length(100.0, LengthUnit.METER));
619 if (gtuType.isOfType(RoadGTUTypes.CAR))
620 {
621 defaultCharacteristics.setParameter(LmrsParameters.VGAIN, new Speed(3.0, SpeedUnit.METER_PER_SECOND));
622 }
623 else if (gtuType.isOfType(RoadGTUTypes.SCHEDULED_BUS))
624 {
625 defaultCharacteristics.setParameter(ParameterTypes.A,
626 new Acceleration(0.8, AccelerationUnit.METER_PER_SECOND_2));
627 }
628 else
629 {
630 throw new RuntimeException("Unable to determine characteristics for GTU of type " + gtuType);
631 }
632
633 }
634
635 }
636
637 }