1 package org.opentrafficsim.road.gtu;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertTrue;
5 import static org.junit.jupiter.api.Assertions.fail;
6
7 import java.util.ArrayList;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import org.djunits.unit.DurationUnit;
14 import org.djunits.unit.LengthUnit;
15 import org.djunits.unit.TimeUnit;
16 import org.djunits.unit.util.UNITS;
17 import org.djunits.value.vdouble.scalar.Acceleration;
18 import org.djunits.value.vdouble.scalar.Direction;
19 import org.djunits.value.vdouble.scalar.Duration;
20 import org.djunits.value.vdouble.scalar.Length;
21 import org.djunits.value.vdouble.scalar.Speed;
22 import org.djunits.value.vdouble.scalar.Time;
23 import org.djutils.draw.point.Point2d;
24 import org.junit.jupiter.api.Test;
25 import org.opentrafficsim.base.parameters.Parameters;
26 import org.opentrafficsim.core.definitions.DefaultsNl;
27 import org.opentrafficsim.core.dsol.AbstractOtsModel;
28 import org.opentrafficsim.core.dsol.OtsModelInterface;
29 import org.opentrafficsim.core.dsol.OtsSimulator;
30 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
31 import org.opentrafficsim.core.gtu.GtuException;
32 import org.opentrafficsim.core.gtu.GtuType;
33 import org.opentrafficsim.core.gtu.RelativePosition;
34 import org.opentrafficsim.core.network.Node;
35 import org.opentrafficsim.core.network.route.Route;
36 import org.opentrafficsim.core.perception.HistoryManagerDevs;
37 import org.opentrafficsim.road.DefaultTestParameters;
38 import org.opentrafficsim.road.definitions.DefaultsRoadNl;
39 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
40 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCfLcTacticalPlanner;
41 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
42 import org.opentrafficsim.road.gtu.lane.tactical.following.GtuFollowingModelOld;
43 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.FixedLaneChangeModel;
44 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
45 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
46 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlanner;
47 import org.opentrafficsim.road.network.RoadNetwork;
48 import org.opentrafficsim.road.network.factory.LaneFactory;
49 import org.opentrafficsim.road.network.lane.Lane;
50 import org.opentrafficsim.road.network.lane.LanePosition;
51 import org.opentrafficsim.road.network.lane.LaneType;
52
53 import nl.tudelft.simulation.dsol.SimRuntimeException;
54
55
56
57
58
59
60
61
62
63
64
65 public class AbstractLaneBasedGtuTest implements UNITS
66 {
67
68
69
70
71 @Test
72 public final void abstractLaneBasedGtuTest() throws Exception
73 {
74
75
76
77
78 OtsSimulatorInterface simulator = new OtsSimulator("abstractLaneBasedGtuTest");
79 RoadNetwork network = new RoadNetwork("lane base gtu test network", simulator);
80 OtsModelInterface model = new DummyModel(simulator);
81 simulator.initialize(Time.ZERO, Duration.ZERO, new Duration(1, DurationUnit.HOUR), model,
82 HistoryManagerDevs.noHistory(simulator));
83 Node nodeAFrom = new Node(network, "AFrom", new Point2d(0, 0), Direction.ZERO);
84 Node nodeATo = new Node(network, "ATo", new Point2d(1000, 0), Direction.ZERO);
85 GtuType gtuType = DefaultsNl.CAR;
86 LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
87
88 Lane[] lanesGroupA = LaneFactory.makeMultiLane(network, "A", nodeAFrom, nodeATo, null, 3, laneType,
89 new Speed(100, KM_PER_HOUR), simulator, DefaultsNl.VEHICLE);
90
91 Node nodeBFrom = new Node(network, "BFrom", new Point2d(10, 0), Direction.ZERO);
92 Node nodeBTo = new Node(network, "BTo", new Point2d(1000, 0), Direction.ZERO);
93 Lane[] lanesGroupB = LaneFactory.makeMultiLane(network, "B", nodeBFrom, nodeBTo, null, 3, laneType,
94 new Speed(100, KM_PER_HOUR), simulator, DefaultsNl.VEHICLE);
95 Set<LanePosition> initialLongitudinalPositions = new LinkedHashSet<>(2);
96
97 Length positionA = new Length(100, METER);
98 initialLongitudinalPositions.add(new LanePosition(lanesGroupA[1], positionA));
99 Length positionB = new Length(90, METER);
100 initialLongitudinalPositions.add(new LanePosition(lanesGroupB[1], positionB));
101
102 Acceleration acceleration = new Acceleration(2, METER_PER_SECOND_2);
103 Duration validFor = new Duration(10, SECOND);
104 GtuFollowingModelOld gfm = new FixedAccelerationModel(acceleration, validFor);
105
106
107 LaneChangeModel laneChangeModel = new FixedLaneChangeModel(null);
108
109 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
110
111 Length carLength = new Length(4, METER);
112
113 Length carWidth = new Length(1.8, METER);
114
115 Speed maximumSpeed = new Speed(200, KM_PER_HOUR);
116
117 String carID = "theCar";
118
119 List<Node> nodeList = new ArrayList<Node>();
120 nodeList.add(nodeAFrom);
121 nodeList.add(nodeATo);
122
123 Route route = new Route("Route", gtuType, nodeList);
124
125 Parameters parameters = DefaultTestParameters.create();
126
127
128
129 LaneBasedGtu car = new LaneBasedGtu(carID, gtuType, carLength, carWidth, maximumSpeed, carLength.times(0.5), network);
130 LaneBasedStrategicalPlanner strategicalPlanner =
131 new LaneBasedStrategicalRoutePlanner(new LaneBasedCfLcTacticalPlanner(gfm, laneChangeModel, car), car);
132 car.setParameters(parameters);
133 car.init(strategicalPlanner, new LanePosition(lanesGroupA[1], positionA), initialSpeed);
134
135 assertEquals(carID, car.getId(), "ID of the car should be identical to the provided one");
136
137
138
139 assertEquals(carWidth, car.getWidth(), "Width should be identical to the provided width");
140 assertEquals(carLength, car.getLength(), "Length should be identical to the provided length");
141 assertEquals(gtuType, car.getType(), "GTU type should be identical to the provided one");
142 assertEquals(positionA.getSI(), car.position(lanesGroupA[1], car.getReference()).getSI(), 0.0001,
143 "front in lanesGroupA[1] is positionA");
144
145
146 assertEquals(2.0, car.getAcceleration().getSI(), 0.00001, "acceleration is 2");
147 assertEquals(initialSpeed.getSI(), car.getSpeed().getSI(), 0.00001, "longitudinal speed is " + initialSpeed);
148 assertEquals(0, car.getOperationalPlan().getStartTime().getSI(), 0.00001, "lastEvaluation time is 0");
149
150
151
152
153
154
155
156
157
158
159
160 for (Lane[] laneGroup : new Lane[][] {lanesGroupA})
161 {
162 for (int laneIndex = 0; laneIndex < laneGroup.length; laneIndex++)
163 {
164 Lane lane = laneGroup[laneIndex];
165 boolean expectException = 1 != laneIndex;
166 for (RelativePosition relativePosition : new RelativePosition[] {car.getFront(), car.getReference(),
167 car.getRear()})
168 {
169
170
171 try
172 {
173 Length position = car.position(lane, relativePosition);
174 if (expectException)
175 {
176
177 fail("Calling position on lane that the car is NOT on should have thrown a NetworkException");
178 }
179 else
180 {
181 Length expectedPosition = laneGroup == lanesGroupA ? positionA : positionB;
182 expectedPosition = expectedPosition.plus(relativePosition.dx());
183
184
185 assertEquals(expectedPosition.getSI(), position.getSI(), 0.0001,
186 "Position should match initial position");
187 }
188 }
189 catch (GtuException ne)
190 {
191 if (!expectException)
192 {
193 System.out.println(ne);
194 fail("Calling position on lane that the car is on should NOT have thrown a NetworkException");
195 }
196 }
197 }
198 }
199 }
200
201
202 assertEquals(0, car.getOperationalPlan().getStartTime().getSI(), 0.00001, "lastEvaluation time is 0");
203
204
205 assertEquals(10.0, car.getOperationalPlan().getEndTime().getSI(), 0.00001, "nextEvaluation time is 10");
206
207 double step = 0.01d;
208 for (int i = 0;; i++)
209 {
210 Time stepTime = new Time(i * step, TimeUnit.BASE_SECOND);
211 if (stepTime.getSI() > validFor.getSI())
212 {
213 break;
214 }
215 if (stepTime.getSI() > 0.5)
216 {
217 step = 0.1;
218 }
219
220 simulator.runUpTo(stepTime);
221 while (simulator.isStartingOrRunning())
222 {
223 try
224 {
225 Thread.sleep(1);
226 }
227 catch (InterruptedException ie)
228 {
229 ie = null;
230 }
231 }
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 Speed longitudinalSpeed = car.getSpeed();
250 double expectedLongitudinalSpeed = initialSpeed.getSI() + stepTime.getSI() * acceleration.getSI();
251 assertEquals(expectedLongitudinalSpeed, longitudinalSpeed.getSI(), 0.00001,
252 "longitudinal speed is " + expectedLongitudinalSpeed);
253 for (RelativePosition relativePosition : new RelativePosition[] {car.getFront(), car.getRear()})
254 {
255 Map<Lane, Double> positions = car.fractionalPositions(relativePosition);
256 assertEquals(1, positions.size(), "Car should be in one lane");
257 Double pos = positions.get(lanesGroupA[1]);
258
259 assertTrue(null != pos, "Car should be in lane 1 of lane group A");
260 assertEquals(pos, car.fractionalPosition(lanesGroupA[1], relativePosition), 0.0000001,
261 "fractional position should be equal to result of fractionalPosition(lane, ...)");
262 }
263 for (Lane[] laneGroup : new Lane[][] {lanesGroupA})
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.dx());
291
292
293 assertEquals(expectedPosition.getSI(), position.getSI(), 0.0001,
294 "Position should match initial position");
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.dx());
321
322
323 double expectedFractionalPosition = expectedPosition.getSI() / lane.getLength().getSI();
324 assertEquals(expectedFractionalPosition, fractionalPosition, 0.000001,
325 "Position should match initial position");
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 Node nodeCFrom = new Node(network, "CFrom", new Point2d(10, 100), Direction.ZERO);
343 Node nodeCTo = new Node(network, "CTo", new Point2d(1000, 0), Direction.ZERO);
344 Lane[] lanesGroupC = LaneFactory.makeMultiLane(network, "C", nodeCFrom, nodeCTo, null, 3, laneType,
345 new Speed(100, KM_PER_HOUR), simulator, DefaultsNl.VEHICLE);
346 for (RelativePosition relativePosition : new RelativePosition[] {car.getFront(), car.getRear()})
347 {
348 Map<Lane, Double> positions = car.fractionalPositions(relativePosition);
349 Double pos = positions.get(lanesGroupA[1]);
350 assertTrue(null != pos, "Car should be in lane 1 of lane group A");
351 assertEquals(pos, car.fractionalPosition(lanesGroupA[1], relativePosition), 0.0000001,
352 "fractional position should be equal to result of fractionalPosition(lane, ...)");
353 pos = positions.get(lanesGroupC[0]);
354 }
355
356
357 }
358 }
359
360
361
362
363
364
365
366
367
368 class DummyModel extends AbstractOtsModel
369 {
370
371 private static final long serialVersionUID = 20150114L;
372
373
374
375
376 DummyModel(final OtsSimulatorInterface simulator)
377 {
378 super(simulator);
379 }
380
381 @Override
382 public final void constructModel() throws SimRuntimeException
383 {
384
385 }
386
387 @Override
388 public final RoadNetwork getNetwork()
389 {
390 return null;
391 }
392
393 }