1 package org.opentrafficsim.road.network.lane.object.sensor;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.TRUCK;
5
6 import java.rmi.RemoteException;
7 import java.util.ArrayList;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Set;
11
12 import javax.naming.NamingException;
13
14 import org.djunits.unit.AccelerationUnit;
15 import org.djunits.unit.DurationUnit;
16 import org.djunits.unit.LengthUnit;
17 import org.djunits.unit.SpeedUnit;
18 import org.djunits.unit.TimeUnit;
19 import org.djunits.value.vdouble.scalar.Acceleration;
20 import org.djunits.value.vdouble.scalar.Duration;
21 import org.djunits.value.vdouble.scalar.Length;
22 import org.djunits.value.vdouble.scalar.Speed;
23 import org.djunits.value.vdouble.scalar.Time;
24 import org.opentrafficsim.core.dsol.OTSDEVSSimulator;
25 import org.opentrafficsim.core.dsol.OTSModelInterface;
26 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
27 import org.opentrafficsim.core.geometry.OTSGeometryException;
28 import org.opentrafficsim.core.geometry.OTSPoint3D;
29 import org.opentrafficsim.core.gtu.GTUDirectionality;
30 import org.opentrafficsim.core.gtu.GTUException;
31 import org.opentrafficsim.core.gtu.GTUType;
32 import org.opentrafficsim.core.gtu.RelativePosition;
33 import org.opentrafficsim.core.gtu.RelativePosition.TYPE;
34 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
35 import org.opentrafficsim.core.network.LongitudinalDirectionality;
36 import org.opentrafficsim.core.network.NetworkException;
37 import org.opentrafficsim.core.network.OTSNetwork;
38 import org.opentrafficsim.core.network.OTSNode;
39 import org.opentrafficsim.road.DefaultTestParameters;
40 import org.opentrafficsim.road.gtu.lane.AbstractLaneBasedGTU;
41 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
42 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
43 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner;
44 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
45 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
46 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
47 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
48 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
49 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
50 import org.opentrafficsim.road.network.factory.LaneFactory;
51 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
52 import org.opentrafficsim.road.network.lane.Lane;
53 import org.opentrafficsim.road.network.lane.LaneType;
54 import org.opentrafficsim.simulationengine.SimpleSimulator;
55
56 import nl.tudelft.simulation.dsol.SimRuntimeException;
57 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
58 import nl.tudelft.simulation.event.EventInterface;
59 import nl.tudelft.simulation.event.EventListenerInterface;
60
61
62
63
64
65
66
67
68
69
70
71
72 public class TrafficLightSensorTest implements EventListenerInterface
73 {
74
75
76
77
78
79
80
81 private static OTSDEVSSimulator makeSimulator() throws SimRuntimeException, NamingException
82 {
83 return new SimpleSimulator(Time.ZERO, Duration.ZERO, new Duration(1, DurationUnit.HOUR), new OTSModelInterface()
84 {
85
86
87 private static final long serialVersionUID = 1L;
88
89
90 private SimulatorInterface<Time, Duration, OTSSimTimeDouble> sim;
91
92 @Override
93 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
94 throws SimRuntimeException, RemoteException
95 {
96 this.sim = theSimulator;
97 }
98
99 @Override
100 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
101 {
102 return this.sim;
103 }
104
105
106 @Override
107 public OTSNetwork getNetwork()
108 {
109 return null;
110 }
111 });
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125 private static Lane[] buildNetwork(final double[] lengths, final OTSDEVSSimulator simulator)
126 throws NetworkException, NamingException, OTSGeometryException, SimRuntimeException
127 {
128 OTSNetwork network = new OTSNetwork("network");
129 OTSNode prevNode = null;
130 Lane[] result = new Lane[lengths.length];
131 LaneType laneType = LaneType.ALL;
132 Speed speedLimit = new Speed(50, SpeedUnit.KM_PER_HOUR);
133 double cumulativeLength = 0;
134 for (int nodeNumber = 0; nodeNumber <= lengths.length; nodeNumber++)
135 {
136 OTSNode node = new OTSNode(network, "node" + nodeNumber, new OTSPoint3D(cumulativeLength, 0, 0));
137 if (null != prevNode)
138 {
139 LongitudinalDirectionality direction = lengths[nodeNumber - 1] > 0 ? LongitudinalDirectionality.DIR_PLUS
140 : LongitudinalDirectionality.DIR_MINUS;
141 OTSNode fromNode = LongitudinalDirectionality.DIR_PLUS == direction ? prevNode : node;
142 OTSNode toNode = LongitudinalDirectionality.DIR_PLUS == direction ? node : prevNode;
143 int laneOffset = LongitudinalDirectionality.DIR_PLUS == direction ? 0 : -1;
144 result[nodeNumber - 1] = LaneFactory.makeMultiLane(network, "Link" + nodeNumber, fromNode, toNode, null, 1,
145 laneOffset, laneOffset, laneType, speedLimit, simulator, direction)[0];
146 System.out.println("Created lane with center line " + result[nodeNumber - 1].getCenterLine()
147 + ", directionality " + direction);
148 }
149 if (nodeNumber < lengths.length)
150 {
151 cumulativeLength += Math.abs(lengths[nodeNumber]);
152 }
153 prevNode = node;
154 }
155
156 Lane lastLane = result[lengths.length - 1];
157 Length sinkPosition = new Length(lengths[lengths.length - 1] > 0 ? lastLane.getLength().si - 10 : 10, LengthUnit.METER);
158 new SinkSensor(lastLane, sinkPosition, simulator);
159 return result;
160 }
161
162
163
164
165
166
167
168
169 private DirectedLanePosition findLaneAndPosition(final Lane[] lanes, final Length position) throws GTUException
170 {
171 Length remainingLength = position;
172 for (Lane lane : lanes)
173 {
174 if (lane.getLength().ge(remainingLength))
175 {
176 boolean reverse =
177 lane.getParentLink().getEndNode().getPoint().x < lane.getParentLink().getStartNode().getPoint().x;
178 if (reverse)
179 {
180 remainingLength = lane.getLength().minus(remainingLength);
181 }
182 return new DirectedLanePosition(lane, remainingLength,
183 reverse ? GTUDirectionality.DIR_MINUS : GTUDirectionality.DIR_PLUS);
184 }
185 remainingLength = remainingLength.minus(lane.getLength());
186 }
187 return null;
188 }
189
190
191
192
193
194
195
196
197
198
199 public final void trafficLightSensorTest()
200 throws NetworkException, NamingException, OTSGeometryException, SimRuntimeException, GTUException
201 {
202 double[][] lengthLists =
203 { { 101.1, -1, 1, -1, 1, -900 }, { 1000 }, { -1000 }, { 101.1, 900 }, { 101.1, 1, 1, 1, 1, 900 }, };
204 for (double[] lengthList : lengthLists)
205 {
206 for (int pos = 50; pos < 130; pos++)
207 {
208 System.out.println("Number of lanes is " + lengthList.length + " pos is " + pos);
209 OTSDEVSSimulator simulator = makeSimulator();
210 Lane[] lanes = buildNetwork(lengthList, simulator);
211 OTSNetwork network = (OTSNetwork) lanes[0].getParentLink().getNetwork();
212 Length a = new Length(100, LengthUnit.METER);
213 Length b = new Length(120, LengthUnit.METER);
214 DirectedLanePosition pA = findLaneAndPosition(lanes, a);
215 DirectedLanePosition pB = findLaneAndPosition(lanes, b);
216 String sensorId = "D123";
217 TYPE entryPosition = RelativePosition.FRONT;
218 TYPE exitPosition = RelativePosition.REAR;
219 List<Lane> intermediateLanes = null;
220 if (lanes.length > 2)
221 {
222 intermediateLanes = new ArrayList<>();
223 for (Lane lane : lanes)
224 {
225 if (lane.equals(pA.getLane()))
226 {
227 continue;
228 }
229 if (lane.equals(pB.getLane()))
230 {
231 break;
232 }
233 intermediateLanes.add(lane);
234 }
235 }
236 TrafficLightSensor tls = new TrafficLightSensor(sensorId, pA.getLane(), pA.getPosition(), pB.getLane(),
237 pB.getPosition(), intermediateLanes, entryPosition, exitPosition, simulator);
238 assertEquals("Id should match the provided id", sensorId, tls.getId());
239 assertEquals("Simulator should match", simulator, tls.getSimulator());
240 assertEquals("Entry position", entryPosition, tls.getPositionTypeEntry());
241 assertEquals("Exit position", exitPosition, tls.getPositionTypeExit());
242 assertEquals("Position a", pA.getPosition().si, tls.getLanePositionA().si, 0.00001);
243 assertEquals("Position b", pB.getPosition().si, tls.getLanePositionB().si, 0.00001);
244 this.loggedEvents.clear();
245 assertEquals("event list is empty", 0, this.loggedEvents.size());
246 tls.addListener(this, NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_ENTRY_EVENT);
247 tls.addListener(this, NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_EXIT_EVENT);
248 assertEquals("event list is empty", 0, this.loggedEvents.size());
249
250 GTUType gtuType = TRUCK;
251 Length gtuLength = new Length(17, LengthUnit.METER);
252 Length gtuWidth = new Length(2, LengthUnit.METER);
253 Speed maximumSpeed = new Speed(90, SpeedUnit.KM_PER_HOUR);
254 LaneBasedGTU gtu =
255 new LaneBasedIndividualGTU("GTU1", gtuType, gtuLength, gtuWidth, maximumSpeed, simulator, network);
256 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(1);
257 Length initialPosition = new Length(pos, LengthUnit.METER);
258 DirectedLanePosition gtuPosition = findLaneAndPosition(lanes, initialPosition);
259 initialLongitudinalPositions.add(new DirectedLanePosition(gtuPosition.getLane(), gtuPosition.getPosition(),
260 gtuPosition.getGtuDirection()));
261 BehavioralCharacteristics behavioralCharacteristics = DefaultTestParameters.create();
262 LaneChangeModel laneChangeModel = new Egoistic();
263 GTUFollowingModelOld gtuFollowingModel = new FixedAccelerationModel(
264 new Acceleration(0, AccelerationUnit.METER_PER_SECOND_2), new Duration(10, DurationUnit.SECOND));
265 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
266 new LaneBasedCFLCTacticalPlanner(gtuFollowingModel, laneChangeModel, gtu), gtu);
267 Speed initialSpeed = new Speed(10, SpeedUnit.METER_PER_SECOND);
268 if (lanes.length == 6 && pos >= 103)
269 {
270 System.out.println("let op. InitialLongitudinalPositions: " + initialLongitudinalPositions);
271 }
272 ((AbstractLaneBasedGTU) gtu).init(strategicalPlanner, initialLongitudinalPositions, initialSpeed);
273 if (initialPosition.plus(gtuLength.divideBy(2)).lt(a) || initialPosition.minus(gtuLength.divideBy(2)).gt(b))
274 {
275 assertEquals("event list is empty", 0, this.loggedEvents.size());
276 }
277 else
278 {
279 if (1 != this.loggedEvents.size())
280 {
281
282
283
284 }
285 }
286 Time stopTime = new Time(100, TimeUnit.BASE_SECOND);
287 while (simulator.getSimulatorTime().get().lt(stopTime))
288 {
289
290 simulator.step();
291 }
292 System.out.println("simulation time is now " + simulator);
293 if (initialPosition.minus(gtuLength.divideBy(2)).lt(b))
294 {
295 assertEquals("event list contains 2 events", 2, this.loggedEvents.size());
296 }
297 else
298 {
299 assertEquals("event list contains 0 events", 0, this.loggedEvents.size());
300 }
301 simulator.cleanUp();
302 }
303 }
304 }
305
306
307 private List<EventInterface> loggedEvents = new ArrayList<>();
308
309
310 @Override
311 public final void notify(final EventInterface event) throws RemoteException
312 {
313 System.out.println("Received event " + event);
314 this.loggedEvents.add(event);
315 }
316
317 }