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