1 package org.opentrafficsim.road.gtu.generator;
2
3 import java.rmi.RemoteException;
4
5 import org.djunits.unit.TimeUnit;
6 import org.djunits.value.ValueException;
7 import org.djunits.value.vdouble.scalar.Duration;
8 import org.djunits.value.vdouble.scalar.Frequency;
9 import org.djunits.value.vdouble.scalar.Time;
10 import org.djunits.value.vdouble.vector.FrequencyVector;
11 import org.djunits.value.vdouble.vector.TimeVector;
12 import org.opentrafficsim.core.distributions.Generator;
13 import org.opentrafficsim.core.distributions.ProbabilityException;
14 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
15 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
16 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
17
18 import nl.tudelft.simulation.language.Throw;
19
20
21
22
23
24
25
26
27
28
29
30
31 public class HeadwayGeneratorDemand implements Generator<Duration>
32 {
33
34
35 private final Interpolation interpolation;
36
37
38 private final TimeVector timeVector;
39
40
41 private final FrequencyVector demandVector;
42
43
44 private final OTSSimulatorInterface simulator;
45
46
47 private static final String HEADWAY_STREAM = "headwayGeneration";
48
49
50
51
52
53
54 public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
55 final OTSSimulatorInterface simulator)
56 {
57 this(timeVector, demandVector, simulator, Interpolation.STEPWISE);
58 }
59
60
61
62
63
64
65
66 public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
67 final OTSSimulatorInterface simulator, final Interpolation interpolation)
68 {
69 Throw.whenNull(timeVector, "Time vector may not be null.");
70 Throw.whenNull(demandVector, "Demand vector may not be null.");
71 Throw.whenNull(simulator, "Simulator may not be null.");
72 Throw.whenNull(interpolation, "Interpolation may not be null.");
73 try
74 {
75 Throw.whenNull(simulator.getReplication().getStream(HEADWAY_STREAM),
76 "Could not obtain random stream '" + HEADWAY_STREAM + "'.");
77 }
78 catch (RemoteException exception)
79 {
80 throw new RuntimeException("Could not obtain replication.", exception);
81 }
82 for (int i = 0; i < timeVector.size() - 1; i++)
83 {
84 try
85 {
86 Throw.when(timeVector.get(i).ge(timeVector.get(i + 1)), IllegalArgumentException.class,
87 "Time vector is not increasing.");
88 }
89 catch (ValueException exception)
90 {
91 throw new RuntimeException(
92 "Value out of range of time vector. Note that HeadwayGenerator does not create a safe copy.",
93 exception);
94 }
95 }
96 Throw.when(timeVector.size() != demandVector.size(), IllegalArgumentException.class,
97 "Time and flow vector should be of the same size.");
98 Throw.when(timeVector.size() < 2, IllegalArgumentException.class, "Time and flow vector should be at least of size 2.");
99 this.timeVector = timeVector;
100 this.demandVector = demandVector;
101 this.simulator = simulator;
102 this.interpolation = interpolation;
103 }
104
105
106 @Override
107 public Duration draw() throws ProbabilityException, ParameterException
108 {
109 Time time = this.simulator.getSimulatorTime().getTime();
110 try
111 {
112 Throw.when(time.lt(this.timeVector.get(0)), IllegalArgumentException.class,
113 "Cannot return a headway at time before first time in vector.");
114
115
116 int i = 0;
117 while (this.timeVector.get(i + 1).lt(time) && i < this.timeVector.size() - 1)
118 {
119 i++;
120 }
121 try
122 {
123 return nextArrival(i, time.minus(this.timeVector.get(i)), 1.0).minus(time);
124 }
125 catch (RemoteException exception)
126 {
127 throw new RuntimeException("Could not obtain replication.", exception);
128 }
129 }
130 catch (ValueException exception)
131 {
132 throw new RuntimeException(
133 "Value out of range of time or demand vector. Note that HeadwayGenerator does not create safe copies.",
134 exception);
135 }
136 }
137
138
139
140
141
142
143
144
145
146
147
148 private Time nextArrival(final int i, final Duration start, final double fractionRemaining)
149 throws ValueException, RemoteException
150 {
151
152
153 if (i == this.timeVector.size() - 1)
154 {
155 return new Time(Double.POSITIVE_INFINITY, TimeUnit.BASE);
156 }
157
158
159 if (this.demandVector.get(i).equals(Frequency.ZERO))
160 {
161
162 return nextArrival(i + 1, Duration.ZERO, this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble());
163 }
164
165
166 Frequency demand;
167 if (this.interpolation.isStepWise())
168 {
169 demand = this.demandVector.get(i);
170 }
171 else
172 {
173 double f = start.si / (this.timeVector.get(i + 1).si - this.timeVector.get(i).si);
174 demand = Frequency.interpolate(this.demandVector.get(i), this.demandVector.get(i + 1), f);
175 }
176 double t = -Math.log(this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble()) / demand.si;
177
178
179 Time arrival = new Time(this.timeVector.get(i).si + start.si + t * fractionRemaining, TimeUnit.BASE);
180
181
182 if (arrival.gt(this.timeVector.get(i + 1)))
183 {
184 double inStep = this.timeVector.get(i + 1).si - (this.timeVector.get(i).si + start.si);
185 return nextArrival(i + 1, Duration.ZERO, fractionRemaining - inStep / t);
186 }
187
188 return arrival;
189
190 }
191
192 }