1 package org.opentrafficsim.road.gtu;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertTrue;
5 import static org.junit.Assert.fail;
6 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
7
8 import java.util.ArrayList;
9 import java.util.HashSet;
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.unit.LengthUnit;
16 import org.djunits.unit.UNITS;
17 import org.djunits.value.vdouble.scalar.Acceleration;
18 import org.djunits.value.vdouble.scalar.Duration;
19 import org.djunits.value.vdouble.scalar.Length;
20 import org.djunits.value.vdouble.scalar.Speed;
21 import org.djunits.value.vdouble.scalar.Time;
22 import org.junit.Test;
23 import org.opentrafficsim.core.dsol.OTSModelInterface;
24 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
25 import org.opentrafficsim.core.geometry.OTSPoint3D;
26 import org.opentrafficsim.core.gtu.GTUDirectionality;
27 import org.opentrafficsim.core.gtu.GTUException;
28 import org.opentrafficsim.core.gtu.GTUType;
29 import org.opentrafficsim.core.gtu.RelativePosition;
30 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
31 import org.opentrafficsim.core.network.LongitudinalDirectionality;
32 import org.opentrafficsim.core.network.Node;
33 import org.opentrafficsim.core.network.OTSNetwork;
34 import org.opentrafficsim.core.network.OTSNode;
35 import org.opentrafficsim.core.network.route.CompleteRoute;
36 import org.opentrafficsim.road.DefaultTestParameters;
37 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
38 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner;
39 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
40 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
41 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.FixedLaneChangeModel;
42 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
43 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
44 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
45 import org.opentrafficsim.road.network.factory.LaneFactory;
46 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
47 import org.opentrafficsim.road.network.lane.Lane;
48 import org.opentrafficsim.road.network.lane.LaneType;
49 import org.opentrafficsim.simulationengine.SimpleSimulator;
50 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
51
52 import nl.tudelft.simulation.dsol.SimRuntimeException;
53 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class AbstractLaneBasedGTUTest implements UNITS
68 {
69
70 private OTSNetwork network = new OTSNetwork("lane base gtu test network");
71
72
73
74
75
76 @Test
77 public void abstractLaneBasedGTUTest() throws Exception
78 {
79
80
81
82 OTSNode nodeAFrom = new OTSNode(this.network, "AFrom", new OTSPoint3D(0, 0, 0));
83 OTSNode nodeATo = new OTSNode(this.network, "ATo", new OTSPoint3D(1000, 0, 0));
84 GTUType gtuType = CAR;
85 Set<GTUType> compatibility = new HashSet<GTUType>();
86 compatibility.add(gtuType);
87 LaneType laneType = new LaneType("CarLane", compatibility);
88
89 OTSModelInterface model = new DummyModel();
90 final SimpleSimulatorInterface simulator =
91 new SimpleSimulator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND), model);
92
93 Lane[] lanesGroupA = LaneFactory.makeMultiLane(this.network, "A", nodeAFrom, nodeATo, null, 3, laneType,
94 new Speed(100, KM_PER_HOUR), simulator, LongitudinalDirectionality.DIR_PLUS);
95
96 OTSNode nodeBFrom = new OTSNode(this.network, "BFrom", new OTSPoint3D(10, 0, 0));
97 OTSNode nodeBTo = new OTSNode(this.network, "BTo", new OTSPoint3D(1000, 0, 0));
98 Lane[] lanesGroupB = LaneFactory.makeMultiLane(this.network, "B", nodeBFrom, nodeBTo, null, 3, laneType,
99 new Speed(100, KM_PER_HOUR), simulator, LongitudinalDirectionality.DIR_PLUS);
100 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(2);
101
102 Length positionA = new Length(100, METER);
103 initialLongitudinalPositions.add(new DirectedLanePosition(lanesGroupA[1], positionA, GTUDirectionality.DIR_PLUS));
104 Length positionB = new Length(90, METER);
105 initialLongitudinalPositions.add(new DirectedLanePosition(lanesGroupB[1], positionB, GTUDirectionality.DIR_PLUS));
106
107 Acceleration acceleration = new Acceleration(2, METER_PER_SECOND_2);
108 Duration validFor = new Duration(10, SECOND);
109 GTUFollowingModelOld gfm = new FixedAccelerationModel(acceleration, validFor);
110
111
112 LaneChangeModel laneChangeModel = new FixedLaneChangeModel(null);
113
114 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
115
116 Length carLength = new Length(4, METER);
117
118 Length carWidth = new Length(1.8, METER);
119
120 Speed maximumSpeed = new Speed(200, KM_PER_HOUR);
121
122 String carID = "theCar";
123
124 List<Node> nodeList = new ArrayList<Node>();
125 nodeList.add(nodeAFrom);
126 nodeList.add(nodeATo);
127
128 CompleteRoute route = new CompleteRoute("Route", gtuType, nodeList);
129
130 BehavioralCharacteristics behavioralCharacteristics = DefaultTestParameters.create();
131
132
133
134 LaneBasedIndividualGTU car =
135 new LaneBasedIndividualGTU(carID, gtuType, carLength, carWidth, maximumSpeed, simulator, this.network);
136 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
137 new LaneBasedCFLCTacticalPlanner(gfm, laneChangeModel, car), car);
138 car.init(strategicalPlanner, initialLongitudinalPositions, initialSpeed);
139
140 assertEquals("ID of the car should be identical to the provided one", carID, car.getId());
141
142
143
144 assertEquals("Width should be identical to the provided width", carWidth, car.getWidth());
145 assertEquals("Length should be identical to the provided length", carLength, car.getLength());
146 assertEquals("GTU type should be identical to the provided one", gtuType, car.getGTUType());
147 assertEquals("front in lanesGroupA[1] is positionA", positionA.getSI(),
148 car.position(lanesGroupA[1], car.getReference()).getSI(), 0.0001);
149 assertEquals("front in lanesGroupB[1] is positionB", positionB.getSI(),
150 car.position(lanesGroupB[1], car.getReference()).getSI(), 0.0001);
151
152
153 assertEquals("acceleration is 2", 2.0, car.getAcceleration().getSI(), 0.00001);
154 assertEquals("longitudinal speed is " + initialSpeed, initialSpeed.getSI(), car.getSpeed().getSI(), 0.00001);
155 assertEquals("lastEvaluation time is 0", 0, car.getOperationalPlan().getStartTime().getSI(), 0.00001);
156
157 try
158 {
159 car.position(null, car.getFront());
160 fail("position on null lane should have thrown a NetworkException");
161 }
162 catch (GTUException ne)
163 {
164
165 }
166 for (Lane[] laneGroup : new Lane[][] { lanesGroupA, lanesGroupB })
167 {
168 for (int laneIndex = 0; laneIndex < laneGroup.length; laneIndex++)
169 {
170 Lane lane = laneGroup[laneIndex];
171 boolean expectException = 1 != laneIndex;
172 for (RelativePosition relativePosition : new RelativePosition[] { car.getFront(), car.getReference(),
173 car.getRear() })
174 {
175
176
177 try
178 {
179 Length position = car.position(lane, relativePosition);
180 if (expectException)
181 {
182
183 fail("Calling position on lane that the car is NOT on should have thrown a NetworkException");
184 }
185 else
186 {
187 Length expectedPosition = laneGroup == lanesGroupA ? positionA : positionB;
188 expectedPosition = expectedPosition.plus(relativePosition.getDx());
189
190
191 assertEquals("Position should match initial position", expectedPosition.getSI(), position.getSI(),
192 0.0001);
193 }
194 }
195 catch (GTUException ne)
196 {
197 if (!expectException)
198 {
199 System.out.println(ne);
200 fail("Calling position on lane that the car is on should NOT have thrown a NetworkException");
201 }
202 }
203 }
204 }
205 }
206
207
208 assertEquals("lastEvaluation time is 0", 0, car.getOperationalPlan().getStartTime().getSI(), 0.00001);
209
210
211 assertEquals("nextEvaluation time is 10", 10.0, car.getOperationalPlan().getEndTime().getSI(), 0.00001);
212
213 double step = 0.01d;
214 for (int i = 0;; i++)
215 {
216 Time stepTime = new Time(i * step, SECOND);
217 if (stepTime.getSI() > validFor.getSI())
218 {
219 break;
220 }
221 if (stepTime.getSI() > 0.5)
222 {
223 step = 0.1;
224 }
225
226 simulator.runUpTo(stepTime);
227 while (simulator.isRunning())
228 {
229 try
230 {
231 Thread.sleep(1);
232 }
233 catch (InterruptedException ie)
234 {
235 ie = null;
236 }
237 }
238
239 if (stepTime.getSI() > 0)
240 {
241 assertEquals("nextEvaluation time is " + validFor, validFor.getSI(),
242 car.getOperationalPlan().getEndTime().getSI(), 0.0001);
243 assertEquals("acceleration is " + acceleration, acceleration.getSI(), car.getAcceleration().getSI(), 0.00001);
244 }
245 Speed longitudinalSpeed = car.getSpeed();
246 double expectedLongitudinalSpeed = initialSpeed.getSI() + stepTime.getSI() * acceleration.getSI();
247 assertEquals("longitudinal speed is " + expectedLongitudinalSpeed, expectedLongitudinalSpeed,
248 longitudinalSpeed.getSI(), 0.00001);
249 for (RelativePosition relativePosition : new RelativePosition[] { car.getFront(), car.getRear() })
250 {
251 Map<Lane, Double> positions = car.fractionalPositions(relativePosition);
252 assertEquals("Car should be in two lanes", 2, positions.size());
253 Double pos = positions.get(lanesGroupA[1]);
254
255 assertTrue("Car should be in lane 1 of lane group A", null != pos);
256 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
257 car.fractionalPosition(lanesGroupA[1], relativePosition), 0.0000001);
258 pos = positions.get(lanesGroupB[1]);
259 assertTrue("Car should be in lane 1 of lane group B", null != pos);
260 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
261 car.fractionalPosition(lanesGroupB[1], relativePosition), 0.0000001);
262 }
263 for (Lane[] laneGroup : new Lane[][] { lanesGroupA, lanesGroupB })
264 {
265 for (int laneIndex = 0; laneIndex < laneGroup.length; laneIndex++)
266 {
267 Lane lane = laneGroup[laneIndex];
268 boolean expectException = 1 != laneIndex;
269 for (RelativePosition relativePosition : new RelativePosition[] { car.getFront(), car.getReference(),
270 car.getRear() })
271 {
272
273
274 try
275 {
276 Length position = car.position(lane, relativePosition);
277 if (expectException)
278 {
279
280 fail("Calling position on lane that the car is NOT on should have thrown a "
281 + "NetworkException");
282 }
283 else
284 {
285 Length expectedPosition = laneGroup == lanesGroupA ? positionA : positionB;
286 expectedPosition = expectedPosition
287 .plus(new Length(stepTime.getSI() * initialSpeed.getSI(), LengthUnit.SI));
288 expectedPosition = expectedPosition.plus(new Length(
289 0.5 * acceleration.getSI() * stepTime.getSI() * stepTime.getSI(), LengthUnit.SI));
290 expectedPosition = expectedPosition.plus(relativePosition.getDx());
291
292
293 assertEquals("Position should match initial position", expectedPosition.getSI(),
294 position.getSI(), 0.0001);
295 }
296 }
297 catch (GTUException ne)
298 {
299 if (!expectException)
300 {
301 System.out.println(ne);
302 fail("Calling position on lane that the car is on should NOT have thrown a NetworkException");
303 }
304 }
305 try
306 {
307 double fractionalPosition = car.fractionalPosition(lane, relativePosition);
308 if (expectException)
309 {
310
311 fail("Calling position on lane that the car is NOT on should have thrown a NetworkException");
312 }
313 else
314 {
315 Length expectedPosition = laneGroup == lanesGroupA ? positionA : positionB;
316 expectedPosition = expectedPosition
317 .plus(new Length(stepTime.getSI() * initialSpeed.getSI(), LengthUnit.SI));
318 expectedPosition = expectedPosition.plus(new Length(
319 0.5 * acceleration.getSI() * stepTime.getSI() * stepTime.getSI(), LengthUnit.SI));
320 expectedPosition = expectedPosition.plus(relativePosition.getDx());
321
322
323 double expectedFractionalPosition = expectedPosition.getSI() / lane.getLength().getSI();
324 assertEquals("Position should match initial position", expectedFractionalPosition,
325 fractionalPosition, 0.000001);
326 }
327 }
328 catch (GTUException ne)
329 {
330 if (!expectException)
331 {
332 System.out.println(ne);
333 fail("Calling fractionalPosition on lane that the car is on should NOT have thrown a "
334 + "NetworkException");
335 }
336 }
337 }
338 }
339 }
340 }
341
342 OTSNode nodeCFrom = new OTSNode(this.network, "CFrom", new OTSPoint3D(10, 100, 0));
343 OTSNode nodeCTo = new OTSNode(this.network, "CTo", new OTSPoint3D(1000, 0, 0));
344 Lane[] lanesGroupC = LaneFactory.makeMultiLane(this.network, "C", nodeCFrom, nodeCTo, null, 3, laneType,
345 new Speed(100, KM_PER_HOUR), simulator, LongitudinalDirectionality.DIR_PLUS);
346 car.enterLane(lanesGroupC[0], new Length(0.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS);
347 for (RelativePosition relativePosition : new RelativePosition[] { car.getFront(), car.getRear() })
348 {
349 Map<Lane, Double> positions = car.fractionalPositions(relativePosition);
350 assertEquals("Car should be in three lanes", 3, positions.size());
351 Double pos = positions.get(lanesGroupA[1]);
352 assertTrue("Car should be in lane 1 of lane group A", null != pos);
353 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
354 car.fractionalPosition(lanesGroupA[1], relativePosition), 0.0000001);
355 pos = positions.get(lanesGroupB[1]);
356 assertTrue("Car should be in lane 1 of lane group B", null != pos);
357 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
358 car.fractionalPosition(lanesGroupB[1], relativePosition), 0.0000001);
359 pos = positions.get(lanesGroupC[0]);
360 assertTrue("Car should be in lane 0 of lane group C", null != pos);
361
362
363
364 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
365 car.fractionalPosition(lanesGroupC[0], relativePosition), 0.0000001);
366 }
367 car.leaveLane(lanesGroupA[1]);
368 for (RelativePosition relativePosition : new RelativePosition[] { car.getFront(), car.getRear() })
369 {
370 Map<Lane, Double> positions = car.fractionalPositions(relativePosition);
371 assertEquals("Car should be in two lanes", 2, positions.size());
372 Double pos = positions.get(lanesGroupB[1]);
373 assertTrue("Car should be in lane 1 of lane group B", null != pos);
374 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
375 car.fractionalPosition(lanesGroupB[1], relativePosition), 0.0000001);
376 pos = positions.get(lanesGroupC[0]);
377 assertTrue("Car should be in lane 0 of lane group C", null != pos);
378
379
380
381 assertEquals("fractional position should be equal to result of fractionalPosition(lane, ...)", pos,
382 car.fractionalPosition(lanesGroupC[0], relativePosition), 0.0000001);
383 }
384
385
386 }
387 }
388
389
390
391
392
393
394
395
396
397
398
399 class DummyModel implements OTSModelInterface
400 {
401
402 private static final long serialVersionUID = 20150114L;
403
404
405 private SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator;
406
407
408
409
410
411 public void setSimulator(SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
412 {
413 this.simulator = simulator;
414 }
415
416
417 @Override
418 public OTSNetwork getNetwork()
419 {
420 return null;
421 }
422
423
424 @Override
425 public void constructModel(SimulatorInterface<Time, Duration, OTSSimTimeDouble> arg0) throws SimRuntimeException
426 {
427
428 }
429
430
431 @Override
432 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
433
434 {
435 if (null == this.simulator)
436 {
437 throw new Error("getSimulator called, but simulator field is null");
438 }
439 return this.simulator;
440 }
441
442 }