1 package org.opentrafficsim.road.gtu.generator.od;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Frequency;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GTUType;
10 import org.opentrafficsim.core.idgenerator.IdGenerator;
11 import org.opentrafficsim.core.network.LinkType;
12 import org.opentrafficsim.core.network.Node;
13 import org.opentrafficsim.road.gtu.generator.CFBARoomChecker;
14 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBias;
15 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
16 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
17 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
18 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
19 import org.opentrafficsim.road.network.RoadNetwork;
20 import org.opentrafficsim.road.network.lane.Lane;
21
22 /**
23 * Options for vehicle generation based on an OD matrix.
24 * <p>
25 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
27 * <p>
28 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
29 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
30 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
31 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
32 */
33 public class ODOptions
34 {
35 /** Headway randomization option. */
36 public static final Option<HeadwayDistribution> HEADWAY_DIST =
37 new Option<>("headway distribution", HeadwayDistribution.EXPONENTIAL);
38
39 /** ID generator option. */
40 public static final Option<IdGenerator> GTU_ID = new Option<>("gtu id", new IdGenerator(""));
41
42 /** GTU characteristics generator option. */
43 public static final Option<GTUCharacteristicsGeneratorOD> GTU_TYPE =
44 new Option<>("gtu type", new DefaultGTUCharacteristicsGeneratorOD());
45
46 /** Room checker option. */
47 public static final Option<RoomChecker> ROOM_CHECKER = new Option<>("room checker", new CFBARoomChecker());
48
49 /** Markov chain for GTU type option. */
50 public static final Option<MarkovCorrelation<GTUType, Frequency>> MARKOV = new Option<>("markov", null);
51
52 /** Initial distance over which lane changes shouldn't be performed option. */
53 public static final Option<Length> NO_LC_DIST = new Option<>("no lc distance", null);
54
55 /** Options overall. */
56 private OptionSet<Void> options = new OptionSet<>();
57
58 /** Options per lane. */
59 private OptionSet<Lane> laneOptions = new OptionSet<>();
60
61 /** Options per node. */
62 private OptionSet<Node> nodeOptions = new OptionSet<>();
63
64 /** Options per road type. */
65 private OptionSet<LinkType> linkTypeOptions = new OptionSet<>();
66
67 /** cache for lane biases per network. */
68 private static final Map<RoadNetwork, Option<LaneBiases>> LANE_BIAS_CACHE = new HashMap<>();
69
70 /**
71 * Lane bias. Default is Truck: truck right (strong right, max 2 lanes), Vehicle (other): weak left.
72 * @param network the network for which to return the lane bias
73 * @return the lane bias
74 */
75 public static final Option<LaneBiases> getLaneBiasOption(final RoadNetwork network)
76 {
77 Option<LaneBiases> laneBiases = LANE_BIAS_CACHE.get(network);
78 if (laneBiases == null)
79 {
80 laneBiases = new Option<>("lane bias",
81 new LaneBiases().addBias(network.getGtuType(GTUType.DEFAULTS.TRUCK), LaneBias.TRUCK_RIGHT)
82 .addBias(network.getGtuType(GTUType.DEFAULTS.VEHICLE), LaneBias.WEAK_LEFT));
83 LANE_BIAS_CACHE.put(network, laneBiases);
84 }
85 return laneBiases;
86 }
87
88 /**
89 * Set option value.
90 * @param option Option<K>; option
91 * @param value K; option value
92 * @param <K> value type
93 * @return this option set
94 */
95 public final <K> ODOptions set(final Option<K> option, final K value)
96 {
97 this.options.set(null, option, value);
98 return this;
99 }
100
101 /**
102 * Set option value for lane.
103 * @param lane Lane; lane
104 * @param option Option<K>; option
105 * @param value K; option value
106 * @param <K> value type
107 * @return this option set
108 */
109 public final <K> ODOptions set(final Lane lane, final Option<K> option, final K value)
110 {
111 this.laneOptions.set(lane, option, value);
112 return this;
113 }
114
115 /**
116 * Set option value for node.
117 * @param node Node; node
118 * @param option Option<K>; option
119 * @param value K; option value
120 * @param <K> value type
121 * @return this option set
122 */
123 public final <K> ODOptions set(final Node node, final Option<K> option, final K value)
124 {
125 this.nodeOptions.set(node, option, value);
126 return this;
127 }
128
129 /**
130 * Set option value for link type.
131 * @param linkType LinkType; link type
132 * @param option Option<K>; option
133 * @param value K; option value
134 * @param <K> value type
135 * @return this option set
136 */
137 public final <K> ODOptions set(final LinkType linkType, final Option<K> option, final K value)
138 {
139 this.linkTypeOptions.set(linkType, option, value);
140 return this;
141 }
142
143 /**
144 * Get option value. If a value is specified for a specific category, it is returned. The following order is used:
145 * <ul>
146 * <li>{@code Lane}</li>
147 * <li>{@code Node} (origin)</li>
148 * <li>{@code LinkType}</li>
149 * <li>None (global option value)</li>
150 * <li>Default option value</li>
151 * </ul>
152 * @param option Option<K>; option
153 * @param lane Lane; lane to obtain specific option value, may be null
154 * @param node Node; node to obtain specific option value, may be null
155 * @param linkType LinkType; link type to obtain specific option value, may be null
156 * @param <K> value type
157 * @return K; option value
158 */
159 public final <K> K get(final Option<K> option, final Lane lane, final Node node, final LinkType linkType)
160 {
161 Throw.whenNull(option, "Option may not be null.");
162 K value = this.laneOptions.get(lane, option);
163 if (value != null)
164 {
165 return value;
166 }
167 value = this.nodeOptions.get(node, option);
168 if (value != null)
169 {
170 return value;
171 }
172 value = this.linkTypeOptions.get(linkType, option);
173 if (value != null)
174 {
175 return value;
176 }
177 value = this.options.get(null, option);
178 if (value != null)
179 {
180 return value;
181 }
182 return option.getDefaultValue();
183 }
184
185 /**
186 * Utility class to store options.
187 * <p>
188 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
189 * <br>
190 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
191 * <p>
192 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
193 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
194 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
195 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
196 * @param <K> option value type
197 */
198 public static final class Option<K>
199 {
200
201 /** Id. */
202 private final String id;
203
204 /** Default value. */
205 private final K defaultValue;
206
207 /**
208 * Constructor.
209 * @param id String; id
210 * @param defaultValue K; default value
211 */
212 Option(final String id, final K defaultValue)
213 {
214 this.id = id;
215 this.defaultValue = defaultValue;
216 }
217
218 /**
219 * Returns the default value.
220 * @return default value
221 */
222 public K getDefaultValue()
223 {
224 return this.defaultValue;
225 }
226
227 /** {@inheritDoc} */
228 @Override
229 public int hashCode()
230 {
231 final int prime = 31;
232 int result = 1;
233 result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
234 return result;
235 }
236
237 /** {@inheritDoc} */
238 @Override
239 public boolean equals(final Object obj)
240 {
241 if (this == obj)
242 {
243 return true;
244 }
245 if (obj == null)
246 {
247 return false;
248 }
249 if (getClass() != obj.getClass())
250 {
251 return false;
252 }
253 Option<?> other = (Option<?>) obj;
254 if (this.id == null)
255 {
256 if (other.id != null)
257 {
258 return false;
259 }
260 }
261 else if (!this.id.equals(other.id))
262 {
263 return false;
264 }
265 return true;
266 }
267
268 /** {@inheritDoc} */
269 @Override
270 public String toString()
271 {
272 return "Option [id=" + this.id + "]";
273 }
274
275 }
276
277 /**
278 * Single set of options for a certain category, i.e. lane, node, link type or null (i.e. global).
279 * <p>
280 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
281 * <br>
282 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
283 * <p>
284 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 11 jan. 2018 <br>
285 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
286 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
287 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
288 * @param <C> category type, i.e. {@code Lane}, {@code Node}, {@code LinkType} or {@code Void} (i.e. global).
289 */
290 private class OptionSet<C>
291 {
292
293 /** Options. */
294 private Map<C, Map<Option<?>, Object>> optionsSet = new HashMap<>();
295
296 /**
297 * Constructor.
298 */
299 OptionSet()
300 {
301 //
302 }
303
304 /**
305 * Set value in option set.
306 * @param category C; category
307 * @param option Option<K>; option
308 * @param value K; value
309 * @param <K> option value type
310 */
311 public <K> void set(final C category, final Option<K> option, final K value)
312 {
313 Map<Option<?>, Object> map = this.optionsSet.get(category);
314 if (map == null)
315 {
316 map = new HashMap<>();
317 this.optionsSet.put(category, map);
318 }
319 map.put(option, value);
320 }
321
322 /**
323 * Returns the option value for the category.
324 * @param category C; category
325 * @param option Option<K>; option
326 * @return option value for the category
327 * @param <K> value type
328 */
329 @SuppressWarnings("unchecked")
330 public <K> K get(final C category, final Option<K> option)
331 {
332 if (!this.optionsSet.containsKey(category))
333 {
334 return null;
335 }
336 return (K) this.optionsSet.get(category).get(option);
337 }
338
339 }
340
341 }