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