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