View Javadoc
1   package org.opentrafficsim.road.network.lane;
2   
3   import java.util.Map;
4   
5   import org.djunits.unit.DurationUnit;
6   import org.djunits.unit.SpeedUnit;
7   import org.djunits.unit.util.UNITS;
8   import org.djunits.value.vdouble.scalar.Acceleration;
9   import org.djunits.value.vdouble.scalar.Direction;
10  import org.djunits.value.vdouble.scalar.Duration;
11  import org.djunits.value.vdouble.scalar.Length;
12  import org.djunits.value.vdouble.scalar.Speed;
13  import org.djutils.draw.point.Point2d;
14  import org.junit.jupiter.api.Test;
15  import org.opentrafficsim.base.parameters.Parameters;
16  import org.opentrafficsim.core.definitions.DefaultsNl;
17  import org.opentrafficsim.core.dsol.AbstractOtsModel;
18  import org.opentrafficsim.core.dsol.OtsModelInterface;
19  import org.opentrafficsim.core.dsol.OtsSimulator;
20  import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
21  import org.opentrafficsim.core.gtu.GtuType;
22  import org.opentrafficsim.core.gtu.RelativePosition;
23  import org.opentrafficsim.core.network.NetworkException;
24  import org.opentrafficsim.core.network.Node;
25  import org.opentrafficsim.core.perception.HistoryManagerDevs;
26  import org.opentrafficsim.road.DefaultTestParameters;
27  import org.opentrafficsim.road.FixedCarFollowing;
28  import org.opentrafficsim.road.definitions.DefaultsRoadNl;
29  import org.opentrafficsim.road.gtu.LaneBasedGtu;
30  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
31  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlanner;
32  import org.opentrafficsim.road.gtu.tactical.lmrs.Lmrs;
33  import org.opentrafficsim.road.gtu.tactical.lmrs.LmrsFactory;
34  import org.opentrafficsim.road.gtu.tactical.lmrs.LmrsFactory.Setting;
35  import org.opentrafficsim.road.network.Lane;
36  import org.opentrafficsim.road.network.LanePosition;
37  import org.opentrafficsim.road.network.LaneType;
38  import org.opentrafficsim.road.network.RoadNetwork;
39  import org.opentrafficsim.road.network.factory.LaneFactory;
40  import org.opentrafficsim.road.network.object.detector.LaneDetector;
41  import org.opentrafficsim.road.network.speed.LaneSpeedLimits;
42  
43  import nl.tudelft.simulation.dsol.SimRuntimeException;
44  import nl.tudelft.simulation.dsol.eventlists.EventListInterface;
45  import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
46  
47  /**
48   * Test detectors and scheduling of trigger.
49   * <p>
50   * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
51   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
52   * </p>
53   * @author Peter Knoppers
54   */
55  public final class DetectorTest implements UNITS
56  {
57  
58      /** Verbose test. */
59      private static final boolean VERBOSE = false;
60  
61      /** */
62      private DetectorTest()
63      {
64          // do not instantiate test class
65      }
66  
67      /**
68       * Test the constructors of SensorLaneEnd and SensorLaneStart.
69       * @throws Exception when something goes wrong (should not happen)
70       */
71      @Test
72      public void sensorTest() throws Exception
73      {
74          // We need a simulator, but for that we first need something that implements OtsModelInterface
75          OtsSimulatorInterface simulator = new OtsSimulator("SensorTest");
76          OtsModelInterface model = new DummyModelForSensorTest(simulator);
77          simulator.initialize(Duration.ZERO, Duration.ZERO, new Duration(3600.0, DurationUnit.SECOND), model,
78                  HistoryManagerDevs.noHistory(simulator));
79          RoadNetwork network = new RoadNetwork("sensor test network", simulator);
80          // Now we need a set of Lanes
81          // To create Lanes we need Nodes and a LaneType
82          Node nodeAFrom = new Node(network, "AFrom", new Point2d(0, 0), Direction.ZERO);
83          Node nodeATo = new Node(network, "ATo", new Point2d(1000, 0), Direction.ZERO);
84          Node nodeBTo = new Node(network, "BTo", new Point2d(20000, 0), Direction.ZERO);
85          // so car won't run off lane B in 100 s.
86          GtuType gtuType = DefaultsNl.CAR;
87          LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
88          LaneSpeedLimits speedLimits = new LaneSpeedLimits(new Speed(120, SpeedUnit.KM_PER_HOUR),
89                  Map.of(DefaultsNl.TRUCK, new Speed(80, SpeedUnit.KM_PER_HOUR)));
90          Lane[] lanesA = LaneFactory.makeMultiLane(network, "A", nodeAFrom, nodeATo, null, 3, laneType, speedLimits, simulator);
91          Lane[] lanesB = LaneFactory.makeMultiLane(network, "B", nodeATo, nodeBTo, null, 3, laneType, speedLimits, simulator);
92  
93          // put a sensor on each of the lanes at the end of LaneA
94          for (Lane lane : lanesA)
95          {
96              Length longitudinalPosition = new Length(999.9999, METER);
97              TriggerDetector sensor =
98                      new TriggerDetector(lane, longitudinalPosition, RelativePosition.REFERENCE, "Trigger@" + lane.toString());
99          }
100 
101         Length positionA = new Length(100, METER);
102         LanePosition initialLongitudinalPositions = new LanePosition(lanesA[1], positionA);
103 
104         // A Car needs an initial speed
105         Speed initialSpeed = new Speed(50, KM_PER_HOUR);
106         // Length of the Car
107         Length carLength = new Length(4, METER);
108         // Width of the Car
109         Length carWidth = new Length(1.8, METER);
110         // Maximum speed of the Car
111         Speed maximumSpeed = new Speed(100, KM_PER_HOUR);
112         // ID of the Car
113         String carID = "theCar";
114         // Create an acceleration profile for the car
115         // Now we can make a car (GTU) (and we don't even have to hold a pointer to it)
116         Parameters parameters = DefaultTestParameters.create();
117 
118         // LaneBasedBehavioralCharacteristics drivingCharacteristics =
119         // new LaneBasedBehavioralCharacteristics(fas, null);
120         LaneBasedGtu car = new LaneBasedGtu(carID, gtuType, carLength, carWidth, maximumSpeed, carLength.times(0.5),
121                 (RoadNetwork) network);
122         LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(new LmrsFactory<>(Lmrs::new)
123                 .set(Setting.CAR_FOLLOWING_MODEL, (h, v) -> new FixedCarFollowing(Acceleration.ofSI(0.5)).get()).create(car),
124                 car);
125         car.setParameters(parameters);
126         car.init(strategicalPlanner, initialLongitudinalPositions.getLocation(), initialSpeed);
127         simulator.runUpTo(Duration.ONE);
128         if (!simulator.isStartingOrRunning())
129         {
130             simulator.start();
131         }
132         while (simulator.isStartingOrRunning())
133         {
134             try
135             {
136                 Thread.sleep(1);
137             }
138             catch (InterruptedException ie)
139             {
140                 ie = null; // ignore
141             }
142         }
143         // Construction of the car scheduled a car move event at t=0
144         EventListInterface<Duration> eventList = simulator.getEventList();
145         SimEventInterface<Duration> triggerEvent = null;
146         for (SimEventInterface<Duration> event : eventList)
147         {
148             if (VERBOSE)
149             {
150                 System.out.println("Scheduled Event " + event);
151             }
152             if (event.toString().contains("trigger"))
153             {
154                 triggerEvent = event;
155             }
156         }
157         // XXX this is not true anymore with OperationalPlans, Perception, etc =>
158         // XXX the number of events that should be scheduled can vary per models chosen
159         // XXX assertEquals("There should be three scheduled events (trigger, leaveLane,
160         // XXX car.move, terminate)", 4, eventList.size());
161         // The sensor should be triggered around t=38.3403 (exact value: 10 / 9 * (sqrt(3541) - 25))
162         // System.out.println("trigger event is " + triggerEvent);
163         // / TODO not triggered in next half second.
164         // XXX assertEquals("Trigger event should be around 38.3403", 38.3403,
165         // XXX triggerEvent.getAbsoluteExecutionTime().get().getSI(), 0.0001);
166     }
167 }
168 
169 /** Test detector. */
170 class TriggerDetector extends LaneDetector
171 {
172     /**
173      * Constructor.
174      * @param lane lane of the sensor
175      * @param longitudinalPosition position of the sensor on the lane
176      * @param positionType trigger position of the GTU
177      * @param name name of the sensor
178      * @throws NetworkException in case position is out of bounds
179      */
180     TriggerDetector(final Lane lane, final Length longitudinalPosition, final RelativePosition.Type positionType,
181             final String name) throws NetworkException
182     {
183         super(name, lane, longitudinalPosition, positionType, DefaultsNl.ROAD_USERS);
184     }
185 
186     @Override
187     public void triggerResponse(final LaneBasedGtu gtu)
188     {
189         // TODO check that the sensor is triggered at the right time.
190     }
191 
192 }
193 
194 /**
195  * Dummy OtsModelInterface.
196  * <p>
197  * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
198  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
199  * </p>
200  * @author Peter Knoppers
201  */
202 class DummyModelForSensorTest extends AbstractOtsModel
203 {
204     /**
205      * Constructor.
206      * @param simulator the simulator to use
207      */
208     DummyModelForSensorTest(final OtsSimulatorInterface simulator)
209     {
210         super(simulator);
211     }
212 
213     @Override
214     public final void constructModel() throws SimRuntimeException
215     {
216         //
217     }
218 
219     @Override
220     public final RoadNetwork getNetwork()
221     {
222         return null;
223     }
224 }