1 package org.opentrafficsim.road.gtu.lane.changing;
2
3 import static org.junit.Assert.assertEquals;
4
5 import java.util.Collection;
6 import java.util.HashSet;
7 import java.util.LinkedHashMap;
8 import java.util.LinkedHashSet;
9 import java.util.Map;
10 import java.util.Set;
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.djunits.unit.LengthUnit;
18 import org.djunits.unit.TimeUnit;
19 import org.djunits.unit.UNITS;
20 import org.djunits.value.vdouble.scalar.Acceleration;
21 import org.djunits.value.vdouble.scalar.DoubleScalar;
22 import org.djunits.value.vdouble.scalar.Duration;
23 import org.djunits.value.vdouble.scalar.Length;
24 import org.djunits.value.vdouble.scalar.Speed;
25 import org.djunits.value.vdouble.scalar.Time;
26 import org.junit.Test;
27 import org.opentrafficsim.core.dsol.OTSModelInterface;
28 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
29 import org.opentrafficsim.core.geometry.OTSGeometryException;
30 import org.opentrafficsim.core.geometry.OTSLine3D;
31 import org.opentrafficsim.core.geometry.OTSPoint3D;
32 import org.opentrafficsim.core.gtu.GTUDirectionality;
33 import org.opentrafficsim.core.gtu.GTUType;
34 import org.opentrafficsim.core.gtu.RelativePosition;
35 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
36 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
37 import org.opentrafficsim.core.network.LateralDirectionality;
38 import org.opentrafficsim.core.network.LinkType;
39 import org.opentrafficsim.core.network.LongitudinalDirectionality;
40 import org.opentrafficsim.core.network.Network;
41 import org.opentrafficsim.core.network.NetworkException;
42 import org.opentrafficsim.core.network.OTSNetwork;
43 import org.opentrafficsim.core.network.OTSNode;
44 import org.opentrafficsim.road.DefaultTestParameters;
45 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
46 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
47 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTUSimple;
48 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner;
49 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
50 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
51 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
52 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
53 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
54 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneMovementStep;
55 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
56 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
57 import org.opentrafficsim.road.network.lane.CrossSectionLink;
58 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
59 import org.opentrafficsim.road.network.lane.Lane;
60 import org.opentrafficsim.road.network.lane.LaneType;
61 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
62 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
63 import org.opentrafficsim.simulationengine.SimpleSimulator;
64
65
66
67
68
69
70
71
72
73
74
75 public class LaneChangeModelTest implements OTSModelInterface, UNITS
76 {
77
78 private static final long serialVersionUID = 20150313;
79
80
81 private Network network = new OTSNetwork("lane change model test network");
82
83
84
85
86
87
88
89
90
91
92
93
94 private static CrossSectionLink makeLink(final Network network, final String name, final OTSNode from, final OTSNode to,
95 final Length width) throws OTSGeometryException, NetworkException
96 {
97
98
99 OTSPoint3D[] coordinates =
100 new OTSPoint3D[] { new OTSPoint3D(from.getPoint().x, from.getPoint().y, 0),
101 new OTSPoint3D(to.getPoint().x, to.getPoint().y, 0) };
102 OTSLine3D line = new OTSLine3D(coordinates);
103 CrossSectionLink link =
104 new CrossSectionLink(network, name, from, to, LinkType.ALL, line, LongitudinalDirectionality.DIR_PLUS,
105 LaneKeepingPolicy.KEEP_RIGHT);
106 return link;
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121 private static Lane makeLane(final CrossSectionLink link, final String id, final LaneType laneType, final Length latPos,
122 final Length width) throws NamingException, NetworkException, OTSGeometryException
123 {
124 Map<GTUType, LongitudinalDirectionality> directionalityMap = new LinkedHashMap<>();
125 directionalityMap.put(GTUType.ALL, LongitudinalDirectionality.DIR_PLUS);
126 Map<GTUType, Speed> speedMap = new LinkedHashMap<>();
127 speedMap.put(GTUType.ALL, new Speed(100, KM_PER_HOUR));
128
129 Lane result =
130 new Lane(link, id, latPos, latPos, width, width, laneType, directionalityMap, speedMap,
131 new OvertakingConditions.LeftAndRight());
132 return result;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 public static Lane[] makeMultiLane(final Network network, final String name, final OTSNode from, final OTSNode to,
147 final LaneType laneType, final int laneCount) throws Exception
148 {
149 Length width = new Length(laneCount * 4.0, METER);
150 final CrossSectionLink link = makeLink(network, name, from, to, width);
151 Lane[] result = new Lane[laneCount];
152 width = new Length(4.0, METER);
153 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
154 {
155
156 Length latPos = new Length((-0.5 - laneIndex) * width.getSI(), METER);
157 result[laneIndex] = makeLane(link, "lane." + laneIndex, laneType, latPos, width);
158 }
159 return result;
160 }
161
162
163
164
165
166 @Test
167 public final void changeRight() throws Exception
168 {
169 GTUType gtuType = new GTUType("car");
170 Set<GTUType> compatibility = new HashSet<GTUType>();
171 compatibility.add(gtuType);
172 LaneType laneType = new LaneType("CarLane", compatibility);
173 int laneCount = 2;
174 Lane[] lanes =
175 makeMultiLane(this.network, "Road with two lanes", new OTSNode(this.network, "From", new OTSPoint3D(0, 0, 0)),
176 new OTSNode(this.network, "To", new OTSPoint3D(200, 0, 0)), laneType, laneCount);
177
178
179
180 lanes[0].accessibleAdjacentLanes(LateralDirectionality.RIGHT, gtuType);
181 assertEquals("Leftmost lane should not have accessible adjacent lanes on the LEFT side", 0, lanes[0]
182 .accessibleAdjacentLanes(LateralDirectionality.LEFT, gtuType).size());
183 assertEquals("Leftmost lane should have one accessible adjacent lane on the RIGHT side", 1, lanes[0]
184 .accessibleAdjacentLanes(LateralDirectionality.RIGHT, gtuType).size());
185 assertEquals("Rightmost lane should have one accessible adjacent lane on the LEFT side", 1, lanes[1]
186 .accessibleAdjacentLanes(LateralDirectionality.LEFT, gtuType).size());
187 assertEquals("Rightmost lane should not have accessible adjacent lanes on the RIGHT side", 0, lanes[1]
188 .accessibleAdjacentLanes(LateralDirectionality.RIGHT, gtuType).size());
189
190 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(1);
191 initialLongitudinalPositions
192 .add(new DirectedLanePosition(lanes[1], new Length(100, METER), GTUDirectionality.DIR_PLUS));
193 SimpleSimulator simpleSimulator =
194 new SimpleSimulator(new Time(0, SECOND), new Duration(0, SECOND), new Duration(3600, SECOND), this);
195 AbstractLaneChangeModel laneChangeModel = new Egoistic();
196 BehavioralCharacteristics behavioralCharacteristics = DefaultTestParameters.create();
197
198
199
200 LaneBasedIndividualGTU car =
201 new LaneBasedIndividualGTU("ReferenceCar", gtuType, new Length(4, METER), new Length(2, METER), new Speed(150,
202 KM_PER_HOUR), simpleSimulator, (OTSNetwork) this.network);
203 LaneBasedStrategicalPlanner strategicalPlanner =
204 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new LaneBasedCFLCTacticalPlanner(
205 new IDMPlusOld(), laneChangeModel, car), car);
206 car.init(strategicalPlanner, initialLongitudinalPositions, new Speed(100, KM_PER_HOUR));
207 car.getTacticalPlanner().getPerception().perceive();
208 Collection<Headway> sameLaneGTUs = new LinkedHashSet<Headway>();
209 sameLaneGTUs
210 .add(new HeadwayGTUSimple(car.getId(), car.getGTUType(), Length.ZERO, car.getLength(), car.getSpeed(), null));
211 Collection<Headway> preferredLaneGTUs = new LinkedHashSet<Headway>();
212 Collection<Headway> nonPreferredLaneGTUs = new LinkedHashSet<Headway>();
213 LaneMovementStep laneChangeModelResult =
214 laneChangeModel.computeLaneChangeAndAcceleration(car, sameLaneGTUs, preferredLaneGTUs, nonPreferredLaneGTUs,
215 new Speed(100, KM_PER_HOUR), new Acceleration(0.3, METER_PER_SECOND_2), new Acceleration(0.1,
216 METER_PER_SECOND_2), new Acceleration(-0.3, METER_PER_SECOND_2));
217
218 assertEquals("Vehicle want to change to the right lane", LateralDirectionality.RIGHT,
219 laneChangeModelResult.getLaneChangeDirection());
220 Length rear = car.position(lanes[0], car.getRear());
221 Length front = car.position(lanes[0], car.getFront());
222 Length reference = car.position(lanes[0], RelativePosition.REFERENCE_POSITION);
223
224
225
226 Length vehicleLength = front.minus(rear);
227 Length collisionStart = reference.minus(vehicleLength);
228 Length collisionEnd = reference.plus(vehicleLength);
229 for (double pos = collisionStart.getSI() + 0.01; pos < collisionEnd.getSI() - 0.01; pos += 0.1)
230 {
231 Set<DirectedLanePosition> otherLongitudinalPositions = new LinkedHashSet<>(1);
232 otherLongitudinalPositions.add(new DirectedLanePosition(lanes[1], new Length(pos, METER),
233 GTUDirectionality.DIR_PLUS));
234
235 behavioralCharacteristics = DefaultTestParameters.create();
236
237
238
239
240
241
242
243
244
245
246
247 LaneBasedIndividualGTU collisionCar =
248 new LaneBasedIndividualGTU("LaneChangeBlockingCarAt" + pos, gtuType, vehicleLength, new Length(2, METER),
249 new Speed(150, KM_PER_HOUR), simpleSimulator, (OTSNetwork) this.network);
250 strategicalPlanner =
251 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new LaneBasedCFLCTacticalPlanner(
252 new IDMPlusOld(), laneChangeModel, collisionCar), collisionCar);
253 collisionCar.init(strategicalPlanner, otherLongitudinalPositions, new Speed(100, KM_PER_HOUR));
254 preferredLaneGTUs.clear();
255 HeadwayGTUSimple collisionHWGTU =
256 new HeadwayGTUSimple(collisionCar.getId(), collisionCar.getGTUType(), new Length(pos - reference.getSI(),
257 LengthUnit.SI), collisionCar.getLength(), collisionCar.getSpeed(), null);
258 preferredLaneGTUs.add(collisionHWGTU);
259 laneChangeModelResult =
260 new Egoistic().computeLaneChangeAndAcceleration(car, sameLaneGTUs, preferredLaneGTUs, nonPreferredLaneGTUs,
261 new Speed(100, KM_PER_HOUR), new Acceleration(0.3, METER_PER_SECOND_2), new Acceleration(0.1,
262 METER_PER_SECOND_2), new Acceleration(-0.3, METER_PER_SECOND_2));
263
264 assertEquals("Vehicle cannot to change to the right lane because that would result in an immediate collision",
265 null, laneChangeModelResult.getLaneChangeDirection());
266 }
267 for (double pos = 0; pos < 180; pos += 5)
268 {
269 Set<DirectedLanePosition> otherLongitudinalPositions = new LinkedHashSet<>(1);
270 otherLongitudinalPositions.add(new DirectedLanePosition(lanes[1], new Length(pos, METER),
271 GTUDirectionality.DIR_PLUS));
272
273 behavioralCharacteristics = new BehavioralCharacteristics();
274 behavioralCharacteristics.setParameter(ParameterTypes.A, new Acceleration(1, METER_PER_SECOND_2));
275 behavioralCharacteristics.setParameter(ParameterTypes.B, new Acceleration(1.5, METER_PER_SECOND_2));
276 behavioralCharacteristics.setParameter(ParameterTypes.S0, new Length(2, METER));
277 behavioralCharacteristics.setParameter(ParameterTypes.T, new Duration(1, SECOND));
278 behavioralCharacteristics.setParameter(ParameterTypes.A, new Acceleration(1, METER_PER_SECOND_2));
279 behavioralCharacteristics.setDefaultParameter(ParameterTypes.LOOKAHEAD);
280 behavioralCharacteristics.setDefaultParameter(ParameterTypes.LOOKBACKOLD);
281 behavioralCharacteristics.setParameter(AbstractIDM.DELTA, 1d);
282
283
284
285
286 LaneBasedIndividualGTU otherCar =
287 new LaneBasedIndividualGTU("OtherCarAt" + pos, gtuType, vehicleLength, new Length(2, METER), new Speed(150,
288 KM_PER_HOUR), simpleSimulator, (OTSNetwork) this.network);
289 strategicalPlanner =
290 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new LaneBasedCFLCTacticalPlanner(
291 new IDMPlusOld(), laneChangeModel, otherCar), otherCar);
292 otherCar.init(strategicalPlanner, otherLongitudinalPositions, new Speed(100, KM_PER_HOUR));
293 preferredLaneGTUs.clear();
294 HeadwayGTUSimple collisionHWGTU =
295 new HeadwayGTUSimple(otherCar.getId(), otherCar.getGTUType(), new Length(pos
296 - car.position(lanes[0], car.getReference()).getSI(), LengthUnit.SI), otherCar.getLength(),
297 otherCar.getSpeed(), null);
298 preferredLaneGTUs.add(collisionHWGTU);
299 laneChangeModelResult =
300 new Egoistic().computeLaneChangeAndAcceleration(car, sameLaneGTUs, preferredLaneGTUs, nonPreferredLaneGTUs,
301 new Speed(100, KM_PER_HOUR), new Acceleration(0.3, METER_PER_SECOND_2), new Acceleration(0.1,
302 METER_PER_SECOND_2), new Acceleration(-0.3, METER_PER_SECOND_2));
303
304 laneChangeModelResult =
305 new Altruistic().computeLaneChangeAndAcceleration(car, sameLaneGTUs, preferredLaneGTUs,
306 nonPreferredLaneGTUs, new Speed(100, KM_PER_HOUR), new Acceleration(0.3, METER_PER_SECOND_2),
307 new Acceleration(0.1, METER_PER_SECOND_2), new Acceleration(-0.3, METER_PER_SECOND_2));
308
309
310
311
312 }
313 }
314
315
316
317
318
319
320 @Override
321 public void constructModel(
322 SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
323 throws SimRuntimeException
324 {
325
326 }
327
328
329 @Override
330 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
331
332 {
333 return null;
334 }
335
336 }