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