package ahfe;
import static org.opentrafficsim.core.gtu.GTUType.CAR;
import static org.opentrafficsim.core.gtu.GTUType.TRUCK;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.djunits.unit.AccelerationUnit;
import org.djunits.unit.DurationUnit;
import org.djunits.unit.FrequencyUnit;
import org.djunits.unit.LengthUnit;
import org.djunits.unit.SpeedUnit;
import org.djunits.unit.TimeUnit;
import org.djunits.value.StorageType;
import org.djunits.value.ValueException;
import org.djunits.value.vdouble.scalar.Acceleration;
import org.djunits.value.vdouble.scalar.Duration;
import org.djunits.value.vdouble.scalar.Frequency;
import org.djunits.value.vdouble.scalar.Length;
import org.djunits.value.vdouble.scalar.Speed;
import org.djunits.value.vdouble.scalar.Time;
import org.djunits.value.vdouble.vector.FrequencyVector;
import org.djunits.value.vdouble.vector.TimeVector;
import org.opentrafficsim.base.parameters.ParameterException;
import org.opentrafficsim.base.parameters.ParameterSet;
import org.opentrafficsim.base.parameters.ParameterTypes;
import org.opentrafficsim.base.parameters.Parameters;
import org.opentrafficsim.core.distributions.ConstantGenerator;
import org.opentrafficsim.core.distributions.Distribution;
import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
import org.opentrafficsim.core.distributions.Generator;
import org.opentrafficsim.core.distributions.ProbabilityException;
import org.opentrafficsim.core.gtu.GTUDirectionality;
import org.opentrafficsim.core.gtu.GTUException;
import org.opentrafficsim.core.gtu.GTUType;
import org.opentrafficsim.core.gtu.Try;
import org.opentrafficsim.core.gtu.animation.GTUColorer;
import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterFactory;
import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterFactoryByType;
import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
import org.opentrafficsim.core.gtu.perception.EgoPerception;
import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
import org.opentrafficsim.core.idgenerator.IdGenerator;
import org.opentrafficsim.core.network.NetworkException;
import org.opentrafficsim.core.network.OTSNetwork;
import org.opentrafficsim.core.network.route.FixedRouteGenerator;
import org.opentrafficsim.core.network.route.Route;
import org.opentrafficsim.core.network.route.RouteGenerator;
import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
import org.opentrafficsim.road.gtu.lane.perception.categories.Anticipation;
import org.opentrafficsim.road.gtu.lane.perception.categories.DelayedNeighborsPerception;
import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
import org.opentrafficsim.road.network.lane.CrossSectionLink;
import org.opentrafficsim.road.network.lane.DirectedLanePosition;
import org.opentrafficsim.road.network.lane.Lane;
import nl.tudelft.simulation.dsol.SimRuntimeException;
import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
import nl.tudelft.simulation.jstats.distributions.DistNormal;
import nl.tudelft.simulation.jstats.distributions.DistUniform;
import nl.tudelft.simulation.jstats.streams.MersenneTwister;
import nl.tudelft.simulation.jstats.streams.StreamInterface;
import nl.tudelft.simulation.language.Throw;
/**
*
* Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
public final class AHFEUtil
{
/**
*
*/
private AHFEUtil()
{
//
}
/**
* @param network the network
* @param gtuColorer the GTU colorer
* @param simulator the simulator
* @param replication replication number
* @param anticipationStrategy anticipation strategy
* @param reactionTime reaction time
* @param anticipationTime anticipation time
* @param truckFraction truck fraction
* @param simulationTime simulation time
* @param leftDemand demand on left highway
* @param rightDemand demand on right highway
* @param leftFraction fraction of traffic generated on left lane
* @param distanceError distance error
* @param speedError speed error
* @param accelerationError acceleration error
* @throws ValueException on value error
* @throws ParameterException on parameter error
* @throws GTUException on gtu error
* @throws ProbabilityException on probability error
* @throws SimRuntimeException on sim runtime error
*/
@SuppressWarnings("checkstyle:parameternumber")
public static void createDemand(final OTSNetwork network, final GTUColorer gtuColorer,
final DEVSSimulatorInterface.TimeDoubleUnit simulator, final int replication, final String anticipationStrategy,
final Duration reactionTime, final Duration anticipationTime, final double truckFraction, final Time simulationTime,
final Frequency leftDemand, final Frequency rightDemand, final double leftFraction, final double distanceError,
final double speedError, final double accelerationError)
throws ValueException, ParameterException, GTUException, SimRuntimeException, ProbabilityException
{
Random seedGenerator = new Random(replication);
Map streams = new HashMap<>();
streams.put("headwayGeneration", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
streams.put("perception", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
simulator.getReplication().setStreams(streams);
TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
IdGenerator idGenerator = new IdGenerator("");
CarFollowingModelFactory idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
PerceptionFactory delayedPerceptionFactory = Try.assign(
() -> new DelayedPerceptionFactory(
(Anticipation) Anticipation.class.getDeclaredField(anticipationStrategy.toUpperCase()).get(null)),
"Exception while obtaining anticipation value %s", anticipationStrategy);
ParameterSet params = new ParameterSet();
params.setDefaultParameter(AbstractIDM.DELTA);
params.setParameter(ParameterTypes.TR, reactionTime);
params.setParameter(DelayedNeighborsPerception.TA, anticipationTime);
params.setDefaultParameter(DelayedNeighborsPerception.TAUE);
params.setParameter(DelayedNeighborsPerception.SERROR, distanceError);
params.setParameter(DelayedNeighborsPerception.VERROR, speedError);
params.setParameter(DelayedNeighborsPerception.AERROR, accelerationError);
LaneBasedTacticalPlannerFactory tacticalFactory =
new LMRSFactoryAHFE(idmPlusFactory, params, delayedPerceptionFactory);
ParameterFactoryByType bcFactory = new ParameterFactoryByType();
// Length lookAhead = new Length(1000.0, LengthUnit.SI);
// Length lookAheadStdev = new Length(250.0, LengthUnit.SI);
Length perception = new Length(1.0, LengthUnit.KILOMETER);
Acceleration b = new Acceleration(2.09, AccelerationUnit.SI);
GTUType gtuType = new GTUType("car", CAR);
bcFactory.addParameter(gtuType, ParameterTypes.FSPEED,
new DistNormal(streams.get("gtuClass"), 123.7 / 120, 12.0 / 120));
bcFactory.addParameter(gtuType, ParameterTypes.B, b);
// bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
// streams.get("gtuClass"));
bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
gtuType = new GTUType("truck", TRUCK);
bcFactory.addParameter(gtuType, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
bcFactory.addParameter(gtuType, ParameterTypes.B, b);
// bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
// streams.get("gtuClass"));
bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
bcFactory.addParameter(gtuType, ParameterTypes.FSPEED, 2.0);
Route leftRoute = new Route("left");
Route rightRoute = new Route("right");
try
{
leftRoute.addNode(network.getNode("LEFTINPRE"));
leftRoute.addNode(network.getNode("LEFTIN"));
leftRoute.addNode(network.getNode("STARTCONVERGE"));
leftRoute.addNode(network.getNode("STARTWEAVING"));
leftRoute.addNode(network.getNode("NARROWING"));
leftRoute.addNode(network.getNode("EXIT"));
rightRoute.addNode(network.getNode("RIGHTINPRE"));
rightRoute.addNode(network.getNode("RIGHTIN"));
rightRoute.addNode(network.getNode("STARTWEAVING"));
rightRoute.addNode(network.getNode("NARROWING"));
rightRoute.addNode(network.getNode("EXIT"));
}
catch (NetworkException exception)
{
exception.printStackTrace();
}
RouteGenerator fixedRouteGeneratorLeft = new FixedRouteGenerator(leftRoute);
RouteGenerator fixedRouteGeneratorRight = new FixedRouteGenerator(rightRoute);
LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
ContinuousDistDoubleScalar.Rel speedCar =
new ContinuousDistDoubleScalar.Rel<>(new DistUniform(streams.get("gtuClass"), 160, 200), SpeedUnit.KM_PER_HOUR);
ContinuousDistDoubleScalar.Rel speedTruck =
new ContinuousDistDoubleScalar.Rel<>(new DistNormal(streams.get("gtuClass"), 80, 2.5), SpeedUnit.KM_PER_HOUR);
LaneBasedTemplateGTUType carLeft =
new LaneBasedTemplateGTUType(new GTUType("car", CAR), new ConstantGenerator<>(Length.createSI(4.0)),
new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, fixedRouteGeneratorLeft);
LaneBasedTemplateGTUType truckLeft =
new LaneBasedTemplateGTUType(new GTUType("truck", TRUCK), new ConstantGenerator<>(Length.createSI(15.0)),
new ConstantGenerator<>(Length.createSI(2.5)), speedTruck, strategicalFactory, fixedRouteGeneratorLeft);
LaneBasedTemplateGTUType carRight =
new LaneBasedTemplateGTUType(new GTUType("car", CAR), new ConstantGenerator<>(Length.createSI(4.0)),
new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, fixedRouteGeneratorRight);
LaneBasedTemplateGTUType truckRight = new LaneBasedTemplateGTUType(new GTUType("truck", TRUCK),
new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)), speedTruck,
strategicalFactory, fixedRouteGeneratorRight);
// GTUTypeGenerator gtuTypeGeneratorLeft = new GTUTypeGenerator(simulator, streams.get("gtuClass"));
// GTUTypeGenerator gtuTypeGeneratorRight = new GTUTypeGenerator(simulator, streams.get("gtuClass"));
Distribution gtuTypeGeneratorLeftLeft = new Distribution<>(streams.get("gtuClass"));
Distribution gtuTypeGeneratorLeftRight = new Distribution<>(streams.get("gtuClass"));
Distribution gtuTypeGeneratorRightLeft = new Distribution<>(streams.get("gtuClass"));
Distribution gtuTypeGeneratorRightRight = new Distribution<>(streams.get("gtuClass"));
if (truckFraction < 1 - leftFraction)
{
double p = truckFraction / (1 - leftFraction);
gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(1.0, carLeft));
gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(1.0 - p, carLeft));
gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(p, truckLeft));
gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(1.0, carRight));
gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(1.0 - p, carRight));
gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(p, truckRight));
}
else
{
double p = (truckFraction - (1 - leftFraction)) / leftFraction;
gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(1.0 - p, carLeft));
gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(p, truckLeft));
gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(1.0, truckLeft));
gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(1.0 - p, carRight));
gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(p, truckRight));
gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(1.0, truckRight));
}
TimeVector timeVector =
new TimeVector(new double[] { 0, 360, 1560, 2160, 3960 }, TimeUnit.BASE_SECOND, StorageType.DENSE);
double leftLeft = leftDemand.si * leftFraction;
FrequencyVector leftLeftDemandPattern = new FrequencyVector(
new double[] { leftLeft * 0.5, leftLeft * 0.5, leftLeft, leftLeft, 0.0 }, FrequencyUnit.SI, StorageType.DENSE);
double leftRight = leftDemand.si * (1 - leftFraction);
FrequencyVector leftRightDemandPattern =
new FrequencyVector(new double[] { leftRight * 0.5, leftRight * 0.5, leftRight, leftRight, 0.0 },
FrequencyUnit.SI, StorageType.DENSE);
double rightLeft = rightDemand.si * leftFraction;
FrequencyVector rightLeftDemandPattern =
new FrequencyVector(new double[] { rightLeft * 0.5, rightLeft * 0.5, rightLeft, rightLeft, 0.0 },
FrequencyUnit.SI, StorageType.DENSE);
double rightRight = rightDemand.si * (1 - leftFraction);
FrequencyVector rightRightDemandPattern =
new FrequencyVector(new double[] { rightRight * 0.5, rightRight * 0.5, rightRight, rightRight, 0.0 },
FrequencyUnit.SI, StorageType.DENSE);
// This defaults to stepwise interpolation, should have been linear.
HeadwayGeneratorDemand leftLeftHeadways = new HeadwayGeneratorDemand(timeVector, leftLeftDemandPattern, simulator);
HeadwayGeneratorDemand leftRightHeadways = new HeadwayGeneratorDemand(timeVector, leftRightDemandPattern, simulator);
HeadwayGeneratorDemand rightLeftHeadways = new HeadwayGeneratorDemand(timeVector, rightLeftDemandPattern, simulator);
HeadwayGeneratorDemand rightRightHeadways = new HeadwayGeneratorDemand(timeVector, rightRightDemandPattern, simulator);
Speed genSpeed = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
CrossSectionLink leftLink = (CrossSectionLink) network.getLink("LEFTINPRE");
CrossSectionLink rightLink = (CrossSectionLink) network.getLink("RIGHTINPRE");
makeGenerator(getLane(leftLink, "FORWARD1"), genSpeed, "LEFTLEFT", idGenerator, simulator, network,
gtuTypeGeneratorLeftLeft, leftLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory, simulationTime,
streams.get("gtuClass"));
makeGenerator(getLane(leftLink, "FORWARD2"), genSpeed, "LEFTRIGHT", idGenerator, simulator, network,
gtuTypeGeneratorLeftRight, leftRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
simulationTime, streams.get("gtuClass"));
makeGenerator(getLane(rightLink, "FORWARD1"), genSpeed, "RIGHTLEFT", idGenerator, simulator, network,
gtuTypeGeneratorRightLeft, rightLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
simulationTime, streams.get("gtuClass"));
makeGenerator(getLane(rightLink, "FORWARD2"), genSpeed, "RIGHTRIGHT", idGenerator, simulator, network,
gtuTypeGeneratorRightRight, rightRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
simulationTime, streams.get("gtuClass"));
}
/**
* Get lane from link by id.
* @param link link
* @param id id
* @return lane
*/
private static Lane getLane(final CrossSectionLink link, final String id)
{
for (Lane lane : link.getLanes())
{
if (lane.getId().equals(id))
{
return lane;
}
}
throw new RuntimeException("Could not find lane " + id + " on link " + link.getId());
}
/**
* @param lane the reference lane for this generator
* @param generationSpeed the speed of the GTU
* @param id the id of the generator itself
* @param idGenerator the generator for the ID
* @param simulator the simulator
* @param network the network
* @param distribution the type generator for the GTU
* @param headwayGenerator the headway generator for the GTU
* @param gtuColorer the GTU colorer for animation
* @param roomChecker the checker to see if there is room for the GTU
* @param bcFactory the factory to generate parameters for the GTU
* @param tacticalFactory the generator for the tactical planner
* @param simulationTime simulation time
* @param stream random number stream
* @throws SimRuntimeException in case of scheduling problems
* @throws ProbabilityException in case of an illegal probability distribution
* @throws GTUException in case the GTU is inconsistent
* @throws ParameterException in case a parameter for the perception is missing
*/
private static void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
final IdGenerator idGenerator, final DEVSSimulatorInterface.TimeDoubleUnit simulator, final OTSNetwork network,
final Distribution distribution, final HeadwayGeneratorDemand headwayGenerator,
final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
final LaneBasedTacticalPlannerFactory> tacticalFactory, final Time simulationTime, final StreamInterface stream)
throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
{
Set initialLongitudinalPositions = new HashSet<>();
// TODO DIR_MINUS
initialLongitudinalPositions
.add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
LaneBasedTemplateGTUTypeDistribution characteristicsGenerator = new LaneBasedTemplateGTUTypeDistribution(distribution);
new LaneBasedGTUGenerator(id, headwayGenerator, gtuColorer, characteristicsGenerator,
GeneratorPositions.create(initialLongitudinalPositions, stream), network, simulator, roomChecker, idGenerator);
}
/**
*
* Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
private static class LMRSFactoryAHFE implements LaneBasedTacticalPlannerFactory
{
/** Constructor for the car-following model. */
private final CarFollowingModelFactory extends CarFollowingModel> carFollowingModelFactory;
/** Default set of parameters for the car-following model. */
private final Parameters defaultCarFollowingParameters;
/** Factory for perception. */
private final PerceptionFactory perceptionFactory;
/**
* Constructor with car-following model class. The class should have an accessible empty constructor.
* @param carFollowingModelFactory factory of the car-following model
* @param defaultCarFollowingParameters default set of parameters for the car-following model
* @param perceptionFactory perception factory
* @throws GTUException if the supplied car-following model does not have an accessible empty constructor
*/
LMRSFactoryAHFE(final CarFollowingModelFactory extends CarFollowingModel> carFollowingModelFactory,
final Parameters defaultCarFollowingParameters, final PerceptionFactory perceptionFactory) throws GTUException
{
this.carFollowingModelFactory = carFollowingModelFactory;
this.defaultCarFollowingParameters = defaultCarFollowingParameters;
this.perceptionFactory = perceptionFactory;
}
/** {@inheritDoc} */
@Override
public final Parameters getParameters()
{
ParameterSet parameters = new ParameterSet();
parameters.setDefaultParameters(ParameterTypes.class);
parameters.setDefaultParameters(LmrsParameters.class);
this.defaultCarFollowingParameters.setAllIn(parameters);
return parameters;
}
/** {@inheritDoc} */
@Override
public final LMRS create(final LaneBasedGTU gtu) throws GTUException
{
LMRS lmrs = new LMRS(this.carFollowingModelFactory.generateCarFollowingModel(), gtu,
this.perceptionFactory.generatePerception(gtu), Synchronization.PASSIVE, Cooperation.PASSIVE,
GapAcceptance.INFORMED, Tailgating.NONE);
lmrs.addMandatoryIncentive(new IncentiveRoute());
lmrs.addVoluntaryIncentive(new IncentiveSpeedWithCourtesy());
if (gtu.getGTUType().getId().equals("car"))
{
lmrs.addVoluntaryIncentive(new IncentiveKeep());
}
else
{
lmrs.addVoluntaryIncentive(new KeepRightTruck());
}
return lmrs;
}
/** {@inheritDoc} */
@Override
public final String toString()
{
return "LMRSFactory [car-following=" + this.carFollowingModelFactory + "]";
}
}
/**
* Perception factory with delay and anticipation for neighbors.
*
* Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
private static class DelayedPerceptionFactory implements PerceptionFactory
{
/** Anticipation form. */
private final Anticipation anticipation;
/**
* Constructor.
* @param anticipation anticipation form.
*/
DelayedPerceptionFactory(final Anticipation anticipation)
{
this.anticipation = anticipation;
}
/** {@inheritDoc} */
@Override
public LanePerception generatePerception(final LaneBasedGTU gtu)
{
LanePerception perception = new CategoricalLanePerception(gtu);
perception.addPerceptionCategory(new DirectEgoPerception(perception));
// perception.addPerceptionCategory(new DirectDefaultSimplePerception(perception));
perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
// perception.addPerceptionCategory(new DirectNeighborsPerception(perception));
perception.addPerceptionCategory(new DelayedNeighborsPerception(perception, this.anticipation));
// perception.addPerceptionCategory(new DirectIntersectionPerception(perception));
return perception;
}
/** {@inheritDoc} */
@Override
public Parameters getParameters()
{
return new ParameterSet();
}
}
/**
*
* Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mrt. 2017
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
private static class KeepRightTruck implements VoluntaryIncentive
{
/**
*
*/
KeepRightTruck()
{
}
/** {@inheritDoc} */
@Override
public Desire determineDesire(final Parameters parameters, final LanePerception perception,
final CarFollowingModel carFollowingModel, final Desire mandatoryDesire, final Desire voluntaryDesire)
throws ParameterException, OperationalPlanException
{
if (perception.getLaneStructure().getRootRecord().getRight() != null
&& perception.getLaneStructure().getRootRecord().getRight().getRight() != null
&& perception.getPerceptionCategory(EgoPerception.class).getSpeed()
.gt(parameters.getParameter(ParameterTypes.VCONG)))
{
// may not be on this lane
return new Desire(0, 1);
}
if (mandatoryDesire.getRight() < 0 || voluntaryDesire.getRight() < 0
|| !perception.getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
{
// no desire to go right if more dominant incentives provide a negative desire to go right
return new Desire(0, 0);
}
// keep right with dFree
return new Desire(0, 1.0);
}
}
/**
* Generates headways based on demand.
*
* Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 17 nov. 2016
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
// TODO replace with ArrivalsHeadwayGenerator and Arrivals
private static class HeadwayGeneratorDemand implements Generator
{
/** Interpolation of demand. */
private final Interpolation interpolation;
/** Vector of time. */
private final TimeVector timeVector;
/** Vector of flow values. */
private final FrequencyVector demandVector;
/** Simulator. */
private final SimulatorInterface.TimeDoubleUnit simulator;
/** Stream name of headway generation. */
private static final String HEADWAY_STREAM = "headwayGeneration";
/**
* @param timeVector a time vector
* @param demandVector the corresponding demand vector
* @param simulator the simulator
*/
public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
final SimulatorInterface.TimeDoubleUnit simulator)
{
this(timeVector, demandVector, simulator, Interpolation.STEPWISE);
}
/**
* @param timeVector a time vector
* @param demandVector the corresponding demand vector
* @param simulator the simulator
* @param interpolation interpolation type
*/
public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
final SimulatorInterface.TimeDoubleUnit simulator, final Interpolation interpolation)
{
Throw.whenNull(timeVector, "Time vector may not be null.");
Throw.whenNull(demandVector, "Demand vector may not be null.");
Throw.whenNull(simulator, "Simulator may not be null.");
Throw.whenNull(interpolation, "Interpolation may not be null.");
Throw.whenNull(simulator.getReplication().getStream(HEADWAY_STREAM),
"Could not obtain random stream '" + HEADWAY_STREAM + "'.");
for (int i = 0; i < timeVector.size() - 1; i++)
{
try
{
Throw.when(timeVector.get(i).ge(timeVector.get(i + 1)), IllegalArgumentException.class,
"Time vector is not increasing.");
}
catch (ValueException exception)
{
throw new RuntimeException(
"Value out of range of time vector. Note that HeadwayGenerator does not create a safe copy.",
exception);
}
}
Throw.when(timeVector.size() != demandVector.size(), IllegalArgumentException.class,
"Time and flow vector should be of the same size.");
Throw.when(timeVector.size() < 2, IllegalArgumentException.class,
"Time and flow vector should be at least of size 2.");
this.timeVector = timeVector;
this.demandVector = demandVector;
this.simulator = simulator;
this.interpolation = interpolation;
}
/** {@inheritDoc} */
@Override
public final Duration draw() throws ProbabilityException, ParameterException
{
Time time = this.simulator.getSimulatorTime();
try
{
Throw.when(time.lt(this.timeVector.get(0)), IllegalArgumentException.class,
"Cannot return a headway at time before first time in vector.");
// get time period of current time
int i = 0;
while (this.timeVector.get(i + 1).lt(time) && i < this.timeVector.size() - 1)
{
i++;
}
try
{
return nextArrival(i, time.minus(this.timeVector.get(i)), 1.0).minus(time);
}
catch (RemoteException exception)
{
throw new RuntimeException("Could not obtain replication.", exception);
}
}
catch (ValueException exception)
{
throw new RuntimeException(
"Value out of range of time or demand vector. Note that HeadwayGenerator does not create safe copies.",
exception);
}
}
/**
* Recursive determination of the next arrival time. Each recursion moves to the next time period. This occurs if a
* randomly determined arrival falls outside of a time period, or when demand in a time period is 0.
* @param i index of time period
* @param start reference time from start of period i, pertains to previous arrival, or zero during recursion
* @param fractionRemaining remaining fraction of headway to apply due to time in earlier time periods
* @return time of next arrival
* @throws ValueException in case of an illegal time vector
* @throws RemoteException in case of not being able to retrieve the replication
*/
private Time nextArrival(final int i, final Duration start, final double fractionRemaining)
throws ValueException, RemoteException
{
// escape if beyond specified time by infinite next arrival (= no traffic)
if (i == this.timeVector.size() - 1)
{
return new Time(Double.POSITIVE_INFINITY, TimeUnit.BASE);
}
// skip zero-demand periods
if (this.demandVector.get(i).equals(Frequency.ZERO))
{
// after zero-demand, the next headway is a random fraction of a random headway as there is no previous arrival
return nextArrival(i + 1, Duration.ZERO,
this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble());
}
// calculate headway from demand
Frequency demand;
if (this.interpolation.isStepWise())
{
demand = this.demandVector.get(i);
}
else
{
double f = start.si / (this.timeVector.get(i + 1).si - this.timeVector.get(i).si);
demand = Frequency.interpolate(this.demandVector.get(i), this.demandVector.get(i + 1), f);
}
double t = -Math.log(this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble()) / demand.si;
// calculate arrival
Time arrival = new Time(this.timeVector.get(i).si + start.si + t * fractionRemaining, TimeUnit.BASE);
// go to next period if arrival is beyond current period
if (arrival.gt(this.timeVector.get(i + 1)))
{
double inStep = this.timeVector.get(i + 1).si - (this.timeVector.get(i).si + start.si);
return nextArrival(i + 1, Duration.ZERO, fractionRemaining - inStep / t);
}
return arrival;
}
/** {@inheritDoc} */
@Override
public final String toString()
{
return "HeadwayGeneratorDemand [interpolation=" + this.interpolation + ", timeVector=" + this.timeVector
+ ", demandVector=" + this.demandVector + ", simulator=" + this.simulator + "]";
}
}
}