From 46789847a7536fde285a51b805e5da30d64d5922 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 13 Jul 2020 15:17:14 -0700 Subject: [PATCH] offstreet parking blocks the road for less time. seeing unrealistic gridlock near the huge parking lots downtown from this and fix a bug with spawning bike trips. never OK to silently not schedule a trip, because it breaks the schedule continuity --- data/MANIFEST.txt | 8 ++--- sim/src/make/spawner.rs | 63 +++++++++++++++++++++--------------- sim/src/mechanics/driving.rs | 31 ++++++++++++------ 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/data/MANIFEST.txt b/data/MANIFEST.txt index 8f63d8018a..a0537067f6 100644 --- a/data/MANIFEST.txt +++ b/data/MANIFEST.txt @@ -28,7 +28,7 @@ data/input/seattle/osm/south_seattle.osm,856ba9af0751432d40f51c0bec8a1664,https: data/input/seattle/osm/udistrict.osm,184c269bd39ac6d475c1d31b01af824f,https://www.dropbox.com/s/35pu17pckr55p74/udistrict.osm.zip?dl=0 data/input/seattle/osm/washington-latest.osm.pbf,0db475bae90a383273865215f5b61f15,https://www.dropbox.com/s/lowvuydkyypnjwi/washington-latest.osm.pbf.zip?dl=0 data/input/seattle/osm/west_seattle.osm,924178166c37e2cc6c284783d27be459,https://www.dropbox.com/s/nkq6xr8jhqk5k9z/west_seattle.osm.zip?dl=0 -data/input/seattle/parcels.bin,05bf59748e15bd4e0c01cc483202a66e,https://www.dropbox.com/s/f1oen08kjcisd72/parcels.bin.zip?dl=0 +data/input/seattle/parcels.bin,58c55a6e18ff3c5e08fa719006b6edf6,https://www.dropbox.com/s/hxc1dbtfpsu6203/parcels.bin.zip?dl=0 data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0 data/input/seattle/popdat.bin,ad38e1f20ce71f488112fe81e32798d2,https://www.dropbox.com/s/ajqii1qpfke8063/popdat.bin.zip?dl=0 data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0 @@ -42,9 +42,9 @@ data/system/maps/montlake.bin,04faf98ee6e6e40998b46d6dffd71288,https://www.dropb data/system/maps/south_seattle.bin,d838a10b4f6c3214d9c5764c65b523e3,https://www.dropbox.com/s/2xc7jtauefi08tk/south_seattle.bin.zip?dl=0 data/system/maps/udistrict.bin,864459a858f573f95937a82080278804,https://www.dropbox.com/s/m8quryc6n0ffo3j/udistrict.bin.zip?dl=0 data/system/maps/west_seattle.bin,75f3395beeb04bd477faf2c2efdc017e,https://www.dropbox.com/s/wlg18qsw9sewkji/west_seattle.bin.zip?dl=0 -data/system/prebaked_results/lakeslice/weekday.bin,534210d60f264979db9c62e83579bd0e,https://www.dropbox.com/s/5rtozd7zq15a0js/weekday.bin.zip?dl=0 -data/system/prebaked_results/montlake/car vs bike contention.bin,bd7bbdee559245ed5dd85ddd67165cf9,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0 -data/system/prebaked_results/montlake/weekday.bin,0cd2262ffebad7f90a001b094a6f5013,https://www.dropbox.com/s/fuqlnv4x6apoeyz/weekday.bin.zip?dl=0 +data/system/prebaked_results/lakeslice/weekday.bin,98964dbbbbb2aaeed77282e6992de60d,https://www.dropbox.com/s/hv1ivrprca3mqeo/weekday.bin.zip?dl=0 +data/system/prebaked_results/montlake/car vs bike contention.bin,1fac82d6dcd567874fd6e0b106956dd9,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0 +data/system/prebaked_results/montlake/weekday.bin,1d8387378fd321631e07351252414768,https://www.dropbox.com/s/z2vuz7tmzvzjkbi/weekday.bin.zip?dl=0 data/system/scenarios/ballard/weekday.bin,5cdb49cad879654f2e070892b6410b6d,https://www.dropbox.com/s/m73hrfjq0vf1n16/weekday.bin.zip?dl=0 data/system/scenarios/downtown/weekday.bin,fa7c46540dbc31f1c5393e7c8b0a7a78,https://www.dropbox.com/s/1gm7tq7uhllkclo/weekday.bin.zip?dl=0 data/system/scenarios/huge_seattle/weekday.bin,f0887cf1c2e5fbfbc0453cd33440b7fa,https://www.dropbox.com/s/4xm3d7s167cyw75/weekday.bin.zip?dl=0 diff --git a/sim/src/make/spawner.rs b/sim/src/make/spawner.rs index 7a77f8c902..23c8fffd4f 100644 --- a/sim/src/make/spawner.rs +++ b/sim/src/make/spawner.rs @@ -74,7 +74,7 @@ impl TripSpawner { &mut self, person: &Person, start_time: Time, - spec: TripSpec, + mut spec: TripSpec, trip_start: TripEndpoint, cancelled: bool, map: &Map, @@ -128,16 +128,37 @@ impl TripSpawner { } } TripSpec::UsingBike { start, goal, .. } => { - // TODO These trips are just silently erased; they don't even show up as aborted - // trips! Really need to fix the underlying problem. + // TODO Might not be possible to walk to the same border if there's no sidewalk + let backup_plan = match goal { + DrivingGoal::ParkNear(b) => Some(TripSpec::JustWalking { + start: start.clone(), + goal: SidewalkSpot::building(*b, map), + }), + DrivingGoal::Border(i, _, off_map) => { + SidewalkSpot::end_at_border(*i, off_map.clone(), map).map(|goal| { + TripSpec::JustWalking { + start: start.clone(), + goal, + } + }) + } + }; + if SidewalkSpot::bike_from_bike_rack(start.sidewalk_pos.lane(), map).is_none() { - println!( - "Can't start biking from {}; no biking or driving lane nearby?", - start.sidewalk_pos.lane() - ); - return; - } - if let DrivingGoal::ParkNear(b) = goal { + if backup_plan.is_some() { + println!( + "Can't start biking from {}; no biking or driving lane nearby? \ + Walking instead", + start.sidewalk_pos.lane() + ); + spec = backup_plan.unwrap(); + } else { + panic!( + "Can't start biking from {}; no biking or driving lane nearby?", + start.sidewalk_pos.lane() + ); + } + } else if let DrivingGoal::ParkNear(b) = goal { let last_lane = goal.goal_pos(PathConstraints::Bike, map).lane(); // If bike_to_sidewalk works, then SidewalkSpot::bike_rack should too. if map @@ -146,28 +167,18 @@ impl TripSpawner { .is_none() { println!( - "Can't fulfill {:?} for a bike trip; no sidewalk near {}", + "Can't fulfill {:?} for a bike trip; no sidewalk near {}. Walking \ + instead.", goal, last_lane ); - return; - } - // A bike trip going from one lane to the same lane should... just walk. - if start.sidewalk_pos.lane() == map.get_b(*b).sidewalk() { + spec = backup_plan.unwrap(); + } else if start.sidewalk_pos.lane() == map.get_b(*b).sidewalk() { + // A bike trip going from one lane to the same lane should... just walk. println!( "Bike trip from {:?} to {:?} will just walk; it's the same sidewalk!", start, goal ); - self.trips.push(( - person.id, - start_time, - TripSpec::JustWalking { - start: start.clone(), - goal: SidewalkSpot::building(*b, map), - }, - trip_start, - cancelled, - )); - return; + spec = backup_plan.unwrap(); } } } diff --git a/sim/src/mechanics/driving.rs b/sim/src/mechanics/driving.rs index 4d73083be9..e87fef37ed 100644 --- a/sim/src/mechanics/driving.rs +++ b/sim/src/mechanics/driving.rs @@ -2,8 +2,8 @@ use crate::mechanics::car::{Car, CarState}; use crate::mechanics::Queue; use crate::{ ActionAtEnd, AgentID, AgentProperties, CarID, Command, CreateCar, DistanceInterval, - DrawCarInput, Event, IntersectionSimState, ParkedCar, ParkingSimState, PersonID, Scheduler, - TimeInterval, TransitSimState, TripManager, UnzoomedAgent, Vehicle, VehicleType, + DrawCarInput, Event, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, PersonID, + Scheduler, TimeInterval, TransitSimState, TripManager, UnzoomedAgent, Vehicle, VehicleType, WalkingSimState, FOLLOWING_DISTANCE, }; use abstutil::{deserialize_btreemap, serialize_btreemap}; @@ -12,8 +12,10 @@ use map_model::{LaneID, Map, Path, PathStep, Traversable}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashSet, VecDeque}; -const TIME_TO_UNPARK: Duration = Duration::const_seconds(10.0); -const TIME_TO_PARK: Duration = Duration::const_seconds(15.0); +const TIME_TO_UNPARK_ONSTRET: Duration = Duration::const_seconds(10.0); +const TIME_TO_PARK_ONSTREET: Duration = Duration::const_seconds(15.0); +const TIME_TO_UNPARK_OFFSTREET: Duration = Duration::const_seconds(5.0); +const TIME_TO_PARK_OFFSTREET: Duration = Duration::const_seconds(5.0); const TIME_TO_WAIT_AT_STOP: Duration = Duration::const_seconds(10.0); // TODO Do something else. @@ -95,10 +97,16 @@ impl DrivingSimState { trip_and_person: params.trip_and_person, }; if let Some(p) = params.maybe_parked_car { + let delay = match p.spot { + ParkingSpot::Onstreet(_, _) => TIME_TO_UNPARK_ONSTRET, + ParkingSpot::Offstreet(_, _) | ParkingSpot::Lot(_, _) => { + TIME_TO_UNPARK_OFFSTREET + } + }; car.state = CarState::Unparking( params.start_dist, p.spot, - TimeInterval::new(now, now + TIME_TO_UNPARK), + TimeInterval::new(now, now + delay), ); } else { // Have to do this early @@ -461,11 +469,14 @@ impl DrivingSimState { } Some(ActionAtEnd::StartParking(spot)) => { car.total_blocked_time += now - blocked_since; - car.state = CarState::Parking( - our_dist, - spot, - TimeInterval::new(now, now + TIME_TO_PARK), - ); + let delay = match spot { + ParkingSpot::Onstreet(_, _) => TIME_TO_PARK_ONSTREET, + ParkingSpot::Offstreet(_, _) | ParkingSpot::Lot(_, _) => { + TIME_TO_PARK_OFFSTREET + } + }; + car.state = + CarState::Parking(our_dist, spot, TimeInterval::new(now, now + delay)); // If we don't do this, then we might have another car creep up // behind, see the spot free, and start parking too. This can // happen with multiple lanes and certain vehicle lengths.