ChannelTaskCooperation.java
package org.opentrafficsim.road.gtu.lane.perception.mental.channel;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Function;
import org.djunits.value.vdouble.scalar.Length;
import org.djutils.exceptions.Try;
import org.opentrafficsim.base.parameters.ParameterException;
import org.opentrafficsim.base.parameters.ParameterTypeDouble;
import org.opentrafficsim.base.parameters.ParameterTypeLength;
import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable.UnderlyingDistance;
import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
/**
* Task demand for potential cut-in or cooperation. This is defined as the maximum value of {@code d*(1-s/x0)} where {@code d}
* is lane change desire towards the ego lane of any leader in either the left or right adjacent lane, {@code s} is the distance
* to the leader with lane change desire and {@code x0} is the look-ahead distance.
* <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/wjschakel">Wouter Schakel</a>
*/
public final class ChannelTaskCooperation extends AbstractTask implements ChannelTask
{
/** Distance discount range. */
public static final ParameterTypeLength X0_D = ChannelMental.X0_D;
/** Standard set of left and right cooperation task. */
private static final Set<ChannelTask> SET = Set.of(new ChannelTaskCooperation(true), new ChannelTaskCooperation(false));
/** Standard supplier that supplies instances for left and right cooperation task. */
public static final Function<LanePerception, Set<ChannelTask>> SUPPLIER = (p) -> SET;
/** Whether this task instance regards the left side. */
private final boolean left;
/**
* Constructor.
* @param left whether this task instance regards the left side.
*/
private ChannelTaskCooperation(final boolean left)
{
super("cooperation");
this.left = left;
}
@Override
public String getId()
{
return this.left ? "cooperation (left)" : "cooperation (right)";
}
@Override
public Object getChannel()
{
return this.left ? LEFT : RIGHT;
}
@Override
public double calculateTaskDemand(final LanePerception perception)
{
NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
"NeighborsPerception not present.");
Iterator<UnderlyingDistance<LaneBasedGtu>> leaders =
neighbors.getLeaders(this.left ? RelativeLane.LEFT : RelativeLane.RIGHT).underlyingWithDistance();
ParameterTypeDouble param = this.left ? LmrsParameters.DRIGHT : LmrsParameters.DLEFT;
Length x0 = Try.assign(() -> perception.getGtu().getParameters().getParameter(X0_D), "Parameter x0_d not present.");
double dMax = 0.0;
while (leaders.hasNext())
{
UnderlyingDistance<LaneBasedGtu> leader = leaders.next();
if (leader.distance().gt(x0))
{
break;
}
double d;
try
{
d = leader.object().getParameters().getParameter(param) * (1.0 - leader.distance().si / x0.si);
dMax = Math.max(dMax, d);
}
catch (ParameterException ex)
{
// leader does not provide lane change desire, ignore
}
}
return Math.min(0.999, dMax);
}
}