LMRS.java

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

  2. import java.util.LinkedHashSet;

  3. import org.djunits.value.vdouble.scalar.Length;
  4. import org.djunits.value.vdouble.scalar.Speed;
  5. import org.djunits.value.vdouble.scalar.Time;
  6. import org.opentrafficsim.base.parameters.ParameterException;
  7. import org.opentrafficsim.base.parameters.ParameterTypeClassList;
  8. import org.opentrafficsim.base.parameters.ParameterTypes;
  9. import org.opentrafficsim.base.parameters.Parameters;
  10. import org.opentrafficsim.base.parameters.constraint.ClassCollectionConstraint;
  11. import org.opentrafficsim.core.gtu.GTUException;
  12. import org.opentrafficsim.core.gtu.perception.EgoPerception;
  13. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
  14. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
  15. import org.opentrafficsim.core.network.NetworkException;
  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.RelativeLane;
  19. import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
  20. import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DelayedNeighborsPerception;
  21. import org.opentrafficsim.road.gtu.lane.plan.operational.LaneChange;
  22. import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder;
  23. import org.opentrafficsim.road.gtu.lane.plan.operational.SimpleOperationalPlan;
  24. import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
  25. import org.opentrafficsim.road.gtu.lane.tactical.Blockable;
  26. import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
  27. import org.opentrafficsim.road.gtu.lane.tactical.Synchronizable;
  28. import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
  29. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
  30. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
  31. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
  32. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
  33. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsData;
  34. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
  35. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsUtil;
  36. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
  37. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
  38. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
  39. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
  40. import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
  41. import org.opentrafficsim.road.network.speed.SpeedLimitProspect;

  42. import nl.tudelft.simulation.language.d3.DirectedPoint;

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

  59.     /** Parameter type for mandatory lane change incentives. */
  60.     public static final ParameterTypeClassList<MandatoryIncentive> MANDATORY = new ParameterTypeClassList<>("man.incent.",
  61.             "Mandatory lane-change incentives.", ParameterTypeClassList.getValueClass(MandatoryIncentive.class));

  62.     /** Parameter type for voluntary lane change incentives. */
  63.     public static final ParameterTypeClassList<VoluntaryIncentive> VOLUNTARY = new ParameterTypeClassList<>("vol.incent.",
  64.             "Voluntary lane-change incentives.", ParameterTypeClassList.getValueClass(VoluntaryIncentive.class));

  65.     /** Parameter type for acceleration incentives. */
  66.     public static final ParameterTypeClassList<AccelerationIncentive> ACCELERATION = new ParameterTypeClassList<>("acc.incent.",
  67.             "Acceleration incentives.", ParameterTypeClassList.getValueClass(AccelerationIncentive.class),
  68.             ClassCollectionConstraint.newInstance(AccelerationBusStop.class));

  69.     /** Serialization id. */
  70.     private static final long serialVersionUID = 20160300L;

  71.     /** Lane change status. */
  72.     private final LaneChange laneChange = new LaneChange();

  73.     /** LMRS data. */
  74.     private final LmrsData lmrsData;

  75.     /** Set of mandatory lane change incentives. */
  76.     private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();

  77.     /** Set of voluntary lane change incentives. */
  78.     private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();

  79.     /** Set of acceleration incentives. */
  80.     private final LinkedHashSet<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();

  81.     /**
  82.      * Constructor setting the car-following model.
  83.      * @param carFollowingModel CarFollowingModel; Car-following model.
  84.      * @param gtu LaneBasedGTU; GTU
  85.      * @param lanePerception LanePerception; perception
  86.      * @param synchronization Synchronization; type of synchronization
  87.      * @param cooperation Cooperation; type of cooperation
  88.      * @param gapAcceptance GapAcceptance; gap-acceptance
  89.      * @param tailGating Tailgating; tail gating
  90.      */
  91.     public LMRS(final CarFollowingModel carFollowingModel, final LaneBasedGTU gtu, final LanePerception lanePerception,
  92.             final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
  93.             final Tailgating tailGating)
  94.     {
  95.         super(carFollowingModel, gtu, lanePerception);
  96.         this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailGating);
  97.     }

  98.     /**
  99.      * Adds a mandatory incentive. Ignores {@code null}.
  100.      * @param incentive MandatoryIncentive; Incentive to add.
  101.      */
  102.     public final void addMandatoryIncentive(final MandatoryIncentive incentive)
  103.     {
  104.         if (incentive != null)
  105.         {
  106.             this.mandatoryIncentives.add(incentive);
  107.         }
  108.     }

  109.     /**
  110.      * Adds a voluntary incentive. Ignores {@code null}.
  111.      * @param incentive VoluntaryIncentive; Incentive to add.
  112.      */
  113.     public final void addVoluntaryIncentive(final VoluntaryIncentive incentive)
  114.     {
  115.         if (incentive != null)
  116.         {
  117.             this.voluntaryIncentives.add(incentive);
  118.         }
  119.     }

  120.     /**
  121.      * Adds an acceleration incentive. Ignores {@code null}.
  122.      * @param incentive AccelerationIncentive; Incentive to add.
  123.      */
  124.     public final void addAccelerationIncentive(final AccelerationIncentive incentive)
  125.     {
  126.         if (incentive != null)
  127.         {
  128.             this.accelerationIncentives.add(incentive);
  129.         }
  130.     }

  131.     /**
  132.      * Sets the default lane change incentives.
  133.      */
  134.     public final void setDefaultIncentives()
  135.     {
  136.         this.mandatoryIncentives.clear();
  137.         this.voluntaryIncentives.clear();
  138.         this.accelerationIncentives.clear();
  139.         this.mandatoryIncentives.add(new IncentiveRoute());
  140.         // this.mandatoryIncentives.add(new IncentiveGetInLane());
  141.         this.voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
  142.         this.voluntaryIncentives.add(new IncentiveKeep());
  143.         this.accelerationIncentives.add(new AccelerationSpeedLimitTransition());
  144.         this.accelerationIncentives.add(new AccelerationTrafficLights());
  145.         this.accelerationIncentives.add(new AccelerationConflicts());
  146.     }

  147.     /** {@inheritDoc} */
  148.     @Override
  149.     public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
  150.             throws OperationalPlanException, GTUException, NetworkException, ParameterException
  151.     {
  152.         // obtain objects to get info
  153.         getPerception().perceive();
  154.         SpeedLimitProspect slp = getPerception().getPerceptionCategory(InfrastructurePerception.class)
  155.                 .getSpeedLimitProspect(RelativeLane.CURRENT);
  156.         SpeedLimitInfo sli = slp.getSpeedLimitInfo(Length.ZERO);
  157.         Parameters params = getGtu().getParameters();

  158.         // LMRS
  159.         SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(getGtu(), startTime, getCarFollowingModel(), this.laneChange,
  160.                 this.lmrsData, getPerception(), this.mandatoryIncentives, this.voluntaryIncentives);

  161.         // Lower acceleration from additional sources, consider adjacent lane when changing lane or synchronizing
  162.         Speed speed = getPerception().getPerceptionCategory(EgoPerception.class).getSpeed();
  163.         RelativeLane[] lanes;
  164.         double dLeft = params.getParameterOrNull(LmrsParameters.DLEFT);
  165.         double dRight = params.getParameterOrNull(LmrsParameters.DRIGHT);
  166.         double dSync = params.getParameterOrNull(LmrsParameters.DSYNC);
  167.         if (this.laneChange.isChangingLane())
  168.         {
  169.             lanes = new RelativeLane[] { RelativeLane.CURRENT, this.laneChange.getSecondLane(getGtu()) };
  170.         }
  171.         else if (dLeft >= dSync && dLeft >= dRight)
  172.         {
  173.             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.LEFT };
  174.         }
  175.         else if (dRight >= dSync)
  176.         {
  177.             lanes = new RelativeLane[] { RelativeLane.CURRENT, RelativeLane.RIGHT };
  178.         }
  179.         else
  180.         {
  181.             lanes = new RelativeLane[] { RelativeLane.CURRENT };
  182.         }
  183.         for (AccelerationIncentive incentive : this.accelerationIncentives)
  184.         {
  185.             for (RelativeLane lane : lanes)
  186.             {
  187.                 incentive.accelerate(simplePlan, lane, getGtu(), getPerception(), getCarFollowingModel(), speed, params, sli);
  188.             }
  189.         }

  190.         if (simplePlan.isLaneChange())
  191.         {
  192.             this.laneChange.setDesiredLaneChangeDuration(getGtu().getParameters().getParameter(ParameterTypes.LCDUR));
  193.             // adjust lane based data in perception
  194.             // TODO make this automatic within the perception itself, e.g. by a lane change event from the tactical planner
  195.             if (getPerception().contains(DelayedNeighborsPerception.class))
  196.             {
  197.                 getPerception().getPerceptionCategory(DelayedNeighborsPerception.class)
  198.                         .changeLane(simplePlan.getLaneChangeDirection());
  199.             }
  200.         }

  201.         // set turn indicator
  202.         simplePlan.setTurnIndicator(getGtu());

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

  205.     }

  206.     /** {@inheritDoc} */
  207.     @Override
  208.     public final Desire getLatestDesire(final Class<? extends Incentive> incentiveClass)
  209.     {
  210.         return this.lmrsData.getLatestDesire(incentiveClass);
  211.     }

  212.     /** {@inheritDoc} */
  213.     @Override
  214.     public Synchronizable.State getSynchronizationState()
  215.     {
  216.         return this.lmrsData.getSynchronizationState();
  217.     }

  218.     /** {@inheritDoc} */
  219.     @Override
  220.     public boolean isBlocking()
  221.     {
  222.         for (AccelerationIncentive acc : this.accelerationIncentives)
  223.         {
  224.             if (acc instanceof AccelerationConflicts)
  225.             {
  226.                 return ((AccelerationConflicts) acc).isBlocking();
  227.             }
  228.         }
  229.         return false;
  230.     }

  231.     /** {@inheritDoc} */
  232.     @Override
  233.     public final String toString()
  234.     {
  235.         return "LMRS [mandatoryIncentives=" + this.mandatoryIncentives + ", voluntaryIncentives=" + this.voluntaryIncentives
  236.                 + ", accelerationIncentives = " + this.accelerationIncentives + "]";
  237.     }

  238. }