View Javadoc
1   package org.opentrafficsim.road.gtu.tactical.lmrs;
2   
3   import org.djunits.value.vdouble.scalar.Acceleration;
4   import org.djutils.immutablecollections.ImmutableLinkedHashMap;
5   import org.opentrafficsim.base.parameters.ParameterException;
6   import org.opentrafficsim.base.parameters.ParameterTypes;
7   import org.opentrafficsim.core.gtu.Stateless;
8   import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
9   import org.opentrafficsim.road.gtu.LaneBasedGtu;
10  import org.opentrafficsim.road.gtu.perception.PerceptionCollectable;
11  import org.opentrafficsim.road.gtu.perception.RelativeLane;
12  import org.opentrafficsim.road.gtu.perception.categories.InfrastructurePerception;
13  import org.opentrafficsim.road.gtu.perception.categories.IntersectionPerception;
14  import org.opentrafficsim.road.gtu.perception.categories.neighbors.NeighborsPerception;
15  import org.opentrafficsim.road.gtu.perception.object.PerceivedConflict;
16  import org.opentrafficsim.road.gtu.perception.object.PerceivedGtu;
17  import org.opentrafficsim.road.gtu.perception.object.PerceivedTrafficLight;
18  import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
19  import org.opentrafficsim.road.gtu.tactical.util.CarFollowingUtil;
20  import org.opentrafficsim.road.gtu.tactical.util.lmrs.Desire;
21  import org.opentrafficsim.road.gtu.tactical.util.lmrs.VoluntaryIncentive;
22  import org.opentrafficsim.road.network.conflict.Conflict;
23  import org.opentrafficsim.road.network.object.trafficlight.TrafficLight;
24  
25  /**
26   * Incentive to join the shortest queue near intersections.
27   * <p>
28   * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
29   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
30   * </p>
31   * @author Alexander Verbraeck
32   * @author Peter Knoppers
33   * @author Wouter Schakel
34   */
35  public final class IncentiveQueue implements VoluntaryIncentive, Stateless<IncentiveQueue>
36  {
37  
38      /** Singleton instance. */
39      public static final IncentiveQueue SINGLETON = new IncentiveQueue();
40  
41      @Override
42      public IncentiveQueue get()
43      {
44          return SINGLETON;
45      }
46  
47      /**
48       * Constructor.
49       */
50      private IncentiveQueue()
51      {
52          //
53      }
54  
55      @Override
56      public Desire determineDesire(final TacticalContextEgo context, final Desire mandatoryDesire,
57              final ImmutableLinkedHashMap<Class<? extends VoluntaryIncentive>, Desire> voluntaryDesire)
58              throws ParameterException, OperationalPlanException
59      {
60          if (!context.getPerception().contains(IntersectionPerception.class))
61          {
62              return Desire.ZERO;
63          }
64          double aCur = context.getCarFollowingAcceleration().si;
65          if (aCur <= 0.0 && context.getSpeed().eq0())
66          {
67              return Desire.ZERO;
68          }
69          IntersectionPerception inter = context.getPerception().getPerceptionCategory(IntersectionPerception.class);
70          PerceptionCollectable<PerceivedConflict, Conflict> conflicts = inter.getConflicts(RelativeLane.CURRENT);
71          PerceptionCollectable<PerceivedTrafficLight, TrafficLight> lights = inter.getTrafficLights(RelativeLane.CURRENT);
72          // TODO: a ramp-metering traffic light triggers this incentive with possible cooperation from the main line
73          // possible solution: make this a state-full class using Lane/LinkTypes to recognize intersections
74          if (conflicts.isEmpty() && lights.isEmpty())
75          {
76              return Desire.ZERO;
77          }
78          Acceleration a = context.getParameters().getParameter(ParameterTypes.A);
79          NeighborsPerception neigbors = context.getPerception().getPerceptionCategory(NeighborsPerception.class);
80          InfrastructurePerception infra = context.getPerception().getPerceptionCategory(InfrastructurePerception.class);
81  
82          double dLeft = 0.0;
83          if (infra.getCrossSection().contains(RelativeLane.LEFT))
84          {
85              PerceptionCollectable<PerceivedGtu, LaneBasedGtu> leaders = neigbors.getLeaders(RelativeLane.LEFT);
86              if (!leaders.isEmpty())
87              {
88                  Acceleration acc = CarFollowingUtil.followSingleLeader(context, leaders.first());
89                  dLeft = (acc.si - aCur) / a.si;
90              }
91          }
92          double dRight = 0.0;
93          if (infra.getCrossSection().contains(RelativeLane.RIGHT))
94          {
95              PerceptionCollectable<PerceivedGtu, LaneBasedGtu> leaders = neigbors.getLeaders(RelativeLane.RIGHT);
96              if (!leaders.isEmpty())
97              {
98                  Acceleration acc = CarFollowingUtil.followSingleLeader(context, leaders.first());
99                  dRight = (acc.si - aCur) / a.si;
100             }
101         }
102         return new Desire(dLeft, dRight);
103     }
104 
105     @Override
106     public String toString()
107     {
108         return "IncentiveQueue";
109     }
110 
111 }