View Javadoc
1   package org.opentrafficsim.road.network.sampling.indicator;
2   
3   import java.util.HashMap;
4   import java.util.List;
5   import java.util.Map;
6   
7   import org.djunits.unit.DurationUnit;
8   import org.djunits.value.ValueException;
9   import org.djunits.value.vdouble.scalar.Duration;
10  import org.djunits.value.vdouble.scalar.Time;
11  import org.djunits.value.vfloat.vector.FloatSpeedVector;
12  import org.djutils.exceptions.Throw;
13  import org.opentrafficsim.kpi.interfaces.GtuDataInterface;
14  import org.opentrafficsim.kpi.sampling.Query;
15  import org.opentrafficsim.kpi.sampling.SamplingException;
16  import org.opentrafficsim.kpi.sampling.Trajectory;
17  import org.opentrafficsim.kpi.sampling.TrajectoryGroup;
18  import org.opentrafficsim.kpi.sampling.indicator.AbstractIndicator;
19  import org.opentrafficsim.road.network.sampling.data.ReferenceSpeed;
20  
21  /**
22   * Delay based on reference speed.
23   * <p>
24   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
26   * <p>
27   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 21 nov. 2016 <br>
28   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
30   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
31   */
32  public class TotalDelayReference extends AbstractIndicator<Duration>
33  {
34  
35      /** Reference speed extended data type. */
36      private static final ReferenceSpeed REF_SPEED_TYPE = new ReferenceSpeed();
37  
38      /** {@inheritDoc} */
39      @Override
40      protected final <G extends GtuDataInterface> Duration calculate(final Query<G> query, final Time startTime,
41              final Time endTime, final List<TrajectoryGroup<G>> trajectoryGroups)
42      {
43          Map<String, Duration> gtuTimes = new HashMap<>();
44          Map<String, Duration> gtuRefTimes = new HashMap<>();
45          for (TrajectoryGroup<? extends GtuDataInterface> trajectoryGroup : trajectoryGroups)
46          {
47              try
48              {
49                  for (Trajectory<?> trajectory : trajectoryGroup.getTrajectories())
50                  {
51                      Duration sumTime;
52                      Duration sumRefTime;
53                      if (gtuTimes.containsKey(trajectory.getGtuId()))
54                      {
55                          sumTime = gtuTimes.get(trajectory.getGtuId());
56                          sumRefTime = gtuRefTimes.get(trajectory.getGtuId());
57                      }
58                      else
59                      {
60                          sumTime = Duration.ZERO;
61                          sumRefTime = Duration.ZERO;
62                      }
63                      Throw.when(!trajectory.contains(REF_SPEED_TYPE), UnsupportedOperationException.class,
64                              "TotalDelayReference can only work with trajectories that have %s extended data.",
65                              REF_SPEED_TYPE.getId());
66                      FloatSpeedVector refSpeed = trajectory.getExtendedData(REF_SPEED_TYPE);
67                      float[] x = trajectory.getX();
68                      try
69                      {
70                          for (int i = 1; i < refSpeed.size(); i++)
71                          {
72                              double refV;
73                              if (!Double.isNaN(refSpeed.get(i).si))
74                              {
75                                  refV = refSpeed.get(i - 1).si;
76                              }
77                              else
78                              {
79                                  refV = (refSpeed.get(i - 1).si + refSpeed.get(i).si) / 2.0;
80                              }
81                              double dx = x[i] - x[i - 1];
82                              sumRefTime = sumRefTime.plus(new Duration(dx / refV, DurationUnit.SI));
83                          }
84                      }
85                      catch (ValueException exception)
86                      {
87                          // should not occur as we check the size of the vector
88                          throw new RuntimeException("Trying to obtain value outside of range.", exception);
89                      }
90                      gtuTimes.put(trajectory.getGtuId(), sumTime.plus(trajectory.getTotalDuration()));
91                      gtuRefTimes.put(trajectory.getGtuId(), sumRefTime);
92                  }
93              }
94              catch (SamplingException exception)
95              {
96                  throw new RuntimeException("Exception while trying to determine delay in trajectory.", exception);
97              }
98          }
99          Duration delaySum = Duration.ZERO;
100         for (String id : gtuTimes.keySet())
101         {
102             Duration gtuTime = gtuTimes.get(id);
103             Duration gtuRefTime = gtuRefTimes.get(id);
104             if (gtuTime.gt(gtuRefTime))
105             {
106                 delaySum = delaySum.plus(gtuTime.minus(gtuRefTime));
107             }
108         }
109         return delaySum;
110     }
111 
112     /** {@inheritDoc} */
113     @Override
114     @SuppressWarnings("checkstyle:designforextension")
115     public String toString()
116     {
117         return "TotalDelayReference";
118     }
119 
120 }