diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index cef482eb781..199eda8a332 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -17,35 +17,12 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |--------------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|------------------|:-----:| | [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | | arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | -| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | -| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | -| bikeParkTime | `duration` | Time to park a bike. | *Optional* | `"PT1M"` | 2.0 | -| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | -| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | -| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | -| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | -| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | -| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | | [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | -| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | -| carParkTime | `duration` | Time to park a car | *Optional* | `"PT1M"` | 2.1 | -| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | -| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | -| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | | [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | | elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | | elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | | elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | | elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | | geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | | ignoreRealtimeUpdates | `boolean` | When true, real-time updates are ignored during this search. | *Optional* | `false` | 2.0 | | [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | @@ -55,24 +32,16 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe | modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | | nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | | numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | -| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | | [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | | [relaxTransitGroupPriority](#rd_relaxTransitGroupPriority) | `string` | The relax function for transit-group-priority | *Optional* | `"0s + 1.00 t"` | 2.5 | | [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | | [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | -| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | -| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | | [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | | [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | | [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | | turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | | [unpreferredCost](#rd_unpreferredCost) | `cost-linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"0s + 1.00 t"` | 2.2 | -| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | | waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | -| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | -| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | -| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | | accessEgress | `object` | Parameters for access and egress routing. | *Optional* | | 2.4 | |    [maxDuration](#rd_accessEgress_maxDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | |    [maxStopCount](#rd_accessEgress_maxStopCount) | `integer` | Maximal number of stops collected in access/egress routing | *Optional* | `500` | 2.4 | @@ -82,8 +51,63 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |          costFactor | `double` | A factor multiplied with the time-penalty to get the cost-penalty. | *Optional* | `0.0` | 2.4 | |          timePenalty | `time-penalty` | Penalty added to the time of a path/leg. | *Optional* | `"0s + 0.00 t"` | 2.4 | | [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | -| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | +| bicycle | `object` | Bicycle preferences. | *Optional* | | 2.5 | +|    [boardCost](#rd_bicycle_boardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a transit vehicle. | *Optional* | `600` | 2.0 | +|    [optimization](#rd_bicycle_optimization) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe-streets"` | 2.0 | +|    reluctance | `double` | A multiplier for how bad cycling is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +|    speed | `double` | Max bicycle speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | +|    parking | `object` | Preferences for parking a vehicle. | *Optional* | | 2.5 | +|       cost | `integer` | Cost to park a vehicle. | *Optional* | `120` | 2.0 | +|       time | `duration` | Time to park a vehicle. | *Optional* | `"PT1M"` | 2.0 | +|       [unpreferredVehicleParkingTagCost](#rd_bicycle_parking_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | +|       [bannedVehicleParkingTags](#rd_bicycle_parking_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | +|       [preferredVehicleParkingTags](#rd_bicycle_parking_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | +|       [requiredVehicleParkingTags](#rd_bicycle_parking_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | +|    rental | `object` | Vehicle rental options | *Optional* | | 2.3 | +|       allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | +|       dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|       dropOffTime | `duration` | Time to drop-off a rented vehicle. | *Optional* | `"PT30S"` | 2.0 | +|       keepingAtDestinationCost | `integer` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0` | 2.2 | +|       pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | +|       pickupTime | `duration` | Time to rent a vehicle. | *Optional* | `"PT1M"` | 2.0 | +|       useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | +|       [allowedNetworks](#rd_bicycle_rental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | +|       [bannedNetworks](#rd_bicycle_rental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | +|    [triangle](#rd_bicycle_triangle) | `object` | Triangle optimization criteria. | *Optional* | | 2.5 | +|       flatness | `double` | Relative importance of flat terrain (range 0-1). | *Optional* | `0.0` | 2.0 | +|       [safety](#rd_bicycle_triangle_safety) | `double` | Relative importance of safety (range 0-1). | *Optional* | `0.0` | 2.0 | +|       time | `double` | Relative importance of duration of travel (range 0-1). | *Optional* | `0.0` | 2.0 | +|    walk | `object` | Preferences for walking a vehicle. | *Optional* | | 2.5 | +|       [hopCost](#rd_bicycle_walk_hopCost) | `integer` | The cost of hopping on or off a vehicle. | *Optional* | `0` | 2.0 | +|       [hopTime](#rd_bicycle_walk_hopTime) | `duration` | The time it takes the user to hop on or off a vehicle. | *Optional* | `"PT0S"` | 2.0 | +|       reluctance | `double` | A multiplier for how bad walking with a vehicle is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | +|       speed | `double` | The user's vehicle walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | +|       stairsReluctance | `double` | How bad is it to walk the vehicle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | | [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | +| car | `object` | Car preferences. | *Optional* | | 2.5 | +|    accelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +|    decelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +|    pickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | +|    pickupTime | `duration` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `"PT1M"` | 2.1 | +|    reluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +|    speed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | +|    parking | `object` | Preferences for parking a vehicle. | *Optional* | | 2.5 | +|       cost | `integer` | Cost to park a vehicle. | *Optional* | `120` | 2.0 | +|       time | `duration` | Time to park a vehicle. | *Optional* | `"PT1M"` | 2.0 | +|       [unpreferredVehicleParkingTagCost](#rd_car_parking_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | +|       [bannedVehicleParkingTags](#rd_car_parking_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | +|       [preferredVehicleParkingTags](#rd_car_parking_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | +|       [requiredVehicleParkingTags](#rd_car_parking_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | +|    rental | `object` | Vehicle rental options | *Optional* | | 2.3 | +|       allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | +|       dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|       dropOffTime | `duration` | Time to drop-off a rented vehicle. | *Optional* | `"PT30S"` | 2.0 | +|       keepingAtDestinationCost | `integer` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0` | 2.2 | +|       pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | +|       pickupTime | `duration` | Time to rent a vehicle. | *Optional* | `"PT1M"` | 2.0 | +|       useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | +|       [allowedNetworks](#rd_car_rental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | +|       [bannedNetworks](#rd_car_rental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | | [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | |    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | |    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | @@ -101,8 +125,6 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `cost-linear-function` | The base function used by the filter. | *Optional* | `"15m + 1.50 t"` | 2.2 | |       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | | [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | -| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | -| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | | [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | |    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | |    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | @@ -113,16 +135,14 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe | [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | |    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | |    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | -| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | -|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | -|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | -|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | -|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | -|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | -|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | -|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | +| walk | `object` | Walking preferences. | *Optional* | | 2.5 | +|    boardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | +|    escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | +|    [reluctance](#rd_walk_reluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +|    [safetyFactor](#rd_walk_safetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | +|    speed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | +|    stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | +|    [stairsTimeFactor](#rd_walk_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | | wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | |    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | |    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | @@ -159,15 +179,6 @@ The minimum extra time after exiting a public transport vehicle. The slack is added to the time when going from the transit vehicle to the stop. -

bikeBoardCost

- -**Since version:** `2.0` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `600` -**Path:** /routingDefaults - -Prevents unnecessary transfers by adding a cost for boarding a vehicle. - -This is the cost that is used when boarding while cycling.This is usually higher that walkBoardCost. -

boardSlack

**Since version:** `2.0` ∙ **Type:** `duration` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"PT0S"` @@ -230,14 +241,6 @@ search, hence, making it a bit slower. Recommended values would be from 12 hours 1 day (region) to 2 days (country like Norway)." -

optimize

- -**Since version:** `2.0` ∙ **Type:** `enum` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"safe"` -**Path:** /routingDefaults -**Enum values:** `quick` | `safe` | `flat` | `greenways` | `triangle` - -The set of characteristics that the user wants to optimize for. -

otherThanPreferredRoutesPenalty

**Since version:** `2.0` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `300` @@ -303,17 +306,6 @@ There is no need to set this when going to the next/previous page. The OTP Serve increase/decrease the search-window when paging to match the requested number of itineraries. -

stairsTimeFactor

- -**Since version:** `2.1` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `3.0` -**Path:** /routingDefaults - -How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. - -Default value is based on: Fujiyama, T., & Tyler, N. (2010). Predicting the walking -speed of pedestrians on stairs. Transportation Planning and Technology, 33(2), 177–202. - -

streetRoutingTimeout

**Since version:** `2.2` ∙ **Type:** `duration` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"PT5S"` @@ -364,38 +356,6 @@ Function should return number of seconds that we are willing to wait for preferr or for an unpreferred agency's departure. For example: `5m + 2.0 t` -

unpreferredVehicleParkingTagCost

- -**Since version:** `2.3` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `300` -**Path:** /routingDefaults - -What cost to add if a parking facility doesn't contain a preferred tag. - -See `preferredVehicleParkingTags`. - -

walkReluctance

- -**Since version:** `2.0` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `2.0` -**Path:** /routingDefaults - -A multiplier for how bad walking is, compared to being in transit for equal lengths of time. - -Empirically, values between 2 and 4 seem to correspond well to the concept of not wanting to walk -too much without asking for totally ridiculous itineraries, but this observation should in no way -be taken as scientific or definitive. Your mileage may vary. -See https://github.com/opentripplanner/OpenTripPlanner/issues/4090 for impact on performance with -high values. - - -

walkSafetyFactor

- -**Since version:** `2.2` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `1.0` -**Path:** /routingDefaults - -Factor for how much the walk safety is considered in routing. - -Value should be between 0 and 1. If the value is set to be 0, safety is ignored. -

maxDuration

**Since version:** `2.1` ∙ **Type:** `duration` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"PT45M"` @@ -473,16 +433,120 @@ How much extra time should be given when alighting a vehicle for each given mode Sometimes there is a need to configure a longer alighting times for specific modes, such as airplanes or ferries. -

bannedVehicleParkingTags

+

boardCost

+ +**Since version:** `2.0` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `600` +**Path:** /routingDefaults/bicycle + +Prevents unnecessary transfers by adding a cost for boarding a transit vehicle. + +This is the cost that is used when boarding while cycling. This is usually higher that walkBoardCost. + +

optimization

+ +**Since version:** `2.0` ∙ **Type:** `enum` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"safe-streets"` +**Path:** /routingDefaults/bicycle +**Enum values:** `shortest-duration` | `safe-streets` | `flat-streets` | `safest-streets` | `triangle` + +The set of characteristics that the user wants to optimize for. + +If the triangle optimization is used, it's enough to just define the triangle parameters + +

unpreferredVehicleParkingTagCost

+ +**Since version:** `2.3` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `300` +**Path:** /routingDefaults/bicycle/parking + +What cost to add if a parking facility doesn't contain a preferred tag. + +See `preferredVehicleParkingTags`. + +

bannedVehicleParkingTags

**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` -**Path:** /routingDefaults +**Path:** /routingDefaults/bicycle/parking Tags with which a vehicle parking will not be used. If empty, no tags are banned. Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). +

preferredVehicleParkingTags

+ +**Since version:** `2.3` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/bicycle/parking + +Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. + +Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + + +

requiredVehicleParkingTags

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/bicycle/parking + +Tags without which a vehicle parking will not be used. If empty, no tags are required. + +Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + + +

allowedNetworks

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/bicycle/rental + +The vehicle rental networks which may be used. If empty all networks may be used. + +

bannedNetworks

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/bicycle/rental + +The vehicle rental networks which may not be used. If empty, no networks are banned. + +

triangle

+ +**Since version:** `2.5` ∙ **Type:** `object` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/bicycle + +Triangle optimization criteria. + +Optimization type doesn't need to be defined if these values are defined. + +

safety

+ +**Since version:** `2.0` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `0.0` +**Path:** /routingDefaults/bicycle/triangle + +Relative importance of safety (range 0-1). + +This factor can also include other concerns such as convenience and general cyclist +preferences by taking into account road surface etc. + + +

hopCost

+ +**Since version:** `2.0` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `0` +**Path:** /routingDefaults/bicycle/walk + +The cost of hopping on or off a vehicle. + +There are different parameters for the cost of renting or parking a vehicle and this is +not meant for controlling the cost of those events. + + +

hopTime

+ +**Since version:** `2.0` ∙ **Type:** `duration` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"PT0S"` +**Path:** /routingDefaults/bicycle/walk + +The time it takes the user to hop on or off a vehicle. + +Time it takes to rent or park a vehicle have their own parameters and this is not meant +for controlling the duration of those events. + +

boardSlackForMode

**Since version:** `2.0` ∙ **Type:** `enum map of duration` ∙ **Cardinality:** `Optional` @@ -495,6 +559,59 @@ Sometimes there is a need to configure a board times for specific modes, such as ferries, where the check-in process needs to be done in good time before ride. +

unpreferredVehicleParkingTagCost

+ +**Since version:** `2.3` ∙ **Type:** `integer` ∙ **Cardinality:** `Optional` ∙ **Default value:** `300` +**Path:** /routingDefaults/car/parking + +What cost to add if a parking facility doesn't contain a preferred tag. + +See `preferredVehicleParkingTags`. + +

bannedVehicleParkingTags

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/car/parking + +Tags with which a vehicle parking will not be used. If empty, no tags are banned. + +Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + + +

preferredVehicleParkingTags

+ +**Since version:** `2.3` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/car/parking + +Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. + +Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + + +

requiredVehicleParkingTags

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/car/parking + +Tags without which a vehicle parking will not be used. If empty, no tags are required. + +Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + + +

allowedNetworks

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/car/rental + +The vehicle rental networks which may be used. If empty all networks may be used. + +

bannedNetworks

+ +**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` +**Path:** /routingDefaults/car/rental + +The vehicle rental networks which may not be used. If empty, no networks are banned. +

itineraryFilters

**Since version:** `2.0` ∙ **Type:** `object` ∙ **Cardinality:** `Optional` @@ -710,26 +827,6 @@ Override the settings in `maxDirectStreetDuration` for specific street modes. Th done because some street modes searches are much more resource intensive than others. -

preferredVehicleParkingTags

- -**Since version:** `2.3` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` -**Path:** /routingDefaults - -Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. - -Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - - -

requiredVehicleParkingTags

- -**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` -**Path:** /routingDefaults - -Tags without which a vehicle parking will not be used. If empty, no tags are required. - -Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - -

transferOptimization

**Since version:** `2.1` ∙ **Type:** `object` ∙ **Cardinality:** `Optional` @@ -871,19 +968,39 @@ The ids of the routes that incur an extra cost when being used. Format: `FeedId: How much cost is added is configured in `unpreferredCost`. -

allowedNetworks

+

reluctance

-**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` -**Path:** /routingDefaults/vehicleRental +**Since version:** `2.0` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `2.0` +**Path:** /routingDefaults/walk -The vehicle rental networks which may be used. If empty all networks may be used. +A multiplier for how bad walking is, compared to being in transit for equal lengths of time. + +Empirically, values between 2 and 4 seem to correspond well to the concept of not wanting to walk +too much without asking for totally ridiculous itineraries, but this observation should in no way +be taken as scientific or definitive. Your mileage may vary. +See https://github.com/opentripplanner/OpenTripPlanner/issues/4090 for impact on performance with +high values. -

bannedNetworks

-**Since version:** `2.1` ∙ **Type:** `string[]` ∙ **Cardinality:** `Optional` -**Path:** /routingDefaults/vehicleRental +

safetyFactor

+ +**Since version:** `2.2` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `1.0` +**Path:** /routingDefaults/walk + +Factor for how much the walk safety is considered in routing. + +Value should be between 0 and 1. If the value is set to be 0, safety is ignored. + +

stairsTimeFactor

+ +**Since version:** `2.1` ∙ **Type:** `double` ∙ **Cardinality:** `Optional` ∙ **Default value:** `3.0` +**Path:** /routingDefaults/walk + +How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. + +Default value is based on: Fujiyama, T., & Tyler, N. (2010). Predicting the walking +speed of pedestrians on stairs. Transportation Planning and Technology, 33(2), 177–202. -The vehicle rental networks which may not be used. If empty, no networks are banned.

maxSlope

@@ -931,34 +1048,59 @@ include stairs as a last result. // router-config.json { "routingDefaults" : { - "walkSpeed" : 1.3, - "bikeSpeed" : 5, - "carSpeed" : 40, "numItineraries" : 12, "transferPenalty" : 0, - "walkReluctance" : 4.0, - "bikeReluctance" : 5.0, - "bikeWalkingReluctance" : 10.0, - "bikeStairsReluctance" : 150.0, - "carReluctance" : 10.0, - "stairsReluctance" : 1.65, "turnReluctance" : 1.0, "elevatorBoardTime" : 90, "elevatorBoardCost" : 90, "elevatorHopTime" : 20, "elevatorHopCost" : 20, - "escalatorReluctance" : 1.5, - "vehicleRental" : { - "pickupCost" : 120, - "dropOffTime" : 30, - "dropOffCost" : 30 + "bicycle" : { + "speed" : 5, + "reluctance" : 5.0, + "boardCost" : 600, + "walk" : { + "reluctance" : 10.0, + "stairsReluctance" : 150.0 + }, + "rental" : { + "pickupCost" : 120, + "dropOffTime" : "30s", + "dropOffCost" : 30 + }, + "parking" : { + "time" : "1m", + "cost" : 120 + }, + "triangle" : { + "safety" : 0.4, + "flatness" : 0.3, + "time" : 0.3 + } + }, + "car" : { + "speed" : 40, + "reluctance" : 10, + "decelerationSpeed" : 2.9, + "accelerationSpeed" : 2.9, + "rental" : { + "pickupCost" : 120, + "dropOffTime" : "30s", + "dropOffCost" : 30 + }, + "parking" : { + "time" : "5m", + "cost" : 600 + } + }, + "walk" : { + "speed" : 1.3, + "reluctance" : 4.0, + "stairsReluctance" : 1.65, + "boardCost" : 600, + "escalatorReluctance" : 1.5 }, - "bikeParkTime" : "1m", - "bikeParkCost" : 120, - "carDropoffTime" : 120, "waitReluctance" : 1.0, - "walkBoardCost" : 600, - "bikeBoardCost" : 600, "otherThanPreferredRoutesPenalty" : 300, "transferSlack" : 120, "boardSlackForMode" : { @@ -995,8 +1137,6 @@ include stairs as a last result. "minBikeParkingDistance" : 300, "debug" : "limit-to-search-window" }, - "carDecelerationSpeed" : 2.9, - "carAccelerationSpeed" : 2.9, "ignoreRealtimeUpdates" : false, "geoidElevation" : false, "maxJourneyDuration" : "36h", diff --git a/docs/RouterConfiguration.md b/docs/RouterConfiguration.md index 5ca87a2aefa..23e2e3763d4 100644 --- a/docs/RouterConfiguration.md +++ b/docs/RouterConfiguration.md @@ -451,34 +451,59 @@ Used to group requests when monitoring OTP. ] }, "routingDefaults" : { - "walkSpeed" : 1.3, - "bikeSpeed" : 5, - "carSpeed" : 40, "numItineraries" : 12, "transferPenalty" : 0, - "walkReluctance" : 4.0, - "bikeReluctance" : 5.0, - "bikeWalkingReluctance" : 10.0, - "bikeStairsReluctance" : 150.0, - "carReluctance" : 10.0, - "stairsReluctance" : 1.65, "turnReluctance" : 1.0, "elevatorBoardTime" : 90, "elevatorBoardCost" : 90, "elevatorHopTime" : 20, "elevatorHopCost" : 20, - "escalatorReluctance" : 1.5, - "vehicleRental" : { - "pickupCost" : 120, - "dropOffTime" : 30, - "dropOffCost" : 30 + "bicycle" : { + "speed" : 5, + "reluctance" : 5.0, + "boardCost" : 600, + "walk" : { + "reluctance" : 10.0, + "stairsReluctance" : 150.0 + }, + "rental" : { + "pickupCost" : 120, + "dropOffTime" : "30s", + "dropOffCost" : 30 + }, + "parking" : { + "time" : "1m", + "cost" : 120 + }, + "triangle" : { + "safety" : 0.4, + "flatness" : 0.3, + "time" : 0.3 + } + }, + "car" : { + "speed" : 40, + "reluctance" : 10, + "decelerationSpeed" : 2.9, + "accelerationSpeed" : 2.9, + "rental" : { + "pickupCost" : 120, + "dropOffTime" : "30s", + "dropOffCost" : 30 + }, + "parking" : { + "time" : "5m", + "cost" : 600 + } + }, + "walk" : { + "speed" : 1.3, + "reluctance" : 4.0, + "stairsReluctance" : 1.65, + "boardCost" : 600, + "escalatorReluctance" : 1.5 }, - "bikeParkTime" : "1m", - "bikeParkCost" : 120, - "carDropoffTime" : 120, "waitReluctance" : 1.0, - "walkBoardCost" : 600, - "bikeBoardCost" : 600, "otherThanPreferredRoutesPenalty" : 300, "transferSlack" : 120, "boardSlackForMode" : { @@ -515,8 +540,6 @@ Used to group requests when monitoring OTP. "minBikeParkingDistance" : 300, "debug" : "limit-to-search-window" }, - "carDecelerationSpeed" : 2.9, - "carAccelerationSpeed" : 2.9, "ignoreRealtimeUpdates" : false, "geoidElevation" : false, "maxJourneyDuration" : "36h", diff --git a/docs/examples/entur/router-config.json b/docs/examples/entur/router-config.json index 0023dab130a..ffdec9ded79 100644 --- a/docs/examples/entur/router-config.json +++ b/docs/examples/entur/router-config.json @@ -1,32 +1,48 @@ { "configVersion" : "{{ Entur CI config build number inserted here }}", "routingDefaults": { - "walkSpeed": 1.3, - "bikeSpeed": 5, - "carSpeed": 40, "numItineraries": 12, "transferPenalty": 0, - "walkReluctance": 4.0, - "bikeReluctance": 5.0, - "bikeWalkingReluctance": 10.0, - "carReluctance": 10.0, - "stairsReluctance": 1.65, "turnReluctance": 1.0, "elevatorBoardTime": 90, "elevatorBoardCost": 90, "elevatorHopTime": 20, "elevatorHopCost": 20, - "vehicleRental": { - "pickupCost": 120, - "dropOffTime": 30, - "dropOffCost": 30 + "bicycle": { + "speed": 5, + "reluctance": 5.0, + "boardCost": 600, + "walk": { + "reluctance": 10.0 + }, + "rental": { + "pickupCost": 120, + "dropOffTime": "30s", + "dropOffCost": 30 + }, + "parking": { + "time": "1m", + "cost": 120 + } + }, + "car": { + "speed": 40, + "reluctance": 4.0, + "decelerationSpeed": 2.9, + "accelerationSpeed": 2.9, + "rental": { + "pickupCost": 120, + "dropOffTime": "30s", + "dropOffCost": 30 + } + }, + "walk": { + "speed": 1.3, + "reluctance": 4.0, + "stairsReluctance": 1.65, + "boardCost": 600 }, - "bikeParkTime": "1m", - "bikeParkCost": 120, - "carDropoffTime": 120, "waitReluctance": 1.0, - "walkBoardCost": 600, - "bikeBoardCost": 600, "otherThanPreferredRoutesPenalty": 300, "transferSlack": 120, // Default slack for any mode is 0 (zero) @@ -41,15 +57,13 @@ }, "accessEgress": { "maxDurationForMode": { - "BIKE_RENTAL": "20m" + "BIKE_RENTAL": "20m" } }, "itineraryFilters" : { "transitGeneralizedCostLimit" : "1h + 2.5 x", "bikeRentalDistanceRatio": 0.3 }, - "carDecelerationSpeed": 2.9, - "carAccelerationSpeed": 2.9, "ignoreRealtimeUpdates": false, "geoidElevation": false, "maxJourneyDuration": "36h", diff --git a/docs/examples/ibi/atlanta/router-config.json b/docs/examples/ibi/atlanta/router-config.json index 5202fe227c1..909c164ec43 100644 --- a/docs/examples/ibi/atlanta/router-config.json +++ b/docs/examples/ibi/atlanta/router-config.json @@ -1,18 +1,28 @@ { "routingDefaults": { - "bikeTriangleSafetyFactor": 0.4, - "bikeTriangleSlopeFactor": 0.3, - "bikeTriangleTimeFactor": 0.3, + "bicycle": { + "triangle": { + "time": 0.3, + "flatness": 0.3, + "safety": 0.4 + }, + "rental": { + "pickupTime": "3m", + "pickupCost": 850 + } + }, + "car": { + "rental": { + "pickupTime": "3m", + "pickupCost": 850 + } + }, "itineraryFilters": { // only show non-transit (ie. walking) when it's at least as good as the transit option "nonTransitGeneralizedCostLimit": "0 + 1.0 x", // add IBI accessibility score between 0 and 1 "accessibilityScore": true }, - "vehicleRental": { - "pickupTime": 180, - "pickupCost": 850 - }, // use stop and trip with unknown wheelchair accessibility during routing "wheelchairAccessibility": { "trip": { diff --git a/docs/examples/ibi/portland/router-config.json b/docs/examples/ibi/portland/router-config.json index 55a487fcfdc..445738762a1 100644 --- a/docs/examples/ibi/portland/router-config.json +++ b/docs/examples/ibi/portland/router-config.json @@ -5,8 +5,10 @@ "alightSlack": "0s", "transferSlack": 180, "waitReluctance": 0.9, - "walkReluctance": 1.75, - "stairsReluctance": 1.65, + "walk": { + "reluctance": 1.75, + "stairsReluctance": 1.65 + }, "numItineraries": 3, "geoidElevation": true, "streetRoutingTimeout": "7s" diff --git a/docs/examples/skanetrafiken/router-config.json b/docs/examples/skanetrafiken/router-config.json index ddec543e516..d65604aaa00 100644 --- a/docs/examples/skanetrafiken/router-config.json +++ b/docs/examples/skanetrafiken/router-config.json @@ -5,7 +5,9 @@ }, "transferSlack": 180, "waitReluctance": 0.175, - "walkReluctance": 5, + "walk": { + "reluctance": 5 + }, "maxDirectStreetDuration": "3700s" }, "transit": { diff --git a/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegacyBicycleOptimizeType.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegacyBicycleOptimizeType.java new file mode 100644 index 00000000000..ff50a03534b --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegacyBicycleOptimizeType.java @@ -0,0 +1,24 @@ +package org.opentripplanner.ext.restapi.mapping; + +import org.opentripplanner.routing.core.BicycleOptimizeType; + +/** + * Bicycle optimization types that are only meant to be used by the REST API. Related to {@link org.opentripplanner.routing.core.BicycleOptimizeType} + */ +public enum LegacyBicycleOptimizeType { + QUICK, + SAFE, + FLAT, + GREENWAYS, + TRIANGLE; + + public static BicycleOptimizeType map(LegacyBicycleOptimizeType type) { + return switch (type) { + case QUICK -> BicycleOptimizeType.SHORTEST_DURATION; + case FLAT -> BicycleOptimizeType.FLAT_STREETS; + case SAFE -> BicycleOptimizeType.SAFE_STREETS; + case GREENWAYS -> BicycleOptimizeType.SAFEST_STREETS; + case TRIANGLE -> BicycleOptimizeType.TRIANGLE; + }; + } +} diff --git a/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java index d09645832cb..bfac498ff8c 100644 --- a/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java @@ -2,6 +2,7 @@ import jakarta.validation.constraints.NotNull; import java.util.function.Consumer; +import org.opentripplanner.ext.restapi.mapping.LegacyBicycleOptimizeType; import org.opentripplanner.framework.lang.ObjectUtils; import org.opentripplanner.routing.algorithm.filterchain.api.TransitGeneralizedCostFilterParams; import org.opentripplanner.routing.api.request.framework.CostLinearFunction; @@ -10,7 +11,6 @@ import org.opentripplanner.routing.api.request.preference.RoutingPreferences; import org.opentripplanner.routing.api.request.preference.VehicleParkingPreferences; import org.opentripplanner.routing.api.request.preference.VehicleRentalPreferences; -import org.opentripplanner.routing.core.BicycleOptimizeType; class RequestToPreferencesMapper { @@ -46,8 +46,8 @@ private void mapCar() { setIfNotNull(req.carReluctance, car::withReluctance); car.withParking(parking -> { mapParking(parking); - setIfNotNull(req.carParkCost, parking::withParkCost); - setIfNotNull(req.carParkTime, parking::withParkTime); + setIfNotNull(req.carParkCost, parking::withCost); + setIfNotNull(req.carParkTime, parking::withTime); }); car.withRental(this::mapRental); }); @@ -67,13 +67,12 @@ private void mapBike() { setIfNotNull(req.bikeSpeed, bike::withSpeed); setIfNotNull(req.bikeReluctance, bike::withReluctance); setIfNotNull(req.bikeBoardCost, bike::withBoardCost); - setIfNotNull(req.bikeWalkingSpeed, bike::withWalkingSpeed); - setIfNotNull(req.bikeWalkingReluctance, bike::withWalkingReluctance); - setIfNotNull(req.bikeSwitchTime, bike::withSwitchTime); - setIfNotNull(req.bikeSwitchCost, bike::withSwitchCost); - setIfNotNull(req.bikeOptimizeType, bike::withOptimizeType); + setIfNotNull( + req.bikeOptimizeType, + optimizeType -> bike.withOptimizeType(LegacyBicycleOptimizeType.map(optimizeType)) + ); - if (req.bikeOptimizeType == BicycleOptimizeType.TRIANGLE) { + if (req.bikeOptimizeType == LegacyBicycleOptimizeType.TRIANGLE) { bike.withOptimizeTriangle(triangle -> { setIfNotNull(req.triangleTimeFactor, triangle::withTime); setIfNotNull(req.triangleSlopeFactor, triangle::withSlope); @@ -83,10 +82,16 @@ private void mapBike() { bike.withParking(parking -> { mapParking(parking); - setIfNotNull(req.bikeParkCost, parking::withParkCost); - setIfNotNull(req.bikeParkTime, parking::withParkTime); + setIfNotNull(req.bikeParkCost, parking::withCost); + setIfNotNull(req.bikeParkTime, parking::withTime); }); bike.withRental(this::mapRental); + bike.withWalking(walk -> { + setIfNotNull(req.bikeWalkingSpeed, walk::withSpeed); + setIfNotNull(req.bikeWalkingReluctance, walk::withReluctance); + setIfNotNull(req.bikeSwitchTime, walk::withHopTime); + setIfNotNull(req.bikeSwitchCost, walk::withHopCost); + }); }); } @@ -143,7 +148,7 @@ private void mapRental(VehicleRentalPreferences.Builder rental) { setIfNotNull( req.keepingRentedBicycleAtDestinationCost, - rental::withArrivingInRentalVehicleAtDestinationCost + cost -> rental.withArrivingInRentalVehicleAtDestinationCost((int) Math.round(cost)) ); rental.withUseAvailabilityInformation(isPlannedForNow); } diff --git a/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java index 38e50b283dc..1c234e3ff9e 100644 --- a/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java @@ -20,6 +20,7 @@ import javax.xml.datatype.XMLGregorianCalendar; import org.opentripplanner.api.parameter.QualifiedModeSet; import org.opentripplanner.ext.dataoverlay.api.DataOverlayParameters; +import org.opentripplanner.ext.restapi.mapping.LegacyBicycleOptimizeType; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.framework.lang.StringUtils; import org.opentripplanner.framework.time.DurationUtils; @@ -28,7 +29,6 @@ import org.opentripplanner.routing.api.request.preference.ItineraryFilterDebugProfile; import org.opentripplanner.routing.api.request.request.filter.SelectRequest; import org.opentripplanner.routing.api.request.request.filter.TransitFilterRequest; -import org.opentripplanner.routing.core.BicycleOptimizeType; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.opentripplanner.standalone.config.framework.file.ConfigFileLoader; import org.opentripplanner.standalone.config.framework.json.NodeAdapter; @@ -249,7 +249,7 @@ public abstract class RoutingResource { */ @Deprecated @QueryParam("optimize") - protected BicycleOptimizeType bikeOptimizeType; + protected LegacyBicycleOptimizeType bikeOptimizeType; /** * The set of modes that a user is willing to use, with qualifiers stating whether vehicles should diff --git a/src/main/java/org/opentripplanner/apis/gtfs/mapping/OptimizationTypeMapper.java b/src/main/java/org/opentripplanner/apis/gtfs/mapping/OptimizationTypeMapper.java new file mode 100644 index 00000000000..1f53652f7b7 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/mapping/OptimizationTypeMapper.java @@ -0,0 +1,19 @@ +package org.opentripplanner.apis.gtfs.mapping; + +import javax.annotation.Nonnull; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; +import org.opentripplanner.routing.core.BicycleOptimizeType; + +public final class OptimizationTypeMapper { + + @Nonnull + public static BicycleOptimizeType map(GraphQLTypes.GraphQLOptimizeType optimizeType) { + return switch (optimizeType) { + case QUICK -> BicycleOptimizeType.SHORTEST_DURATION; + case FLAT -> BicycleOptimizeType.FLAT_STREETS; + case SAFE -> BicycleOptimizeType.SAFE_STREETS; + case GREENWAYS -> BicycleOptimizeType.SAFEST_STREETS; + case TRIANGLE -> BicycleOptimizeType.TRIANGLE; + }; + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapper.java b/src/main/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapper.java index 2eeaf229b11..212bfbcf380 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapper.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapper.java @@ -16,6 +16,7 @@ import org.opentripplanner.api.parameter.QualifiedMode; import org.opentripplanner.api.parameter.QualifiedModeSet; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.framework.time.ZoneIdFallback; import org.opentripplanner.model.GenericLocation; @@ -24,6 +25,7 @@ import org.opentripplanner.routing.api.request.preference.ItineraryFilterDebugProfile; import org.opentripplanner.routing.api.request.preference.VehicleParkingPreferences; import org.opentripplanner.routing.api.request.preference.VehicleRentalPreferences; +import org.opentripplanner.routing.api.request.preference.VehicleWalkingPreferences; import org.opentripplanner.routing.api.request.request.filter.SelectRequest; import org.opentripplanner.routing.api.request.request.filter.TransitFilterRequest; import org.opentripplanner.routing.core.BicycleOptimizeType; @@ -67,15 +69,15 @@ public static RouteRequest toRouteRequest( request.withPreferences(preferences -> { preferences.withBike(bike -> { callWith.argument("bikeReluctance", bike::withReluctance); - callWith.argument("bikeWalkingReluctance", bike::withWalkingReluctance); - callWith.argument("bikeWalkingSpeed", bike::withWalkingSpeed); callWith.argument("bikeSpeed", bike::withSpeed); - callWith.argument("bikeSwitchTime", bike::withSwitchTime); - callWith.argument("bikeSwitchCost", bike::withSwitchCost); callWith.argument("bikeBoardCost", bike::withBoardCost); if (environment.getArgument("optimize") != null) { - bike.withOptimizeType(BicycleOptimizeType.valueOf(environment.getArgument("optimize"))); + bike.withOptimizeType( + OptimizationTypeMapper.map( + GraphQLTypes.GraphQLOptimizeType.valueOf(environment.getArgument("optimize")) + ) + ); } if (bike.optimizeType() == BicycleOptimizeType.TRIANGLE) { bike.withOptimizeTriangle(triangle -> { @@ -87,6 +89,7 @@ public static RouteRequest toRouteRequest( bike.withParking(parking -> setParkingPreferences(callWith, parking)); bike.withRental(rental -> setRentalPreferences(callWith, request, rental)); + bike.withWalking(walking -> setVehicleWalkingPreferences(callWith, walking)); }); preferences.withCar(car -> { @@ -331,6 +334,16 @@ private static void setRentalPreferences( ); } + private static void setVehicleWalkingPreferences( + CallerWithEnvironment callWith, + VehicleWalkingPreferences.Builder walking + ) { + callWith.argument("bikeWalkingReluctance", walking::withReluctance); + callWith.argument("bikeWalkingSpeed", walking::withSpeed); + callWith.argument("bikeSwitchTime", time -> walking.withHopTime((int) time)); + callWith.argument("bikeSwitchCost", cost -> walking.withHopCost((int) cost)); + } + private static class CallerWithEnvironment { private final DataFetchingEnvironment environment; diff --git a/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapper.java b/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapper.java index 3ccdd9007a4..1179c034e93 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapper.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapper.java @@ -27,7 +27,7 @@ public static void mapBikePreferences( "walkReluctance", r -> { bike.withReluctance((double) r); - bike.withWalkingReluctance(WALK_BIKE_RELATIVE_RELUCTANCE * (double) r); + bike.withWalking(w -> w.withReluctance(WALK_BIKE_RELATIVE_RELUCTANCE * (double) r)); } ); diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/DefaultRouteRequestType.java b/src/main/java/org/opentripplanner/apis/transmodel/model/DefaultRouteRequestType.java index 5e4dca2bfc2..80b6418c314 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/DefaultRouteRequestType.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/DefaultRouteRequestType.java @@ -184,7 +184,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeRentalPickupTime") .description("Time to rent a bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.bike().rental().pickupTime()) + .dataFetcher(env -> (int) preferences.bike().rental().pickupTime().toSeconds()) .build() ) .field( @@ -193,7 +193,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeRentalPickupCost") .description("Cost to rent a bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.bike().rental().pickupCost()) + .dataFetcher(env -> preferences.bike().rental().pickupCost().toSeconds()) .build() ) .field( @@ -202,7 +202,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeRentalDropOffTime") .description("Time to drop-off a rented bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.bike().rental().dropoffTime()) + .dataFetcher(env -> (int) preferences.bike().rental().dropOffTime().toSeconds()) .build() ) .field( @@ -211,7 +211,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeRentalDropOffCost") .description("Cost to drop-off a rented bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.bike().rental().dropoffCost()) + .dataFetcher(env -> preferences.bike().rental().dropOffCost().toSeconds()) .build() ) .field( @@ -220,7 +220,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeParkTime") .description("Time to park a bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> (int) preferences.bike().parking().parkTime().toSeconds()) + .dataFetcher(env -> (int) preferences.bike().parking().time().toSeconds()) .build() ) .field( @@ -229,7 +229,7 @@ private GraphQLObjectType createGraphQLType() { .name("bikeParkCost") .description("Cost to park a bike.") .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.bike().parking().parkCost().toSeconds()) + .dataFetcher(env -> preferences.bike().parking().cost().toSeconds()) .build() ) .field( @@ -240,7 +240,7 @@ private GraphQLObjectType createGraphQLType() { "Time to park a car in a park and ride, w/o taking into account driving and walking cost." ) .type(Scalars.GraphQLInt) - .dataFetcher(env -> preferences.car().dropoffTime()) + .dataFetcher(env -> 0) .build() ) .field( diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/EnumTypes.java b/src/main/java/org/opentripplanner/apis/transmodel/model/EnumTypes.java index 12aa19fbaea..e2897d868c9 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/EnumTypes.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/EnumTypes.java @@ -64,10 +64,10 @@ public class EnumTypes { public static final GraphQLEnumType BICYCLE_OPTIMISATION_METHOD = GraphQLEnumType .newEnum() .name("BicycleOptimisationMethod") - .value("quick", BicycleOptimizeType.QUICK) - .value("safe", BicycleOptimizeType.SAFE) - .value("flat", BicycleOptimizeType.FLAT) - .value("greenways", BicycleOptimizeType.GREENWAYS) + .value("quick", BicycleOptimizeType.SHORTEST_DURATION) + .value("safe", BicycleOptimizeType.SAFE_STREETS) + .value("flat", BicycleOptimizeType.FLAT_STREETS) + .value("greenways", BicycleOptimizeType.SAFEST_STREETS) .value("triangle", BicycleOptimizeType.TRIANGLE) .build(); diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/BikePreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/BikePreferences.java index 5717876bbfc..26da1476b38 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/BikePreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/BikePreferences.java @@ -2,6 +2,8 @@ import static org.opentripplanner.framework.lang.DoubleUtils.doubleEquals; import static org.opentripplanner.framework.lang.ObjectUtils.ifNotNull; +import static org.opentripplanner.routing.core.BicycleOptimizeType.SAFE_STREETS; +import static org.opentripplanner.routing.core.BicycleOptimizeType.TRIANGLE; import java.io.Serializable; import java.util.Objects; @@ -25,45 +27,32 @@ public final class BikePreferences implements Serializable { private final double speed; private final double reluctance; private final Cost boardCost; - private final double walkingSpeed; - private final double walkingReluctance; - private final int switchTime; - private final Cost switchCost; private final VehicleParkingPreferences parking; private final VehicleRentalPreferences rental; - private final double stairsReluctance; private final BicycleOptimizeType optimizeType; private final TimeSlopeSafetyTriangle optimizeTriangle; + private final VehicleWalkingPreferences walking; private BikePreferences() { this.speed = 5; this.reluctance = 2.0; this.boardCost = Cost.costOfMinutes(10); - this.walkingSpeed = 1.33; - this.walkingReluctance = 5.0; - this.switchTime = 0; - this.switchCost = Cost.ZERO; this.parking = VehicleParkingPreferences.DEFAULT; this.rental = VehicleRentalPreferences.DEFAULT; - this.optimizeType = BicycleOptimizeType.SAFE; + this.optimizeType = SAFE_STREETS; this.optimizeTriangle = TimeSlopeSafetyTriangle.DEFAULT; - // very high reluctance to carry the bike up/down a flight of stairs - this.stairsReluctance = 10; + this.walking = VehicleWalkingPreferences.DEFAULT; } private BikePreferences(Builder builder) { this.speed = Units.speed(builder.speed); this.reluctance = Units.reluctance(builder.reluctance); this.boardCost = builder.boardCost; - this.walkingSpeed = Units.speed(builder.walkingSpeed); - this.walkingReluctance = Units.reluctance(builder.walkingReluctance); - this.switchTime = Units.duration(builder.switchTime); - this.switchCost = builder.switchCost; this.parking = builder.parking; this.rental = builder.rental; this.optimizeType = Objects.requireNonNull(builder.optimizeType); this.optimizeTriangle = Objects.requireNonNull(builder.optimizeTriangle); - this.stairsReluctance = Units.reluctance(builder.stairsReluctance); + this.walking = builder.walking; } public static BikePreferences.Builder of() { @@ -94,36 +83,6 @@ public int boardCost() { return boardCost.toSeconds(); } - /** - * The walking speed when walking a bike. Default: 1.33 m/s ~ Same as walkSpeed - */ - public double walkingSpeed() { - return walkingSpeed; - } - - /** - * A multiplier for how bad walking is, compared to being in transit for equal - * lengths of time. Empirically, values between 2 and 4 seem to correspond - * well to the concept of not wanting to walk too much without asking for - * totally ridiculous itineraries, but this observation should in no way be - * taken as scientific or definitive. Your mileage may vary. See - * https://github.com/opentripplanner/OpenTripPlanner/issues/4090 for impact on - * performance with high values. Default value: 2.0 - */ - public double walkingReluctance() { - return walkingReluctance; - } - - /** Time to get on and off your own bike */ - public int switchTime() { - return switchTime; - } - - /** Cost of getting on and off your own bike */ - public int switchCost() { - return switchCost.toSeconds(); - } - /** Parking preferences that can be different per request */ public VehicleParkingPreferences parking() { return parking; @@ -135,7 +94,7 @@ public VehicleRentalPreferences rental() { } /** - * The set of characteristics that the user wants to optimize for -- defaults to SAFE. + * The set of characteristics that the user wants to optimize for -- defaults to SAFE_STREETS. */ public BicycleOptimizeType optimizeType() { return optimizeType; @@ -145,8 +104,9 @@ public TimeSlopeSafetyTriangle optimizeTriangle() { return optimizeTriangle; } - public double stairsReluctance() { - return stairsReluctance; + /** Bike walking preferences that can be different per request */ + public VehicleWalkingPreferences walking() { + return walking; } @Override @@ -158,15 +118,11 @@ public boolean equals(Object o) { doubleEquals(that.speed, speed) && doubleEquals(that.reluctance, reluctance) && boardCost.equals(that.boardCost) && - doubleEquals(that.walkingSpeed, walkingSpeed) && - doubleEquals(that.walkingReluctance, walkingReluctance) && - switchTime == that.switchTime && - switchCost.equals(that.switchCost) && - parking.equals(that.parking) && - rental.equals(that.rental) && + Objects.equals(parking, that.parking) && + Objects.equals(rental, that.rental) && optimizeType == that.optimizeType && optimizeTriangle.equals(that.optimizeTriangle) && - doubleEquals(stairsReluctance, that.stairsReluctance) + Objects.equals(walking, that.walking) ); } @@ -176,15 +132,11 @@ public int hashCode() { speed, reluctance, boardCost, - walkingSpeed, - walkingReluctance, - switchTime, - switchCost, parking, rental, optimizeType, optimizeTriangle, - stairsReluctance + walking ); } @@ -195,15 +147,11 @@ public String toString() { .addNum("speed", speed, DEFAULT.speed) .addNum("reluctance", reluctance, DEFAULT.reluctance) .addObj("boardCost", boardCost, DEFAULT.boardCost) - .addNum("walkingSpeed", walkingSpeed, DEFAULT.walkingSpeed) - .addNum("walkingReluctance", walkingReluctance, DEFAULT.walkingReluctance) - .addDurationSec("switchTime", switchTime, DEFAULT.switchTime) - .addObj("switchCost", switchCost, DEFAULT.switchCost) .addObj("parking", parking, DEFAULT.parking) .addObj("rental", rental, DEFAULT.rental) .addEnum("optimizeType", optimizeType, DEFAULT.optimizeType) .addObj("optimizeTriangle", optimizeTriangle, DEFAULT.optimizeTriangle) - .addNum("stairsReluctance", stairsReluctance, DEFAULT.stairsReluctance) + .addObj("walking", walking, DEFAULT.walking) .toString(); } @@ -214,31 +162,22 @@ public static class Builder { private double speed; private double reluctance; private Cost boardCost; - private double walkingSpeed; - private double walkingReluctance; - private int switchTime; - private Cost switchCost; private VehicleParkingPreferences parking; private VehicleRentalPreferences rental; private BicycleOptimizeType optimizeType; private TimeSlopeSafetyTriangle optimizeTriangle; - - public double stairsReluctance; + private VehicleWalkingPreferences walking; public Builder(BikePreferences original) { this.original = original; this.speed = original.speed; this.reluctance = original.reluctance; this.boardCost = original.boardCost; - this.walkingSpeed = original.walkingSpeed; - this.walkingReluctance = original.walkingReluctance; - this.switchTime = original.switchTime; - this.switchCost = original.switchCost; this.parking = original.parking; this.rental = original.rental; this.optimizeType = original.optimizeType; this.optimizeTriangle = original.optimizeTriangle; - this.stairsReluctance = original.stairsReluctance; + this.walking = original.walking; } public BikePreferences original() { @@ -272,42 +211,6 @@ public Builder withBoardCost(int boardCost) { return this; } - public double walkingSpeed() { - return walkingSpeed; - } - - public Builder withWalkingSpeed(double walkingSpeed) { - this.walkingSpeed = walkingSpeed; - return this; - } - - public double walkingReluctance() { - return walkingReluctance; - } - - public Builder withWalkingReluctance(double walkingReluctance) { - this.walkingReluctance = walkingReluctance; - return this; - } - - public int switchTime() { - return switchTime; - } - - public Builder withSwitchTime(int switchTime) { - this.switchTime = switchTime; - return this; - } - - public Cost switchCost() { - return switchCost; - } - - public Builder withSwitchCost(int switchCost) { - this.switchCost = Cost.costOfSeconds(switchCost); - return this; - } - public Builder withParking(Consumer body) { this.parking = ifNotNull(this.parking, original.parking).copyOf().apply(body).build(); return this; @@ -331,6 +234,17 @@ public TimeSlopeSafetyTriangle optimizeTriangle() { return optimizeTriangle; } + /** This also sets the optimization type as TRIANGLE if triangle parameters are defined */ + public Builder withForcedOptimizeTriangle(Consumer body) { + var builder = TimeSlopeSafetyTriangle.of(); + body.accept(builder); + this.optimizeTriangle = builder.buildOrDefault(this.optimizeTriangle); + if (!builder.isEmpty()) { + this.optimizeType = TRIANGLE; + } + return this; + } + public Builder withOptimizeTriangle(Consumer body) { var builder = TimeSlopeSafetyTriangle.of(); body.accept(builder); @@ -338,8 +252,8 @@ public Builder withOptimizeTriangle(Consumer bo return this; } - public Builder withStairsReluctance(double value) { - this.stairsReluctance = value; + public Builder withWalking(Consumer body) { + this.walking = ifNotNull(this.walking, original.walking).copyOf().apply(body).build(); return this; } diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/CarPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/CarPreferences.java index 6b103e8f3b7..b2f226cf307 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/CarPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/CarPreferences.java @@ -3,6 +3,7 @@ import static org.opentripplanner.framework.lang.ObjectUtils.ifNotNull; import java.io.Serializable; +import java.time.Duration; import java.util.Objects; import java.util.function.Consumer; import org.opentripplanner.framework.lang.DoubleUtils; @@ -25,9 +26,8 @@ public final class CarPreferences implements Serializable { private final double reluctance; private final VehicleParkingPreferences parking; private final VehicleRentalPreferences rental; - private final int pickupTime; + private final Duration pickupTime; private final Cost pickupCost; - private final int dropoffTime; private final double accelerationSpeed; private final double decelerationSpeed; @@ -37,9 +37,8 @@ private CarPreferences() { this.reluctance = 2.0; this.parking = VehicleParkingPreferences.DEFAULT; this.rental = VehicleRentalPreferences.DEFAULT; - this.pickupTime = 60; + this.pickupTime = Duration.ofMinutes(1); this.pickupCost = Cost.costOfMinutes(2); - this.dropoffTime = 120; this.accelerationSpeed = 2.9; this.decelerationSpeed = 2.9; } @@ -49,9 +48,8 @@ private CarPreferences(Builder builder) { this.reluctance = Units.reluctance(builder.reluctance); this.parking = builder.parking; this.rental = builder.rental; - this.pickupTime = Units.duration(builder.pickupTime); + this.pickupTime = Duration.ofSeconds(Units.duration(builder.pickupTime)); this.pickupCost = builder.pickupCost; - this.dropoffTime = Units.duration(builder.dropoffTime); this.accelerationSpeed = Units.acceleration(builder.accelerationSpeed); this.decelerationSpeed = Units.acceleration(builder.decelerationSpeed); } @@ -88,21 +86,13 @@ public VehicleRentalPreferences rental() { } /** Time of getting in/out of a carPickup (taxi) */ - public int pickupTime() { + public Duration pickupTime() { return pickupTime; } /** Cost of getting in/out of a carPickup (taxi) */ - public int pickupCost() { - return pickupCost.toSeconds(); - } - - /** - * Time to park a car in a park and ride, w/o taking into account driving and walking cost (time - * to park, switch off, pick your stuff, lock the car, etc...) - */ - public int dropoffTime() { - return dropoffTime; + public Cost pickupCost() { + return pickupCost; } /** @@ -131,9 +121,8 @@ public boolean equals(Object o) { DoubleUtils.doubleEquals(that.reluctance, reluctance) && parking.equals(that.parking) && rental.equals(that.rental) && - pickupTime == that.pickupTime && + Objects.equals(pickupTime, that.pickupTime) && pickupCost.equals(that.pickupCost) && - dropoffTime == that.dropoffTime && DoubleUtils.doubleEquals(that.accelerationSpeed, accelerationSpeed) && DoubleUtils.doubleEquals(that.decelerationSpeed, decelerationSpeed) ); @@ -148,7 +137,6 @@ public int hashCode() { rental, pickupTime, pickupCost, - dropoffTime, accelerationSpeed, decelerationSpeed ); @@ -162,9 +150,8 @@ public String toString() { .addNum("reluctance", reluctance, DEFAULT.reluctance) .addObj("parking", parking, DEFAULT.parking) .addObj("rental", rental, DEFAULT.rental) - .addNum("pickupTime", pickupTime, DEFAULT.pickupTime) + .addObj("pickupTime", pickupTime, DEFAULT.pickupTime) .addObj("pickupCost", pickupCost, DEFAULT.pickupCost) - .addNum("dropoffTime", dropoffTime, DEFAULT.dropoffTime) .addNum("accelerationSpeed", accelerationSpeed, DEFAULT.accelerationSpeed) .addNum("decelerationSpeed", decelerationSpeed, DEFAULT.decelerationSpeed) .toString(); @@ -180,7 +167,6 @@ public static class Builder { private VehicleRentalPreferences rental; private int pickupTime; private Cost pickupCost; - private int dropoffTime; private double accelerationSpeed; private double decelerationSpeed; @@ -190,9 +176,8 @@ public Builder(CarPreferences original) { this.reluctance = original.reluctance; this.parking = original.parking; this.rental = original.rental; - this.pickupTime = original.pickupTime; + this.pickupTime = (int) original.pickupTime.toSeconds(); this.pickupCost = original.pickupCost; - this.dropoffTime = original.dropoffTime; this.accelerationSpeed = original.accelerationSpeed; this.decelerationSpeed = original.decelerationSpeed; } @@ -221,8 +206,8 @@ public Builder withRental(Consumer body) { return this; } - public Builder withPickupTime(int pickupTime) { - this.pickupTime = pickupTime; + public Builder withPickupTime(Duration pickupTime) { + this.pickupTime = (int) pickupTime.toSeconds(); return this; } @@ -231,11 +216,6 @@ public Builder withPickupCost(int pickupCost) { return this; } - public Builder withDropoffTime(int dropoffTime) { - this.dropoffTime = dropoffTime; - return this; - } - public Builder withAccelerationSpeed(double accelerationSpeed) { this.accelerationSpeed = accelerationSpeed; return this; diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/RoutingPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/RoutingPreferences.java index 3230bbf5968..d3d22160935 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/RoutingPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/RoutingPreferences.java @@ -129,7 +129,7 @@ public SystemPreferences system() { */ public double getSpeed(TraverseMode mode, boolean walkingBike) { return switch (mode) { - case WALK -> walkingBike ? bike.walkingSpeed() : walk.speed(); + case WALK -> walkingBike ? bike.walking().speed() : walk.speed(); case BICYCLE -> bike.speed(); case CAR -> car.speed(); default -> throw new IllegalArgumentException("getSpeed(): Invalid mode " + mode); diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/TimeSlopeSafetyTriangle.java b/src/main/java/org/opentripplanner/routing/api/request/preference/TimeSlopeSafetyTriangle.java index b901d738213..99925a441fd 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/TimeSlopeSafetyTriangle.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/TimeSlopeSafetyTriangle.java @@ -1,5 +1,6 @@ package org.opentripplanner.routing.api.request.preference; +import static org.opentripplanner.framework.lang.DoubleUtils.doubleEquals; import static org.opentripplanner.framework.lang.DoubleUtils.roundTo2Decimals; /** @@ -109,6 +110,13 @@ public Builder withSafety(double safety) { return this; } + /** + * Returns true if none of the values are set (i.e. all values are zero). + */ + public boolean isEmpty() { + return doubleEquals(time, ZERO) && doubleEquals(slope, ZERO) && doubleEquals(safety, ZERO); + } + public TimeSlopeSafetyTriangle build() { return new TimeSlopeSafetyTriangle(time, slope, safety); } diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferences.java index c02862c4d79..f7183812c3a 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferences.java @@ -23,16 +23,16 @@ public final class VehicleParkingPreferences implements Serializable { private final Cost unpreferredVehicleParkingTagCost; private final VehicleParkingFilter filter; private final VehicleParkingFilter preferred; - private final Duration parkTime; - private final Cost parkCost; + private final Duration time; + private final Cost cost; /** Create a new instance with default values. */ private VehicleParkingPreferences() { this.unpreferredVehicleParkingTagCost = Cost.costOfMinutes(5); this.filter = VehicleParkingFilter.empty(); this.preferred = VehicleParkingFilter.empty(); - this.parkTime = Duration.ofMinutes(1); - this.parkCost = Cost.costOfMinutes(2); + this.time = Duration.ofMinutes(1); + this.cost = Cost.costOfMinutes(2); } private VehicleParkingPreferences(Builder builder) { @@ -47,8 +47,8 @@ private VehicleParkingPreferences(Builder builder) { builder.notPreferredVehicleParkingTags, builder.preferredVehicleParkingTags ); - this.parkTime = builder.parkTime; - this.parkCost = builder.parkCost; + this.time = builder.time; + this.cost = builder.cost; } public static VehicleParkingPreferences.Builder of() { @@ -85,13 +85,13 @@ public VehicleParkingFilter preferred() { } /** Time to park a vehicle */ - public Duration parkTime() { - return parkTime; + public Duration time() { + return time; } /** Cost of parking a bike. */ - public Cost parkCost() { - return parkCost; + public Cost cost() { + return cost; } @Override @@ -103,14 +103,14 @@ public boolean equals(Object o) { Objects.equals(unpreferredVehicleParkingTagCost, that.unpreferredVehicleParkingTagCost) && Objects.equals(filter, that.filter) && Objects.equals(preferred, that.preferred) && - Objects.equals(parkCost, that.parkCost) && - Objects.equals(parkTime, that.parkTime) + Objects.equals(cost, that.cost) && + Objects.equals(time, that.time) ); } @Override public int hashCode() { - return Objects.hash(unpreferredVehicleParkingTagCost, filter, preferred, parkCost, parkTime); + return Objects.hash(unpreferredVehicleParkingTagCost, filter, preferred, cost, time); } @Override @@ -124,8 +124,8 @@ public String toString() { ) .addObj("filter", filter, DEFAULT.filter) .addObj("preferred", preferred, DEFAULT.preferred) - .addObj("parkCost", parkCost, DEFAULT.parkCost) - .addObj("parkTime", parkTime, DEFAULT.parkTime) + .addObj("cost", cost, DEFAULT.cost) + .addObj("time", time, DEFAULT.time) .toString(); } @@ -137,8 +137,8 @@ public static class Builder { private List requiredVehicleParkingTags; private List preferredVehicleParkingTags; private List notPreferredVehicleParkingTags; - private Cost parkCost; - private Duration parkTime; + private Cost cost; + private Duration time; private Builder(VehicleParkingPreferences original) { this.original = original; @@ -147,8 +147,8 @@ private Builder(VehicleParkingPreferences original) { this.requiredVehicleParkingTags = original.filter.select(); this.preferredVehicleParkingTags = original.preferred.select(); this.notPreferredVehicleParkingTags = original.preferred.not(); - this.parkCost = original.parkCost; - this.parkTime = original.parkTime; + this.cost = original.cost; + this.time = original.time; } public Builder withUnpreferredVehicleParkingTagCost(int cost) { @@ -180,18 +180,18 @@ public Builder withNotPreferredVehicleParkingTags(Set notPreferredVehicl return this; } - public Builder withParkCost(int cost) { - this.parkCost = Cost.costOfSeconds(cost); + public Builder withCost(int cost) { + this.cost = Cost.costOfSeconds(cost); return this; } - public Builder withParkTime(int seconds) { - this.parkTime = Duration.ofSeconds(seconds); + public Builder withTime(int seconds) { + this.time = Duration.ofSeconds(seconds); return this; } - public Builder withParkTime(Duration duration) { - this.parkTime = duration; + public Builder withTime(Duration duration) { + this.time = duration; return this; } diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java index 8e18d2a81d5..6c9bbfea875 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java @@ -1,10 +1,10 @@ package org.opentripplanner.routing.api.request.preference; import java.io.Serializable; +import java.time.Duration; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; -import org.opentripplanner.framework.lang.DoubleUtils; import org.opentripplanner.framework.model.Cost; import org.opentripplanner.framework.model.Units; import org.opentripplanner.framework.tostring.ToStringBuilder; @@ -17,38 +17,38 @@ public final class VehicleRentalPreferences implements Serializable { public static final VehicleRentalPreferences DEFAULT = new VehicleRentalPreferences(); - private final int pickupTime; + private final Duration pickupTime; private final Cost pickupCost; - private final int dropoffTime; - private final Cost dropoffCost; + private final Duration dropOffTime; + private final Cost dropOffCost; private final boolean useAvailabilityInformation; - private final double arrivingInRentalVehicleAtDestinationCost; + private final Cost arrivingInRentalVehicleAtDestinationCost; private final boolean allowArrivingInRentedVehicleAtDestination; private final Set allowedNetworks; private final Set bannedNetworks; private VehicleRentalPreferences() { - this.pickupTime = 60; + this.pickupTime = Duration.ofMinutes(1); this.pickupCost = Cost.costOfMinutes(2); - this.dropoffTime = 30; - this.dropoffCost = Cost.costOfSeconds(30); + this.dropOffTime = Duration.ofSeconds(30); + this.dropOffCost = Cost.costOfSeconds(30); this.useAvailabilityInformation = false; - this.arrivingInRentalVehicleAtDestinationCost = 0; + this.arrivingInRentalVehicleAtDestinationCost = Cost.costOfSeconds(0); this.allowArrivingInRentedVehicleAtDestination = false; this.allowedNetworks = Set.of(); this.bannedNetworks = Set.of(); } private VehicleRentalPreferences(Builder builder) { - this.pickupTime = builder.pickupTime; + this.pickupTime = Duration.ofSeconds(Units.duration(builder.pickupTime)); this.pickupCost = builder.pickupCost; - this.dropoffTime = builder.dropoffTime; - this.dropoffCost = builder.dropoffCost; + this.dropOffTime = Duration.ofSeconds(Units.duration(builder.dropOffTime)); + this.dropOffCost = builder.dropOffCost; this.useAvailabilityInformation = builder.useAvailabilityInformation; this.arrivingInRentalVehicleAtDestinationCost = - DoubleUtils.roundTo1Decimal(builder.arrivingInRentalVehicleAtDestinationCost); + builder.arrivingInRentalVehicleAtDestinationCost; this.allowArrivingInRentedVehicleAtDestination = builder.allowArrivingInRentedVehicleAtDestination; this.allowedNetworks = builder.allowedNetworks; @@ -64,7 +64,7 @@ public Builder copyOf() { } /** Time to rent a vehicle */ - public int pickupTime() { + public Duration pickupTime() { return pickupTime; } @@ -72,18 +72,18 @@ public int pickupTime() { * Cost of renting a vehicle. The cost is a bit more than actual time to model the associated cost * and trouble. */ - public int pickupCost() { - return pickupCost.toSeconds(); + public Cost pickupCost() { + return pickupCost; } /** Time to drop-off a rented vehicle */ - public int dropoffTime() { - return dropoffTime; + public Duration dropOffTime() { + return dropOffTime; } /** Cost of dropping-off a rented vehicle */ - public int dropoffCost() { - return dropoffCost.toSeconds(); + public Cost dropOffCost() { + return dropOffCost; } /** @@ -97,7 +97,7 @@ public boolean useAvailabilityInformation() { /** * The cost of arriving at the destination with the rented vehicle, to discourage doing so. */ - public double arrivingInRentalVehicleAtDestinationCost() { + public Cost arrivingInRentalVehicleAtDestinationCost() { return arrivingInRentalVehicleAtDestinationCost; } @@ -127,16 +127,15 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; VehicleRentalPreferences that = (VehicleRentalPreferences) o; return ( - pickupTime == that.pickupTime && + Objects.equals(pickupTime, that.pickupTime) && Objects.equals(pickupCost, that.pickupCost) && - dropoffTime == that.dropoffTime && - Objects.equals(dropoffCost, that.dropoffCost) && + Objects.equals(dropOffTime, that.dropOffTime) && + Objects.equals(dropOffCost, that.dropOffCost) && useAvailabilityInformation == that.useAvailabilityInformation && - Double.compare( + Objects.equals( that.arrivingInRentalVehicleAtDestinationCost, arrivingInRentalVehicleAtDestinationCost - ) == - 0 && + ) && allowArrivingInRentedVehicleAtDestination == that.allowArrivingInRentedVehicleAtDestination && allowedNetworks.equals(that.allowedNetworks) && bannedNetworks.equals(that.bannedNetworks) @@ -148,8 +147,8 @@ public int hashCode() { return Objects.hash( pickupTime, pickupCost, - dropoffTime, - dropoffCost, + dropOffTime, + dropOffCost, useAvailabilityInformation, arrivingInRentalVehicleAtDestinationCost, allowArrivingInRentedVehicleAtDestination, @@ -162,12 +161,12 @@ public int hashCode() { public String toString() { return ToStringBuilder .of(VehicleRentalPreferences.class) - .addDurationSec("pickupTime", pickupTime, DEFAULT.pickupTime) + .addDuration("pickupTime", pickupTime, DEFAULT.pickupTime) .addObj("pickupCost", pickupCost, DEFAULT.pickupCost) - .addDurationSec("dropoffTime", dropoffTime, DEFAULT.dropoffTime) - .addObj("dropoffCost", dropoffCost, DEFAULT.dropoffCost) + .addDuration("dropOffTime", dropOffTime, DEFAULT.dropOffTime) + .addObj("dropOffCost", dropOffCost, DEFAULT.dropOffCost) .addBoolIfTrue("useAvailabilityInformation", useAvailabilityInformation) - .addNum( + .addObj( "arrivingInRentalVehicleAtDestinationCost", arrivingInRentalVehicleAtDestinationCost, DEFAULT.arrivingInRentalVehicleAtDestinationCost @@ -186,20 +185,20 @@ public static class Builder { private final VehicleRentalPreferences original; private int pickupTime; private Cost pickupCost; - private int dropoffTime; - private Cost dropoffCost; + private int dropOffTime; + private Cost dropOffCost; private boolean useAvailabilityInformation; - private double arrivingInRentalVehicleAtDestinationCost; + private Cost arrivingInRentalVehicleAtDestinationCost; private boolean allowArrivingInRentedVehicleAtDestination; private Set allowedNetworks; private Set bannedNetworks; private Builder(VehicleRentalPreferences original) { this.original = original; - this.pickupTime = Units.duration(original.pickupTime); + this.pickupTime = (int) original.pickupTime.toSeconds(); this.pickupCost = original.pickupCost; - this.dropoffTime = Units.duration(original.dropoffTime); - this.dropoffCost = original.dropoffCost; + this.dropOffTime = (int) original.dropOffTime.toSeconds(); + this.dropOffCost = original.dropOffCost; this.useAvailabilityInformation = original.useAvailabilityInformation; this.arrivingInRentalVehicleAtDestinationCost = original.arrivingInRentalVehicleAtDestinationCost; @@ -218,18 +217,28 @@ public Builder withPickupTime(int pickupTime) { return this; } + public Builder withPickupTime(Duration pickupTime) { + this.pickupTime = (int) pickupTime.toSeconds(); + return this; + } + public Builder withPickupCost(int pickupCost) { this.pickupCost = Cost.costOfSeconds(pickupCost); return this; } - public Builder withDropoffTime(int dropoffTime) { - this.dropoffTime = dropoffTime; + public Builder withDropOffTime(int dropOffTime) { + this.dropOffTime = dropOffTime; return this; } - public Builder withDropoffCost(int dropoffCost) { - this.dropoffCost = Cost.costOfSeconds(dropoffCost); + public Builder withDropOffTime(Duration dropOffTime) { + this.dropOffTime = (int) dropOffTime.toSeconds(); + return this; + } + + public Builder withDropOffCost(int dropOffCost) { + this.dropOffCost = Cost.costOfSeconds(dropOffCost); return this; } @@ -239,9 +248,10 @@ public Builder withUseAvailabilityInformation(boolean useAvailabilityInformation } public Builder withArrivingInRentalVehicleAtDestinationCost( - double arrivingInRentalVehicleAtDestinationCost + int arrivingInRentalVehicleAtDestinationCost ) { - this.arrivingInRentalVehicleAtDestinationCost = arrivingInRentalVehicleAtDestinationCost; + this.arrivingInRentalVehicleAtDestinationCost = + Cost.costOfSeconds(arrivingInRentalVehicleAtDestinationCost); return this; } diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferences.java new file mode 100644 index 00000000000..aa3631e1c6b --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferences.java @@ -0,0 +1,185 @@ +package org.opentripplanner.routing.api.request.preference; + +import java.io.Serializable; +import java.time.Duration; +import java.util.Objects; +import java.util.function.Consumer; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.framework.model.Units; +import org.opentripplanner.framework.tostring.ToStringBuilder; + +/** + * Preferences for walking a vehicle. + *

+ * THIS CLASS IS IMMUTABLE AND THREAD-SAFE. + */ +public class VehicleWalkingPreferences implements Serializable { + + public static final VehicleWalkingPreferences DEFAULT = new VehicleWalkingPreferences(); + + private final double speed; + private final double reluctance; + private final Duration hopTime; + private final Cost hopCost; + private final double stairsReluctance; + + private VehicleWalkingPreferences() { + this.speed = 1.33; + this.reluctance = 5.0; + this.hopTime = Duration.ZERO; + this.hopCost = Cost.ZERO; + // very high reluctance to carry the bike up/down a flight of stairs + this.stairsReluctance = 10; + } + + /** + * Sets the vehicle walking preferences, does some input value validation and rounds + * reluctances and speed to not have too many decimals. + */ + private VehicleWalkingPreferences(Builder builder) { + this.speed = Units.speed(builder.speed); + this.reluctance = Units.reluctance(builder.reluctance); + this.hopTime = Duration.ofSeconds(Units.duration(builder.hopTime)); + this.hopCost = Cost.costOfSeconds(builder.hopCost); + this.stairsReluctance = Units.reluctance(builder.stairsReluctance); + } + + public static VehicleWalkingPreferences.Builder of() { + return new VehicleWalkingPreferences.Builder(DEFAULT); + } + + public VehicleWalkingPreferences.Builder copyOf() { + return new VehicleWalkingPreferences.Builder(this); + } + + /** + * The walking speed when walking a vehicle. Default: 1.33 m/s ~ Same as walkSpeed. + */ + public double speed() { + return speed; + } + + /** + * A multiplier for how bad walking is, compared to being in transit for equal + * lengths of time. Empirically, values between 2 and 4 seem to correspond + * well to the concept of not wanting to walk too much without asking for + * totally ridiculous itineraries, but this observation should in no way be + * taken as scientific or definitive. Your mileage may vary. See + * https://github.com/opentripplanner/OpenTripPlanner/issues/4090 for impact on + * performance with high values. Default value: 2.0 + */ + public double reluctance() { + return reluctance; + } + + /** Time to get on and off your own vehicle. */ + public Duration hopTime() { + return hopTime; + } + + /** Cost of getting on and off your own vehicle. */ + public Cost hopCost() { + return hopCost; + } + + /** Reluctance of walking carrying a vehicle up a flight of stairs. */ + public double stairsReluctance() { + return stairsReluctance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VehicleWalkingPreferences that = (VehicleWalkingPreferences) o; + return ( + speed == that.speed && + reluctance == that.reluctance && + Objects.equals(hopTime, that.hopTime) && + Objects.equals(hopCost, that.hopCost) && + stairsReluctance == that.stairsReluctance + ); + } + + @Override + public int hashCode() { + return Objects.hash(speed, reluctance, hopTime, hopCost, stairsReluctance); + } + + @Override + public String toString() { + return ToStringBuilder + .of(VehicleWalkingPreferences.class) + .addNum("speed", speed, DEFAULT.speed) + .addNum("reluctance", reluctance, DEFAULT.reluctance) + .addObj("hopTime", hopTime, DEFAULT.hopTime) + .addObj("hopCost", hopCost, DEFAULT.hopCost) + .addNum("stairsReluctance", stairsReluctance, DEFAULT.stairsReluctance) + .toString(); + } + + public static class Builder { + + private final VehicleWalkingPreferences original; + private double speed; + private double reluctance; + private int hopTime; + private int hopCost; + private double stairsReluctance; + + private Builder(VehicleWalkingPreferences original) { + this.original = original; + this.speed = original.speed; + this.reluctance = original.reluctance; + this.hopTime = (int) original.hopTime.toSeconds(); + this.hopCost = original.hopCost.toSeconds(); + this.stairsReluctance = original.stairsReluctance; + } + + public VehicleWalkingPreferences.Builder withSpeed(double speed) { + this.speed = speed; + return this; + } + + public VehicleWalkingPreferences.Builder withReluctance(double reluctance) { + this.reluctance = reluctance; + return this; + } + + public VehicleWalkingPreferences.Builder withHopTime(Duration hopTime) { + this.hopTime = (int) hopTime.toSeconds(); + return this; + } + + public VehicleWalkingPreferences.Builder withHopTime(int hopTime) { + this.hopTime = hopTime; + return this; + } + + public VehicleWalkingPreferences.Builder withHopCost(int hopCost) { + this.hopCost = hopCost; + return this; + } + + public VehicleWalkingPreferences.Builder withStairsReluctance(double stairsReluctance) { + this.stairsReluctance = stairsReluctance; + return this; + } + + public VehicleWalkingPreferences original() { + return original; + } + + public VehicleWalkingPreferences.Builder apply( + Consumer body + ) { + body.accept(this); + return this; + } + + public VehicleWalkingPreferences build() { + var newObj = new VehicleWalkingPreferences(this); + return original.equals(newObj) ? original : newObj; + } + } +} diff --git a/src/main/java/org/opentripplanner/routing/core/BicycleOptimizeType.java b/src/main/java/org/opentripplanner/routing/core/BicycleOptimizeType.java index b5a47af82de..1d639e0af8b 100644 --- a/src/main/java/org/opentripplanner/routing/core/BicycleOptimizeType.java +++ b/src/main/java/org/opentripplanner/routing/core/BicycleOptimizeType.java @@ -9,10 +9,14 @@ * combined presets of routing parameters, except for triangle. */ public enum BicycleOptimizeType { - QUICK,/* the fastest trip */ - SAFE, - FLAT,/* needs a rewrite */ - GREENWAYS, + /** This was previously called QUICK */ + SHORTEST_DURATION, + /** This was previously called SAFE */ + SAFE_STREETS, + /** This was previously called FLAT. Needs a rewrite. */ + FLAT_STREETS, + /** This was previously called GREENWAYS. */ + SAFEST_STREETS, TRIANGLE; private static final Set NON_TRIANGLE_VALUES = Collections.unmodifiableSet( diff --git a/src/main/java/org/opentripplanner/service/vehiclerental/street/VehicleRentalEdge.java b/src/main/java/org/opentripplanner/service/vehiclerental/street/VehicleRentalEdge.java index 66665f73b54..dc9fed8b9a3 100644 --- a/src/main/java/org/opentripplanner/service/vehiclerental/street/VehicleRentalEdge.java +++ b/src/main/java/org/opentripplanner/service/vehiclerental/street/VehicleRentalEdge.java @@ -161,8 +161,14 @@ public State[] traverse(State s0) { } } - s1.incrementWeight(pickedUp ? preferences.pickupCost() : preferences.dropoffCost()); - s1.incrementTimeInSeconds(pickedUp ? preferences.pickupTime() : preferences.dropoffTime()); + s1.incrementWeight( + pickedUp ? preferences.pickupCost().toSeconds() : preferences.dropOffCost().toSeconds() + ); + s1.incrementTimeInSeconds( + pickedUp + ? (int) preferences.pickupTime().toSeconds() + : (int) preferences.dropOffTime().toSeconds() + ); s1.setBackMode(null); return s1.makeStateArray(); } diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java index b733b2c7d8d..4538f6de84d 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java @@ -8,11 +8,13 @@ import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_5; import static org.opentripplanner.standalone.config.routerequest.ItineraryFiltersConfig.mapItineraryFilterParams; import static org.opentripplanner.standalone.config.routerequest.TransferConfig.mapTransferPreferences; -import static org.opentripplanner.standalone.config.routerequest.VehicleRentalConfig.setVehicleRental; +import static org.opentripplanner.standalone.config.routerequest.TriangleOptimizationConfig.mapOptimizationTriangle; +import static org.opentripplanner.standalone.config.routerequest.VehicleParkingConfig.mapParking; +import static org.opentripplanner.standalone.config.routerequest.VehicleRentalConfig.mapRental; +import static org.opentripplanner.standalone.config.routerequest.VehicleWalkingConfig.mapVehicleWalking; import static org.opentripplanner.standalone.config.routerequest.WheelchairConfig.mapWheelchairPreferences; import java.time.Duration; -import java.util.List; import org.opentripplanner.api.parameter.QualifiedModeSet; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.routing.api.request.RequestModes; @@ -25,7 +27,6 @@ import org.opentripplanner.routing.api.request.preference.StreetPreferences; import org.opentripplanner.routing.api.request.preference.SystemPreferences; import org.opentripplanner.routing.api.request.preference.TransitPreferences; -import org.opentripplanner.routing.api.request.preference.VehicleParkingPreferences; import org.opentripplanner.routing.api.request.preference.WalkPreferences; import org.opentripplanner.standalone.config.framework.json.NodeAdapter; import org.opentripplanner.standalone.config.sandbox.DataOverlayParametersMapper; @@ -332,178 +333,54 @@ The board time is added to the time when going from the stop (offboard) to onboa ); } - private static void mapBikePreferences(NodeAdapter c, BikePreferences.Builder builder) { + private static void mapBikePreferences(NodeAdapter root, BikePreferences.Builder builder) { var dft = builder.original(); + NodeAdapter c = root.of("bicycle").since(V2_5).summary("Bicycle preferences.").asObject(); builder .withSpeed( c - .of("bikeSpeed") + .of("speed") .since(V2_0) - .summary("Max bike speed along streets, in meters per second") + .summary("Max bicycle speed along streets, in meters per second") .asDouble(dft.speed()) ) .withReluctance( c - .of("bikeReluctance") + .of("reluctance") .since(V2_0) .summary( - "A multiplier for how bad biking is, compared to being in transit for equal lengths of time." + "A multiplier for how bad cycling is, compared to being in transit for equal lengths of time." ) .asDouble(dft.reluctance()) ) .withBoardCost( c - .of("bikeBoardCost") + .of("boardCost") .since(V2_0) - .summary("Prevents unnecessary transfers by adding a cost for boarding a vehicle.") + .summary( + "Prevents unnecessary transfers by adding a cost for boarding a transit vehicle." + ) .description( - "This is the cost that is used when boarding while cycling." + + "This is the cost that is used when boarding while cycling. " + "This is usually higher that walkBoardCost." ) .asInt(dft.boardCost()) ) - .withWalkingSpeed( - c - .of("bikeWalkingSpeed") - .since(V2_1) - .summary( - "The user's bike walking speed in meters/second. Defaults to approximately 3 MPH." - ) - .asDouble(dft.walkingSpeed()) - ) - .withWalkingReluctance( - c - .of("bikeWalkingReluctance") - .since(V2_1) - .summary( - "A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time." - ) - .asDouble(dft.walkingReluctance()) - ) - .withSwitchTime( - c - .of("bikeSwitchTime") - .since(V2_0) - .summary("The time it takes the user to fetch their bike and park it again in seconds.") - .asInt(dft.switchTime()) - ) - .withSwitchCost( - c - .of("bikeSwitchCost") - .since(V2_0) - .summary("The cost of the user fetching their bike and parking it again.") - .asInt(dft.switchCost()) - ) .withOptimizeType( c - .of("optimize") + .of("optimization") .since(V2_0) .summary("The set of characteristics that the user wants to optimize for.") - .asEnum(dft.optimizeType()) - ) - .withOptimizeTriangle(it -> - it - .withTime( - c - .of("bikeTriangleTimeFactor") - .since(V2_0) - .summary("For bike triangle routing, how much time matters (range 0-1).") - .asDouble(it.time()) - ) - .withSlope( - c - .of("bikeTriangleSlopeFactor") - .since(V2_0) - .summary("For bike triangle routing, how much slope matters (range 0-1).") - .asDouble(it.slope()) - ) - .withSafety( - c - .of("bikeTriangleSafetyFactor") - .since(V2_0) - .summary("For bike triangle routing, how much safety matters (range 0-1).") - .asDouble(it.safety()) - ) - ) - .withStairsReluctance( - c - .of("bikeStairsReluctance") - .since(V2_3) - .summary( - "How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour." - ) - .asDouble(dft.stairsReluctance()) - ) - .withParking(it -> - it - .withUnpreferredVehicleParkingTagCost( - c - .of("unpreferredVehicleParkingTagCost") - .since(V2_3) - .summary("What cost to add if a parking facility doesn't contain a preferred tag.") - .description("See `preferredVehicleParkingTags`.") - .asInt( - VehicleParkingPreferences.DEFAULT.unpreferredVehicleParkingTagCost().toSeconds() - ) - ) - .withBannedVehicleParkingTags( - c - .of("bannedVehicleParkingTags") - .since(V2_1) - .summary( - "Tags with which a vehicle parking will not be used. If empty, no tags are banned." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) - ) - .withRequiredVehicleParkingTags( - c - .of("requiredVehicleParkingTags") - .since(V2_1) - .summary( - "Tags without which a vehicle parking will not be used. If empty, no tags are required." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) - ) - .withParkTime( - c - .of("bikeParkTime") - .since(V2_0) - .summary("Time to park a bike.") - .asDuration(VehicleParkingPreferences.DEFAULT.parkTime()) - ) - .withParkCost( - c - .of("bikeParkCost") - .since(V2_0) - .summary("Cost to park a bike.") - .asInt(VehicleParkingPreferences.DEFAULT.parkCost().toSeconds()) - ) - .withPreferredVehicleParkingTags( - c - .of("preferredVehicleParkingTags") - .since(V2_3) - .summary( - "Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) + .description( + "If the triangle optimization is used, it's enough to just define the triangle parameters" ) + .asEnum(dft.optimizeType()) ) - .withRental(it -> setVehicleRental(c, it)); + // triangle overrides the optimization type if defined + .withForcedOptimizeTriangle(it -> mapOptimizationTriangle(c, it)) + .withWalking(it -> mapVehicleWalking(c, it)) + .withParking(it -> mapParking(c, it)) + .withRental(it -> mapRental(c, it)); } private static void mapStreetPreferences(NodeAdapter c, StreetPreferences.Builder builder) { @@ -692,132 +569,56 @@ The street search(AStar) aborts after this duration and any paths found are retu ); } - private static void mapCarPreferences(NodeAdapter c, CarPreferences.Builder builder) { + private static void mapCarPreferences(NodeAdapter root, CarPreferences.Builder builder) { var dft = builder.original(); + NodeAdapter c = root.of("car").since(V2_5).summary("Car preferences.").asObject(); builder .withSpeed( c - .of("carSpeed") + .of("speed") .since(V2_0) .summary("Max car speed along streets, in meters per second") .asDouble(dft.speed()) ) .withReluctance( c - .of("carReluctance") + .of("reluctance") .since(V2_0) .summary( "A multiplier for how bad driving is, compared to being in transit for equal lengths of time." ) .asDouble(dft.reluctance()) ) - .withDropoffTime( - c - .of("carDropoffTime") - .since(V2_0) - .summary( - "Time to park a car in a park and ride, w/o taking into account driving and walking cost." - ) - .asInt(dft.dropoffTime()) - ) .withPickupCost( c - .of("carPickupCost") + .of("pickupCost") .since(V2_1) .summary("Add a cost for car pickup changes when a pickup or drop off takes place") - .asInt(dft.pickupCost()) + .asInt(dft.pickupCost().toSeconds()) ) .withPickupTime( c - .of("carPickupTime") + .of("pickupTime") .since(V2_1) .summary("Add a time for car pickup changes when a pickup or drop off takes place") - .asInt(dft.pickupTime()) + .asDuration(dft.pickupTime()) ) .withAccelerationSpeed( c - .of("carAccelerationSpeed") + .of("accelerationSpeed") .since(V2_0) .summary("The acceleration speed of an automobile, in meters per second per second.") .asDouble(dft.accelerationSpeed()) ) .withDecelerationSpeed( c - .of("carDecelerationSpeed") + .of("decelerationSpeed") .since(V2_0) .summary("The deceleration speed of an automobile, in meters per second per second.") .asDouble(dft.decelerationSpeed()) ) - .withParking(it -> - it - .withUnpreferredVehicleParkingTagCost( - c - .of("unpreferredVehicleParkingTagCost") - .since(V2_3) - .summary("What cost to add if a parking facility doesn't contain a preferred tag.") - .description("See `preferredVehicleParkingTags`.") - .asInt( - VehicleParkingPreferences.DEFAULT.unpreferredVehicleParkingTagCost().toSeconds() - ) - ) - .withBannedVehicleParkingTags( - c - .of("bannedVehicleParkingTags") - .since(V2_1) - .summary( - "Tags with which a vehicle parking will not be used. If empty, no tags are banned." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) - ) - .withRequiredVehicleParkingTags( - c - .of("requiredVehicleParkingTags") - .since(V2_1) - .summary( - "Tags without which a vehicle parking will not be used. If empty, no tags are required." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) - ) - .withParkCost( - c - .of("carParkCost") - .since(V2_1) - .summary("Cost of parking a car.") - .asInt(VehicleParkingPreferences.DEFAULT.parkCost().toSeconds()) - ) - .withParkTime( - c - .of("carParkTime") - .since(V2_1) - .summary("Time to park a car") - .asDuration(VehicleParkingPreferences.DEFAULT.parkTime()) - ) - .withPreferredVehicleParkingTags( - c - .of("preferredVehicleParkingTags") - .since(V2_3) - .summary( - "Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised." - ) - .description( - """ - Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). - """ - ) - .asStringSet(List.of()) - ) - ) - .withRental(it -> setVehicleRental(c, it)); + .withParking(it -> mapParking(c, it)) + .withRental(it -> mapRental(c, it)); } private static void mapSystemPreferences(NodeAdapter c, SystemPreferences.Builder builder) { @@ -868,19 +669,20 @@ private static void mapSystemPreferences(NodeAdapter c, SystemPreferences.Builde } } - private static void mapWalkPreferences(NodeAdapter c, WalkPreferences.Builder walk) { + private static void mapWalkPreferences(NodeAdapter root, WalkPreferences.Builder walk) { var dft = walk.original(); + NodeAdapter c = root.of("walk").since(V2_5).summary("Walking preferences.").asObject(); walk .withSpeed( c - .of("walkSpeed") + .of("speed") .since(V2_0) .summary("The user's walking speed in meters/second.") .asDouble(dft.speed()) ) .withReluctance( c - .of("walkReluctance") + .of("reluctance") .since(V2_0) .summary( "A multiplier for how bad walking is, compared to being in transit for equal lengths of time." @@ -898,7 +700,7 @@ private static void mapWalkPreferences(NodeAdapter c, WalkPreferences.Builder wa ) .withBoardCost( c - .of("walkBoardCost") + .of("boardCost") .since(V2_0) .summary( """ @@ -932,7 +734,7 @@ private static void mapWalkPreferences(NodeAdapter c, WalkPreferences.Builder wa ) .withSafetyFactor( c - .of("walkSafetyFactor") + .of("safetyFactor") .since(V2_2) .summary("Factor for how much the walk safety is considered in routing.") .description( diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/TriangleOptimizationConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/TriangleOptimizationConfig.java new file mode 100644 index 00000000000..e6da735a4ac --- /dev/null +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/TriangleOptimizationConfig.java @@ -0,0 +1,54 @@ +package org.opentripplanner.standalone.config.routerequest; + +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_0; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_5; + +import org.opentripplanner.routing.api.request.preference.TimeSlopeSafetyTriangle; +import org.opentripplanner.standalone.config.framework.json.NodeAdapter; + +public class TriangleOptimizationConfig { + + static void mapOptimizationTriangle(NodeAdapter c, TimeSlopeSafetyTriangle.Builder preferences) { + var optimizationTriangle = c + .of("triangle") + .since(V2_5) + .summary("Triangle optimization criteria.") + .description("Optimization type doesn't need to be defined if these values are defined.") + .asObject(); + mapTriangleParameters(optimizationTriangle, preferences); + } + + private static void mapTriangleParameters( + NodeAdapter c, + TimeSlopeSafetyTriangle.Builder builder + ) { + builder + .withTime( + c + .of("time") + .since(V2_0) + .summary("Relative importance of duration of travel (range 0-1).") + .asDouble(builder.time()) + ) + .withSlope( + c + .of("flatness") + .since(V2_0) + .summary("Relative importance of flat terrain (range 0-1).") + .asDouble(builder.slope()) + ) + .withSafety( + c + .of("safety") + .since(V2_0) + .summary("Relative importance of safety (range 0-1).") + .description( + """ + This factor can also include other concerns such as convenience and general cyclist + preferences by taking into account road surface etc. + """ + ) + .asDouble(builder.safety()) + ); + } +} diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleParkingConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleParkingConfig.java new file mode 100644 index 00000000000..218ac3b33df --- /dev/null +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleParkingConfig.java @@ -0,0 +1,93 @@ +package org.opentripplanner.standalone.config.routerequest; + +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_0; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_1; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_3; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_5; + +import java.util.List; +import org.opentripplanner.routing.api.request.preference.VehicleParkingPreferences; +import org.opentripplanner.standalone.config.framework.json.NodeAdapter; + +public class VehicleParkingConfig { + + static void mapParking(NodeAdapter c, VehicleParkingPreferences.Builder preferences) { + var vehicleParking = c + .of("parking") + .since(V2_5) + .summary("Preferences for parking a vehicle.") + .asObject(); + mapParkingPreferences(vehicleParking, preferences); + } + + private static void mapParkingPreferences( + NodeAdapter c, + VehicleParkingPreferences.Builder builder + ) { + builder + .withUnpreferredVehicleParkingTagCost( + c + .of("unpreferredVehicleParkingTagCost") + .since(V2_3) + .summary("What cost to add if a parking facility doesn't contain a preferred tag.") + .description("See `preferredVehicleParkingTags`.") + .asInt(VehicleParkingPreferences.DEFAULT.unpreferredVehicleParkingTagCost().toSeconds()) + ) + .withBannedVehicleParkingTags( + c + .of("bannedVehicleParkingTags") + .since(V2_1) + .summary( + "Tags with which a vehicle parking will not be used. If empty, no tags are banned." + ) + .description( + """ + Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + """ + ) + .asStringSet(List.of()) + ) + .withRequiredVehicleParkingTags( + c + .of("requiredVehicleParkingTags") + .since(V2_1) + .summary( + "Tags without which a vehicle parking will not be used. If empty, no tags are required." + ) + .description( + """ + Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + """ + ) + .asStringSet(List.of()) + ) + .withTime( + c + .of("time") + .since(V2_0) + .summary("Time to park a vehicle.") + .asDuration(VehicleParkingPreferences.DEFAULT.time()) + ) + .withCost( + c + .of("cost") + .since(V2_0) + .summary("Cost to park a vehicle.") + .asInt(VehicleParkingPreferences.DEFAULT.cost().toSeconds()) + ) + .withPreferredVehicleParkingTags( + c + .of("preferredVehicleParkingTags") + .since(V2_3) + .summary( + "Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised." + ) + .description( + """ + Vehicle parking tags can originate from different places depending on the origin of the parking(OSM or RT feed). + """ + ) + .asStringSet(List.of()) + ); + } +} diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleRentalConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleRentalConfig.java index 057daa7001c..401d977762d 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleRentalConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleRentalConfig.java @@ -10,28 +10,44 @@ public class VehicleRentalConfig { - static void mapRentalPreferences(NodeAdapter c, VehicleRentalPreferences.Builder builder) { + static void mapRental(NodeAdapter c, VehicleRentalPreferences.Builder preferences) { + var vehicleRental = c.of("rental").since(V2_3).summary("Vehicle rental options").asObject(); + mapRentalPreferences(vehicleRental, preferences); + } + + private static void mapRentalPreferences( + NodeAdapter c, + VehicleRentalPreferences.Builder builder + ) { var dft = builder.original(); builder - .withDropoffCost( + .withDropOffCost( c .of("dropOffCost") .since(V2_0) .summary("Cost to drop-off a rented vehicle.") - .asInt(dft.dropoffCost()) + .asInt(dft.dropOffCost().toSeconds()) ) - .withDropoffTime( + .withDropOffTime( c .of("dropOffTime") .since(V2_0) .summary("Time to drop-off a rented vehicle.") - .asInt(dft.dropoffTime()) + .asDuration(dft.dropOffTime()) ) .withPickupCost( - c.of("pickupCost").since(V2_0).summary("Cost to rent a vehicle.").asInt(dft.pickupCost()) + c + .of("pickupCost") + .since(V2_0) + .summary("Cost to rent a vehicle.") + .asInt(dft.pickupCost().toSeconds()) ) .withPickupTime( - c.of("pickupTime").since(V2_0).summary("Time to rent a vehicle.").asInt(dft.pickupTime()) + c + .of("pickupTime") + .since(V2_0) + .summary("Time to rent a vehicle.") + .asDuration(dft.pickupTime()) ) .withUseAvailabilityInformation( c @@ -49,7 +65,7 @@ static void mapRentalPreferences(NodeAdapter c, VehicleRentalPreferences.Builder .summary( "The cost of arriving at the destination with the rented vehicle, to discourage doing so." ) - .asDouble(dft.arrivingInRentalVehicleAtDestinationCost()) + .asInt(dft.arrivingInRentalVehicleAtDestinationCost().toSeconds()) ) .withAllowArrivingInRentedVehicleAtDestination( c @@ -79,13 +95,4 @@ static void mapRentalPreferences(NodeAdapter c, VehicleRentalPreferences.Builder .asStringSet(dft.bannedNetworks()) ); } - - static void setVehicleRental(NodeAdapter c, VehicleRentalPreferences.Builder preferences) { - var vehicleRental = c - .of("vehicleRental") - .since(V2_3) - .summary("Vehicle rental options") - .asObject(); - mapRentalPreferences(vehicleRental, preferences); - } } diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleWalkingConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleWalkingConfig.java new file mode 100644 index 00000000000..f2ba922c8e3 --- /dev/null +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleWalkingConfig.java @@ -0,0 +1,82 @@ +package org.opentripplanner.standalone.config.routerequest; + +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_0; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_1; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_3; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_5; + +import org.opentripplanner.routing.api.request.preference.VehicleWalkingPreferences; +import org.opentripplanner.standalone.config.framework.json.NodeAdapter; + +public class VehicleWalkingConfig { + + static void mapVehicleWalking(NodeAdapter c, VehicleWalkingPreferences.Builder preferences) { + var vehicleWalking = c + .of("walk") + .since(V2_5) + .summary("Preferences for walking a vehicle.") + .asObject(); + mapVehicleWalkingPreferences(vehicleWalking, preferences); + } + + private static void mapVehicleWalkingPreferences( + NodeAdapter c, + VehicleWalkingPreferences.Builder builder + ) { + var dft = builder.original(); + builder + .withSpeed( + c + .of("speed") + .since(V2_1) + .summary( + "The user's vehicle walking speed in meters/second. Defaults to approximately 3 MPH." + ) + .asDouble(dft.speed()) + ) + .withReluctance( + c + .of("reluctance") + .since(V2_1) + .summary( + "A multiplier for how bad walking with a vehicle is, compared to being in transit for equal lengths of time." + ) + .asDouble(dft.reluctance()) + ) + .withHopTime( + c + .of("hopTime") + .since(V2_0) + .summary("The time it takes the user to hop on or off a vehicle.") + .description( + """ + Time it takes to rent or park a vehicle have their own parameters and this is not meant + for controlling the duration of those events. + """ + ) + .asDuration(dft.hopTime()) + ) + .withHopCost( + c + .of("hopCost") + .since(V2_0) + .summary("The cost of hopping on or off a vehicle.") + .description( + """ + There are different parameters for the cost of renting or parking a vehicle and this is + not meant for controlling the cost of those events. + """ + ) + .asInt(dft.hopCost().toSeconds()) + ) + .withStairsReluctance( + c + .of("stairsReluctance") + .since(V2_3) + .summary( + "How bad is it to walk the vehicle up/down a flight of stairs compared to taking a detour." + ) + .asDouble(dft.stairsReluctance()) + ); + } +} diff --git a/src/main/java/org/opentripplanner/street/model/edge/BikeWalkableEdge.java b/src/main/java/org/opentripplanner/street/model/edge/BikeWalkableEdge.java index eb17c5d0900..799a5b006e6 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/BikeWalkableEdge.java +++ b/src/main/java/org/opentripplanner/street/model/edge/BikeWalkableEdge.java @@ -17,8 +17,8 @@ default void switchToWalkingBike(RoutingPreferences preferences, StateEditor edi editor.setBackWalkingBike(true); if (shouldIncludeCost) { - editor.incrementWeight(preferences.bike().switchCost()); - editor.incrementTimeInSeconds(preferences.bike().switchTime()); + editor.incrementWeight(preferences.bike().walking().hopCost().toSeconds()); + editor.incrementTimeInSeconds((int) preferences.bike().walking().hopTime().toSeconds()); } } @@ -28,8 +28,8 @@ default void switchToBiking(RoutingPreferences preferences, StateEditor editor) editor.setBackWalkingBike(false); if (shouldIncludeCost) { - editor.incrementWeight(preferences.bike().switchCost()); - editor.incrementTimeInSeconds(preferences.bike().switchTime()); + editor.incrementWeight(preferences.bike().walking().hopCost().toSeconds()); + editor.incrementTimeInSeconds((int) preferences.bike().walking().hopTime().toSeconds()); } } diff --git a/src/main/java/org/opentripplanner/street/model/edge/CarPickupableEdge.java b/src/main/java/org/opentripplanner/street/model/edge/CarPickupableEdge.java index ec50e3b60ca..7ea1678bbe7 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/CarPickupableEdge.java +++ b/src/main/java/org/opentripplanner/street/model/edge/CarPickupableEdge.java @@ -30,13 +30,13 @@ default void dropOffAfterDriving(State state, StateEditor editor) { ? CarPickupState.WALK_TO_PICKUP : CarPickupState.WALK_FROM_DROP_OFF ); - editor.incrementTimeInSeconds(state.getPreferences().car().pickupTime()); - editor.incrementWeight(state.getPreferences().car().pickupCost()); + editor.incrementTimeInSeconds((int) state.getPreferences().car().pickupTime().toSeconds()); + editor.incrementWeight(state.getPreferences().car().pickupCost().toSeconds()); } default void driveAfterPickup(State state, StateEditor editor) { editor.setCarPickupState(CarPickupState.IN_CAR); - editor.incrementTimeInSeconds(state.getPreferences().car().pickupTime()); - editor.incrementWeight(state.getPreferences().car().pickupCost()); + editor.incrementTimeInSeconds((int) state.getPreferences().car().pickupTime().toSeconds()); + editor.incrementWeight(state.getPreferences().car().pickupCost().toSeconds()); } } diff --git a/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java b/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java index d0b0018898a..1e3594ee04b 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java +++ b/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java @@ -51,7 +51,7 @@ public class StreetEdge private static final Logger LOG = LoggerFactory.getLogger(StreetEdge.class); - private static final double GREENWAY_SAFETY_FACTOR = 0.1; + private static final double SAFEST_STREETS_SAFETY_FACTOR = 0.1; /** If you have more than 16 flags, increase flags to short or int */ static final int BACK_FLAG_INDEX = 0; @@ -231,7 +231,9 @@ public double calculateSpeed( final double speed = switch (traverseMode) { - case WALK -> walkingBike ? preferences.bike().walkingSpeed() : preferences.walk().speed(); + case WALK -> walkingBike + ? preferences.bike().walking().speed() + : preferences.walk().speed(); case BICYCLE, SCOOTER -> preferences.bike().speed(); case CAR -> getCarSpeed(); case FLEX -> throw new IllegalArgumentException("getSpeed(): Invalid mode " + traverseMode); @@ -1215,17 +1217,17 @@ private TraversalCosts bicycleTraversalCost(RoutingPreferences pref, double spee double time = getEffectiveBikeDistance() / speed; double weight; switch (pref.bike().optimizeType()) { - case GREENWAYS -> { + case SAFEST_STREETS -> { weight = bicycleSafetyFactor * getDistanceMeters() / speed; - if (bicycleSafetyFactor <= GREENWAY_SAFETY_FACTOR) { - // greenways are treated as even safer than they really are + if (bicycleSafetyFactor <= SAFEST_STREETS_SAFETY_FACTOR) { + // safest streets are treated as even safer than they really are weight *= 0.66; } } - case SAFE -> weight = getEffectiveBicycleSafetyDistance() / speed; - case FLAT -> /* see notes in StreetVertex on speed overhead */weight = + case SAFE_STREETS -> weight = getEffectiveBicycleSafetyDistance() / speed; + case FLAT_STREETS -> /* see notes in StreetVertex on speed overhead */weight = getEffectiveBikeDistanceForWorkCost() / speed; - case QUICK -> weight = getEffectiveBikeDistance() / speed; + case SHORTEST_DURATION -> weight = getEffectiveBikeDistance() / speed; case TRIANGLE -> { double quick = getEffectiveBikeDistance(); double safety = getEffectiveBicycleSafetyDistance(); @@ -1276,7 +1278,7 @@ private TraversalCosts walkingTraversalCosts( time = weight = (getEffectiveBikeDistance() / speed); if (isStairs()) { // we do allow walking the bike across a stairs but there is a very high default penalty - weight *= preferences.bike().stairsReluctance(); + weight *= preferences.bike().walking().stairsReluctance(); } } else { // take slopes into account when walking diff --git a/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeReluctanceCalculator.java b/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeReluctanceCalculator.java index 669adc2489f..ee2f3d833ee 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeReluctanceCalculator.java +++ b/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeReluctanceCalculator.java @@ -10,7 +10,7 @@ private StreetEdgeReluctanceCalculator() {} /** * Compute reluctance for a regular street section. Note! This does not apply if in a wheelchair, - * see {@link #computeWheelchairReluctance(RouteRequest, double, boolean, boolean)}. + * see {@link #computeWheelchairReluctance(RoutingPreferences, double, boolean, boolean)}. */ static double computeReluctance( RoutingPreferences pref, @@ -22,7 +22,7 @@ static double computeReluctance( return pref.walk().stairsReluctance(); } else { return switch (traverseMode) { - case WALK -> walkingBike ? pref.bike().walkingReluctance() : pref.walk().reluctance(); + case WALK -> walkingBike ? pref.bike().walking().reluctance() : pref.walk().reluctance(); case BICYCLE -> pref.bike().reluctance(); case CAR -> pref.car().reluctance(); default -> throw new IllegalArgumentException( diff --git a/src/main/java/org/opentripplanner/street/model/edge/StreetTransitEntityLink.java b/src/main/java/org/opentripplanner/street/model/edge/StreetTransitEntityLink.java index 926eebc31d9..df5b24a5928 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/StreetTransitEntityLink.java +++ b/src/main/java/org/opentripplanner/street/model/edge/StreetTransitEntityLink.java @@ -143,7 +143,7 @@ private State[] buildState(State s0, StateEditor s1, RoutingPreferences pref) { s0.mayKeepRentedVehicleAtDestination() && rentalPreferences.allowArrivingInRentedVehicleAtDestination() ) { - s1.incrementWeight(rentalPreferences.arrivingInRentalVehicleAtDestinationCost()); + s1.incrementWeight(rentalPreferences.arrivingInRentalVehicleAtDestinationCost().toSeconds()); } s1.setBackMode(null); diff --git a/src/main/java/org/opentripplanner/street/model/edge/TemporaryFreeEdge.java b/src/main/java/org/opentripplanner/street/model/edge/TemporaryFreeEdge.java index 011d0fec7f1..d825a8fcbea 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/TemporaryFreeEdge.java +++ b/src/main/java/org/opentripplanner/street/model/edge/TemporaryFreeEdge.java @@ -48,7 +48,7 @@ public State[] traverse(State s0) { s0.mayKeepRentedVehicleAtDestination() && rentalPreferences.allowArrivingInRentedVehicleAtDestination() ) { - s1.incrementWeight(rentalPreferences.arrivingInRentalVehicleAtDestinationCost()); + s1.incrementWeight(rentalPreferences.arrivingInRentalVehicleAtDestinationCost().toSeconds()); } return s1.makeStateArray(); diff --git a/src/main/java/org/opentripplanner/street/model/edge/VehicleParkingEdge.java b/src/main/java/org/opentripplanner/street/model/edge/VehicleParkingEdge.java index be909c1dc4c..d32f13d6ea4 100644 --- a/src/main/java/org/opentripplanner/street/model/edge/VehicleParkingEdge.java +++ b/src/main/java/org/opentripplanner/street/model/edge/VehicleParkingEdge.java @@ -94,20 +94,10 @@ protected State[] traverseUnPark(State s0) { if (streetMode.includesBiking()) { final BikePreferences bike = s0.getPreferences().bike(); - return traverseUnPark( - s0, - bike.parking().parkCost(), - bike.parking().parkTime(), - TraverseMode.BICYCLE - ); + return traverseUnPark(s0, bike.parking().cost(), bike.parking().time(), TraverseMode.BICYCLE); } else if (streetMode.includesDriving()) { final CarPreferences car = s0.getPreferences().car(); - return traverseUnPark( - s0, - car.parking().parkCost(), - car.parking().parkTime(), - TraverseMode.CAR - ); + return traverseUnPark(s0, car.parking().cost(), car.parking().time(), TraverseMode.CAR); } else { return State.empty(); } @@ -151,14 +141,14 @@ private State[] traversePark(State s0) { return traversePark( s0, - preferences.bike().parking().parkCost(), - preferences.bike().parking().parkTime() + preferences.bike().parking().cost(), + preferences.bike().parking().time() ); } else if (streetMode.includesDriving()) { return traversePark( s0, - preferences.car().parking().parkCost(), - preferences.car().parking().parkTime() + preferences.car().parking().cost(), + preferences.car().parking().time() ); } else { return State.empty(); diff --git a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java index 9f8bbffb22d..f15aff9048b 100644 --- a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java +++ b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java @@ -549,18 +549,18 @@ protected void route(String from, String to) { BicycleOptimizeType getSelectedOptimizeType() { if (opQuick.isSelected()) { - return BicycleOptimizeType.QUICK; + return BicycleOptimizeType.SHORTEST_DURATION; } if (opSafe.isSelected()) { - return BicycleOptimizeType.SAFE; + return BicycleOptimizeType.SAFE_STREETS; } if (opFlat.isSelected()) { - return BicycleOptimizeType.FLAT; + return BicycleOptimizeType.FLAT_STREETS; } if (opGreenways.isSelected()) { - return BicycleOptimizeType.GREENWAYS; + return BicycleOptimizeType.SAFEST_STREETS; } - return BicycleOptimizeType.QUICK; + return BicycleOptimizeType.SHORTEST_DURATION; } private Container makeDiffTab() { diff --git a/src/test/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapperTest.java b/src/test/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapperTest.java index fba953cd93a..b05dd77e2a9 100644 --- a/src/test/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapperTest.java +++ b/src/test/java/org/opentripplanner/apis/gtfs/mapping/RouteRequestMapperTest.java @@ -2,15 +2,17 @@ import static graphql.execution.ExecutionContextBuilder.newExecutionContextBuilder; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.params.provider.Arguments.of; -import static org.opentripplanner.routing.core.BicycleOptimizeType.SAFE; +import static org.opentripplanner.routing.core.BicycleOptimizeType.SAFE_STREETS; import static org.opentripplanner.routing.core.BicycleOptimizeType.TRIANGLE; import graphql.ExecutionInput; import graphql.execution.ExecutionId; import graphql.schema.DataFetchingEnvironment; import graphql.schema.DataFetchingEnvironmentImpl; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -21,12 +23,12 @@ import org.opentripplanner._support.time.ZoneIds; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.TestRoutingService; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; import org.opentripplanner.ext.fares.impl.DefaultFareService; import org.opentripplanner.model.plan.PlanTestConstants; import org.opentripplanner.routing.api.request.RouteRequest; import org.opentripplanner.routing.api.request.preference.TimeSlopeSafetyTriangle; import org.opentripplanner.routing.api.request.preference.VehicleParkingPreferences; -import org.opentripplanner.routing.core.BicycleOptimizeType; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graphfinder.GraphFinder; import org.opentripplanner.service.realtimevehicles.internal.DefaultRealtimeVehicleService; @@ -149,7 +151,7 @@ private static Map mode(String mode) { void defaultBikeOptimize() { Map arguments = Map.of(); var routeRequest = RouteRequestMapper.toRouteRequest(executionContext(arguments), context); - assertEquals(SAFE, routeRequest.preferences().bike().optimizeType()); + assertEquals(SAFE_STREETS, routeRequest.preferences().bike().optimizeType()); } @Test @@ -170,14 +172,14 @@ void bikeTriangle() { ); } - static Stream noTriangleCases = BicycleOptimizeType - .nonTriangleValues() - .stream() + static Stream noTriangleCases = Arrays + .stream(GraphQLTypes.GraphQLOptimizeType.values()) + .filter(value -> value != GraphQLTypes.GraphQLOptimizeType.TRIANGLE) .map(Arguments::of); @ParameterizedTest @VariableSource("noTriangleCases") - void noTriangle(BicycleOptimizeType bot) { + void noTriangle(GraphQLTypes.GraphQLOptimizeType bot) { Map arguments = Map.of( "optimize", bot.name(), @@ -187,13 +189,25 @@ void noTriangle(BicycleOptimizeType bot) { var routeRequest = RouteRequestMapper.toRouteRequest(executionContext(arguments), context); - assertEquals(bot, routeRequest.preferences().bike().optimizeType()); + assertEquals(OptimizationTypeMapper.map(bot), routeRequest.preferences().bike().optimizeType()); assertEquals( TimeSlopeSafetyTriangle.DEFAULT, routeRequest.preferences().bike().optimizeTriangle() ); } + @Test + void walkReluctance() { + var reluctance = 119d; + Map arguments = Map.of("walkReluctance", reluctance); + + var routeRequest = RouteRequestMapper.toRouteRequest(executionContext(arguments), context); + assertEquals(reluctance, routeRequest.preferences().walk().reluctance()); + + var noParamsRequest = RouteRequestMapper.toRouteRequest(executionContext(Map.of()), context); + assertNotEquals(reluctance, noParamsRequest.preferences().walk().reluctance()); + } + private DataFetchingEnvironment executionContext(Map arguments) { ExecutionInput executionInput = ExecutionInput .newExecutionInput() diff --git a/src/test/java/org/opentripplanner/apis/transmodel/mapping/TripRequestMapperTest.java b/src/test/java/org/opentripplanner/apis/transmodel/mapping/TripRequestMapperTest.java index 3058f622281..9a01a36cbcb 100644 --- a/src/test/java/org/opentripplanner/apis/transmodel/mapping/TripRequestMapperTest.java +++ b/src/test/java/org/opentripplanner/apis/transmodel/mapping/TripRequestMapperTest.java @@ -272,7 +272,7 @@ public void testBikeTriangleFactors() { @Test void testDefaultTriangleFactors() { var req2 = TripRequestMapper.createRequest(executionContext(Map.of())); - assertEquals(BicycleOptimizeType.SAFE, req2.preferences().bike().optimizeType()); + assertEquals(BicycleOptimizeType.SAFE_STREETS, req2.preferences().bike().optimizeType()); assertEquals(TimeSlopeSafetyTriangle.DEFAULT, req2.preferences().bike().optimizeTriangle()); } diff --git a/src/test/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapperTest.java b/src/test/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapperTest.java index 378571eeea9..a72fd25cbfa 100644 --- a/src/test/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapperTest.java +++ b/src/test/java/org/opentripplanner/apis/transmodel/mapping/preferences/BikePreferencesMapperTest.java @@ -18,7 +18,7 @@ static List mapBikePreferencesTestCases() { Arguments.of( "walkReluctance", 10.0, - "BikePreferences{reluctance: 10.0, walkingReluctance: 27.0}" + "BikePreferences{reluctance: 10.0, walking: VehicleWalkingPreferences{reluctance: 27.0}}" ), Arguments.of("bikeSpeed", 10.0, "BikePreferences{speed: 10.0}"), Arguments.of( diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/BikePreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/BikePreferencesTest.java index 9da7852cc2c..8a6ac3f4f45 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/BikePreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/BikePreferencesTest.java @@ -11,11 +11,7 @@ class BikePreferencesTest { public static final double SPEED = 2.0; public static final double RELUCTANCE = 1.2; - public static final double WALKING_SPEED = 1.15; public static final int BOARD_COST = 660; - public static final double WALKING_RELUCTANCE = 1.45; - public static final int SWITCH_TIME = 200; - public static final int SWITCH_COST = 450; public static final TimeSlopeSafetyTriangle TRIANGLE = TimeSlopeSafetyTriangle .of() .withSlope(1) @@ -29,13 +25,9 @@ class BikePreferencesTest { .withSpeed(SPEED) .withReluctance(RELUCTANCE) .withBoardCost(BOARD_COST) - .withWalkingSpeed(WALKING_SPEED) - .withWalkingReluctance(WALKING_RELUCTANCE) - .withSwitchTime(SWITCH_TIME) - .withSwitchCost(SWITCH_COST) .withOptimizeType(OPTIMIZE_TYPE) .withRental(rental -> rental.withPickupTime(RENTAL_PICKUP_TIME).build()) - .withParking(parking -> parking.withParkCost(PARK_COST).build()) + .withParking(parking -> parking.withCost(PARK_COST).build()) .withOptimizeTriangle(it -> it.withSlope(1).build()) .build(); @@ -54,26 +46,6 @@ void boardCost() { assertEquals(BOARD_COST, subject.boardCost()); } - @Test - void walkingSpeed() { - assertEquals(WALKING_SPEED, subject.walkingSpeed()); - } - - @Test - void walkingReluctance() { - assertEquals(WALKING_RELUCTANCE, subject.walkingReluctance()); - } - - @Test - void switchTime() { - assertEquals(SWITCH_TIME, subject.switchTime()); - } - - @Test - void switchCost() { - assertEquals(SWITCH_COST, subject.switchCost()); - } - @Test void optimizeType() { assertEquals(OPTIMIZE_TYPE, subject.optimizeType()); @@ -92,7 +64,7 @@ void rental() { @Test void parking() { - var vehicleParking = VehicleParkingPreferences.of().withParkCost(PARK_COST).build(); + var vehicleParking = VehicleParkingPreferences.of().withCost(PARK_COST).build(); assertEquals(vehicleParking, subject.parking()); } @@ -119,11 +91,7 @@ void testToString() { "speed: 2.0, " + "reluctance: 1.2, " + "boardCost: $660, " + - "walkingSpeed: 1.15, " + - "walkingReluctance: 1.45, " + - "switchTime: 3m20s, " + - "switchCost: $450, " + - "parking: VehicleParkingPreferences{parkCost: $30}, " + + "parking: VehicleParkingPreferences{cost: $30}, " + "rental: VehicleRentalPreferences{pickupTime: 30s}, " + "optimizeType: TRIANGLE, " + "optimizeTriangle: TimeSlopeSafetyTriangle[time=0.0, slope=1.0, safety=0.0]" + @@ -131,4 +99,27 @@ void testToString() { subject.toString() ); } + + @Test + void testForcedTriangleOptimization() { + var trianglePreferences = BikePreferences + .of() + .withForcedOptimizeTriangle(it -> it.withSlope(1).build()) + .build(); + assertEquals(BicycleOptimizeType.TRIANGLE, trianglePreferences.optimizeType()); + + var conflictingPreferences = BikePreferences + .of() + .withOptimizeType(BicycleOptimizeType.SAFE_STREETS) + .withForcedOptimizeTriangle(it -> it.withSlope(1).build()) + .build(); + assertEquals(BicycleOptimizeType.TRIANGLE, conflictingPreferences.optimizeType()); + + var emptyTrianglePreferences = BikePreferences + .of() + .withOptimizeType(BicycleOptimizeType.SAFE_STREETS) + .withForcedOptimizeTriangle(it -> it.build()) + .build(); + assertEquals(BicycleOptimizeType.SAFE_STREETS, emptyTrianglePreferences.optimizeType()); + } } diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/CarPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/CarPreferencesTest.java index c81cb41d883..4359ed9b33d 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/CarPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/CarPreferencesTest.java @@ -4,7 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.opentripplanner.routing.api.request.preference.ImmutablePreferencesAsserts.assertEqualsAndHashCode; +import java.time.Duration; import org.junit.jupiter.api.Test; +import org.opentripplanner.framework.model.Cost; class CarPreferencesTest { @@ -16,7 +18,6 @@ class CarPreferencesTest { private static final int PICKUP_COST = 500; private static final double ACCELERATION_SPEED = 3.1; private static final double DECELERATION_SPEED = 3.5; - public static final int DROPOFF_TIME = 450; public static final int RENTAL_PICKUP_TIME = 30; public static final int PARK_COST = 30; @@ -24,13 +25,12 @@ class CarPreferencesTest { .of() .withSpeed(SPEED) .withReluctance(RELUCTANCE) - .withPickupTime(PICKUP_TIME) + .withPickupTime(Duration.ofSeconds(PICKUP_TIME)) .withPickupCost(PICKUP_COST) - .withDropoffTime(DROPOFF_TIME) .withAccelerationSpeed(ACCELERATION_SPEED) .withDecelerationSpeed(DECELERATION_SPEED) .withRental(rental -> rental.withPickupTime(RENTAL_PICKUP_TIME).build()) - .withParking(parking -> parking.withParkCost(PARK_COST).build()) + .withParking(parking -> parking.withCost(PARK_COST).build()) .build(); @Test @@ -45,17 +45,12 @@ void reluctance() { @Test void pickupTime() { - assertEquals(PICKUP_TIME, subject.pickupTime()); + assertEquals(Duration.ofSeconds(PICKUP_TIME), subject.pickupTime()); } @Test void pickupCost() { - assertEquals(PICKUP_COST, subject.pickupCost()); - } - - @Test - void dropoffTime() { - assertEquals(DROPOFF_TIME, subject.dropoffTime()); + assertEquals(Cost.costOfSeconds(PICKUP_COST), subject.pickupCost()); } @Test @@ -76,7 +71,7 @@ void rental() { @Test void parking() { - var vehicleParking = VehicleParkingPreferences.of().withParkCost(PARK_COST).build(); + var vehicleParking = VehicleParkingPreferences.of().withCost(PARK_COST).build(); assertEquals(vehicleParking, subject.parking()); } @@ -99,11 +94,10 @@ void testToString() { "CarPreferences{" + "speed: 20.0, " + "reluctance: 5.1, " + - "parking: VehicleParkingPreferences{parkCost: $30}, " + + "parking: VehicleParkingPreferences{cost: $30}, " + "rental: VehicleRentalPreferences{pickupTime: 30s}, " + - "pickupTime: 600, " + + "pickupTime: PT10M, " + "pickupCost: $500, " + - "dropoffTime: 450, " + "accelerationSpeed: 3.1, decelerationSpeed: 3.5" + "}", subject.toString() diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferencesTest.java index 35666b53f9f..ff43a7ddba6 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleParkingPreferencesTest.java @@ -38,20 +38,20 @@ void unpreferredCost() { } @Test - void parkCost() { - assertEquals(PARKING_COST, subject.parkCost()); + void cost() { + assertEquals(PARKING_COST, subject.cost()); } @Test - void parkTime() { - assertEquals(PARKING_TIME, subject.parkTime()); + void time() { + assertEquals(PARKING_TIME, subject.time()); } @Test void testCopyOfEqualsAndHashCode() { // Create a copy, make a change and set it back again to force creating a new object - var other = subject.copyOf().withParkCost(10).build(); - var same = other.copyOf().withParkCost(PARKING_COST.toSeconds()).build(); + var other = subject.copyOf().withCost(10).build(); + var same = other.copyOf().withCost(PARKING_COST.toSeconds()).build(); assertEqualsAndHashCode(subject, other, same); } @@ -63,8 +63,8 @@ void testToString() { "unpreferredVehicleParkingTagCost: $360, " + "filter: VehicleParkingFilter{not: [tags=[not]], select: [tags=[bar]]}, " + "preferred: VehicleParkingFilter{not: [tags=[bar]], select: [tags=[foo]]}, " + - "parkCost: $240, " + - "parkTime: PT2M}", + "cost: $240, " + + "time: PT2M}", subject.toString() ); } @@ -81,8 +81,8 @@ private VehicleParkingPreferences createPreferences() { .withUnpreferredVehicleParkingTagCost(UNPREFERRED_COST) .withRequiredVehicleParkingTags(REQUIRED_TAGS) .withBannedVehicleParkingTags(BANNED_TAGS) - .withParkCost(PARKING_COST.toSeconds()) - .withParkTime(PARKING_TIME) + .withCost(PARKING_COST.toSeconds()) + .withTime(PARKING_TIME) .build(); } } diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferencesTest.java index 6092c8139bc..1b7068d0cd4 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferencesTest.java @@ -4,8 +4,10 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.opentripplanner.routing.api.request.preference.ImmutablePreferencesAsserts.assertEqualsAndHashCode; +import java.time.Duration; import java.util.Set; import org.junit.jupiter.api.Test; +import org.opentripplanner.framework.model.Cost; class VehicleRentalPreferencesTest { @@ -23,8 +25,8 @@ class VehicleRentalPreferencesTest { .of() .withPickupTime(PICKUP_TIME) .withPickupCost(PICKUP_COST) - .withDropoffTime(DROPOFF_TIME) - .withDropoffCost(DROPOFF_COST) + .withDropOffTime(DROPOFF_TIME) + .withDropOffCost(DROPOFF_COST) .withArrivingInRentalVehicleAtDestinationCost(ARRIVE_IN_RENTAL_COST) .withUseAvailabilityInformation(USE_AVAILABILITY_INFORMATION) .withAllowArrivingInRentedVehicleAtDestination(ALLOW_ARRIVING_IN_RENTED_VEHICLE) @@ -34,22 +36,22 @@ class VehicleRentalPreferencesTest { @Test void pickupTime() { - assertEquals(PICKUP_TIME, subject.pickupTime()); + assertEquals(Duration.ofSeconds(PICKUP_TIME), subject.pickupTime()); } @Test void pickupCost() { - assertEquals(PICKUP_COST, subject.pickupCost()); + assertEquals(Cost.costOfSeconds(PICKUP_COST), subject.pickupCost()); } @Test void dropoffTime() { - assertEquals(DROPOFF_TIME, subject.dropoffTime()); + assertEquals(Duration.ofSeconds(DROPOFF_TIME), subject.dropOffTime()); } @Test void dropoffCost() { - assertEquals(DROPOFF_COST, subject.dropoffCost()); + assertEquals(Cost.costOfSeconds(DROPOFF_COST), subject.dropOffCost()); } @Test @@ -59,7 +61,10 @@ void useAvailabilityInformation() { @Test void arrivingInRentalVehicleAtDestinationCost() { - assertEquals(ARRIVE_IN_RENTAL_COST, subject.arrivingInRentalVehicleAtDestinationCost()); + assertEquals( + Cost.costOfSeconds(ARRIVE_IN_RENTAL_COST), + subject.arrivingInRentalVehicleAtDestinationCost() + ); } @Test @@ -102,10 +107,10 @@ void testToString() { "VehicleRentalPreferences{" + "pickupTime: 25s, " + "pickupCost: $250, " + - "dropoffTime: 45s, " + - "dropoffCost: $450, " + + "dropOffTime: 45s, " + + "dropOffCost: $450, " + "useAvailabilityInformation, " + - "arrivingInRentalVehicleAtDestinationCost: 500.0, " + + "arrivingInRentalVehicleAtDestinationCost: $500, " + "allowArrivingInRentedVehicleAtDestination, " + "allowedNetworks: [foo], " + "bannedNetworks: [bar]" + diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferencesTest.java new file mode 100644 index 00000000000..9571eee8cc5 --- /dev/null +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferencesTest.java @@ -0,0 +1,77 @@ +package org.opentripplanner.routing.api.request.preference; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.routing.api.request.preference.ImmutablePreferencesAsserts.assertEqualsAndHashCode; + +import java.time.Duration; +import org.junit.jupiter.api.Test; +import org.opentripplanner.framework.model.Cost; + +class VehicleWalkingPreferencesTest { + + private static final double SPEED = 1.45; + private static final double RELUCTANCE = 5.5; + private static final Duration HOP_TIME = Duration.ofSeconds(15); + private static final Cost HOP_COST = Cost.costOfSeconds(20); + private static final double STAIRS_RELUCTANCE = 11; + + private final VehicleWalkingPreferences subject = createPreferences(); + + @Test + void speed() { + assertEquals(SPEED, subject.speed()); + } + + @Test + void reluctance() { + assertEquals(RELUCTANCE, subject.reluctance()); + } + + @Test + void hopTime() { + assertEquals(HOP_TIME, subject.hopTime()); + } + + @Test + void hopCost() { + assertEquals(HOP_COST, subject.hopCost()); + } + + @Test + void stairsReluctance() { + assertEquals(STAIRS_RELUCTANCE, subject.stairsReluctance()); + } + + @Test + void testCopyOfEqualsAndHashCode() { + // Create a copy, make a change and set it back again to force creating a new object + var other = subject.copyOf().withSpeed(5.4).build(); + var same = other.copyOf().withSpeed(SPEED).build(); + assertEqualsAndHashCode(subject, other, same); + } + + @Test + void testToString() { + assertEquals("VehicleWalkingPreferences{}", VehicleWalkingPreferences.DEFAULT.toString()); + assertEquals( + "VehicleWalkingPreferences{" + + "speed: 1.45, " + + "reluctance: 5.5, " + + "hopTime: PT15S, " + + "hopCost: $20, " + + "stairsReluctance: 11.0}", + subject.toString() + ); + } + + private VehicleWalkingPreferences createPreferences() { + return VehicleWalkingPreferences + .of() + .withSpeed(SPEED) + .withReluctance(RELUCTANCE) + .withHopTime(HOP_TIME) + .withHopCost(HOP_COST.toSeconds()) + .withStairsReluctance(STAIRS_RELUCTANCE) + .build(); + } +} diff --git a/src/test/java/org/opentripplanner/street/integration/BarrierRoutingTest.java b/src/test/java/org/opentripplanner/street/integration/BarrierRoutingTest.java index e9b979e3b5b..d1ea3c8e59d 100644 --- a/src/test/java/org/opentripplanner/street/integration/BarrierRoutingTest.java +++ b/src/test/java/org/opentripplanner/street/integration/BarrierRoutingTest.java @@ -66,7 +66,10 @@ public void shouldWalkForBarriers() { from, to, BIKE, - rr -> rr.withPreferences(p -> p.withBike(it -> it.withWalkingReluctance(1d))), + rr -> + rr.withPreferences(p -> + p.withBike(it -> it.withWalking(walking -> walking.withReluctance(1d))) + ), itineraries -> itineraries .stream() diff --git a/src/test/java/org/opentripplanner/street/integration/BicycleRoutingTest.java b/src/test/java/org/opentripplanner/street/integration/BicycleRoutingTest.java index 300615269a1..d5b7733f3e8 100644 --- a/src/test/java/org/opentripplanner/street/integration/BicycleRoutingTest.java +++ b/src/test/java/org/opentripplanner/street/integration/BicycleRoutingTest.java @@ -75,7 +75,9 @@ private static String computePolyline(Graph graph, GenericLocation from, Generic request.setDateTime(dateTime); request.setFrom(from); request.setTo(to); - request.withPreferences(p -> p.withBike(it -> it.withOptimizeType(BicycleOptimizeType.QUICK))); + request.withPreferences(p -> + p.withBike(it -> it.withOptimizeType(BicycleOptimizeType.SHORTEST_DURATION)) + ); request.journey().direct().setMode(StreetMode.BIKE); var temporaryVertices = new TemporaryVerticesContainer( diff --git a/src/test/java/org/opentripplanner/street/integration/BikeRentalTest.java b/src/test/java/org/opentripplanner/street/integration/BikeRentalTest.java index 0694a991069..8dc1e240392 100644 --- a/src/test/java/org/opentripplanner/street/integration/BikeRentalTest.java +++ b/src/test/java/org/opentripplanner/street/integration/BikeRentalTest.java @@ -620,7 +620,7 @@ private List runStreetSearchAndCreateDescriptor( request.withPreferences(preferences -> preferences.withBike(bike -> bike.withRental(rental -> - rental.withPickupTime(42).withPickupCost(62).withDropoffCost(33).withDropoffTime(15) + rental.withPickupTime(42).withPickupCost(62).withDropOffCost(33).withDropOffTime(15) ) ) ); diff --git a/src/test/java/org/opentripplanner/street/integration/BikeWalkingTest.java b/src/test/java/org/opentripplanner/street/integration/BikeWalkingTest.java index 66086c6d168..417f1b87347 100644 --- a/src/test/java/org/opentripplanner/street/integration/BikeWalkingTest.java +++ b/src/test/java/org/opentripplanner/street/integration/BikeWalkingTest.java @@ -375,7 +375,7 @@ private List runStreetSearchAndCreateDescriptor( preferences .withWalk(w -> w.withSpeed(10)) .withBike(it -> - it.withSpeed(20d).withWalkingSpeed(5d).withSwitchTime(100).withSwitchCost(1000) + it.withSpeed(20d).withWalking(w -> w.withSpeed(5d).withHopTime(100).withHopCost(1000)) ) ); request.setArriveBy(arriveBy); diff --git a/src/test/java/org/opentripplanner/street/integration/ParkAndRideTest.java b/src/test/java/org/opentripplanner/street/integration/ParkAndRideTest.java index 6dd53ae0c6e..c4f7f52f4ec 100644 --- a/src/test/java/org/opentripplanner/street/integration/ParkAndRideTest.java +++ b/src/test/java/org/opentripplanner/street/integration/ParkAndRideTest.java @@ -142,16 +142,16 @@ protected List runStreetSearchAndCreateDescriptor( b.withParking(parking -> { parking.withRequiredVehicleParkingTags(requiredTags); parking.withBannedVehicleParkingTags(bannedTags); - parking.withParkCost(120); - parking.withParkTime(60); + parking.withCost(120); + parking.withTime(60); }) ) .withCar(c -> c.withParking(parking -> { parking.withRequiredVehicleParkingTags(requiredTags); parking.withBannedVehicleParkingTags(bannedTags); - parking.withParkCost(240); - parking.withParkTime(180); + parking.withCost(240); + parking.withTime(180); }) ) ); diff --git a/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeCostTest.java b/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeCostTest.java index 4712841a8d9..2ecfa51822a 100644 --- a/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeCostTest.java +++ b/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeCostTest.java @@ -159,7 +159,9 @@ public void bikeStairsReluctance(double stairsReluctance, long expectedCost) { .buildAndConnect(); var req = StreetSearchRequest.of(); - req.withPreferences(p -> p.withBike(b -> b.withStairsReluctance(stairsReluctance))); + req.withPreferences(p -> + p.withBike(b -> b.withWalking(w -> w.withStairsReluctance(stairsReluctance))) + ); req.withMode(StreetMode.BIKE); var result = traverse(stairsEdge, req.build()); assertEquals(expectedCost, (long) result.weight); diff --git a/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java b/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java index e131bae1a7a..42d841b9fa3 100644 --- a/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java +++ b/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java @@ -55,7 +55,9 @@ public void before() { references .withStreet(s -> s.withTurnReluctance(1.0)) .withWalk(it -> it.withSpeed(1.0).withReluctance(1.0).withStairsReluctance(1.0)) - .withBike(it -> it.withSpeed(5.0f).withReluctance(1.0).withWalkingSpeed(0.8)) + .withBike(it -> + it.withSpeed(5.0f).withReluctance(1.0).withWalking(w -> w.withSpeed(0.8)) + ) .withCar(c -> c.withSpeed(15.0f).withReluctance(1.0)) ) .build(); @@ -218,7 +220,9 @@ public void testBikeSwitch() { StreetEdge e2 = streetEdge(v2, v0, 0.0, StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE); StreetSearchRequestBuilder noPenalty = StreetSearchRequest.copyOf(proto); - noPenalty.withPreferences(p -> p.withBike(it -> it.withSwitchTime(0).withSwitchCost(0))); + noPenalty.withPreferences(p -> + p.withBike(it -> it.withWalking(w -> w.withHopTime(0).withHopCost(0))) + ); State s0 = new State(v0, noPenalty.withMode(StreetMode.BIKE).build()); State s1 = e0.traverse(s0)[0]; @@ -226,7 +230,9 @@ public void testBikeSwitch() { State s3 = e2.traverse(s2)[0]; StreetSearchRequestBuilder withPenalty = StreetSearchRequest.copyOf(proto); - withPenalty.withPreferences(p -> p.withBike(it -> it.withSwitchTime(42).withSwitchCost(23))); + withPenalty.withPreferences(p -> + p.withBike(it -> it.withWalking(w -> w.withHopTime(42).withHopCost(23))) + ); State s4 = new State(v0, withPenalty.withMode(StreetMode.BIKE).build()); State s5 = e0.traverse(s4)[0]; diff --git a/src/test/java/org/opentripplanner/street/model/edge/StreetVehicleParkingLinkTest.java b/src/test/java/org/opentripplanner/street/model/edge/StreetVehicleParkingLinkTest.java index a9932381b40..a2a052d3b5c 100644 --- a/src/test/java/org/opentripplanner/street/model/edge/StreetVehicleParkingLinkTest.java +++ b/src/test/java/org/opentripplanner/street/model/edge/StreetVehicleParkingLinkTest.java @@ -64,7 +64,7 @@ void foo(Set parkingTags, Set not, Set select, boolean s bike.withParking(parkingPreferences -> { parkingPreferences.withRequiredVehicleParkingTags(select); parkingPreferences.withBannedVehicleParkingTags(not); - parkingPreferences.withParkCost(0); + parkingPreferences.withCost(0); }); }) ); diff --git a/src/test/java/org/opentripplanner/street/model/edge/VehicleParkingPreferredTagsTest.java b/src/test/java/org/opentripplanner/street/model/edge/VehicleParkingPreferredTagsTest.java index 41ecbe162bb..5969121b6d6 100644 --- a/src/test/java/org/opentripplanner/street/model/edge/VehicleParkingPreferredTagsTest.java +++ b/src/test/java/org/opentripplanner/street/model/edge/VehicleParkingPreferredTagsTest.java @@ -88,7 +88,7 @@ private void runTest( bike.withParking(parkingPreferences -> { parkingPreferences.withUnpreferredVehicleParkingTagCost(EXTRA_COST); parkingPreferences.withPreferredVehicleParkingTags(preferredTags); - parkingPreferences.withParkCost(0); + parkingPreferences.withCost(0); }); }) ); diff --git a/src/test/resources/standalone/config/router-config.json b/src/test/resources/standalone/config/router-config.json index 5abb5ef87a6..863b9bec279 100644 --- a/src/test/resources/standalone/config/router-config.json +++ b/src/test/resources/standalone/config/router-config.json @@ -12,34 +12,59 @@ ] }, "routingDefaults": { - "walkSpeed": 1.3, - "bikeSpeed": 5, - "carSpeed": 40, "numItineraries": 12, "transferPenalty": 0, - "walkReluctance": 4.0, - "bikeReluctance": 5.0, - "bikeWalkingReluctance": 10.0, - "bikeStairsReluctance": 150.0, - "carReluctance": 10.0, - "stairsReluctance": 1.65, "turnReluctance": 1.0, "elevatorBoardTime": 90, "elevatorBoardCost": 90, "elevatorHopTime": 20, "elevatorHopCost": 20, - "escalatorReluctance": 1.5, - "vehicleRental": { - "pickupCost": 120, - "dropOffTime": 30, - "dropOffCost": 30 + "bicycle": { + "speed": 5, + "reluctance": 5.0, + "boardCost": 600, + "walk": { + "reluctance": 10.0, + "stairsReluctance": 150.0 + }, + "rental": { + "pickupCost": 120, + "dropOffTime": "30s", + "dropOffCost": 30 + }, + "parking": { + "time": "1m", + "cost": 120 + }, + "triangle": { + "safety": 0.4, + "flatness": 0.3, + "time": 0.3 + } + }, + "car": { + "speed": 40, + "reluctance": 10, + "decelerationSpeed": 2.9, + "accelerationSpeed": 2.9, + "rental": { + "pickupCost": 120, + "dropOffTime": "30s", + "dropOffCost": 30 + }, + "parking": { + "time": "5m", + "cost": 600 + } + }, + "walk": { + "speed": 1.3, + "reluctance": 4.0, + "stairsReluctance": 1.65, + "boardCost": 600, + "escalatorReluctance": 1.5 }, - "bikeParkTime": "1m", - "bikeParkCost": 120, - "carDropoffTime": 120, "waitReluctance": 1.0, - "walkBoardCost": 600, - "bikeBoardCost": 600, "otherThanPreferredRoutesPenalty": 300, "transferSlack": 120, // Default slack for any mode is 0 (zero) @@ -74,8 +99,6 @@ "minBikeParkingDistance": 300, "debug": "limit-to-search-window" }, - "carDecelerationSpeed": 2.9, - "carAccelerationSpeed": 2.9, "ignoreRealtimeUpdates": false, "geoidElevation": false, "maxJourneyDuration": "36h", diff --git a/test/performance/norway/speed-test-config.json b/test/performance/norway/speed-test-config.json index e673155eb4f..e4ca99d7fe5 100644 --- a/test/performance/norway/speed-test-config.json +++ b/test/performance/norway/speed-test-config.json @@ -39,13 +39,17 @@ } }, "routingDefaults": { - // Default is 1.4 m/s = ~ 5.0 km/t - "walkSpeed": 1.4, - // Should not be used - a high cost indicate an error - "bikeBoardCost": 222000, - "walkBoardCost": 600, + "bicycle": { + // Should not be used - a high cost indicate an error + "boardCost": 222000 + }, + "walk": { + // Default is 1.4 m/s = ~ 5.0 km/t + "speed": 1.4, + "boardCost": 600, + "reluctance": 4.0 + }, "transferPenalty": 0, - "walkReluctance": 4.0, "waitReluctance": 1.0, "boardSlack": "30s", "alightSlack": "15s", diff --git a/test/performance/skanetrafiken/speed-test-config.json b/test/performance/skanetrafiken/speed-test-config.json index a43cc97095d..66184ab124f 100644 --- a/test/performance/skanetrafiken/speed-test-config.json +++ b/test/performance/skanetrafiken/speed-test-config.json @@ -15,10 +15,12 @@ } }, "routingDefaults": { - "walkSpeed": 1.38, + "walk": { + "speed": 1.38, + "reluctance": 5 + }, "transferSlack": 180, "waitReluctance": 0.175, - "walkReluctance": 5, "maxDirectStreetDuration": "1h1m", "boardSlackForMode": { "RAIL": "12m" diff --git a/test/performance/switzerland/speed-test-config.json b/test/performance/switzerland/speed-test-config.json index f37c8497ffa..19ac7a1358a 100644 --- a/test/performance/switzerland/speed-test-config.json +++ b/test/performance/switzerland/speed-test-config.json @@ -39,13 +39,17 @@ } }, "routingDefaults": { - // Default is 1.4 m/s = ~ 5.0 km/t - "walkSpeed": 1.4, - // Should not be used - a high cost indicate an error - "bikeBoardCost": 222000, - "walkBoardCost": 600, + "bicycle": { + // Should not be used - a high cost indicate an error + "boardCost": 222000 + }, + "walk": { + // Default is 1.4 m/s = ~ 5.0 km/t + "speed": 1.4, + "boardCost": 600, + "reluctance": 4.0 + }, "transferPenalty": 0, - "walkReluctance": 4.0, "waitReluctance": 1.0, "boardSlack": "30s", "alightSlack": "15s",