1 package org.opentrafficsim.demo.cacc;
2
3 import java.awt.Color;
4 import java.io.BufferedWriter;
5 import java.io.IOException;
6 import java.io.OutputStreamWriter;
7 import java.rmi.RemoteException;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14
15 import org.djunits.Throw;
16 import org.djunits.unit.DurationUnit;
17 import org.djunits.unit.FrequencyUnit;
18 import org.djunits.unit.SpeedUnit;
19 import org.djunits.unit.TimeUnit;
20 import org.djunits.value.ValueRuntimeException;
21 import org.djunits.value.storage.StorageType;
22 import org.djunits.value.vdouble.scalar.Acceleration;
23 import org.djunits.value.vdouble.scalar.Direction;
24 import org.djunits.value.vdouble.scalar.Duration;
25 import org.djunits.value.vdouble.scalar.Length;
26 import org.djunits.value.vdouble.scalar.Speed;
27 import org.djunits.value.vdouble.scalar.Time;
28 import org.djunits.value.vdouble.vector.FrequencyVector;
29 import org.djunits.value.vdouble.vector.TimeVector;
30 import org.djunits.value.vdouble.vector.base.DoubleVector;
31 import org.djunits.value.vfloat.scalar.FloatDuration;
32 import org.djutils.cli.CliException;
33 import org.djutils.cli.CliUtil;
34 import org.djutils.event.EventInterface;
35 import org.djutils.event.EventListenerInterface;
36 import org.djutils.exceptions.Try;
37 import org.opentrafficsim.base.compressedfiles.CompressionType;
38 import org.opentrafficsim.base.compressedfiles.Writer;
39 import org.opentrafficsim.base.parameters.ParameterException;
40 import org.opentrafficsim.base.parameters.ParameterTypes;
41 import org.opentrafficsim.base.parameters.Parameters;
42 import org.opentrafficsim.core.animation.gtu.colorer.AccelerationGTUColorer;
43 import org.opentrafficsim.core.animation.gtu.colorer.IDGTUColorer;
44 import org.opentrafficsim.core.animation.gtu.colorer.SpeedGTUColorer;
45 import org.opentrafficsim.core.animation.gtu.colorer.SwitchableGTUColorer;
46 import org.opentrafficsim.core.distributions.ConstantGenerator;
47 import org.opentrafficsim.core.distributions.Distribution;
48 import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
49 import org.opentrafficsim.core.distributions.ProbabilityException;
50 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
51 import org.opentrafficsim.core.geometry.Bezier;
52 import org.opentrafficsim.core.geometry.OTSLine3D;
53 import org.opentrafficsim.core.geometry.OTSPoint3D;
54 import org.opentrafficsim.core.gtu.GTUDirectionality;
55 import org.opentrafficsim.core.gtu.GTUException;
56 import org.opentrafficsim.core.gtu.GTUType;
57 import org.opentrafficsim.core.gtu.TemplateGTUType;
58 import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
59 import org.opentrafficsim.core.gtu.perception.EgoPerception;
60 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
61 import org.opentrafficsim.core.network.Link;
62 import org.opentrafficsim.core.network.LinkType;
63 import org.opentrafficsim.core.network.NetworkException;
64 import org.opentrafficsim.core.network.Node;
65 import org.opentrafficsim.core.parameters.ParameterFactory;
66 import org.opentrafficsim.core.parameters.ParameterFactoryByType;
67 import org.opentrafficsim.draw.factory.DefaultAnimationFactory;
68 import org.opentrafficsim.draw.graphs.ContourDataSource;
69 import org.opentrafficsim.draw.graphs.ContourPlotSpeed;
70 import org.opentrafficsim.draw.graphs.GraphPath;
71 import org.opentrafficsim.draw.graphs.road.GraphLaneUtil;
72 import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
73 import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
74 import org.opentrafficsim.kpi.sampling.SamplingException;
75 import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
76 import org.opentrafficsim.kpi.sampling.Trajectory;
77 import org.opentrafficsim.kpi.sampling.TrajectoryGroup;
78 import org.opentrafficsim.kpi.sampling.meta.FilterDataGtuType;
79 import org.opentrafficsim.road.gtu.colorer.DesiredSpeedColorer;
80 import org.opentrafficsim.road.gtu.colorer.FixedColor;
81 import org.opentrafficsim.road.gtu.colorer.GTUTypeColorer;
82 import org.opentrafficsim.road.gtu.colorer.ReactionTimeColorer;
83 import org.opentrafficsim.road.gtu.colorer.SplitColorer;
84 import org.opentrafficsim.road.gtu.colorer.SynchronizationColorer;
85 import org.opentrafficsim.road.gtu.colorer.TaskColorer;
86 import org.opentrafficsim.road.gtu.colorer.TaskSaturationColorer;
87 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
88 import org.opentrafficsim.road.gtu.generator.Platoons;
89 import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
90 import org.opentrafficsim.road.gtu.generator.od.ODApplier;
91 import org.opentrafficsim.road.gtu.generator.od.ODApplier.GeneratorObjects;
92 import org.opentrafficsim.road.gtu.generator.od.ODOptions;
93 import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD;
94 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
95 import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
96 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
97 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
98 import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
99 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
100 import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
101 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
102 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectIntersectionPerception;
103 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation;
104 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
105 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Estimation;
106 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
107 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType.PerceivedHeadwayGtuType;
108 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
109 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
110 import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
111 import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationHeadway;
112 import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationSituationalAwareness;
113 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
114 import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller.BehavioralAdaptation;
115 import org.opentrafficsim.road.gtu.lane.perception.mental.Task;
116 import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager;
117 import org.opentrafficsim.road.gtu.lane.tactical.cacc.CaccController;
118 import org.opentrafficsim.road.gtu.lane.tactical.cacc.CaccControllerFactory;
119 import org.opentrafficsim.road.gtu.lane.tactical.cacc.CaccParameters;
120 import org.opentrafficsim.road.gtu.lane.tactical.cacc.CaccTacticalPlanner;
121 import org.opentrafficsim.road.gtu.lane.tactical.cacc.CaccTacticalPlannerFactory;
122 import org.opentrafficsim.road.gtu.lane.tactical.cacc.LongitudinalControllerFactory;
123 import org.opentrafficsim.road.gtu.lane.tactical.cacc.Platoon;
124 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
125 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
126 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
127 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
128 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
129 import org.opentrafficsim.road.gtu.strategical.od.Categorization;
130 import org.opentrafficsim.road.gtu.strategical.od.Category;
131 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
132 import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
133 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
134 import org.opentrafficsim.road.network.OTSRoadNetwork;
135 import org.opentrafficsim.road.network.lane.CrossSectionLink;
136 import org.opentrafficsim.road.network.lane.Lane;
137 import org.opentrafficsim.road.network.lane.LaneDirection;
138 import org.opentrafficsim.road.network.lane.LaneType;
139 import org.opentrafficsim.road.network.lane.OTSRoadNode;
140 import org.opentrafficsim.road.network.lane.Stripe;
141 import org.opentrafficsim.road.network.lane.Stripe.Permeable;
142 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
143 import org.opentrafficsim.road.network.lane.object.sensor.Detector;
144 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
145 import org.opentrafficsim.road.network.sampling.LaneData;
146 import org.opentrafficsim.road.network.sampling.RoadSampler;
147 import org.opentrafficsim.road.network.sampling.data.TimeToCollision;
148 import org.opentrafficsim.swing.graphs.SwingContourPlot;
149 import org.opentrafficsim.swing.gui.OTSSimulationApplication;
150 import org.opentrafficsim.swing.script.AbstractSimulationScript;
151
152 import nl.tudelft.simulation.dsol.swing.gui.TablePanel;
153 import nl.tudelft.simulation.jstats.streams.StreamInterface;
154 import picocli.CommandLine;
155 import picocli.CommandLine.Option;
156
157
158
159
160
161
162
163
164
165
166
167 public class CaccSimulationAdv extends AbstractSimulationScript
168 {
169
170
171 private static final long serialVersionUID = 1L;
172
173
174 private RoadSampler sampler;
175
176
177 private final TimeToCollision ttc = new TimeToCollision();
178
179
180 private final FilterDataGtuType metaGtu = new FilterDataGtuType();
181
182
183 private CaccController caccController;
184
185
186 private GTUType caccGTUType;
187
188
189 private final List<SpaceTimeRegion> regions = new ArrayList<>();
190
191
192 private List<Lane> graphLanes = new ArrayList<>();
193
194
195
196
197
198
199
200
201 @Option(names = "--hExp", description = "Exponential decay of car-following task by headway", defaultValue = "4.0 s")
202 private Duration hExp;
203
204
205
206 @Option(names = "--alpha", description = "Fraction of primary task that can be reduced by anticipation reliance",
207 defaultValue = "0.8")
208 private double alpha;
209
210
211
212 @Option(names = "--beta", description = "Fraction of auxiliary tasks that can be reduced by anticipation reliance",
213 defaultValue = "0.6")
214 private double beta;
215
216
217
218 @Option(names = "--nn", description = "Network name", defaultValue = "onramp")
219 private String networkName;
220
221
222 @Option(names = "--intensity", description = "Intensity factor", defaultValue = "1.00")
223 private double intensity;
224
225
226 @Option(names = "--penetration", description = "Fraction of vehicles equipped with CACC", defaultValue = "1.00")
227 private double penetration;
228
229
230 @Option(names = "--platoon", description = "Platoon size", defaultValue = "3")
231 private int platoonSize;
232
233
234 @Option(names = "--headway", description = "Platoon headway", defaultValue = "0.9")
235 private double headway;
236
237
238 @Option(names = "--synchronization", description = "Synchronization", defaultValue = "0.0")
239 private double synchronization;
240
241
242 @Option(names = "--setspeed", description = "Free flow speed of platoon vehicles", defaultValue = "80 km/h")
243 private Speed setspeed;
244
245
246 @Option(names = "--sd", description = "Simulation time", defaultValue = "4500s")
247 private Duration simulationDuration;
248
249
250 @Option(names = "--graphs", description = "Show graphs", defaultValue = "true")
251 private boolean graphs;
252
253
254 @Option(names = "--nol", description = "Number of lanes", defaultValue = "3")
255 private int numberOfLanes;
256
257
258 @Option(names = "--controller", description = "Controller", defaultValue = "CACC")
259 private String controller;
260
261
262 @Option(names = "--outputFileDets", description = "Output file for detections",
263 defaultValue = "C:\\\\Temp\\\\Journal-Platoon\\\\DetsDefault.csv")
264 private String outputFileDets;
265
266
267 @Option(names = "--outputFileTraj", description = "Output file for trajectories",
268 defaultValue = "C:\\\\Temp\\\\Journal-Platoon\\\\GenDefault")
269 private String outputFileTraj;
270
271
272 @Option(names = "--outputFileGen", description = "Output file for generators",
273 defaultValue = "C:\\Temp\\Journal-Platoon\\GenDefault")
274 private String outputFileGen;
275
276
277 @Option(names = "--strategies", description = "Strategies (boolean)", defaultValue = "false")
278 private boolean strategies;
279
280
281 @Option(names = "--adaptation", description = "Adaptation (boolean)", defaultValue = "false")
282 private boolean adaptation;
283
284
285 @Option(names = "--tasks", description = "Tasks (boolean)", defaultValue = "true")
286 private boolean tasks;
287
288
289 @Option(names = "--fractionUnderestimation", description = "Fraction underestimation", defaultValue = "0.75")
290 private double fractionUnderestimation;
291
292
293 @Option(names = "--startSpacing", description = "Gross equilibrium distance at 25m/s with s0=3m, l=12m and T=0.3s",
294 defaultValue = "0.5")
295 private double startSpacing;
296
297
298
299
300
301
302 protected CaccSimulationAdv(final String[] properties) throws NoSuchFieldException, CliException
303 {
304 super("Truck CACC", "Simulation of CACC trucks");
305 CommandLine cmd = new CommandLine(this);
306 CliUtil.changeOptionDefault(AbstractSimulationScript.class, "seed", "5");
307 CliUtil.execute(cmd, properties);
308 }
309
310
311
312
313
314
315
316
317 public static void main(final String[] args) throws NoSuchFieldException, CliException, Exception
318 {
319 new CaccSimulationAdv(args).start();
320 }
321
322
323 @Override
324 protected OTSRoadNetwork setupSimulation(final OTSSimulatorInterface sim) throws Exception
325 {
326 OTSRoadNetwork network = new OTSRoadNetwork(this.networkName, true, sim);
327 GTUType carGTUType = network.getGtuType(GTUType.DEFAULTS.CAR);
328 GTUType truckGTUType = network.getGtuType(GTUType.DEFAULTS.TRUCK);
329 this.caccGTUType = new GTUType("CACC", truckGTUType);
330 LinkType freewayLinkType = network.getLinkType(LinkType.DEFAULTS.FREEWAY);
331 LaneType freewayLaneType = network.getLaneType(LaneType.DEFAULTS.FREEWAY);
332 GTUType vehicle = network.getGtuType(GTUType.DEFAULTS.VEHICLE);
333 this.caccController = new CaccController();
334 this.caccController.setCACCGTUType(this.caccGTUType);
335 setGtuColorer(new SwitchableGTUColorer(0, new FixedColor(Color.BLUE, "Blue"),
336 new GTUTypeColorer().add(carGTUType, Color.BLUE).add(truckGTUType, Color.RED).add(this.caccGTUType,
337 Color.GREEN),
338 (new TaskColorer("car-following")), (new TaskColorer("lane-changing")), (new TaskSaturationColorer()),
339 (new ReactionTimeColorer(Duration.instantiateSI(1.0))), new IDGTUColorer(),
340 new SpeedGTUColorer(new Speed(150, SpeedUnit.KM_PER_HOUR)),
341 new DesiredSpeedColorer(new Speed(50, SpeedUnit.KM_PER_HOUR), new Speed(150, SpeedUnit.KM_PER_HOUR)),
342 new AccelerationGTUColorer(Acceleration.instantiateSI(-6.0), Acceleration.instantiateSI(2)), new SplitColorer(),
343 new SynchronizationColorer(), new TaskColorer("car-following")));
344
345
346 ParameterFactoryByType parameters = new ParameterFactoryByType();
347
348 parameters.addParameter(CaccParameters.T_SYSTEM_CACC, new Duration(this.headway, DurationUnit.SI));
349 parameters.addParameter(CaccParameters.A_REDUCED, Acceleration.instantiateSI(this.synchronization));
350 parameters.addParameter(CaccParameters.SET_SPEED, this.setspeed);
351
352 CaccControllerFactory longitudinalControllerFactory;
353 String controllerName = this.controller;
354 if (controllerName.equals("CACC"))
355 {
356 longitudinalControllerFactory = new CaccControllerFactory();
357 }
358 else
359 {
360 throw new RuntimeException("Controller " + controllerName + " not supported.");
361 }
362
363 Length laneWidth = Length.instantiateSI(3.5);
364 Length stripeWidth = Length.instantiateSI(0.2);
365 Map<String, GeneratorObjects> odApplierOutput;
366
367 String platoonDetector1;
368
369 if (networkName.equals("onramp"))
370 {
371
372 OTSPoint3D pointA = new OTSPoint3D(0, 0);
373 OTSPoint3D pointB = new OTSPoint3D(2000, 0);
374 OTSPoint3D pointC = new OTSPoint3D(2330, 0);
375 OTSPoint3D pointD = new OTSPoint3D(3330, 0);
376 OTSPoint3D pointE = new OTSPoint3D(1300, -40);
377
378
379 OTSRoadNode nodeA = new OTSRoadNode(network, "A", pointA, Direction.ZERO);
380 OTSRoadNode nodeB = new OTSRoadNode(network, "B", pointB, Direction.ZERO);
381 OTSRoadNode nodeC = new OTSRoadNode(network, "C", pointC, Direction.ZERO);
382 OTSRoadNode nodeD = new OTSRoadNode(network, "D", pointD, Direction.ZERO);
383 OTSRoadNode nodeE = new OTSRoadNode(network, "E", pointE, Direction.ZERO);
384
385
386 CrossSectionLink linkAB = new CrossSectionLink(network, "AB", nodeA, nodeB, freewayLinkType,
387 new OTSLine3D(pointA, pointB), LaneKeepingPolicy.KEEPRIGHT);
388 CrossSectionLink linkBC = new CrossSectionLink(network, "BC", nodeB, nodeC, freewayLinkType,
389 new OTSLine3D(pointB, pointC), LaneKeepingPolicy.KEEPRIGHT);
390 CrossSectionLink linkCD = new CrossSectionLink(network, "CD", nodeC, nodeD, freewayLinkType,
391 new OTSLine3D(pointC, pointD), LaneKeepingPolicy.KEEPRIGHT);
392 CrossSectionLink linkEB = new CrossSectionLink(network, "EB", nodeE, nodeB, freewayLinkType,
393 Bezier.cubic(nodeE.getLocation(), nodeB.getLocation()), LaneKeepingPolicy.KEEPRIGHT);
394
395
396 int n = this.numberOfLanes;
397
398 for (int i = 0; i < n; i++)
399 {
400 for (CrossSectionLink link : new CrossSectionLink[] {linkAB, linkBC, linkCD})
401 {
402 Lane lane = new Lane(link, "Lane " + (i + 1), laneWidth.times((0.5 + i)), laneWidth, freewayLaneType,
403 new Speed(100, SpeedUnit.KM_PER_HOUR));
404 Length offset = laneWidth.times(i + 1.0);
405 Stripe stripe = new Stripe(link, offset, offset, stripeWidth);
406 if (i < n - 1)
407 {
408 if (lane.getParentLink().getId().equals("BC"))
409 {
410
411 stripe.addPermeability(vehicle, Permeable.BOTH);
412 }
413 else
414 {
415 stripe.addPermeability(vehicle, Permeable.BOTH);
416 }
417 }
418 if (lane.getParentLink().getId().equals("BC"))
419 {
420
421 new Detector(lane.getFullId(), lane, Length.instantiateSI(330.0), sim);
422 }
423
424 if (lane.getParentLink().getId().equals("CD"))
425 {
426 new SinkSensor(lane, lane.getLength().minus(Length.instantiateSI(100.0)), GTUDirectionality.DIR_PLUS,
427 sim);
428 new SinkSensor(lane, lane.getLength().minus(Length.instantiateSI(90.0)), GTUDirectionality.DIR_PLUS,
429 sim);
430 new SinkSensor(lane, lane.getLength().minus(Length.instantiateSI(80.0)), GTUDirectionality.DIR_PLUS,
431 sim);
432
433
434
435 }
436 if (lane.getParentLink().getId().equals("AB"))
437 {
438
439 this.graphLanes.add(lane);
440 }
441 }
442 }
443 new Stripe(linkAB, Length.ZERO, Length.ZERO, stripeWidth);
444 Stripe stripe = new Stripe(linkBC, Length.ZERO, Length.ZERO, stripeWidth);
445 stripe.addPermeability(vehicle, Permeable.LEFT);
446 new Stripe(linkCD, Length.ZERO, Length.ZERO, stripeWidth);
447 new Lane(linkBC, "Acceleration lane", laneWidth.times(-0.5), laneWidth, freewayLaneType,
448 new Speed(100, SpeedUnit.KM_PER_HOUR));
449 Lane onramp = new Lane(linkEB, "Onramp", laneWidth.times(-0.5), laneWidth, freewayLaneType,
450 new Speed(100, SpeedUnit.KM_PER_HOUR));
451 new Stripe(linkEB, Length.ZERO, Length.ZERO, stripeWidth);
452 new Stripe(linkEB, laneWidth.neg(), laneWidth.neg(), stripeWidth);
453 new Stripe(linkBC, laneWidth.neg(), laneWidth.neg(), stripeWidth);
454
455
456
457
458
459 List<OTSRoadNode> origins = new ArrayList<>();
460 origins.add(nodeA);
461 origins.add(nodeE);
462 List<OTSRoadNode> destinations = new ArrayList<>();
463 destinations.add(nodeD);
464 TimeVector timeVector = DoubleVector.instantiate(new double[] {0.0, 0.25, 0.50, 0.75, 1.0, 1.25, 1.50, 1.75, 2.0},
465 TimeUnit.BASE_HOUR, StorageType.DENSE);
466 Interpolation interpolation = Interpolation.LINEAR;
467 Categorization categorization = new Categorization("CACC", GTUType.class, Lane.class);
468
469 Category carCategory2 = new Category(categorization, carGTUType, this.graphLanes.get(2));
470 Category carCategory1 = new Category(categorization, carGTUType, this.graphLanes.get(1));
471 Category carCategory0 = new Category(categorization, carGTUType, this.graphLanes.get(0));
472 Category carCategoryR = new Category(categorization, carGTUType, onramp);
473 Category truCategory0 = new Category(categorization, truckGTUType, this.graphLanes.get(0));
474 Category truCategoryR = new Category(categorization, truckGTUType, onramp);
475 Category caccCategory = new Category(categorization, caccGTUType, this.graphLanes.get(0));
476 ODMatrix odMatrix = new ODMatrix("CACC OD", origins, destinations, categorization, timeVector, interpolation);
477
478 double intensityIncrease = this.intensity;
479 double platoonPenetration = this.penetration;
480
481 float[] mainlineDemand = new float[] {2584, 3028, 3228, 3510, 3228, 0};
482
483
484
485
486
487 List<Double> demandList = new ArrayList<Double>();
488 demandList.add((double) mainlineDemand[0] * 0.15 * intensityIncrease);
489 demandList.add((double) mainlineDemand[1] * 0.15 * intensityIncrease);
490 demandList.add(mainlineDemand[2] * 0.15 * intensityIncrease);
491 demandList.add(mainlineDemand[3] * 0.15 * intensityIncrease);
492 demandList.add(mainlineDemand[4] * 0.15 * intensityIncrease);
493 demandList.add(mainlineDemand[5] * 0.15 * intensityIncrease);
494 demandList.add(mainlineDemand[5] * 0.15 * intensityIncrease);
495 demandList.add(mainlineDemand[5] * 0.15 * intensityIncrease);
496 demandList.add((double) 0);
497 demandList.add((double) 0);
498 List<Double> demandPlatoon = new ArrayList<Double>();
499
500 List<Double> demandPlatoonVehicles = new ArrayList<Double>();
501
502 for (int k = 0; k < demandList.size(); k++)
503 {
504 double platoonVehicles = (demandList.get(k) * platoonPenetration);
505 double platoonPlatoons = (Math.round(platoonVehicles / platoonSize)) / 4;
506
507 double newDemandVal = Math.max(demandList.get(k) - platoonVehicles, 0);
508 demandList.set(k, newDemandVal);
509 demandPlatoon.add(platoonPlatoons);
510 platoonVehicles = platoonPlatoons * platoonSize * 4;
511
512 demandPlatoonVehicles.add(platoonVehicles);
513 }
514
515
516 Set<LaneDirection> position = new LinkedHashSet<>();
517 position.add(new LaneDirection(this.graphLanes.get(0), GTUDirectionality.DIR_PLUS));
518 DefaultGTUCharacteristicsGeneratorOD characteristicsGenerator =
519 getCharacteristicsGenerator(longitudinalControllerFactory, sim, parameters);
520 Platoons<Category> platoons =
521 Platoons.ofCategory(characteristicsGenerator, sim, sim.getReplication().getStream("generation"), position);
522
523 platoons.fixInfo(nodeA, nodeD, caccCategory);
524
525 double dt = this.startSpacing;
526
527
528
529
530 List<Double> generationTimes = new ArrayList<Double>();
531 double previous = 0;
532
533 for (int k = 0; k < demandList.size(); k++)
534 {
535 for (int i = 0; i < demandPlatoon.get(k); i++)
536 {
537 double lambda = (demandPlatoon.get(k) * 4);
538 StreamInterface rand = sim.getReplication().getStream("generation");
539
540 double arrival = (Math.log(1 - rand.nextDouble()) / (-lambda) * 3600);
541
542
543 double startTime = (arrival + previous);
544
545 generationTimes.add(startTime);
546 previous = previous + arrival;
547 }
548 }
549
550
551 Collections.sort(generationTimes);
552
553 for (int i = 0; i < generationTimes.size() - 1; i++)
554 {
555 double diff = generationTimes.get(i + 1) - generationTimes.get(i);
556 double generationDuration = 0.5;
557 double maxDuration = (generationDuration * platoonSize) + 1.0;
558 if (diff <= maxDuration)
559 {
560 generationTimes.set(i + 1, generationTimes.get(i) + maxDuration);
561 }
562
563
564 double endTime = generationTimes.get(i) + (generationDuration * platoonSize);
565 platoons.addPlatoon(Time.instantiateSI(generationTimes.get(i)), Time.instantiateSI(endTime));
566
567 for (double t = generationTimes.get(i); t < endTime; t += dt)
568 {
569 platoons.addGtu(Time.instantiateSI(t));
570 }
571 }
572
573
574
575 odMatrix.putDemandVector(nodeA, nodeD, carCategory2,
576 freq(new double[] {mainlineDemand[0] * 0.85 * (intensityIncrease),
577 mainlineDemand[1] * 0.85 * (intensityIncrease), mainlineDemand[2] * 0.85 * (intensityIncrease),
578 mainlineDemand[3] * 0.85 * (intensityIncrease), mainlineDemand[4] * 0.85 * (intensityIncrease),
579 mainlineDemand[5] * 0.85 * (intensityIncrease), mainlineDemand[5] * 0.85 * (intensityIncrease), 0,
580 0}),
581 timeVector, interpolation, 0.26);
582 odMatrix.putDemandVector(nodeA, nodeD, carCategory1,
583 freq(new double[] {mainlineDemand[0] * 0.85 * (intensityIncrease),
584 mainlineDemand[1] * 0.85 * (intensityIncrease), mainlineDemand[2] * 0.85 * (intensityIncrease),
585 mainlineDemand[3] * 0.85 * (intensityIncrease), mainlineDemand[4] * 0.85 * (intensityIncrease),
586 mainlineDemand[5] * 0.85 * (intensityIncrease), mainlineDemand[5] * 0.85 * (intensityIncrease), 0,
587 0}),
588 timeVector, interpolation, 0.32);
589 odMatrix.putDemandVector(nodeA, nodeD, carCategory0,
590 platoons.compensate(carCategory0, freq(new double[] {mainlineDemand[0] * 0.85 * (intensityIncrease),
591 mainlineDemand[1] * 0.85 * (intensityIncrease), mainlineDemand[2] * 0.85 * (intensityIncrease),
592 mainlineDemand[3] * 0.85 * (intensityIncrease), mainlineDemand[4] * 0.85 * (intensityIncrease),
593 mainlineDemand[5] * 0.85 * (intensityIncrease), mainlineDemand[5] * 0.85 * (intensityIncrease), 0,
594 0}), timeVector, interpolation),
595 timeVector, interpolation, 0.32);
596 odMatrix.putDemandVector(nodeE, nodeD, carCategoryR,
597 freq(new double[] {mainlineDemand[0] * 0.85 * 0.25 * (intensityIncrease),
598 mainlineDemand[1] * 0.85 * 0.25 * (intensityIncrease),
599 mainlineDemand[2] * 0.85 * 0.25 * (intensityIncrease),
600 mainlineDemand[3] * 0.85 * 0.25 * (intensityIncrease),
601 mainlineDemand[4] * 0.85 * 0.25 * (intensityIncrease),
602 mainlineDemand[5] * 0.85 * 0.25 * (intensityIncrease),
603 mainlineDemand[5] * 0.85 * 0.25 * (intensityIncrease), 0, 0}));
604
605 odMatrix.putDemandVector(nodeE, nodeD, truCategoryR,
606 freq(new double[] {mainlineDemand[0] * 0.15 * 0.25 * (intensityIncrease),
607 mainlineDemand[1] * 0.15 * 0.25 * (intensityIncrease),
608 mainlineDemand[2] * 0.15 * 0.25 * (intensityIncrease),
609 mainlineDemand[3] * 0.15 * 0.25 * (intensityIncrease),
610 mainlineDemand[4] * 0.15 * 0.25 * (intensityIncrease),
611 mainlineDemand[5] * 0.15 * 0.25 * (intensityIncrease),
612 mainlineDemand[5] * 0.15 * 0.25 * (intensityIncrease), 0, 0}));
613
614 if (this.penetration != 1.0)
615 {
616 odMatrix.putDemandVector(nodeA, nodeD, truCategory0, platoons.compensate(truCategory0,
617 freq(new double[] {demandList.get(0), demandList.get(1), demandList.get(2), demandList.get(3),
618 demandList.get(4), demandList.get(5), demandList.get(6), demandList.get(7), demandList.get(8)}),
619 timeVector, interpolation));
620 }
621 if (this.penetration != 0.0)
622 {
623 odMatrix.putDemandVector(nodeA, nodeD, caccCategory,
624 platoons.compensate(caccCategory, freq(new double[] {demandPlatoonVehicles.get(0),
625 demandPlatoonVehicles.get(1), demandPlatoonVehicles.get(2), demandPlatoonVehicles.get(3),
626 demandPlatoonVehicles.get(4), demandPlatoonVehicles.get(5), demandPlatoonVehicles.get(6),
627 demandPlatoonVehicles.get(7), demandPlatoonVehicles.get(8)}), timeVector, interpolation));
628 }
629
630 ODOptions odOptions = new ODOptions().set(ODOptions.NO_LC_DIST, Length.instantiateSI(300.0)).set(ODOptions.GTU_TYPE,
631 characteristicsGenerator);
632 odApplierOutput = ODApplier.applyOD(network, odMatrix, odOptions);
633
634
635 platoonDetector1 = "A1";
636 platoons.start(odApplierOutput.get(platoonDetector1).getGenerator());
637
638
639 BufferedWriter bw;
640 bw = new BufferedWriter(
641 new OutputStreamWriter(Writer.createOutputStream(this.outputFileGen, CompressionType.NONE)));
642 bw.write(String.format("Platoon generation times [s]: %s", generationTimes));
643 bw.close();
644 }
645 else if (networkName.equals("onrampMERGE"))
646 {
647
648 OTSPoint3D pointA = new OTSPoint3D(0, 0);
649 OTSPoint3D pointB = new OTSPoint3D(2000, 0);
650 OTSPoint3D pointC = new OTSPoint3D(2330, 0);
651 OTSPoint3D pointD = new OTSPoint3D(3330, 0);
652 OTSPoint3D pointE = new OTSPoint3D(1300, -40);
653
654
655 OTSRoadNode nodeA = new OTSRoadNode(network, "A", pointA, Direction.ZERO);
656 OTSRoadNode nodeB = new OTSRoadNode(network, "B", pointB, Direction.ZERO);
657 OTSRoadNode nodeC = new OTSRoadNode(network, "C", pointC, Direction.ZERO);
658 OTSRoadNode nodeD = new OTSRoadNode(network, "D", pointD, Direction.ZERO);
659 OTSRoadNode nodeE = new OTSRoadNode(network, "E", pointE, Direction.ZERO);
660
661
662 CrossSectionLink linkAB = new CrossSectionLink(network, "AB", nodeA, nodeB, freewayLinkType,
663 new OTSLine3D(pointA, pointB), LaneKeepingPolicy.KEEPRIGHT);
664 CrossSectionLink linkBC = new CrossSectionLink(network, "BC", nodeB, nodeC, freewayLinkType,
665 new OTSLine3D(pointB, pointC), LaneKeepingPolicy.KEEPRIGHT);
666 CrossSectionLink linkCD = new CrossSectionLink(network, "CD", nodeC, nodeD, freewayLinkType,
667 new OTSLine3D(pointC, pointD), LaneKeepingPolicy.KEEPRIGHT);
668 CrossSectionLink linkEB = new CrossSectionLink(network, "EB", nodeE, nodeB, freewayLinkType,
669 Bezier.cubic(nodeE.getLocation(), nodeB.getLocation()), LaneKeepingPolicy.KEEPRIGHT);
670
671
672 int n = this.numberOfLanes;
673
674 for (int i = 0; i < n; i++)
675 {
676 for (CrossSectionLink link : new CrossSectionLink[] {linkAB, linkBC, linkCD})
677 {
678 Lane lane = new Lane(link, "Lane " + (i + 1), laneWidth.times((0.5 + i)), laneWidth, freewayLaneType,
679 new Speed(100, SpeedUnit.KM_PER_HOUR));
680 Length offset = laneWidth.times(i + 1.0);
681 Stripe stripe = new Stripe(link, offset, offset, stripeWidth);
682 if (i < n - 1)
683 {
684 if (lane.getParentLink().getId().equals("BC"))
685 {
686
687 stripe.addPermeability(vehicle, Permeable.BOTH);
688
689 }
690 else
691 {
692 stripe.addPermeability(vehicle, Permeable.BOTH);
693 }
694 }
695 if (lane.getParentLink().getId().equals("BC"))
696 {
697 new Detector(lane.getFullId(), lane, Length.instantiateSI(330.0), sim);
698 }
699
700 if (lane.getParentLink().getId().equals("CD"))
701 {
702 new SinkSensor(lane, lane.getLength().minus(Length.instantiateSI(100.0)), GTUDirectionality.DIR_PLUS,
703 sim);
704
705
706
707 }
708 if (lane.getParentLink().getId().equals("AB"))
709 {
710
711 this.graphLanes.add(lane);
712 }
713 }
714 }
715 new Stripe(linkAB, Length.ZERO, Length.ZERO, stripeWidth);
716 Stripe stripe = new Stripe(linkBC, Length.ZERO, Length.ZERO, stripeWidth);
717 stripe.addPermeability(vehicle, Permeable.LEFT);
718 new Stripe(linkCD, Length.ZERO, Length.ZERO, stripeWidth);
719 new Lane(linkBC, "Acceleration lane", laneWidth.times(-0.5), laneWidth, freewayLaneType,
720 new Speed(100, SpeedUnit.KM_PER_HOUR));
721 Lane onramp = new Lane(linkEB, "Onramp", laneWidth.times(-0.5), laneWidth, freewayLaneType,
722 new Speed(100, SpeedUnit.KM_PER_HOUR));
723 new Stripe(linkEB, Length.ZERO, Length.ZERO, stripeWidth);
724 new Stripe(linkEB, laneWidth.neg(), laneWidth.neg(), stripeWidth);
725 new Stripe(linkBC, laneWidth.neg(), laneWidth.neg(), stripeWidth);
726
727
728 List<OTSRoadNode> origins = new ArrayList<>();
729 origins.add(nodeA);
730 origins.add(nodeE);
731 List<OTSRoadNode> destinations = new ArrayList<>();
732 destinations.add(nodeD);
733 TimeVector timeVector = DoubleVector.instantiate(new double[] {0.0, 0.25, 0.50, 0.75, 1.0, 1.25, 1.50, 1.75, 2.0},
734 TimeUnit.BASE_HOUR, StorageType.DENSE);
735 Interpolation interpolation = Interpolation.LINEAR;
736 Categorization categorization = new Categorization("CACC", GTUType.class, Lane.class);
737 Category carCategory1 = new Category(categorization, carGTUType, this.graphLanes.get(1));
738 Category carCategory0 = new Category(categorization, carGTUType, this.graphLanes.get(0));
739 Category carCategoryR = new Category(categorization, carGTUType, onramp);
740 Category truCategory0 = new Category(categorization, truckGTUType, this.graphLanes.get(0));
741 Category truCategoryR = new Category(categorization, truckGTUType, onramp);
742 Category caccCategory = new Category(categorization, caccGTUType, onramp);
743 ODMatrix odMatrix = new ODMatrix("CACC OD", origins, destinations, categorization, timeVector, interpolation);
744
745 double intensityIncrease = this.intensity;
746 double platoonPenetration = this.penetration;
747
748
749 List<Double> demandList = new ArrayList<Double>();
750 demandList.add((double) 0);
751 demandList.add((double) 0);
752 demandList.add(45 * (1 + intensityIncrease));
753 demandList.add(45 * (1 + intensityIncrease));
754 demandList.add(45 * (1 + intensityIncrease));
755 demandList.add(45 * (1 + intensityIncrease));
756 demandList.add(45 * (1 + intensityIncrease));
757
758 demandList.add((double) 0);
759 demandList.add((double) 0);
760 List<Double> demandPlatoon = new ArrayList<Double>();
761
762 List<Double> demandPlatoonVehicles = new ArrayList<Double>();
763
764 for (int k = 0; k < demandList.size(); k++)
765 {
766 double platoonVehicles = (demandList.get(k) * platoonPenetration);
767
768
769 double platoonPlatoons = Math.ceil(Math.abs(platoonVehicles / platoonSize)) / 4;
770 double newDemandVal = Math.max(demandList.get(k) - platoonVehicles, 0);
771 demandList.set(k, newDemandVal);
772 demandPlatoon.add(platoonPlatoons);
773 platoonVehicles = platoonPlatoons * platoonSize * 4;
774
775 demandPlatoonVehicles.add(platoonVehicles);
776 }
777
778
779 Set<LaneDirection> position = new LinkedHashSet<>();
780 position.add(new LaneDirection(onramp, GTUDirectionality.DIR_PLUS));
781 DefaultGTUCharacteristicsGeneratorOD characteristicsGenerator =
782 getCharacteristicsGenerator(longitudinalControllerFactory, sim, parameters);
783 Platoons<Category> platoons =
784 Platoons.ofCategory(characteristicsGenerator, sim, sim.getReplication().getStream("generation"), position);
785
786 platoons.fixInfo(nodeE, nodeD, caccCategory);
787
788 double dt = this.startSpacing;
789
790
791
792
793 List<Double> generationTimes = new ArrayList<Double>();
794 double previous = 0;
795
796 for (int k = 0; k < demandList.size(); k++)
797 {
798 for (int i = 0; i < demandPlatoon.get(k); i++)
799 {
800 double lambda = (demandPlatoon.get(k) * 4);
801 StreamInterface rand = sim.getReplication().getStream("generation");
802
803 double arrival = (Math.log(1 - rand.nextDouble()) / (-lambda) * 3600);
804
805
806 double startTime = (arrival + previous);
807
808 generationTimes.add(startTime);
809 previous = previous + arrival;
810 }
811 }
812
813
814 Collections.sort(generationTimes);
815
816 for (int i = 0; i < generationTimes.size() - 1; i++)
817 {
818 double diff = generationTimes.get(i + 1) - generationTimes.get(i);
819 double generationDuration = 0.5;
820 double maxDuration = (generationDuration * platoonSize) + 1.0;
821 if (diff <= maxDuration)
822 {
823 generationTimes.set(i + 1, generationTimes.get(i) + maxDuration);
824 }
825
826
827 double endTime = generationTimes.get(i) + (generationDuration * platoonSize);
828 platoons.addPlatoon(Time.instantiateSI(generationTimes.get(i)), Time.instantiateSI(endTime));
829
830 for (double t = generationTimes.get(i); t < endTime; t += dt)
831 {
832 platoons.addGtu(Time.instantiateSI(t));
833 }
834 }
835
836
837 odMatrix.putDemandVector(nodeA, nodeD, carCategory1,
838 freq(new double[] {0, 0, 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease),
839 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease),
840
841 0, 0}),
842 timeVector, interpolation, 0.5);
843 odMatrix.putDemandVector(nodeA, nodeD, carCategory0,
844 freq(new double[] {0, 0, 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease),
845 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease), 1000 * (1 + intensityIncrease),
846
847 0, 0}),
848 timeVector, interpolation, 0.5);
849 odMatrix.putDemandVector(nodeE, nodeD, carCategoryR,
850 platoons.compensate(carCategoryR,
851 freq(new double[] {0, 0, 250 * (1 + intensityIncrease), 250 * (1 + intensityIncrease),
852 250 * (1 + intensityIncrease), 250 * (1 + intensityIncrease), 250 * (1 + intensityIncrease),
853
854 0, 0}),
855 timeVector, interpolation));
856
857 odMatrix.putDemandVector(nodeA, nodeD, truCategory0,
858 platoons.compensate(truCategory0,
859 freq(new double[] {0, 0, 180 * (1 + intensityIncrease), 180 * (1 + intensityIncrease),
860 180 * (1 + intensityIncrease), 180 * (1 + intensityIncrease), 180 * (1 + intensityIncrease),
861
862 0, 0}),
863 timeVector, interpolation));
864
865 if (this.penetration != 1.0)
866 {
867 odMatrix.putDemandVector(nodeE, nodeD, truCategoryR,
868 freq(new double[] {demandList.get(0), demandList.get(1), demandList.get(2), demandList.get(3),
869 demandList.get(4), demandList.get(5), demandList.get(6), demandList.get(7), demandList.get(8)}),
870 timeVector, interpolation);
871 }
872 if (this.penetration != 0.0)
873 {
874 odMatrix.putDemandVector(nodeE, nodeD, caccCategory,
875 platoons.compensate(caccCategory, freq(new double[] {demandPlatoonVehicles.get(0),
876 demandPlatoonVehicles.get(1), demandPlatoonVehicles.get(2), demandPlatoonVehicles.get(3),
877 demandPlatoonVehicles.get(4), demandPlatoonVehicles.get(5), demandPlatoonVehicles.get(6),
878 demandPlatoonVehicles.get(7), demandPlatoonVehicles.get(8)}), timeVector, interpolation));
879 }
880
881
882 ODOptions odOptions = new ODOptions().set(ODOptions.NO_LC_DIST, Length.instantiateSI(300.0)).set(ODOptions.GTU_TYPE,
883 characteristicsGenerator);
884 odApplierOutput = ODApplier.applyOD(network, odMatrix, odOptions);
885
886
887 platoonDetector1 = "E1";
888 platoons.start(odApplierOutput.get(platoonDetector1).getGenerator());
889
890
891 BufferedWriter bw;
892 bw = new BufferedWriter(
893 new OutputStreamWriter(Writer.createOutputStream(this.outputFileGen, CompressionType.NONE)));
894 bw.write(String.format("Platoon generation times [s]: %s", generationTimes));
895 bw.close();
896
897 }
898 else
899 {
900 throw new RuntimeException("Network " + networkName + " not supported.");
901 }
902
903
904 odApplierOutput.get(platoonDetector1).getGenerator().addListener(new EventListenerInterface()
905 {
906
907 private Platoon platoon = null;
908
909
910 private LaneBasedGTU lastGtu;
911
912
913 @Override
914 public void notify(final EventInterface event) throws RemoteException
915 {
916 if (event.getType().equals(LaneBasedGTUGenerator.GTU_GENERATED_EVENT))
917 {
918 LaneBasedGTU gtu = (LaneBasedGTU) event.getContent();
919 if (gtu.getGTUType().equals(caccGTUType))
920 {
921
922
923
924
925 if (this.lastGtu == null || this.lastGtu.isDestroyed()
926 || this.lastGtu.getLocation().distance(gtu.getLocation()) > 3.0 * gtu.getSpeed().si
927 || this.platoon.size() >= platoonSize)
928 {
929 this.platoon = new Platoon();
930 }
931 this.platoon.addGtu(gtu.getId());
932 ((CaccTacticalPlanner) gtu.getTacticalPlanner()).setPlatoon(this.platoon);
933 this.lastGtu = gtu;
934 }
935 }
936 }
937 }, LaneBasedGTUGenerator.GTU_GENERATED_EVENT);
938
939
940 DefaultAnimationFactory.animateNetwork(network, sim, getGtuColorer());
941
942
943 this.sampler = RoadSampler.build(network).registerExtendedDataType(this.ttc)
944 .registerFilterDataType(new FilterDataGtuType()).create();
945
946
947 Time start = new Time(0.25, TimeUnit.BASE_HOUR);
948 Time end = new Time(2.00, TimeUnit.BASE_HOUR);
949 for (Link link : network.getLinkMap().values())
950 {
951 for (Lane lane : ((CrossSectionLink) link).getLanes())
952 {
953 KpiLaneDirection kpiLane = new KpiLaneDirection(new LaneData(lane), KpiGtuDirectionality.DIR_PLUS);
954 SpaceTimeRegion region = new SpaceTimeRegion(kpiLane, Length.ZERO, lane.getLength(), start, end);
955 this.regions.add(region);
956 this.sampler.registerSpaceTimeRegion(region);
957 }
958 }
959
960
961 for (Link link : network.getLinkMap().values())
962 {
963 for (Lane lane : ((CrossSectionLink) link).getLanes())
964 {
965 KpiLaneDirection kpiLane = new KpiLaneDirection(new LaneData(lane), KpiGtuDirectionality.DIR_PLUS);
966 SpaceTimeRegion region = new SpaceTimeRegion(kpiLane, Length.ZERO, lane.getLength(), start, end);
967 this.regions.add(region);
968 this.sampler.registerSpaceTimeRegion(region);
969 }
970 }
971 return network;
972 }
973
974
975 @Override
976 protected void addTabs(final OTSSimulatorInterface sim, final OTSSimulationApplication<?> animation)
977 {
978 if (this.graphs)
979 {
980
981 int h = (int) Math.sqrt(this.graphLanes.size());
982 int w = (int) Math.ceil(((double) this.graphLanes.size()) / h);
983 TablePanel charts = new TablePanel(w, h);
984 animation.getAnimationPanel().getTabbedPane().addTab(animation.getAnimationPanel().getTabbedPane().getTabCount(),
985 "statistics", charts);
986
987
988 int h2 = 0;
989 int w2 = 0;
990 for (int i = 0; i < this.graphLanes.size(); i++)
991 {
992 GraphPath<KpiLaneDirection> graphPath;
993 try
994 {
995
996 graphPath = GraphLaneUtil.createPath("Lane" + (i + 1),
997 new LaneDirection(this.graphLanes.get(i), GTUDirectionality.DIR_PLUS));
998 GraphPath.initRecording(sampler, graphPath);
999 }
1000 catch (NetworkException exception)
1001 {
1002 throw new RuntimeException(exception);
1003 }
1004 ContourDataSource<?> dataPool = new ContourDataSource<>(this.sampler.getSamplerData(), graphPath);
1005 SwingContourPlot plot = new SwingContourPlot(new ContourPlotSpeed("Speed lane " + (i + 1), sim, dataPool));
1006 charts.setCell(plot.getContentPane(), w2, h2);
1007 w2++;
1008 if (w2 > w)
1009 {
1010 w = 0;
1011 h2++;
1012 }
1013 }
1014 }
1015 }
1016
1017
1018 @Override
1019 protected void onSimulationEnd()
1020 {
1021
1022 Detector.writeToFile(getNetwork(), this.outputFileDets, true);
1023
1024
1025 double tts = 0.0;
1026 List<Float> ttcList = new ArrayList<>();
1027 List<String> ttcListGtuType = new ArrayList<>();
1028 List<Float> decList = new ArrayList<>();
1029 List<String> decListGtuType = new ArrayList<>();
1030 int[] counts = new int[120];
1031 Length detectorPosition = Length.instantiateSI(100.0);
1032 for (SpaceTimeRegion region : this.regions)
1033 {
1034 TrajectoryGroup<?> trajectoryGroup =
1035 this.sampler.getSamplerData().getTrajectoryGroup(region.getLaneDirection()).getTrajectoryGroup(
1036 region.getStartPosition(), region.getEndPosition(), region.getStartTime(), region.getEndTime());
1037 for (Trajectory<?> trajectory : trajectoryGroup)
1038 {
1039 try
1040 {
1041 tts += trajectory.getTotalDuration().si;
1042 String gtuTypeId = trajectory.getMetaData(metaGtu).getId();
1043 for (FloatDuration ttcVal : trajectory.getExtendedData(this.ttc))
1044 {
1045 if (!Float.isNaN(ttcVal.si) && ttcVal.si < 20)
1046 {
1047 ttcList.add(ttcVal.si);
1048 ttcListGtuType.add(gtuTypeId);
1049 }
1050 }
1051 for (float decVal : trajectory.getA())
1052 {
1053 if (decVal < -2.0)
1054 {
1055 decList.add(decVal);
1056 decListGtuType.add(gtuTypeId);
1057 }
1058 }
1059 if (region.getLaneDirection().getLaneData().getLinkData().getId().equals("CD") && trajectory.size() > 1
1060 && trajectory.getX(0) < detectorPosition.si
1061 && trajectory.getX(trajectory.size() - 1) > detectorPosition.si)
1062 {
1063 double t = trajectory.getTimeAtPosition(detectorPosition).si - region.getStartTime().si;
1064 counts[(int) (t / 60.0)]++;
1065 }
1066 }
1067 catch (SamplingException exception)
1068 {
1069 throw new RuntimeException("Unexpected exception: TimeToCollission not available or index out of bounds.",
1070 exception);
1071 }
1072 }
1073 }
1074 int qMax = 0;
1075 for (int i = 0; i < counts.length - 4; i++)
1076 {
1077 int q = 0;
1078 for (int j = i; j < i + 5; j++)
1079 {
1080 q += counts[j];
1081 }
1082 qMax = qMax > q ? qMax : q;
1083 }
1084 BufferedWriter bw;
1085 try
1086 {
1087 bw = new BufferedWriter(
1088 new OutputStreamWriter(Writer.createOutputStream(this.outputFileTraj, CompressionType.NONE)));
1089 bw.write(String.format("total time spent [s]: %.0f", tts));
1090 bw.newLine();
1091 bw.write(String.format("maximum flow [veh/5min]: %d", qMax));
1092 bw.newLine();
1093 bw.write(String.format("time to collision [s]: %s", ttcList));
1094 bw.newLine();
1095 bw.write(String.format("time to collision GTU type: %s", ttcListGtuType));
1096 bw.newLine();
1097 bw.write(String.format("strong decelerations [m/s^2]: %s", decList));
1098 bw.newLine();
1099 bw.write(String.format("strong decelerations GTU type: %s", decListGtuType));
1100 bw.close();
1101 }
1102 catch (IOException exception)
1103 {
1104 throw new RuntimeException(exception);
1105 }
1106 }
1107
1108
1109
1110
1111
1112
1113
1114 private FrequencyVector freq(final double[] array) throws ValueRuntimeException
1115 {
1116 return DoubleVector.instantiate(array, FrequencyUnit.PER_HOUR, StorageType.DENSE);
1117 }
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127 private DefaultGTUCharacteristicsGeneratorOD getCharacteristicsGenerator(
1128 final LongitudinalControllerFactory<? extends CaccController> longitudinalControllerFactory,
1129 final OTSSimulatorInterface simulator, final ParameterFactory parameters)
1130 {
1131
1132 Set<TemplateGTUType> templates = new LinkedHashSet<>();
1133 templates.add(new TemplateGTUType(caccGTUType, new ConstantGenerator<>(Length.instantiateSI(12.0)),
1134 new ConstantGenerator<>(Length.instantiateSI(2.55)),
1135 new ConstantGenerator<>(Speed.instantiateSI(this.setspeed.si + 2.78))));
1136
1137 return new DefaultGTUCharacteristicsGeneratorOD(templates, new StrategicalPlannerFactorySupplierOD()
1138 {
1139
1140 private LaneBasedStrategicalPlannerFactory<?> lmrsFactory = null;
1141
1142
1143 private LaneBasedStrategicalPlannerFactory<?> caccFactory = null;
1144
1145
1146 @Override
1147 public LaneBasedStrategicalPlannerFactory<?> getFactory(final Node origin, final Node destination,
1148 final Category category, final StreamInterface randomStream) throws GTUException
1149 {
1150 GTUType gtuType = category.get(GTUType.class);
1151 if (!gtuType.equals(caccGTUType))
1152 {
1153 if (this.lmrsFactory == null)
1154 {
1155
1156 Distribution<Estimation> estimation;
1157 try
1158 {
1159 estimation = new Distribution<>(randomStream);
1160 estimation.add(new FrequencyAndObject<>(fractionUnderestimation, Estimation.UNDERESTIMATION));
1161 estimation.add(new FrequencyAndObject<>(1.0 - fractionUnderestimation, Estimation.OVERESTIMATION));
1162 }
1163 catch (ProbabilityException ex)
1164 {
1165 throw new GTUException("Random stream is null.", ex);
1166 }
1167
1168 PerceptionFactory perceptionFactory = new LmrsPerceptionFactory(estimation);
1169
1170 this.lmrsFactory = new LaneBasedStrategicalRoutePlannerFactory(
1171 new LMRSFactory(new IDMPlusFactory(randomStream), perceptionFactory), parameters);
1172 }
1173 return this.lmrsFactory;
1174 }
1175 if (this.caccFactory == null)
1176 {
1177 this.caccFactory = new LaneBasedStrategicalRoutePlannerFactory(
1178 new CaccTacticalPlannerFactory(new IDMPlusFactory(randomStream), longitudinalControllerFactory,
1179 simulator, caccGTUType),
1180 parameters);
1181 }
1182 return this.caccFactory;
1183 }
1184 });
1185 }
1186
1187
1188 private class LmrsPerceptionFactory extends DefaultLMRSPerceptionFactory
1189 {
1190
1191 private final Distribution<Estimation> estimation;
1192
1193
1194
1195
1196
1197 LmrsPerceptionFactory(final Distribution<Estimation> estimation)
1198 {
1199 this.estimation = estimation;
1200 }
1201
1202
1203 @Override
1204 public LanePerception generatePerception(final LaneBasedGTU gtu)
1205 {
1206 Set<Task> tasksSet = new LinkedHashSet<>();
1207 if (tasks)
1208 {
1209 tasksSet.add(new CarFollowingTaskAR());
1210 tasksSet.add(new LaneChangeTaskAR());
1211 }
1212
1213 Set<BehavioralAdaptation> behavioralAdapatations = new LinkedHashSet<>();
1214 behavioralAdapatations.add(new AdaptationSituationalAwareness());
1215 if (adaptation)
1216 {
1217 behavioralAdapatations.add(new AdaptationHeadway());
1218 }
1219 LanePerception perception;
1220 if (tasks)
1221 {
1222 Fuller fuller = new Fuller(tasksSet, behavioralAdapatations, new TaskManagerAR());
1223 perception = new CategoricalLanePerception(gtu, fuller);
1224 }
1225 else
1226 {
1227 perception = new CategoricalLanePerception(gtu);
1228 }
1229 perception.addPerceptionCategory(new DirectEgoPerception<>(perception));
1230 perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
1231 Estimation est = Try.assign(() -> this.estimation.draw(), "Probability exception while drawing estimation.");
1232 perception.addPerceptionCategory(
1233 new DirectNeighborsPerception(perception, new PerceivedHeadwayGtuType(est, Anticipation.CONSTANT_SPEED)));
1234 perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
1235 perception.addPerceptionCategory(new DirectIntersectionPerception(perception, HeadwayGtuType.WRAP));
1236 return perception;
1237 }
1238
1239
1240 @Override
1241 public Parameters getParameters() throws ParameterException
1242 {
1243 Parameters params = super.getParameters();
1244
1245
1246
1247 params.setParameter(Fuller.TC, 1.0);
1248 params.setParameter(Fuller.TS_CRIT, 1.0);
1249 params.setParameter(Fuller.TS_MAX, 2.0);
1250 params.setParameter(AdaptationSituationalAwareness.SA, 1.0);
1251 params.setParameter(AdaptationSituationalAwareness.SA_MAX, 1.0);
1252 params.setParameter(AdaptationSituationalAwareness.SA_MIN, 0.5);
1253 params.setParameter(AdaptationSituationalAwareness.TR_MAX, Duration.instantiateSI(2.0));
1254 params.setParameter(ParameterTypes.TR, Duration.ZERO);
1255 params.setParameter(AdaptationHeadway.BETA_T, 1.0);
1256 return params;
1257 }
1258 }
1259
1260
1261 private class TaskManagerAR implements TaskManager
1262 {
1263
1264 @Override
1265 public void manage(final Set<Task> tasksMan, final LanePerception perception, final LaneBasedGTU gtu,
1266 final Parameters parameters) throws ParameterException, GTUException
1267 {
1268 Task primary = null;
1269 Set<Task> auxiliaryTasks = new LinkedHashSet<>();
1270 for (Task task : tasksMan)
1271 {
1272 if (task.getId().equals("lane-changing"))
1273 {
1274 primary = task;
1275 }
1276 else
1277 {
1278 auxiliaryTasks.add(task);
1279 }
1280 }
1281 Throw.whenNull(primary, "There is no task with id 'lane-changing'.");
1282 double primaryTaskDemand = primary.calculateTaskDemand(perception, gtu, parameters);
1283 primary.setTaskDemand(primaryTaskDemand);
1284
1285 double a = alpha;
1286 double b = beta;
1287 primary.setAnticipationReliance(a * primaryTaskDemand * (1.0 - primaryTaskDemand));
1288 for (Task auxiliary : auxiliaryTasks)
1289 {
1290 double auxiliaryTaskLoad = auxiliary.calculateTaskDemand(perception, gtu, parameters);
1291 auxiliary.setTaskDemand(auxiliaryTaskLoad);
1292
1293 auxiliary.setAnticipationReliance(b * auxiliaryTaskLoad * primaryTaskDemand);
1294 }
1295 }
1296 }
1297
1298
1299 private class CarFollowingTaskAR extends AbstractTask
1300 {
1301
1302 CarFollowingTaskAR()
1303 {
1304 super("car-following");
1305 }
1306
1307
1308 @Override
1309 public double calculateTaskDemand(final LanePerception perception, final LaneBasedGTU gtuCF,
1310 final Parameters parameters) throws ParameterException, GTUException
1311 {
1312 try
1313 {
1314 NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
1315 PerceptionCollectable<HeadwayGTU, LaneBasedGTU> leaders = neighbors.getLeaders(RelativeLane.CURRENT);
1316 CategoricalLanePerception clp = (CategoricalLanePerception) perception;
1317 if (null == ((DirectEgoPerception<?, ?>) clp.getPerceptionCategory(EgoPerception.class)).getTimeStampedSpeed())
1318 {
1319
1320
1321 try
1322 {
1323 clp.getPerceptionCategory(EgoPerception.class).updateAll();
1324 if (null == clp.getPerceptionCategory(EgoPerception.class).getSpeed())
1325 {
1326 System.out.println("fixed perception is " + perception);
1327 }
1328 }
1329 catch (GTUException | NetworkException | ParameterException e)
1330 {
1331 e.printStackTrace();
1332 }
1333 }
1334
1335
1336 return leaders.isEmpty() ? 0.0 : Math.exp(-leaders.first().getDistance().si
1337 / (perception.getGtu().getSpeed().si * hExp.si));
1338 }
1339 catch (OperationalPlanException ex)
1340 {
1341 throw new GTUException(ex);
1342 }
1343 }
1344 }
1345
1346
1347 private class LaneChangeTaskAR extends AbstractTask
1348 {
1349
1350 LaneChangeTaskAR()
1351 {
1352 super("lane-changing");
1353 }
1354
1355
1356 @Override
1357 public double calculateTaskDemand(final LanePerception perception, final LaneBasedGTU gtuLC,
1358 final Parameters parameters) throws ParameterException, GTUException
1359 {
1360 return Math.max(0.0,
1361 Math.max(parameters.getParameter(LmrsParameters.DLEFT), parameters.getParameter(LmrsParameters.DRIGHT)));
1362 }
1363 }
1364
1365 }