View Javadoc
1   package org.opentrafficsim.road.network.factory;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertNotNull;
5   import static org.junit.Assert.fail;
6   
7   import java.io.IOException;
8   import java.net.URL;
9   import java.util.HashSet;
10  import java.util.Set;
11  
12  import javax.naming.NamingException;
13  import javax.xml.parsers.ParserConfigurationException;
14  
15  import org.djunits.unit.LengthUnit;
16  import org.djunits.unit.UNITS;
17  import org.djunits.value.vdouble.scalar.Duration;
18  import org.djunits.value.vdouble.scalar.Length;
19  import org.djunits.value.vdouble.scalar.Time;
20  import org.junit.Assert;
21  import org.opentrafficsim.base.modelproperties.PropertyException;
22  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
23  import org.opentrafficsim.core.dsol.OTSModelInterface;
24  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
25  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
26  import org.opentrafficsim.core.geometry.OTSGeometryException;
27  import org.opentrafficsim.core.gtu.GTUException;
28  import org.opentrafficsim.core.gtu.RelativePosition;
29  import org.opentrafficsim.core.gtu.RelativePosition.TYPE;
30  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
31  import org.opentrafficsim.core.network.Link;
32  import org.opentrafficsim.core.network.NetworkException;
33  import org.opentrafficsim.core.network.Node;
34  import org.opentrafficsim.core.network.OTSNetwork;
35  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
36  import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
37  import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
38  import org.opentrafficsim.road.network.lane.CrossSectionElement;
39  import org.opentrafficsim.road.network.lane.CrossSectionLink;
40  import org.opentrafficsim.road.network.lane.Lane;
41  import org.opentrafficsim.road.network.lane.object.sensor.AbstractSensor;
42  import org.opentrafficsim.simulationengine.SimpleAnimator;
43  import org.xml.sax.SAXException;
44  
45  import nl.tudelft.simulation.dsol.SimRuntimeException;
46  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
47  import nl.tudelft.simulation.language.Throw;
48  import nl.tudelft.simulation.language.io.URLResource;
49  
50  /**
51   * Test of the XML Parser.
52   * <p>
53   * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
54   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
55   * <p>
56   * $LastChangedDate: 2015-07-15 12:52:42 +0200 (Wed, 15 Jul 2015) $, @version $Revision: 1113 $, by $Author: pknoppers $,
57   * initial version Jul 17, 2015 <br>
58   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
59   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
60   */
61  public class XMLNetworkGeneratorTest implements UNITS
62  {
63      /** AssertionError thrown by the sensor trigger. */
64      @SuppressWarnings("checkstyle:visibilitymodifier")
65      protected AssertionError triggerError = null;
66  
67      /**
68       * Test an XML model that generates several GTUs quickly after another.
69       * @throws OperationalPlanException if DefaultAlexander perception category is not present
70       */
71      // Test
72      public final void testXMLNetworkSensors() throws OperationalPlanException
73      {
74          try
75          {
76              TestXMLModel model = new TestXMLModel();
77              final SimpleAnimator simulator = new SimpleAnimator(Time.ZERO, Duration.ZERO, new Duration(120.0, SECOND), model);
78  
79              // get nodes, links, and the lanes.
80              Node n1 = model.getNetwork().getNodeMap().get("N1");
81              Node n2 = model.getNetwork().getNodeMap().get("N2");
82              assertNotNull(n1);
83              Assert.assertTrue(n1.getLinks() != null);
84              Assert.assertTrue(n1.getLinks().size() > 0);
85              Link l12 = n1.getLinks().iterator().next();
86              assertNotNull(l12);
87              CrossSectionLink csl12 = (CrossSectionLink) l12;
88              Assert.assertTrue(csl12.getCrossSectionElementList().size() > 0);
89              Lane lane12 = (Lane) csl12.getCrossSectionElementList().get(0);
90              assertNotNull(lane12);
91  
92              assertNotNull(n2);
93              Assert.assertTrue(n2.getLinks() != null);
94              Assert.assertTrue(n2.getLinks().size() > 0);
95              Link l23 = n2.getLinks().iterator().next();
96              assertNotNull(l23);
97              CrossSectionLink csl23 = (CrossSectionLink) l23;
98              Assert.assertTrue(csl23.getCrossSectionElementList().size() > 0);
99              Lane lane23 = (Lane) csl23.getCrossSectionElementList().get(0);
100             assertNotNull(lane23);
101 
102             // add a sensor to check the time the vehicles pass
103             new ReportingSensor("LANE23.START", lane23, new Length(1E-4, LengthUnit.SI), RelativePosition.REFERENCE, simulator);
104 
105             simulator.setSpeedFactor(1000);
106             simulator.start();
107 
108             // wait till the simulation is over
109             while (simulator.isRunning())
110             {
111                 try
112                 {
113                     Thread.sleep(1, 0);
114                     if (this.triggerError != null)
115                     {
116                         throw this.triggerError;
117                     }
118                     Set<LaneBasedGTU> gtus = new HashSet<>();
119                     gtus.addAll(lane12.getGtuList().toList());
120                     gtus.addAll(lane23.getGtuList().toList());
121                     for (LaneBasedGTU gtu : gtus)
122                     {
123                         // check that all vehicles drive 10 m/s and never have to break
124                         boolean not10ms = Math.abs(gtu.getSpeed().getSI() - 10.0) > 0.0001;
125                         if (not10ms)
126                         {
127                             // TODO repair headway in such a way that vehicle does not have to brake (safe distance)
128                             System.err.println("Speed of GTU " + gtu + "<> 10 m/s: " + gtu.getSpeed() + ", headway = "
129                                     + gtu.getTacticalPlanner().getPerception()
130                                             .getPerceptionCategory(DefaultSimplePerception.class).getForwardHeadwayGTU()
131                                             .getDistance());
132                             // fail("Speed of GTU " + gtu + "<> 10 m/s: " + gtu.getSpeed() + ", headway = "
133                             // + gtu.headway(new Length(250.0, METER)));
134                         }
135                     }
136                 }
137                 catch (InterruptedException ie)
138                 {
139                     // ignore
140                 }
141             }
142         }
143         catch (SimRuntimeException | NamingException | NetworkException | PropertyException exception)
144         {
145             fail(exception.toString());
146         }
147     }
148 
149     /**
150      * Reporting sensor.
151      */
152     private class ReportingSensor extends AbstractSensor
153     {
154         /** */
155         private static final long serialVersionUID = 1L;
156 
157         /** The sensor id. */
158         private final String id;
159 
160         /** The simulator. */
161         private final OTSDEVSSimulatorInterface simulator;
162 
163         /** Last time car passed. */
164         private double lastSimTimeCheck = 0.0;
165 
166         /**
167          * @param lane the lane for the ReportingSensor
168          * @param longitudinalPosition the position on the lane
169          * @param positionType the type of trigger (REAR, FRONT, etc.)
170          * @param id the sensor id
171          * @param simulator the simulator
172          * @throws NetworkException when the position on the lane is out of bounds
173          */
174         public ReportingSensor(final String id, final Lane lane, final Length longitudinalPosition, final TYPE positionType,
175                 final OTSDEVSSimulatorInterface simulator) throws NetworkException
176         {
177             super("REPORT@" + lane.toString(), lane, longitudinalPosition, positionType, simulator);
178             this.id = id;
179             this.simulator = simulator;
180         }
181 
182         /** {@inheritDoc} */
183         @Override
184         public void triggerResponse(final LaneBasedGTU gtu)
185         {
186             try
187             {
188                 int gtuNumber = Integer.parseInt(gtu.getId().toString().substring(gtu.getId().toString().indexOf(':') + 1)) - 1;
189                 double simTimeSec = this.simulator.getSimulatorTime().getTime().doubleValue();
190                 if ("LANE23.START".equals(this.id))
191                 {
192                     // second lane, start, reference point of the GTU
193                     // gen at t=0 at 50 m with back, front needs to travel 50 m = 5 sec
194                     // next vehicle has to be later -- more than the 1 sec interarrival time
195                     if (gtuNumber == 0)
196                     {
197                         assertEquals(5.0, simTimeSec, 0.001);
198                         this.lastSimTimeCheck = 5.0;
199                     }
200                     else
201                     {
202                         System.out.println("IAT for " + gtu + " is " + (simTimeSec - this.lastSimTimeCheck) + " s");
203                         Assert.assertTrue("IAT for " + gtu + " is " + (simTimeSec - this.lastSimTimeCheck) + " s",
204                                 simTimeSec - this.lastSimTimeCheck > 1.0);
205                         this.lastSimTimeCheck = simTimeSec;
206                     }
207                 }
208             }
209             catch (AssertionError ae)
210             {
211                 XMLNetworkGeneratorTest.this.triggerError = ae;
212             }
213         }
214 
215         /** {@inheritDoc} */
216         @Override
217         public String toString()
218         {
219             return "ReportingSensor [id=" + this.id + "]";
220         }
221 
222         /** {@inheritDoc} */
223         @Override
224         @SuppressWarnings("checkstyle:designforextension")
225         public ReportingSensor clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator,
226                 final boolean animation) throws NetworkException
227         {
228             Throw.when(!(newCSE instanceof Lane), NetworkException.class, "sensors can only be cloned for Lanes");
229             Throw.when(!(newSimulator instanceof OTSDEVSSimulatorInterface), NetworkException.class,
230                     "simulator should be a DEVSSimulator");
231             return new ReportingSensor(getId(), (Lane) newCSE, getLongitudinalPosition(), getPositionType(),
232                     (OTSDEVSSimulatorInterface) newSimulator);
233         }
234 
235     }
236 
237     /**
238      * Model to test the XML parser.
239      * <p>
240      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
241      * All rights reserved. BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim
242      * License</a>.
243      * <p>
244      * $LastChangedDate: 2015-07-15 12:52:42 +0200 (Wed, 15 Jul 2015) $, @version $Revision: 1113 $, by $Author: pknoppers $,
245      * initial version un 27, 2015 <br>
246      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
247      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
248      */
249     class TestXMLModel implements OTSModelInterface
250     {
251         /** */
252         private static final long serialVersionUID = 20150717L;
253 
254         /** The simulator. */
255         private OTSDEVSSimulatorInterface simulator;
256 
257         /** The generated network. */
258         private OTSNetwork network;
259 
260         /** */
261         public TestXMLModel()
262         {
263             super();
264         }
265 
266         /** {@inheritDoc} */
267         @SuppressWarnings("unchecked")
268         @Override
269         public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> pSimulator)
270                 throws SimRuntimeException
271         {
272             this.simulator = (OTSDEVSSimulatorInterface) pSimulator;
273             URL url = URLResource.getResource("/org/opentrafficsim/core/network/factory/gen-overlap-test.xml");
274             XmlNetworkLaneParser nlp = new XmlNetworkLaneParser(this.simulator);
275             try
276             {
277                 this.network = nlp.build(url);
278             }
279             catch (NetworkException | ParserConfigurationException | SAXException | IOException | NamingException | GTUException
280                     | OTSGeometryException exception)
281             {
282                 exception.printStackTrace();
283             }
284         }
285 
286         /** {@inheritDoc} */
287         @Override
288         public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
289 
290         {
291             return this.simulator;
292         }
293 
294         /**
295          * @return network.
296          */
297         public final OTSNetwork getNetwork()
298         {
299             return this.network;
300         }
301     }
302 }