/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.core; import org.opentripplanner.routing.edgetype.PlainStreetEdge; import org.opentripplanner.routing.vertextype.IntersectionVertex; import lombok.Setter; public class SimpleIntersectionTraversalCostModel extends AbstractIntersectionTraversalCostModel { // Model parameters are here. // // Constants for when there is a traffic light. /** Probability that the left turn is active if there is a light. */ @Setter private Double leftTurnActiveProb = 1.0 / 6.0; /** Probability that the right turn is active if there is a light. */ @Setter private Double rightTurnActiveProb = 1.0 / 3.0; /** Probability you can continue straight ahead if there is a light. */ @Setter private Double continueStraightActiveProb = 1.0 / 3.0; /** * Expected time it takes to make a right at a light. * * NOTE(flamholz): default seems to be based on the assumption that there are rights on red? */ @Setter private Double expectedRightAtLightTimeSec = 15.0; /** Expected time it takes to continue straight at a light. */ @Setter private Double expectedStraightAtLightTimeSec = 26.2666666667; /** Expected time it takes to turn left at a light. */ @Setter private Double expectedLeftAtLightTimeSec = 41.666666667; // Constants for when there is no traffic light /** Probability that you stop to turn if there is no light. */ @Setter private Double noLightStopToTurnProb = 1.0; /** * Probability that you stop to continue straight if there is no light. * * Default based on the assumption that most intersections have stop signs. */ @Setter private Double noLightStopToContinueProb = 0.75; /** Expected time it takes to make a right without a stop light. */ @Setter private Double expectedRightNoLightTimeSec = 10.0; /** * Expected time it takes to continue straight without a stop light. * * LOS B: http://en.wikipedia.org/wiki/Level_of_Service#LOS_for_At-Grade_Intersections */ @Setter private Double expectedStraightNoLightTimeSec = 12.0; /** Expected time it takes to turn left without a stop light. */ @Setter private Double expectedLeftNoLightTimeSec = 15.0; @Override public double computeTraversalCost(IntersectionVertex v, PlainStreetEdge from, PlainStreetEdge to, TraverseMode mode, RoutingRequest options, float fromSpeed, float toSpeed) { // If the vertex is free-flowing then (by definition) there is no cost to traverse it. if (v.inferredFreeFlowing()) { return 0; } // Non-driving cases are much simpler. Handled generically in the base class. if (!mode.isDriving()) { return computeNonDrivingTraversalCost(v, from, to, fromSpeed, toSpeed); } double turnCost = 0; double probabilityStopToTurn = 0; int turnAngle = calculateTurnAngle(from, to, options); if (v.isTrafficLight()) { // Use constants that apply when there are stop lights. if (isRightTurn(turnAngle)) { turnCost = expectedRightAtLightTimeSec; probabilityStopToTurn = 1.0 - rightTurnActiveProb; } else if (isLeftTurn(turnAngle)) { turnCost = expectedLeftAtLightTimeSec; probabilityStopToTurn = 1.0 - leftTurnActiveProb; } else { turnCost = expectedStraightAtLightTimeSec; probabilityStopToTurn = 1.0 - continueStraightActiveProb; } } else { // Use constants that apply when no stop lights. if (isRightTurn(turnAngle)) { turnCost = expectedRightNoLightTimeSec; probabilityStopToTurn = noLightStopToTurnProb; } else if (isLeftTurn(turnAngle)) { turnCost = expectedLeftNoLightTimeSec; probabilityStopToTurn = noLightStopToTurnProb; } else { turnCost = expectedStraightNoLightTimeSec; probabilityStopToTurn = noLightStopToContinueProb; } } // Note that both acceleration and deceleration are multipled by 0.5, because half // of the acceleration/deceleration time has already been accounted for in the base // time calculations (this requires some algebra, but is correct). // Calculate deceleration by multiplying the time for deceleration by the probability // of stopping (expected value) double decelerationTime = fromSpeed / options.carDecelerationSpeed; turnCost += decelerationTime * 0.5 * probabilityStopToTurn; // Calculate acceleration the same way double accelerationTime = (toSpeed / options.carAccelerationSpeed); turnCost += accelerationTime * 0.5 * probabilityStopToTurn; return turnCost; } }