OperationalPlan.java
- package org.opentrafficsim.core.gtu.plan.operational;
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import org.djunits.unit.AccelerationUnit;
- import org.djunits.unit.LengthUnit;
- import org.djunits.unit.SpeedUnit;
- import org.djunits.unit.TimeUnit;
- import org.djunits.value.vdouble.scalar.Acceleration;
- import org.djunits.value.vdouble.scalar.Duration;
- import org.djunits.value.vdouble.scalar.Length;
- import org.djunits.value.vdouble.scalar.Speed;
- import org.djunits.value.vdouble.scalar.Time;
- import org.opentrafficsim.core.geometry.OTSGeometryException;
- import org.opentrafficsim.core.geometry.OTSLine3D;
- import org.opentrafficsim.core.geometry.OTSPoint3D;
- import org.opentrafficsim.core.gtu.GTU;
- import org.opentrafficsim.core.math.Solver;
- import nl.tudelft.simulation.language.d3.DirectedPoint;
- /**
- * An Operational plan describes a path through the world with a speed profile that a GTU intends to follow. The OperationalPlan
- * can be updated or replaced at any time (including before it has been totally executed), for which a tactical planner is
- * responsible. The operational plan is implemented using segments of the movement (time, location, speed, acceleration) that
- * the GTU will use to plan its location and movement. Within an OperationalPlan the GTU cannot reverse direction along the path
- * of movement. This ensures that the timeAtDistance method will never have to select among several valid solutions.
- * <p>
- * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
- * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
- * </p>
- * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
- * initial version Nov 14, 2015 <br>
- * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
- * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
- */
- public class OperationalPlan implements Serializable
- {
- /** */
- private static final long serialVersionUID = 20151114L;
- /** The path to follow from a certain time till a certain time. */
- private final OTSLine3D path;
- /** The absolute start time when we start executing the path. */
- private final Time startTime;
- /** The GTU speed when we start executing the path. */
- private final Speed startSpeed;
- /** The segments that make up the path with an acceleration, constant speed or deceleration profile. */
- private final List<OperationalPlan.Segment> operationalPlanSegmentList;
- /** The duration of executing the entire operational plan. */
- private final Duration totalDuration;
- /** The length of the entire operational plan. */
- private final Length totalLength;
- /** The speed at the end of the operational plan. */
- private final Speed endSpeed;
- /** Is this operational plan a wait plan? */
- private final boolean waitPlan;
- /** GTU for debugging purposes. */
- private final GTU gtu;
- /**
- * An array of relative start times of each segment, expressed in the SI unit, where the last time is the overall ending
- * time of the operational plan.
- */
- private final double[] segmentStartTimesRelSI;
- /**
- * The maximum difference in the length of the path and the calculated driven distance implied by the segment list. The same
- * constant is also used as a maximum between speeds of segments that should align in terms of speed.
- */
- static final double MAX_DELTA_SI = 1E-6;
- /** The drifting speed. Speeds under this value will be cropped to zero. */
- public static final double DRIFTING_SPEED_SI = 1E-3;
- /**
- * Construct an operational plan.
- * @param gtu the GTU for debugging purposes
- * @param path the path to follow from a certain time till a certain time. The path should have <i>at least</i> the length
- * @param startTime the absolute start time when we start executing the path
- * @param startSpeed the GTU speed when we start executing the path
- * @param operationalPlanSegmentList the segments that make up the path with an acceleration, constant speed or deceleration
- * profile
- * @throws OperationalPlanException when the path is too short for the operation
- */
- public OperationalPlan(final GTU gtu, final OTSLine3D path, final Time startTime, final Speed startSpeed,
- final List<Segment> operationalPlanSegmentList) throws OperationalPlanException
- {
- this.waitPlan = false;
- this.gtu = gtu;
- this.startTime = startTime;
- this.startSpeed = startSpeed;
- this.operationalPlanSegmentList = operationalPlanSegmentList;
- this.segmentStartTimesRelSI = new double[this.operationalPlanSegmentList.size() + 1];
- // check the driven distance of the segments
- Speed v0 = this.startSpeed;
- double distanceSI = 0.0;
- double durationSI = 0.0;
- for (int i = 0; i < this.operationalPlanSegmentList.size(); i++)
- {
- Segment segment = this.operationalPlanSegmentList.get(i);
- if (Math.abs(v0.si) < DRIFTING_SPEED_SI && segment.accelerationSI(0.0) == 0.0)
- {
- v0 = Speed.ZERO;
- }
- segment.setV0(v0);
- this.segmentStartTimesRelSI[i] = durationSI;
- distanceSI += segment.distanceSI();
- v0 = segment.endSpeed();
- durationSI += segment.getDuration().si;
- }
- this.segmentStartTimesRelSI[this.segmentStartTimesRelSI.length - 1] = durationSI;
- try
- {
- this.path = path.extract(0.0, Math.min(distanceSI, path.getLengthSI()));
- }
- catch (OTSGeometryException exception)
- {
- throw new OperationalPlanException(exception);
- }
- this.totalDuration = new Duration(durationSI, TimeUnit.SI);
- this.totalLength = new Length(distanceSI, LengthUnit.SI);
- this.endSpeed = v0;
- double pathDistanceDeviation = Math.abs(this.totalLength.si - this.path.getLengthSI()) / this.totalLength.si;
- if (pathDistanceDeviation < -0.01 || pathDistanceDeviation > 0.01)
- {
- System.err.println("path length and driven distance deviate more than 1% for operationalPlan: " + this);
- }
- }
- /**
- * Build a plan where the GTU will wait for a certain time.
- * @param gtu the GTU for debugging purposes
- * @param waitPoint the point at which the GTU will wait
- * @param startTime the current time or a time in the future when the plan should start
- * @param duration the waiting time
- * @throws OperationalPlanException when construction of a waiting path fails
- */
- public OperationalPlan(final GTU gtu, final DirectedPoint waitPoint, final Time startTime, final Duration duration)
- throws OperationalPlanException
- {
- this.waitPlan = true;
- this.gtu = gtu;
- this.startTime = startTime;
- this.startSpeed = Speed.ZERO;
- this.endSpeed = Speed.ZERO;
- this.totalDuration = duration;
- this.totalLength = Length.ZERO;
- // make a path
- OTSPoint3D p2 = new OTSPoint3D(waitPoint.x + Math.cos(waitPoint.getRotZ()), waitPoint.y + Math.sin(waitPoint.getRotZ()),
- waitPoint.z);
- try
- {
- this.path = new OTSLine3D(new OTSPoint3D(waitPoint), p2);
- }
- catch (OTSGeometryException exception)
- {
- throw new OperationalPlanException(exception);
- }
- this.operationalPlanSegmentList = new ArrayList<>();
- Segment segment = new SpeedSegment(duration);
- segment.setV0(Speed.ZERO);
- this.operationalPlanSegmentList.add(segment);
- this.segmentStartTimesRelSI = new double[2];
- this.segmentStartTimesRelSI[0] = 0.0;
- this.segmentStartTimesRelSI[1] = duration.si;
- }
- /**
- * Return the path that will be traveled. If the plan is a wait plan, the start point of the path is good; the end point of
- * the path is bogus (should only be used to determine the orientation of the GTU).
- * @return the path
- */
- public final OTSLine3D getPath()
- {
- return this.path;
- }
- /**
- * Return the (absolute) start time of the operational plan.
- * @return startTime
- */
- public final Time getStartTime()
- {
- return this.startTime;
- }
- /**
- * Return the start speed of the entire plan.
- * @return startSpeed
- */
- public final Speed getStartSpeed()
- {
- return this.startSpeed;
- }
- /**
- * @return the end speed when completing the entire plan.
- */
- public final Speed getEndSpeed()
- {
- return this.endSpeed;
- }
- /**
- * Return the segments (parts with constant speed, acceleration or deceleration) of the operational plan. <br>
- * The caller MUST NOT MODIFY the returned object.
- * @return operationalPlanSegmentList
- */
- public final List<OperationalPlan.Segment> getOperationalPlanSegmentList()
- {
- return this.operationalPlanSegmentList;
- }
- /**
- * Return the time it will take to complete the entire operational plan.
- * @return the time it will take to complete the entire operational plan
- */
- public final Duration getTotalDuration()
- {
- return this.totalDuration;
- }
- /**
- * Return the distance the entire operational plan will cover.
- * @return the distance of the entire operational plan
- */
- public final Length getTotalLength()
- {
- return this.totalLength;
- }
- /**
- * Return the time it will take to complete the entire operational plan.
- * @return the time it will take to complete the entire operational plan
- */
- public final Time getEndTime()
- {
- return this.startTime.plus(this.totalDuration);
- }
- /**
- * Provide the end location of this operational plan as a DirectedPoint.
- * @return the end location
- */
- public final DirectedPoint getEndLocation()
- {
- try
- {
- if (this.waitPlan)
- {
- return this.path.getLocationFraction(0.0); // no move...
- }
- else
- {
- return this.path.getLocationFraction(1.0);
- }
- }
- catch (OTSGeometryException exception)
- {
- // should not happen -- only for fractions less than 0.0 or larger than 1.0.
- throw new RuntimeException(exception);
- }
- }
- /**
- * Store a Segment and the progress within that segment in one Object.
- * <p>
- * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
- * All rights reserved. <br>
- * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
- * <p>
- * @version $Revision$, $LastChangedDate$, by $Author$, initial version Dec 16, 2015 <br>
- * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
- * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
- */
- private class SegmentProgress implements Serializable
- {
- /** */
- private static final long serialVersionUID = 20160000L;
- /** Active Segment. */
- private final Segment segment;
- /** Start time of the Segment. */
- private final Time segmentStartTime;
- /** Position on the path of the plan. */
- private final Length segmentStartPosition;
- /**
- * Construct a new SegmentProgress object.
- * @param segment Segment; the Segment
- * @param segmentStartTime Time; the start time of the Segment
- * @param segmentStartPosition Length; the position of the start of the segment on the path of the OperationalPlan
- */
- SegmentProgress(final Segment segment, final Time segmentStartTime, final Length segmentStartPosition)
- {
- this.segment = segment;
- this.segmentStartTime = segmentStartTime;
- this.segmentStartPosition = segmentStartPosition;
- }
- /**
- * Retrieve the Segment.
- * @return Segment
- */
- public final Segment getSegment()
- {
- return this.segment;
- }
- /**
- * Retrieve the start time of the Segment.
- * @return Time; the start time of the Segment
- */
- public final Time getSegmentStartTime()
- {
- return this.segmentStartTime;
- }
- /**
- * Retrieve the fractionalPosition at the start of the Segment.
- * @return double; the fractional position at the start of the Segment
- */
- public final Length getSegmentStartPosition()
- {
- return this.segmentStartPosition;
- }
- /** {@inheritDoc} */
- @Override
- public final String toString()
- {
- return String.format("SegmentProgress segment=%s startpos.rel=%s starttime.abs=%s", this.segment,
- this.segmentStartPosition, this.segmentStartTime);
- }
- }
- /**
- * Find the Segment and the progress within that Segment at a specified time.
- * @param time Time; the time
- * @return SegmentProgress; the Segment and progress within that segment, or null when no Segment applies to the specified
- * time
- * @throws OperationalPlanException when SegmentProgress cannot be determined
- */
- private SegmentProgress getSegmentProgress(final Time time) throws OperationalPlanException
- {
- if (time.lt(this.startTime))
- {
- throw new OperationalPlanException(
- this.gtu + ", t = " + time + "SegmentProgress cannot be determined for time before startTime "
- + getStartTime() + " of this OperationalPlan");
- }
- double cumulativeDistance = 0;
- for (int i = 0; i < this.segmentStartTimesRelSI.length - 1; i++)
- {
- if (this.startTime.si + this.segmentStartTimesRelSI[i + 1] >= time.si)
- {
- return new SegmentProgress(this.operationalPlanSegmentList.get(i),
- new Time(this.startTime.si + this.segmentStartTimesRelSI[i], TimeUnit.SI),
- new Length(cumulativeDistance, LengthUnit.SI));
- }
- }
- throw new OperationalPlanException(this.gtu + ", t = " + time
- + " SegmentProgress cannot be determined for time after endTime " + getEndTime() + " of this OperationalPlan");
- }
- /**
- * Return the time when the GTU will reach the given distance.
- * @param distance the distance to calculate the time for
- * @return the time it will take to have traveled the given distance
- */
- public final Time timeAtDistance(final Length distance)
- {
- double remainingDistanceSI = distance.si;
- double timeAtStartOfSegment = this.startTime.si;
- for (Segment segment : this.operationalPlanSegmentList)
- {
- double distanceOfSegment = segment.distanceSI();
- if (distanceOfSegment > remainingDistanceSI)
- {
- return new Time(
- timeAtStartOfSegment + segment.timeAtDistance(new Length(remainingDistanceSI, LengthUnit.SI)).si,
- TimeUnit.SI);
- }
- remainingDistanceSI -= distanceOfSegment;
- timeAtStartOfSegment += segment.getDurationSI();
- }
- return new Time(Double.NaN, TimeUnit.SI);
- }
- /**
- * Calculate the location at the given time.
- * @param time the absolute time to look for a location
- * @return the location at the given time.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final DirectedPoint getLocation(final Time time) throws OperationalPlanException
- {
- SegmentProgress sp = getSegmentProgress(time);
- Segment segment = sp.getSegment();
- Duration deltaT = time.minus(sp.getSegmentStartTime());
- double distanceTraveledInSegment = segment.distanceSI(deltaT.si);
- double startDistance = sp.getSegmentStartPosition().si;
- double fraction = (startDistance + distanceTraveledInSegment) / this.path.getLengthSI();
- DirectedPoint p = new DirectedPoint();
- try
- {
- p = this.path.getLocationFraction(fraction, 0.01);
- }
- catch (OTSGeometryException exception)
- {
- System.err.println("OperationalPlan.getLocation(): " + exception.getMessage());
- p = this.path.getLocationFractionExtended(fraction);
- }
- p.setZ(p.getZ() + 0.001);
- return p;
- }
- /**
- * Calculate the speed of the GTU after the given duration since the start of the plan.
- * @param time the relative time to look for a location
- * @return the location after the given duration since the start of the plan.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Speed getSpeed(final Duration time) throws OperationalPlanException
- {
- return getSpeed(time.plus(this.startTime));
- }
- /**
- * Calculate the speed of the GTU at the given time.
- * @param time the absolute time to look for a location
- * @return the location at the given time.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Speed getSpeed(final Time time) throws OperationalPlanException
- {
- SegmentProgress sp = getSegmentProgress(time);
- return new Speed(sp.getSegment().speedSI(time.minus(sp.getSegmentStartTime()).si), SpeedUnit.SI);
- }
- /**
- * Calculate the acceleration of the GTU after the given duration since the start of the plan.
- * @param time the relative time to look for a location
- * @return the location after the given duration since the start of the plan.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Acceleration getAcceleration(final Duration time) throws OperationalPlanException
- {
- return getAcceleration(time.plus(this.startTime));
- }
- /**
- * Calculate the acceleration of the GTU at the given time.
- * @param time the absolute time to look for a location
- * @return the location at the given time.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Acceleration getAcceleration(final Time time) throws OperationalPlanException
- {
- SegmentProgress sp = getSegmentProgress(time);
- return new Acceleration(sp.getSegment().accelerationSI(time.minus(sp.getSegmentStartTime()).si), AccelerationUnit.SI);
- }
- /**
- * Calculate the location after the given duration since the start of the plan.
- * @param time the relative time to look for a location
- * @return the location after the given duration since the start of the plan.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final DirectedPoint getLocation(final Duration time) throws OperationalPlanException
- {
- double distanceSI = getTraveledDistanceSI(time);
- return this.path.getLocationExtendedSI(distanceSI);
- }
- /**
- * Calculate the distance traveled as part of this plan after the given duration since the start of the plan. This method
- * returns the traveled distance as a double in SI units.
- * @param duration the relative time to calculate the traveled distance
- * @return the distance traveled as part of this plan after the given duration since the start of the plan.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final double getTraveledDistanceSI(final Duration duration) throws OperationalPlanException
- {
- Time absTime = duration.plus(this.startTime);
- SegmentProgress sp = getSegmentProgress(absTime);
- return sp.getSegment().distanceSI(absTime.minus(sp.getSegmentStartTime()).si);
- }
- /**
- * Calculate the distance traveled as part of this plan after the given duration since the start of the plan.
- * @param duration the relative time to calculate the traveled distance
- * @return the distance traveled as part of this plan after the given duration since the start of the plan.
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Length getTraveledDistance(final Duration duration) throws OperationalPlanException
- {
- return new Length(getTraveledDistanceSI(duration), LengthUnit.SI);
- }
- /**
- * Calculate the distance traveled as part of this plan at the given absolute time. This method returns the traveled
- * distance as a double in SI units.
- * @param time the absolute time to calculate the traveled distance for as part of this plan
- * @return the distance traveled as part of this plan at the given time
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final double getTraveledDistanceSI(final Time time) throws OperationalPlanException
- {
- return getTraveledDistanceSI(time.minus(this.startTime));
- }
- /**
- * Calculate the distance traveled as part of this plan at the given absolute time.
- * @param time the absolute time to calculate the traveled distance for as part of this plan
- * @return the distance traveled as part of this plan at the given time
- * @throws OperationalPlanException when the time is after the validity of the operational plan
- */
- public final Length getTraveledDistance(final Time time) throws OperationalPlanException
- {
- return new Length(getTraveledDistanceSI(time.minus(this.startTime)), LengthUnit.SI);
- }
- /** {@inheritDoc} */
- @SuppressWarnings("checkstyle:designforextension")
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((this.operationalPlanSegmentList == null) ? 0 : this.operationalPlanSegmentList.hashCode());
- result = prime * result + ((this.path == null) ? 0 : this.path.hashCode());
- result = prime * result + ((this.startSpeed == null) ? 0 : this.startSpeed.hashCode());
- result = prime * result + ((this.startTime == null) ? 0 : this.startTime.hashCode());
- return result;
- }
- /** {@inheritDoc} */
- @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:designforextension" })
- @Override
- public boolean equals(final Object obj)
- {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- OperationalPlan other = (OperationalPlan) obj;
- if (this.operationalPlanSegmentList == null)
- {
- if (other.operationalPlanSegmentList != null)
- return false;
- }
- else if (!this.operationalPlanSegmentList.equals(other.operationalPlanSegmentList))
- return false;
- if (this.path == null)
- {
- if (other.path != null)
- return false;
- }
- else if (!this.path.equals(other.path))
- return false;
- if (this.startSpeed == null)
- {
- if (other.startSpeed != null)
- return false;
- }
- else if (!this.startSpeed.equals(other.startSpeed))
- return false;
- if (this.startTime == null)
- {
- if (other.startTime != null)
- return false;
- }
- else if (!this.startTime.equals(other.startTime))
- return false;
- return true;
- }
- /** {@inheritDoc} */
- @SuppressWarnings("checkstyle:designforextension")
- @Override
- public String toString()
- {
- return "OperationalPlan [path=" + this.path + ", startTime=" + this.startTime + ", startSpeed=" + this.startSpeed
- + ", operationalPlanSegmentList=" + this.operationalPlanSegmentList + ", totalDuration=" + this.totalDuration
- + ", segmentStartTimesSI=" + Arrays.toString(this.segmentStartTimesRelSI) + ", endSpeed = " + this.endSpeed
- + "]";
- }
- /****************************************************************************************************************/
- /******************************************** SEGMENT DEFINITIONS ***********************************************/
- /****************************************************************************************************************/
- /**
- * The segment of an operational plan contains a part of the speed profile of a movement in which some of the variables
- * determining movement (speed, acceleration) are constant.
- * <p>
- * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
- * All rights reserved. <br>
- * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
- * </p>
- * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
- * initial version Nov 14, 2015 <br>
- * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
- * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
- */
- public abstract static class Segment implements Serializable
- {
- /** */
- private static final long serialVersionUID = 20151114L;
- /** The duration of the acceleration or speed for this segment. */
- @SuppressWarnings("checkstyle:visibilitymodifier")
- protected final Duration duration;
- /** The initial speed for this segment. */
- @SuppressWarnings("checkstyle:visibilitymodifier")
- protected Speed v0;
- /**
- * @param duration the duration of the acceleration or speed for this segment
- */
- public Segment(final Duration duration)
- {
- super();
- this.duration = duration;
- }
- /**
- * @param v0 the initial speed of this segment; called from the Operational Plan constructor.
- */
- final void setV0(final Speed v0)
- {
- this.v0 = v0;
- }
- /**
- * @return duration the duration of the acceleration or speed for this segment
- */
- public final Duration getDuration()
- {
- return this.duration;
- }
- /**
- * @return duration the duration of the acceleration or speed for this segment
- */
- public final double getDurationSI()
- {
- return this.duration.si;
- }
- /**
- * Calculate the distance covered by a GTU in this segment.
- * @return distance covered
- */
- final double distanceSI()
- {
- return distanceSI(getDuration().si);
- }
- /**
- * Calculate the distance covered by a GTU in this segment after relative time t.
- * @param t the relative time since starting this segment for which to calculate the distance covered
- * @return distance covered
- */
- abstract double distanceSI(double t);
- /**
- * Calculate the speed of a GTU in this segment after relative time t.
- * @param t the relative time since starting this segment for which to calculate the speed
- * @return speed at relative time t
- */
- abstract double speedSI(double t);
- /**
- * Calculate the acceleration of a GTU in this segment after relative time t.
- * @param t the relative time since starting this segment for which to calculate the acceleration
- * @return acceleration at relative time t
- */
- abstract double accelerationSI(double t);
- /**
- * Calculate the end speed for this segment.
- * @return speed at end of the segment
- */
- abstract Speed endSpeed();
- /**
- * Calculate the time it takes for the GTU to travel from the start of this Segment to the specified distance within
- * this Segment.
- * @param distance the distance for which the travel time has to be calculated
- * @return the time at distance
- */
- abstract Duration timeAtDistance(final Length distance);
- /** {@inheritDoc} */
- @SuppressWarnings("checkstyle:designforextension")
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((this.duration == null) ? 0 : this.duration.hashCode());
- result = prime * result + ((this.v0 == null) ? 0 : this.v0.hashCode());
- return result;
- }
- /** {@inheritDoc} */
- @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:designforextension" })
- @Override
- public boolean equals(final Object obj)
- {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Segment other = (Segment) obj;
- if (this.duration == null)
- {
- if (other.duration != null)
- return false;
- }
- else if (!this.duration.equals(other.duration))
- return false;
- if (this.v0 == null)
- {
- if (other.v0 != null)
- return false;
- }
- else if (!this.v0.equals(other.v0))
- return false;
- return true;
- }
- }
- /**
- * The segment of an operational plan in which the acceleration is constant.
- * <p>
- * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
- * All rights reserved. <br>
- * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
- * </p>
- * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
- * initial version Nov 14, 2015 <br>
- * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
- * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
- */
- public static class AccelerationSegment extends Segment
- {
- /** */
- private static final long serialVersionUID = 20151114L;
- /** The acceleration for the given duration. */
- private final Acceleration acceleration;
- /**
- * @param duration the duration of the constant acceleration for this segment
- * @param acceleration the acceleration for the given duration
- */
- public AccelerationSegment(final Duration duration, final Acceleration acceleration)
- {
- super(duration);
- this.acceleration = acceleration;
- }
- /** {@inheritDoc} */
- @Override
- final double distanceSI(final double t)
- {
- return this.v0.si * t + 0.5 * this.acceleration.si * t * t;
- }
- /** {@inheritDoc} */
- @Override
- final double accelerationSI(final double t)
- {
- return this.acceleration.si;
- }
- /** {@inheritDoc} */
- @Override
- final double speedSI(final double t)
- {
- return this.v0.si + this.acceleration.si * t;
- }
- /** {@inheritDoc} */
- @Override
- final Speed endSpeed()
- {
- return this.v0.plus(this.acceleration.multiplyBy(getDuration()));
- }
- /** {@inheritDoc} */
- @Override
- public final int hashCode()
- {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + ((this.acceleration == null) ? 0 : this.acceleration.hashCode());
- return result;
- }
- /** {@inheritDoc} */
- @Override
- @SuppressWarnings("checkstyle:needbraces")
- public final boolean equals(final Object obj)
- {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- AccelerationSegment other = (AccelerationSegment) obj;
- if (this.acceleration == null)
- {
- if (other.acceleration != null)
- return false;
- }
- else if (!this.acceleration.equals(other.acceleration))
- return false;
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public final Duration timeAtDistance(final Length distance)
- {
- double[] solutions = Solver.solve(this.acceleration.si / 2, this.v0.si, -distance.si);
- // Find the solution that occurs within our duration (there should be only one).
- for (double solution : solutions)
- {
- if (solution >= 0 && solution <= this.duration.si)
- {
- return new Duration(solution, TimeUnit.SI);
- }
- }
- System.err.println("AccelerationSegment " + this + " timeAtDistance( " + distance + ") failed");
- return null; // No valid solution
- }
- /** {@inheritDoc} */
- @Override
- public final String toString()
- {
- return "AccelerationSegment [t=" + this.duration + ", v0=" + this.v0 + ", a=" + this.acceleration + "]";
- }
- }
- /**
- * The segment of an operational plan in which the speed is constant.
- * <p>
- * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
- * All rights reserved. <br>
- * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
- * </p>
- * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
- * initial version Nov 14, 2015 <br>
- * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
- * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
- */
- public static class SpeedSegment extends Segment
- {
- /** */
- private static final long serialVersionUID = 20151114L;
- /**
- * @param duration the duration of the constant speed for this segment
- */
- public SpeedSegment(final Duration duration)
- {
- super(duration);
- }
- /** {@inheritDoc} */
- @Override
- final double distanceSI(final double t)
- {
- return this.v0.si * t;
- }
- /** {@inheritDoc} */
- @Override
- final double accelerationSI(final double t)
- {
- return 0.0;
- }
- /** {@inheritDoc} */
- @Override
- final double speedSI(final double t)
- {
- return this.v0.si;
- }
- /** {@inheritDoc} */
- @Override
- final Speed endSpeed()
- {
- return this.v0;
- }
- /**
- * @return speed
- */
- public final Speed getSpeed()
- {
- return this.v0;
- }
- /** {@inheritDoc} */
- @Override
- public final Duration timeAtDistance(final Length distance)
- {
- double[] solution = Solver.solve(this.v0.si, -distance.si);
- if (solution.length > 0 && solution[0] >= 0 && solution[0] <= getDurationSI())
- {
- return new Duration(solution[0], TimeUnit.SI);
- }
- System.err.println("SpeedSegment " + this + " timeAtDistance( " + distance + ") failed");
- return null; // No valid solution
- }
- /** {@inheritDoc} */
- @Override
- public final String toString()
- {
- return "SpeedSegment [t=" + this.duration + ", v0=" + this.v0 + "]";
- }
- }
- }