ArFuller.java
package org.opentrafficsim.road.gtu.lane.perception.mental.ar;
import java.util.Set;
import org.djutils.exceptions.Throw;
import org.opentrafficsim.base.parameters.ParameterException;
import org.opentrafficsim.base.parameters.ParameterTypeDouble;
import org.opentrafficsim.base.parameters.Parameters;
import org.opentrafficsim.base.parameters.constraint.DualBound;
import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
import org.opentrafficsim.road.gtu.lane.perception.mental.BehavioralAdaptation;
import org.opentrafficsim.road.gtu.lane.perception.mental.SumFuller;
/**
* Extends Fuller with the concept of anticipation reliance (AR).
* <p>
* Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* </p>
* @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
* @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
*/
public class ArFuller extends SumFuller<ArTask>
{
/** Fraction of primary task that can be reduced by anticipation reliance. */
public static final ParameterTypeDouble ALPHA = new ParameterTypeDouble("alpha",
"Fraction of primary task that can be reduced by anticipation reliance.", 0.8, DualBound.UNITINTERVAL);
/** Fraction of auxiliary tasks that can be reduced by anticipation reliance. */
public static final ParameterTypeDouble BETA = new ParameterTypeDouble("beta",
"Fraction of auxiliary tasks that can be reduced by anticipation reliance.", 0.6, DualBound.UNITINTERVAL);
/** Primary task id. */
private final String primaryTaskId;
/**
* Constructor.
* @param tasks tasks
* @param behavioralAdapatations behavioralAdapatations
* @param primaryTaskId String; primary task id
*/
public ArFuller(final Set<ArTask> tasks, final Set<BehavioralAdaptation> behavioralAdapatations, final String primaryTaskId)
{
super(tasks, behavioralAdapatations);
this.primaryTaskId = primaryTaskId;
}
@Override
protected double getTotalTaskDemand(final LanePerception perception) throws ParameterException
{
manage(perception);
return getTasks().stream().mapToDouble((t) -> t.getTaskDemand() - t.getAnticipationReliance()).sum();
}
/**
* Manage task demand and anticipation reliance levels.
* @param perception perception
* @throws ParameterException if a parameter is missing or out of bounds
*/
// protected such that it may be overridden
protected void manage(final LanePerception perception) throws ParameterException
{
ArTask primary = null;
for (ArTask task : getTasks())
{
if (task.getId().equals(this.primaryTaskId))
{
primary = task;
break;
}
}
Throw.whenNull(primary, "There is no primary task with id '%s'.", this.primaryTaskId);
double primaryTaskDemand = primary.getTaskDemand(perception);
// max AR is alpha of TD, actual AR approaches 0 for increasing TD
Parameters parameters = perception.getGtu().getParameters();
double a = parameters.getParameter(ALPHA);
double b = parameters.getParameter(BETA);
primary.setAnticipationReliance(a * primaryTaskDemand * (1.0 - primaryTaskDemand));
for (ArTask auxiliary : getTasks())
{
if (!auxiliary.getId().equals(this.primaryTaskId))
{
double auxiliaryTaskLoad = auxiliary.getTaskDemand(perception);
// max AR is beta of TD, actual AR approaches 0 as primary TD approaches 0
auxiliary.setAnticipationReliance(b * auxiliaryTaskLoad * primaryTaskDemand);
}
}
}
@Override
public String toString()
{
return "ArFuller [tasks=" + getTasks() + "]";
}
}