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