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