LMRS.java

  1. package org.opentrafficsim.road.gtu.lane.tactical.lmrs;

  2. import org.djunits.value.vdouble.scalar.Length;
  3. import org.djunits.value.vdouble.scalar.Speed;
  4. import org.djunits.value.vdouble.scalar.Time;
  5. import org.djutils.exceptions.Try;
  6. import org.opentrafficsim.base.parameters.ParameterException;
  7. import org.opentrafficsim.base.parameters.ParameterTypes;
  8. import org.opentrafficsim.base.parameters.Parameters;
  9. import org.opentrafficsim.core.gtu.GTUException;
  10. import org.opentrafficsim.core.gtu.perception.EgoPerception;
  11. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
  12. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
  13. import org.opentrafficsim.core.network.NetworkException;
  14. import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
  15. import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
  16. import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
  17. import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
  18. import org.opentrafficsim.road.gtu.lane.plan.operational.LaneChange;
  19. import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder;
  20. import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
  21. import org.opentrafficsim.road.gtu.lane.tactical.Blockable;
  22. import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
  23. import org.opentrafficsim.road.gtu.lane.tactical.Synchronizable;
  24. import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
  25. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
  26. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
  27. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
  28. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
  29. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsData;
  30. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
  31. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil;
  32. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
  33. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
  34. import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
  35. import org.opentrafficsim.road.network.speed.SpeedLimitProspect;

  36. import org.opentrafficsim.core.geometry.DirectedPoint;

  37. /**
  38.  * Implementation of the LMRS (Lane change Model with Relaxation and Synchronization). See Schakel, W.J., Knoop, V.L., and Van
  39.  * Arem, B. (2012), <a href="http://victorknoop.eu/research/papers/TRB2012_LMRS_reviewed.pdf">LMRS: Integrated Lane Change Model
  40.  * with Relaxation and Synchronization</a>, Transportation Research Records: Journal of the Transportation Research Board, No.
  41.  * 2316, pp. 47-57. Note in the official versions of TRB and TRR some errors appeared due to the typesetting of the papers (not
  42.  * in the preprint provided here). A list of errata for the official versions is found
  43.  * <a href="http://victorknoop.eu/research/papers/Erratum_LMRS.pdf">here</a>.
  44.  * <p>
  45.  * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  46.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
  47.  * <p>
  48.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
  49.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  50.  */
  51. public class LMRS extends AbstractIncentivesTacticalPlanner implements DesireBased, Synchronizable, Blockable
  52. {

  53.     /** Serialization id. */
  54.     private static final long serialVersionUID = 20160300L;

  55.     /** Lane change status. */
  56.     private final LaneChange laneChange;

  57.     /** LMRS data. */
  58.     private final LmrsData lmrsData;

  59.     /**
  60.      * Constructor setting the car-following model.
  61.      * @param carFollowingModel CarFollowingModel; Car-following model.
  62.      * @param gtu LaneBasedGTU; GTU
  63.      * @param lanePerception LanePerception; perception
  64.      * @param synchronization Synchronization; type of synchronization
  65.      * @param cooperation Cooperation; type of cooperation
  66.      * @param gapAcceptance GapAcceptance; gap-acceptance
  67.      * @param tailgating Tailgating; tail gating
  68.      */
  69.     public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu, final LanePerception lanePerception,
  70.             final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
  71.             final Tailgating tailgating)
  72.     {
  73.         super(carFollowingModel, gtu, lanePerception);
  74.         this.laneChange = Try.assign(() -> new LaneChange(gtu), "Parameter LCDUR is required.", GTUException.class);
  75.         this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailgating);
  76.     }

  77.     /** {@inheritDoc} */
  78.     @Override
  79.     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
  80.             throws OperationalPlanException, GTUException, NetworkException, ParameterException
  81.     {
  82.         // obtain objects to get info
  83.         SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
  84.                 .getSpeedLimitProspect(RelativeLane.CURRENT);
  85.         SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
  86.         Parameters params = getGtu().getParameters();

  87.         // LMRS
  88.         SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
  89.                 this.lmrsData, getPerception(), getMandatoryIncentives(), getVoluntaryIncentives());

  90.         // Lower acceleration from additional sources, consider adjacent lane when changing lane or synchronizing
  91.         Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
  92.         RelativeLane[] lanes;
  93.         double dLeft = params.getParameterOrNull(LmrsParameters.DLEFT);
  94.         double dRight = params.getParameterOrNull(LmrsParameters.DRIGHT);
  95.         double dSync = params.getParameterOrNull(LmrsParameters.DSYNC);
  96.         if (this.laneChange.isChangingLane())
  97.         {
  98.             lanes = new RelativeLane[] { RelativeLane.CURRENT, this.laneChange.getSecondLane(getGtu()) };
  99.         }
  100.         else if (dLeft >= dSync && dLeft >= dRight)
  101.         {
  102.             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.LEFT };
  103.         }
  104.         else if (dRight >= dSync)
  105.         {
  106.             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.RIGHT };
  107.         }
  108.         else
  109.         {
  110.             lanes = new RelativeLane[] { RelativeLane.CURRENT };
  111.         }
  112.         for (RelativeLane lane : lanes)
  113.         {
  114.             // On the current lane, consider all incentives. On adjacent lanes only consider incentives beyond the distance over
  115.             // which a lane change is not yet possible, i.e. the merge distance.
  116.             // TODO: consider route in incentives (only if not on current lane?)
  117.             Length mergeDistance = lane.isCurrent() ? Length.ZERO
  118.                     : Synchronization.getMergeDistance(getPerception(), lane.getLateralDirectionality());
  119.             for (AccelerationIncentive incentive : getAccelerationIncentives())
  120.             {
  121.                 incentive.accelerate(simplePlan, lane, mergeDistance, getGtu(), getPerception(), getCarFollowingModel(), speed,
  122.                         params, sli);
  123.             }
  124.         }

  125.         if (simplePlan.isLaneChange())
  126.         {
  127.             this.laneChange.setDesiredLaneChangeDuration(getGtu().getParameters().getParameter(ParameterTypes.LCDUR));
  128.             // adjust lane based data in perception
  129.         }

  130.         // set turn indicator
  131.         simplePlan.setTurnIndicator(getGtu());

  132.         // create plan
  133.         return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), startTime, simplePlan, this.laneChange);

  134.     }

  135.     /** {@inheritDoc} */
  136.     @Override
  137.     public final Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
  138.     {
  139.         return this.lmrsData.getLatestDesire(incentiveClass);
  140.     }

  141.     /** {@inheritDoc} */
  142.     @Override
  143.     public Synchronizable.State getSynchronizationState()
  144.     {
  145.         return this.lmrsData.getSynchronizationState();
  146.     }

  147.     /** {@inheritDoc} */
  148.     @Override
  149.     public boolean isBlocking()
  150.     {
  151.         for (AccelerationIncentive acc : getAccelerationIncentives())
  152.         {
  153.             if (acc instanceof AccelerationConflicts)
  154.             {
  155.                 return ((AccelerationConflicts) acc).isBlocking();
  156.             }
  157.         }
  158.         return false;
  159.     }

  160.     /** {@inheritDoc} */
  161.     @Override
  162.     public final String toString()
  163.     {
  164.         return "LMRS [mandatoryIncentives=" + getMandatoryIncentives() + ", voluntaryIncentives=" + getVoluntaryIncentives()
  165.                 + ", accelerationIncentives = " + getAccelerationIncentives() + "]";
  166.     }

  167. }