View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception.mental.channel;
2   
3   import java.util.Iterator;
4   import java.util.Set;
5   import java.util.function.Function;
6   
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.djunits.value.vdouble.scalar.Speed;
9   import org.djutils.exceptions.Try;
10  import org.opentrafficsim.base.parameters.ParameterTypeLength;
11  import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
12  import org.opentrafficsim.base.parameters.ParameterTypes;
13  import org.opentrafficsim.core.gtu.Stateless;
14  import org.opentrafficsim.core.gtu.perception.EgoPerception;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
17  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
18  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable.UnderlyingDistance;
19  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
20  import org.opentrafficsim.road.gtu.lane.perception.categories.IntersectionPerception;
21  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
22  import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
23  
24  /**
25   * Task demand for acceleration from stand-still or low speeds. This mostly functions to increase attention when leaving a
26   * queue. This is defined as the maximum of {@code max(0,-dv)/v0 * (1-s/x0)}, where {@code dv} is the approaching speed to a
27   * leader, {@code v0} is the desired speed, {@code s} is the distance to the leader and {@code x0} is the look-ahead distance.
28   * <p>
29   * Copyright (c) 2024-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
30   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
31   * </p>
32   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
33   */
34  public class ChannelTaskAcceleration extends AbstractTask implements ChannelTask, Stateless<ChannelTaskAcceleration>
35  {
36  
37      /** Distance discount range. */
38      public static final ParameterTypeLength X0 = ParameterTypes.LOOKAHEAD;
39  
40      /** Speed threshold below which traffic is considered congested. */
41      public static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;
42  
43      /** Singleton instance. */
44      public static final ChannelTaskAcceleration SINGLETON = new ChannelTaskAcceleration();
45  
46      /** Default set that is returned by the supplier. */
47      private static final Set<ChannelTask> SET = Set.of(SINGLETON);
48  
49      /** Standard supplier that supplies a single instance of the acceleration task. */
50      public static final Function<LanePerception, Set<ChannelTask>> SUPPLIER = (p) -> SET;
51  
52      /**
53       * Constructor.
54       */
55      public ChannelTaskAcceleration()
56      {
57          super("acceleration");
58      }
59  
60      @Override
61      public ChannelTaskAcceleration get()
62      {
63          return SINGLETON;
64      }
65  
66      @Override
67      public Object getChannel()
68      {
69          return FRONT;
70      }
71  
72      @Override
73      public double calculateTaskDemand(final LanePerception perception)
74      {
75          NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
76                  "NeighborsPerception not present.");
77          EgoPerception<?, ?> ego =
78                  Try.assign(() -> perception.getPerceptionCategory(EgoPerception.class), "EgoPerception not present.");
79          Speed v = ego.getSpeed();
80          Speed vCong = Try.assign(() -> perception.getGtu().getParameters().getParameter(VCONG), "Parameter VCONG not present");
81          Length x0 = Try.assign(() -> perception.getGtu().getParameters().getParameter(X0), "Parameter LOOKAHEAD not present.");
82          Iterator<UnderlyingDistance<LaneBasedGtu>> leaders =
83                  neighbors.getLeaders(RelativeLane.CURRENT).underlyingWithDistance();
84          /*
85           * We limit this search by a first conflict. Traffic from other directions on the intersection should not let the
86           * required level of attention for free acceleration flicker for each passing vehicle.
87           */
88          Length limit = Length.POSITIVE_INFINITY;
89          try
90          {
91              var conflicts = perception.getPerceptionCategory(IntersectionPerception.class).getConflicts(RelativeLane.CURRENT);
92              if (!conflicts.isEmpty())
93              {
94                  limit = conflicts.first().getDistance();
95              }
96          }
97          catch (OperationalPlanException ex)
98          {
99              // ignore if intersections are no perceived
100         }
101         double td = 0.0;
102         while (leaders.hasNext())
103         {
104             UnderlyingDistance<LaneBasedGtu> leader = leaders.next();
105             if (leader.distance().gt(limit))
106             {
107                 break;
108             }
109             Speed vLead = leader.object().getSpeed();
110             Length s = leader.distance();
111             td = Math.max(td, Math.max(Math.min((vLead.si - v.si) / vCong.si, 1.0), 0.0) * (1.0 - s.si / x0.si));
112         }
113         return td >= 1.0 ? 0.999 : td;
114     }
115 
116 }