LmrsData.java
package org.opentrafficsim.road.gtu.tactical.util.lmrs;
import java.util.LinkedHashSet;
import java.util.Set;
import org.djunits.value.vdouble.scalar.Speed;
import org.opentrafficsim.base.TimeStampedObject;
import org.opentrafficsim.core.gtu.TurnIndicatorStatus;
import org.opentrafficsim.road.gtu.LaneBasedGtu;
import org.opentrafficsim.road.gtu.perception.PerceptionCollectable;
import org.opentrafficsim.road.gtu.perception.object.PerceivedGtu;
import org.opentrafficsim.road.gtu.tactical.Synchronizable;
import org.opentrafficsim.road.gtu.tactical.WithDesiredSpeed;
/**
* Keeps data for LMRS for a specific GTU.
* <p>
* Copyright (c) 2013-2026 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 Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
public final class LmrsData implements Synchronizable, WithDesiredSpeed
{
/** Form of synchronization. */
private final Synchronization synchronization;
/** Form of cooperation. */
private final Cooperation cooperation;
/** Form of gap-acceptance. */
private final GapAcceptance gapAcceptance;
/** Form of tail gating. */
private final Tailgating tailgating;
/** Most recent leaders. */
private final Set<String> leaders = new LinkedHashSet<>();
/** Current leaders. */
private final Set<String> tempLeaders = new LinkedHashSet<>();
/** Synchronization state. */
private Synchronizable.State synchronizationState = Synchronizable.State.NONE;
/** Desired speed. */
private Speed desiredSpeed;
/** Vehicle that is being synchronized to. */
private String syncVehicle;
/** Whether the longitudinal control is human. */
private boolean humanLongitudinalControl = true;
/** Turn indicator for lane change. */
private TimeStampedObject<TurnIndicatorStatus> laneChangeIndicator;
/**
* Constructor.
* @param synchronization synchronization
* @param cooperation cooperation
* @param gapAcceptance gap-acceptance
* @param tailgating tail gating
*/
public LmrsData(final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
final Tailgating tailgating)
{
this.synchronization = synchronization;
this.cooperation = cooperation;
this.gapAcceptance = gapAcceptance;
this.tailgating = tailgating;
}
/**
* Remembers the leaders of the current time step (those forwarded to isNewLeader()) for the next time step.
*/
void initStep()
{
this.leaders.clear();
this.leaders.addAll(this.tempLeaders);
this.tempLeaders.clear();
this.synchronizationState = Synchronizable.State.NONE;
}
/**
* Checks if the given leader is a new leader. It should be a current leader.
* @param gtu gtu to check
* @return whether the gtu is a new leader
*/
boolean isNewLeader(final PerceivedGtu gtu)
{
this.tempLeaders.add(gtu.getId());
return !this.leaders.contains(gtu.getId());
}
/**
* Remembers the gtu that is synchronized to.
* @param gtu gtu that is synchronized to
*/
void setSyncVehicle(final PerceivedGtu gtu)
{
this.syncVehicle = gtu == null ? null : gtu.getId();
}
/**
* Returns whether the provided gtu is the gtu that is synchronized to.
* @param gtu gtu to inquiry
* @return whether the provided gtu is the gtu that is synchronized to
*/
boolean isSyncVehicle(final PerceivedGtu gtu)
{
return this.syncVehicle == null ? false : gtu.getId().equals(this.syncVehicle);
}
/**
* Returns the gtu from the set that is the current sync vehicle, or {@code null} of there is no sync vehicle or it is not
* in the set.
* @param adjLeaders leaders in adjacent lane
* @return gtu from the set that is the current sync vehicle
*/
PerceivedGtu getSyncVehicle(final PerceptionCollectable<PerceivedGtu, LaneBasedGtu> adjLeaders)
{
if (this.syncVehicle == null)
{
return null;
}
for (PerceivedGtu leader : adjLeaders)
{
if (leader.getId().equals(this.syncVehicle))
{
return leader;
}
}
return null;
}
/**
* Returns the synchronization.
* @return synchronization
*/
Synchronization getSynchronization()
{
return this.synchronization;
}
/**
* Returns the cooperation.
* @return cooperation
*/
Cooperation getCooperation()
{
return this.cooperation;
}
/**
* Return the gap-acceptance.
* @return gap-acceptance
*/
GapAcceptance getGapAcceptance()
{
return this.gapAcceptance;
}
/**
* Return the tail gating.
* @return gap-acceptance
*/
Tailgating getTailgating()
{
return this.tailgating;
}
/**
* Sets the synchronization state, but only if the given value is more critical than any previous. The order is NONE,
* COOPERATING, SYNCHRONIZING, INDICATING.
* @param synchronizationState Synchronizable.State; synchronization step
*/
void setSynchronizationState(final Synchronizable.State synchronizationState)
{
if (synchronizationState.compareTo(this.synchronizationState) > 0)
{
this.synchronizationState = synchronizationState;
}
}
@Override
public Synchronizable.State getSynchronizationState()
{
return this.synchronizationState;
}
/**
* Set desired speed.
* @param desiredSpeed desired speed
*/
public void setDesiredSpeed(final Speed desiredSpeed)
{
this.desiredSpeed = desiredSpeed;
}
@Override
public Speed getDesiredSpeed()
{
return this.desiredSpeed;
}
/**
* Return whether control is human.
* @return humanLongitudinalControl.
*/
boolean isHumanLongitudinalControl()
{
return this.humanLongitudinalControl;
}
/**
* Set human longitudinal control.
* @param humanLongitudinalControl set humanLongitudinalControl.
*/
public void setHumanLongitudinalControl(final boolean humanLongitudinalControl)
{
this.humanLongitudinalControl = humanLongitudinalControl;
}
/**
* Return initiated lane change.
* @return initiated lane change
*/
public TimeStampedObject<TurnIndicatorStatus> getInitiatedLaneChange()
{
return this.laneChangeIndicator;
}
/**
* Set turn indicator for lane change.
* @param laneChangeIndicator indicator for lane change
*/
@SuppressWarnings("hiddenfield")
public void setInitiatedLaneChange(final TimeStampedObject<TurnIndicatorStatus> laneChangeIndicator)
{
this.laneChangeIndicator = laneChangeIndicator;
}
@Override
public String toString()
{
return "LmrsData [synchronization=" + this.synchronization + ", leaders=" + this.leaders + ", tempLeaders="
+ this.tempLeaders + ", syncVehicle=" + this.syncVehicle + "]";
}
}