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