sim/mechanics/
parking.rs

1use std::collections::{hash_map::Entry, BTreeMap, BTreeSet, BinaryHeap, HashMap};
2
3use enum_dispatch::enum_dispatch;
4use rand::{Rng, SeedableRng};
5use rand_xorshift::XorShiftRng;
6use serde::{Deserialize, Serialize};
7
8use abstutil::{
9    deserialize_btreemap, deserialize_multimap, serialize_btreemap, serialize_multimap, MultiMap,
10    Timer,
11};
12use geom::{Distance, PolyLine, Pt2D};
13use map_model::{
14    BuildingID, Lane, LaneID, LaneType, Map, OffstreetParking, ParkingLotID, PathConstraints,
15    PathStep, Position, Traversable, TurnID,
16};
17
18use crate::{CarID, CarStatus, DrawCarInput, Event, ParkedCar, ParkingSpot, PersonID, Vehicle};
19
20/// Manages the state of parked cars. There are two implementations:
21/// - NormalParkingSimState allows only one vehicle per ParkingSpot defined in the map
22/// - InfiniteParkingSimState pretends every building has infinite capacity, and onstreet parking is
23///   ignored
24#[enum_dispatch(ParkingSimState)]
25pub trait ParkingSim {
26    /// Returns any cars that got very abruptly evicted from existence, and also cars actively
27    /// moving into a deleted spot.
28    fn handle_live_edits(&mut self, map: &Map, timer: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>);
29    fn get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot>;
30    fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot>;
31    fn get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot>;
32    fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID);
33    /// Needed when abruptly deleting a car, in case they're being deleted during their last step.
34    fn unreserve_spot(&mut self, car: CarID);
35    fn remove_parked_car(&mut self, p: ParkedCar);
36    fn add_parked_car(&mut self, p: ParkedCar);
37    fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput>;
38    fn get_draw_cars_in_lots(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput>;
39    fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>;
40    /// There's no DrawCarInput for cars parked offstreet, so we need this.
41    fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D>;
42    fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput>;
43    fn is_free(&self, spot: ParkingSpot) -> bool;
44    fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar>;
45    /// The vehicle's front is currently at the given driving_pos. Returns all valid spots and their
46    /// driving position.
47    fn get_all_free_spots(
48        &self,
49        driving_pos: Position,
50        vehicle: &Vehicle,
51        // Either the building where a seeded car starts or the target of a trip. For filtering
52        // private spots.
53        target: BuildingID,
54        map: &Map,
55    ) -> Vec<(ParkingSpot, Position)>;
56    fn spot_to_driving_pos(&self, spot: ParkingSpot, vehicle: &Vehicle, map: &Map) -> Position;
57    fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position;
58    fn get_owner_of_car(&self, id: CarID) -> Option<PersonID>;
59    fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar>;
60    /// (Filled, available)
61    fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>);
62    /// Unrealistically assumes the driver has knowledge of currently free parking spots, even if
63    /// they're far away. Since they don't reserve the spot in advance, somebody else can still beat
64    /// them there, producing some nice, realistic churn if there's too much contention. But
65    /// the implementation has some internal jitter between different vehicles, to discourage
66    /// everybody near one spot from all competing for it.
67    /// Note the first PathStep is the turn after start, NOT PathStep::Lane(start).
68    fn path_to_free_parking_spot(
69        &self,
70        start: LaneID,
71        vehicle: &Vehicle,
72        target: BuildingID,
73        map: &Map,
74    ) -> Option<(Vec<PathStep>, ParkingSpot, Position)>;
75    fn collect_events(&mut self) -> Vec<Event>;
76    fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)>;
77    fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID>;
78}
79
80#[enum_dispatch]
81#[derive(Serialize, Deserialize, Clone)]
82pub enum ParkingSimState {
83    Normal(NormalParkingSimState),
84    Infinite(InfiniteParkingSimState),
85}
86
87impl ParkingSimState {
88    /// Counterintuitive: any spots located in blackholes are just not represented here. If somebody
89    /// tries to drive from a blackholed spot, they couldn't reach most places.
90    pub fn new(map: &Map, infinite: bool, timer: &mut Timer) -> ParkingSimState {
91        if infinite {
92            ParkingSimState::Infinite(InfiniteParkingSimState::new(map))
93        } else {
94            ParkingSimState::Normal(NormalParkingSimState::new(map, timer))
95        }
96    }
97
98    pub fn is_infinite(&self) -> bool {
99        match self {
100            ParkingSimState::Normal(_) => false,
101            ParkingSimState::Infinite(_) => true,
102        }
103    }
104}
105
106#[derive(Serialize, Deserialize, Clone)]
107pub struct NormalParkingSimState {
108    #[serde(
109        serialize_with = "serialize_btreemap",
110        deserialize_with = "deserialize_btreemap"
111    )]
112    parked_cars: BTreeMap<CarID, ParkedCar>,
113    #[serde(
114        serialize_with = "serialize_btreemap",
115        deserialize_with = "deserialize_btreemap"
116    )]
117    occupants: BTreeMap<ParkingSpot, CarID>,
118    #[serde(
119        serialize_with = "serialize_btreemap",
120        deserialize_with = "deserialize_btreemap"
121    )]
122    reserved_spots: BTreeMap<ParkingSpot, CarID>,
123
124    // On-street
125    onstreet_lanes: BTreeMap<LaneID, ParkingLane>,
126    // TODO Really this could be 0, 1, or 2 lanes. Full MultiMap is overkill.
127    #[serde(
128        serialize_with = "serialize_multimap",
129        deserialize_with = "deserialize_multimap"
130    )]
131    driving_to_parking_lanes: MultiMap<LaneID, LaneID>,
132
133    // Off-street
134    num_spots_per_offstreet: BTreeMap<BuildingID, usize>,
135    // Cache dist_along
136    #[serde(
137        serialize_with = "serialize_multimap",
138        deserialize_with = "deserialize_multimap"
139    )]
140    driving_to_offstreet: MultiMap<LaneID, (BuildingID, Distance)>,
141
142    // Parking lots
143    num_spots_per_lot: BTreeMap<ParkingLotID, usize>,
144    #[serde(
145        serialize_with = "serialize_multimap",
146        deserialize_with = "deserialize_multimap"
147    )]
148    driving_to_lots: MultiMap<LaneID, ParkingLotID>,
149
150    events: Vec<Event>,
151}
152
153impl NormalParkingSimState {
154    fn new(map: &Map, timer: &mut Timer) -> NormalParkingSimState {
155        let mut sim = NormalParkingSimState {
156            parked_cars: BTreeMap::new(),
157            occupants: BTreeMap::new(),
158            reserved_spots: BTreeMap::new(),
159
160            onstreet_lanes: BTreeMap::new(),
161            driving_to_parking_lanes: MultiMap::new(),
162            num_spots_per_offstreet: BTreeMap::new(),
163            driving_to_offstreet: MultiMap::new(),
164            num_spots_per_lot: BTreeMap::new(),
165            driving_to_lots: MultiMap::new(),
166
167            events: Vec::new(),
168        };
169        for l in map.all_lanes() {
170            if let Some(lane) = ParkingLane::new(l, map) {
171                sim.driving_to_parking_lanes.insert(lane.driving_lane, l.id);
172                sim.onstreet_lanes.insert(lane.parking_lane, lane);
173            }
174        }
175        // This is slow on huge maps
176        for (b, pos, num_spots) in timer
177            .parallelize(
178                "setup offstreet parking",
179                map.all_buildings().iter().collect(),
180                |b| {
181                    if let Some((pos, _)) = b.driving_connection(map) {
182                        if !map.get_l(pos.lane()).driving_blackhole {
183                            let num_spots = b.num_parking_spots();
184                            if num_spots > 0 {
185                                Some((b.id, pos, num_spots))
186                            } else {
187                                None
188                            }
189                        } else {
190                            None
191                        }
192                    } else {
193                        None
194                    }
195                },
196            )
197            .into_iter()
198            .flatten()
199        {
200            sim.num_spots_per_offstreet.insert(b, num_spots);
201            sim.driving_to_offstreet
202                .insert(pos.lane(), (b, pos.dist_along()));
203        }
204
205        for pl in map.all_parking_lots() {
206            if !map.get_l(pl.driving_pos.lane()).driving_blackhole {
207                sim.num_spots_per_lot.insert(pl.id, pl.capacity());
208                sim.driving_to_lots.insert(pl.driving_pos.lane(), pl.id);
209            }
210        }
211
212        sim
213    }
214}
215
216impl ParkingSim for NormalParkingSimState {
217    fn handle_live_edits(&mut self, map: &Map, timer: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>) {
218        let (filled_before, _) = self.get_all_parking_spots();
219        let new = NormalParkingSimState::new(map, timer);
220        let (_, avail_after) = new.get_all_parking_spots();
221        let avail_after: BTreeSet<ParkingSpot> = avail_after.into_iter().collect();
222
223        // Use the new spots
224        self.onstreet_lanes = new.onstreet_lanes;
225        self.driving_to_parking_lanes = new.driving_to_parking_lanes;
226        self.num_spots_per_offstreet = new.num_spots_per_offstreet;
227        self.driving_to_offstreet = new.driving_to_offstreet;
228        self.num_spots_per_lot = new.num_spots_per_lot;
229        self.driving_to_lots = new.driving_to_lots;
230
231        // For every spot filled or reserved before, make sure that same spot still exists. If not,
232        // evict that car.
233        let mut evicted = Vec::new();
234        for spot in filled_before {
235            if !avail_after.contains(&spot) {
236                // If the spot isn't occupied, it must be reserved; a car is in the process of
237                // parking in it. That'll be handled below.
238                if let Some(car) = self.occupants.remove(&spot) {
239                    evicted.push(self.parked_cars.remove(&car).unwrap());
240                }
241            }
242        }
243
244        let mut moving_into_deleted_spot = Vec::new();
245        self.reserved_spots.retain(|spot, car| {
246            if avail_after.contains(spot) {
247                true
248            } else {
249                moving_into_deleted_spot.push(*car);
250                false
251            }
252        });
253
254        (evicted, moving_into_deleted_spot)
255    }
256
257    fn get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
258        let mut spots: Vec<ParkingSpot> = Vec::new();
259        if let Some(lane) = self.onstreet_lanes.get(&l) {
260            for spot in lane.spots() {
261                if self.is_free(spot) {
262                    spots.push(spot);
263                }
264            }
265        }
266        spots
267    }
268
269    fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot> {
270        let mut spots: Vec<ParkingSpot> = Vec::new();
271        for idx in 0..self.num_spots_per_offstreet.get(&b).cloned().unwrap_or(0) {
272            let spot = ParkingSpot::Offstreet(b, idx);
273            if self.is_free(spot) {
274                spots.push(spot);
275            }
276        }
277        spots
278    }
279
280    fn get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot> {
281        let mut spots: Vec<ParkingSpot> = Vec::new();
282        for idx in 0..self.num_spots_per_lot.get(&pl).cloned().unwrap_or(0) {
283            let spot = ParkingSpot::Lot(pl, idx);
284            if self.is_free(spot) {
285                spots.push(spot);
286            }
287        }
288        spots
289    }
290
291    fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID) {
292        assert!(self.is_free(spot));
293        self.reserved_spots.insert(spot, car);
294
295        // Sanity check the spot exists
296        match spot {
297            ParkingSpot::Onstreet(l, idx) => {
298                assert!(idx < self.onstreet_lanes[&l].spot_dist_along.len());
299            }
300            ParkingSpot::Offstreet(b, idx) => {
301                assert!(idx < self.num_spots_per_offstreet[&b]);
302            }
303            ParkingSpot::Lot(pl, idx) => {
304                assert!(idx < self.num_spots_per_lot[&pl]);
305            }
306        }
307    }
308
309    fn unreserve_spot(&mut self, car: CarID) {
310        self.reserved_spots.retain(|_, c| car != *c);
311    }
312
313    fn remove_parked_car(&mut self, p: ParkedCar) {
314        if self.parked_cars.remove(&p.vehicle.id).is_none() {
315            panic!("remove_parked_car {:?} missing from parked_cars", p);
316        }
317        if self.occupants.remove(&p.spot).is_none() {
318            panic!("remove_parked_car {:?} missing from occupants", p);
319        }
320        self.events
321            .push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot));
322    }
323
324    fn add_parked_car(&mut self, p: ParkedCar) {
325        self.events
326            .push(Event::CarReachedParkingSpot(p.vehicle.id, p.spot));
327
328        assert_eq!(self.reserved_spots.remove(&p.spot), Some(p.vehicle.id));
329
330        assert!(!self.occupants.contains_key(&p.spot));
331        self.occupants.insert(p.spot, p.vehicle.id);
332
333        assert!(!self.parked_cars.contains_key(&p.vehicle.id));
334        self.parked_cars.insert(p.vehicle.id, p);
335    }
336
337    fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> {
338        let mut cars = Vec::new();
339        if let Some(lane) = self.onstreet_lanes.get(&id) {
340            for spot in lane.spots() {
341                if let Some(car) = self.occupants.get(&spot) {
342                    cars.push(self.get_draw_car(*car, map).unwrap());
343                }
344            }
345        }
346        cars
347    }
348
349    fn get_draw_cars_in_lots(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> {
350        let mut cars = Vec::new();
351        for pl in self.driving_to_lots.get(id) {
352            for idx in 0..self.num_spots_per_lot[pl] {
353                if let Some(car) = self.occupants.get(&ParkingSpot::Lot(*pl, idx)) {
354                    if let Some(d) = self.get_draw_car(*car, map) {
355                        cars.push(d);
356                    }
357                }
358            }
359        }
360        cars
361    }
362
363    fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
364        let p = self.parked_cars.get(&id)?;
365        match p.spot {
366            ParkingSpot::Onstreet(lane, idx) => {
367                let front_dist =
368                    self.onstreet_lanes[&lane].dist_along_for_car(idx, &p.vehicle, map);
369                Some(DrawCarInput {
370                    id: p.vehicle.id,
371                    waiting_for_turn: None,
372                    status: CarStatus::Parked,
373                    intent: None,
374                    on: Traversable::Lane(lane),
375                    partly_on: Vec::new(),
376                    label: None,
377                    person: None,
378
379                    body: map
380                        .get_l(lane)
381                        .lane_center_pts
382                        .exact_slice(front_dist - p.vehicle.length, front_dist),
383                })
384            }
385            ParkingSpot::Offstreet(_, _) => None,
386            ParkingSpot::Lot(pl, idx) => {
387                let pl = map.get_pl(pl);
388                // Some cars might be in the unrenderable extra_spots.
389                let (pt, angle) = pl.spots.get(idx)?;
390                let buffer = Distance::meters(0.5);
391                Some(DrawCarInput {
392                    id: p.vehicle.id,
393                    waiting_for_turn: None,
394                    status: CarStatus::Parked,
395                    intent: None,
396                    // Just used for z-order
397                    on: Traversable::Lane(pl.driving_pos.lane()),
398                    partly_on: Vec::new(),
399                    label: None,
400                    person: None,
401
402                    body: PolyLine::must_new(vec![
403                        pt.project_away(buffer, *angle),
404                        pt.project_away(map_model::PARKING_LOT_SPOT_LENGTH - buffer, *angle),
405                    ]),
406                })
407            }
408        }
409    }
410
411    fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D> {
412        let p = self.parked_cars.get(&id)?;
413        match p.spot {
414            ParkingSpot::Onstreet(_, _) => Some(self.get_draw_car(id, map).unwrap().body.last_pt()),
415            ParkingSpot::Lot(pl, _) => {
416                if let Some(car) = self.get_draw_car(id, map) {
417                    Some(car.body.last_pt())
418                } else {
419                    Some(map.get_pl(pl).polygon.center())
420                }
421            }
422            ParkingSpot::Offstreet(b, _) => Some(map.get_b(b).label_center),
423        }
424    }
425
426    fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
427        self.parked_cars
428            .keys()
429            .filter_map(|id| self.get_draw_car(*id, map))
430            .collect()
431    }
432
433    fn is_free(&self, spot: ParkingSpot) -> bool {
434        !self.occupants.contains_key(&spot) && !self.reserved_spots.contains_key(&spot)
435    }
436
437    fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar> {
438        let car = self.occupants.get(&spot)?;
439        Some(&self.parked_cars[car])
440    }
441
442    fn get_all_free_spots(
443        &self,
444        driving_pos: Position,
445        vehicle: &Vehicle,
446        // Either the building where a seeded car starts or the target of a trip. For filtering
447        // private spots.
448        target: BuildingID,
449        map: &Map,
450    ) -> Vec<(ParkingSpot, Position)> {
451        let mut candidates = Vec::new();
452
453        for l in self.driving_to_parking_lanes.get(driving_pos.lane()) {
454            for spot in self.onstreet_lanes[l].spots() {
455                if self.is_free(spot)
456                    && driving_pos.dist_along()
457                        <= self.spot_to_driving_pos(spot, vehicle, map).dist_along()
458                {
459                    candidates.push(spot);
460                }
461            }
462        }
463
464        for (b, bldg_dist) in self.driving_to_offstreet.get(driving_pos.lane()) {
465            if let OffstreetParking::Private(_, _) = map.get_b(*b).parking {
466                if target != *b {
467                    continue;
468                }
469            }
470            if driving_pos.dist_along() < *bldg_dist {
471                for idx in 0..self.num_spots_per_offstreet[b] {
472                    let spot = ParkingSpot::Offstreet(*b, idx);
473                    if self.is_free(spot) {
474                        candidates.push(spot);
475                    }
476                }
477            }
478        }
479
480        for pl in self.driving_to_lots.get(driving_pos.lane()) {
481            let lot_dist = map.get_pl(*pl).driving_pos.dist_along();
482            if driving_pos.dist_along() < lot_dist {
483                for idx in 0..self.num_spots_per_lot[pl] {
484                    let spot = ParkingSpot::Lot(*pl, idx);
485                    if self.is_free(spot) {
486                        candidates.push(spot);
487                    }
488                }
489            }
490        }
491
492        candidates
493            .into_iter()
494            .map(|spot| (spot, self.spot_to_driving_pos(spot, vehicle, map)))
495            .collect()
496    }
497
498    fn spot_to_driving_pos(&self, spot: ParkingSpot, vehicle: &Vehicle, map: &Map) -> Position {
499        match spot {
500            ParkingSpot::Onstreet(l, idx) => {
501                let lane = &self.onstreet_lanes[&l];
502                Position::new(l, lane.dist_along_for_car(idx, vehicle, map))
503                    .equiv_pos_for_long_object(lane.driving_lane, vehicle.length, map)
504            }
505            ParkingSpot::Offstreet(b, _) => map.get_b(b).driving_connection(map).unwrap().0,
506            ParkingSpot::Lot(pl, _) => map.get_pl(pl).driving_pos,
507        }
508    }
509
510    fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position {
511        match spot {
512            ParkingSpot::Onstreet(l, idx) => {
513                let lane = &self.onstreet_lanes[&l];
514                // Always centered in the entire parking spot
515                Position::new(
516                    l,
517                    lane.spot_dist_along[idx] - (map.get_config().street_parking_spot_length / 2.0),
518                )
519                .equiv_pos(lane.sidewalk, map)
520            }
521            ParkingSpot::Offstreet(b, _) => map.get_b(b).sidewalk_pos,
522            ParkingSpot::Lot(pl, _) => map.get_pl(pl).sidewalk_pos,
523        }
524    }
525
526    fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
527        self.parked_cars.get(&id).and_then(|p| p.vehicle.owner)
528    }
529    fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
530        self.parked_cars.get(&id)
531    }
532
533    fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
534        let mut spots = Vec::new();
535        for lane in self.onstreet_lanes.values() {
536            spots.extend(lane.spots());
537        }
538        for (b, num_spots) in &self.num_spots_per_offstreet {
539            for idx in 0..*num_spots {
540                spots.push(ParkingSpot::Offstreet(*b, idx));
541            }
542        }
543        for (pl, num_spots) in &self.num_spots_per_lot {
544            for idx in 0..*num_spots {
545                spots.push(ParkingSpot::Lot(*pl, idx));
546            }
547        }
548
549        let mut filled = Vec::new();
550        let mut available = Vec::new();
551        for spot in spots {
552            if self.is_free(spot) {
553                available.push(spot);
554            } else {
555                filled.push(spot);
556            }
557        }
558        (filled, available)
559    }
560
561    fn path_to_free_parking_spot(
562        &self,
563        start: LaneID,
564        vehicle: &Vehicle,
565        target: BuildingID,
566        map: &Map,
567    ) -> Option<(Vec<PathStep>, ParkingSpot, Position)> {
568        let mut backrefs: HashMap<LaneID, TurnID> = HashMap::new();
569        // Don't travel far.
570        // This is a max-heap, so negate all distances. Tie breaker is lane ID, arbitrary but
571        // deterministic.
572        let mut queue: BinaryHeap<(Distance, LaneID)> = BinaryHeap::new();
573        queue.push((Distance::ZERO, start));
574
575        // We need a source of randomness between different cars, but it needs to be deterministic
576        // across repeated runs of the exact same simulation. This also shouldn't be the same
577        // starting seed for one vehicle across different decisions through the simulation, because
578        // then they might always prefer the first or third turn the most or whatever.
579        let mut rng =
580            XorShiftRng::seed_from_u64((vehicle.id.id + start.encode_u32() as usize) as u64);
581
582        while !queue.is_empty() {
583            let (dist_so_far, current) = queue.pop().unwrap();
584            // If the current lane has a spot open, we wouldn't be asking. This can happen if a spot
585            // opens up on the 'start' lane, but behind the car.
586            if current != start {
587                // Pick the closest to the start of the lane, since that's closest to where we came
588                // from
589                if let Some((spot, pos)) = self
590                    .get_all_free_spots(Position::start(current), vehicle, target, map)
591                    .into_iter()
592                    .min_by_key(|(_, pos)| pos.dist_along())
593                {
594                    let mut steps = vec![PathStep::Lane(current)];
595                    let mut current = current;
596                    loop {
597                        if current == start {
598                            // Don't include PathStep::Lane(start)
599                            steps.pop();
600                            steps.reverse();
601                            return Some((steps, spot, pos));
602                        }
603                        let turn = backrefs[&current];
604                        steps.push(PathStep::Turn(turn));
605                        steps.push(PathStep::Lane(turn.src));
606                        current = turn.src;
607                    }
608                }
609            }
610            for turn in map.get_turns_for(current, PathConstraints::Car) {
611                if let Entry::Vacant(e) = backrefs.entry(turn.id.dst) {
612                    let dist_this_step = turn.geom.length() + map.get_l(current).length();
613                    // When vehicles search away from the first lane for a spot, don't all go in
614                    // the same direction! Do this by jittering which turn they explore.
615                    // At worst, they consider a route to be 10% of its true length, so somebody
616                    // might go up to 10x farther than necessary. From some quick tests, these
617                    // worst cases aren't happening -- because it'd be unlikely to roll a higher
618                    // number here many times in a row, and if there are only a few lanes away, it
619                    // doesn't matter that much anyway.
620                    let jitter = rng.gen_range(0.1..0.9);
621                    e.insert(turn.id);
622                    // Remember, keep things negative
623                    queue.push((dist_so_far - jitter * dist_this_step, turn.id.dst));
624                }
625            }
626        }
627
628        None
629    }
630
631    fn collect_events(&mut self) -> Vec<Event> {
632        std::mem::take(&mut self.events)
633    }
634
635    fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)> {
636        self.parked_cars
637            .values()
638            .map(|p| {
639                (
640                    self.spot_to_sidewalk_pos(p.spot, map),
641                    p.vehicle.owner.unwrap(),
642                )
643            })
644            .collect()
645    }
646
647    fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID> {
648        let mut cars = Vec::new();
649        for idx in 0..self.num_spots_per_offstreet.get(&b).cloned().unwrap_or(0) {
650            let spot = ParkingSpot::Offstreet(b, idx);
651            if let Some(car) = self.occupants.get(&spot) {
652                cars.push(*car);
653            }
654        }
655        cars
656    }
657}
658
659#[derive(Serialize, Deserialize, Clone)]
660struct ParkingLane {
661    parking_lane: LaneID,
662    driving_lane: LaneID,
663    sidewalk: LaneID,
664    // The front of the parking spot (farthest along the lane)
665    spot_dist_along: Vec<Distance>,
666}
667
668impl ParkingLane {
669    fn new(lane: &Lane, map: &Map) -> Option<ParkingLane> {
670        if lane.lane_type != LaneType::Parking {
671            return None;
672        }
673
674        let driving_lane = if let Some(l) = map.get_parent(lane.id).parking_to_driving(lane.id) {
675            l
676        } else {
677            error!("Parking lane {} has no driving lane!", lane.id);
678            return None;
679        };
680        if map.get_l(driving_lane).driving_blackhole {
681            return None;
682        }
683        let sidewalk = if let Some(l) = map
684            .get_parent(lane.id)
685            .find_closest_lane(lane.id, |l| l.is_walkable())
686        {
687            l
688        } else {
689            warn!("Parking lane {} has no sidewalk!", lane.id);
690            return None;
691        };
692
693        Some(ParkingLane {
694            parking_lane: lane.id,
695            driving_lane,
696            sidewalk,
697            spot_dist_along: (0..lane.number_parking_spots(map.get_config()))
698                .map(|idx| map.get_config().street_parking_spot_length * (2.0 + idx as f64))
699                .collect(),
700        })
701    }
702
703    fn dist_along_for_car(&self, spot_idx: usize, vehicle: &Vehicle, map: &Map) -> Distance {
704        // Find the offset to center this particular car in the parking spot
705        self.spot_dist_along[spot_idx]
706            - (map.get_config().street_parking_spot_length - vehicle.length) / 2.0
707    }
708
709    fn spots(&self) -> Vec<ParkingSpot> {
710        let mut spots = Vec::new();
711        for idx in 0..self.spot_dist_along.len() {
712            spots.push(ParkingSpot::Onstreet(self.parking_lane, idx));
713        }
714        spots
715    }
716}
717
718/// This assigns infinite private parking to all buildings and none anywhere else. This effectively
719/// disables the simulation of parking entirely, making driving trips just go directly between
720/// buildings. Useful for maps without good parking data (which is currently all of them) and
721/// experiments where parking contention skews results and just gets in the way.
722//
723// TODO Reconsider this split implementation. There's lots of copied code. We can maybe just use
724// NormalParkingSimState with an 'infinite: bool' and rethinking num_spots_per_offstreet.
725#[derive(Serialize, Deserialize, Clone)]
726pub struct InfiniteParkingSimState {
727    #[serde(
728        serialize_with = "serialize_btreemap",
729        deserialize_with = "deserialize_btreemap"
730    )]
731    parked_cars: BTreeMap<CarID, ParkedCar>,
732    #[serde(
733        serialize_with = "serialize_btreemap",
734        deserialize_with = "deserialize_btreemap"
735    )]
736    occupants: BTreeMap<ParkingSpot, CarID>,
737    #[serde(
738        serialize_with = "serialize_btreemap",
739        deserialize_with = "deserialize_btreemap"
740    )]
741    reserved_spots: BTreeMap<ParkingSpot, CarID>,
742
743    // Cache dist_along
744    #[serde(
745        serialize_with = "serialize_multimap",
746        deserialize_with = "deserialize_multimap"
747    )]
748    driving_to_offstreet: MultiMap<LaneID, (BuildingID, Distance)>,
749    // For an entry b1 -> b2, b1 is blackholed, so instead go park at b2 and walk the rest of the
750    // way.
751    blackholed_building_redirects: BTreeMap<BuildingID, BuildingID>,
752
753    // An optimization for get_free_bldg_spot
754    num_occupants_per_offstreet: BTreeMap<BuildingID, usize>,
755
756    events: Vec<Event>,
757}
758
759impl InfiniteParkingSimState {
760    fn new(map: &Map) -> InfiniteParkingSimState {
761        let mut sim = InfiniteParkingSimState {
762            parked_cars: BTreeMap::new(),
763            occupants: BTreeMap::new(),
764            reserved_spots: BTreeMap::new(),
765
766            driving_to_offstreet: MultiMap::new(),
767            blackholed_building_redirects: BTreeMap::new(),
768
769            num_occupants_per_offstreet: BTreeMap::new(),
770
771            events: Vec::new(),
772        };
773        let mut blackholes = Vec::new();
774        for b in map.all_buildings() {
775            if let Some((pos, _)) = b.driving_connection(map) {
776                if !map.get_l(pos.lane()).driving_blackhole {
777                    sim.driving_to_offstreet
778                        .insert(pos.lane(), (b.id, pos.dist_along()));
779                    continue;
780                }
781            }
782            blackholes.push(b.id);
783        }
784
785        // For every blackholed building, find a nearby building that isn't blackholed
786        for b in blackholes {
787            // TODO This is a simple DFS. Could sort by distance.
788            let mut queue = vec![map.find_driving_lane_near_building(b)];
789            let mut seen = BTreeSet::new();
790            loop {
791                let current = queue.pop().unwrap();
792                if seen.contains(&current) {
793                    continue;
794                }
795                seen.insert(current);
796                if let Some((redirect, _)) = sim.driving_to_offstreet.get(current).iter().next() {
797                    sim.blackholed_building_redirects.insert(b, *redirect);
798                    break;
799                }
800                for turn in map.get_turns_for(current, PathConstraints::Car) {
801                    queue.push(turn.id.dst);
802                }
803            }
804        }
805
806        sim
807    }
808
809    fn get_free_bldg_spot(&self, b: BuildingID) -> ParkingSpot {
810        if let Some(redirect) = self.blackholed_building_redirects.get(&b) {
811            // This won't recurse endlessly; the redirect is not a key in
812            // blackholed_building_redirects.
813            return self.get_free_bldg_spot(*redirect);
814        }
815
816        // As long as the index is unique, it doesn't matter what it actually is, so optimize for
817        // initially seeding many cars in one building by starting with the number of cars already
818        // there. As the simulation runs, we'll wind up skipping some intermediate indices, but it
819        // doesn't matter.
820        let mut i = self
821            .num_occupants_per_offstreet
822            .get(&b)
823            .cloned()
824            .unwrap_or(0);
825        loop {
826            let spot = ParkingSpot::Offstreet(b, i);
827            if self.is_free(spot) {
828                return spot;
829            }
830            i += 1;
831        }
832    }
833}
834
835impl ParkingSim for InfiniteParkingSimState {
836    fn handle_live_edits(&mut self, map: &Map, _: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>) {
837        // Can live edits possibly affect anything?
838        let new = InfiniteParkingSimState::new(map);
839        self.driving_to_offstreet = new.driving_to_offstreet;
840        self.blackholed_building_redirects = new.blackholed_building_redirects;
841
842        (Vec::new(), Vec::new())
843    }
844
845    fn get_free_onstreet_spots(&self, _: LaneID) -> Vec<ParkingSpot> {
846        Vec::new()
847    }
848
849    fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot> {
850        // Just returns the next free spot
851        vec![self.get_free_bldg_spot(b)]
852    }
853
854    fn get_free_lot_spots(&self, _: ParkingLotID) -> Vec<ParkingSpot> {
855        Vec::new()
856    }
857
858    fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID) {
859        assert!(self.is_free(spot));
860        self.reserved_spots.insert(spot, car);
861    }
862
863    fn unreserve_spot(&mut self, car: CarID) {
864        self.reserved_spots.retain(|_, c| car != *c);
865    }
866
867    fn remove_parked_car(&mut self, p: ParkedCar) {
868        self.parked_cars
869            .remove(&p.vehicle.id)
870            .expect("remove_parked_car missing from parked_cars");
871        self.occupants
872            .remove(&p.spot)
873            .expect("remove_parked_car missing from occupants");
874        self.events
875            .push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot));
876
877        if let ParkingSpot::Offstreet(b, _) = p.spot {
878            *self.num_occupants_per_offstreet.get_mut(&b).unwrap() -= 1;
879        }
880    }
881
882    fn add_parked_car(&mut self, p: ParkedCar) {
883        self.events
884            .push(Event::CarReachedParkingSpot(p.vehicle.id, p.spot));
885
886        assert_eq!(self.reserved_spots.remove(&p.spot), Some(p.vehicle.id));
887
888        assert!(!self.occupants.contains_key(&p.spot));
889        self.occupants.insert(p.spot, p.vehicle.id);
890
891        if let ParkingSpot::Offstreet(b, _) = p.spot {
892            *self.num_occupants_per_offstreet.entry(b).or_insert(0) += 1;
893        }
894
895        assert!(!self.parked_cars.contains_key(&p.vehicle.id));
896        self.parked_cars.insert(p.vehicle.id, p);
897    }
898
899    fn get_draw_cars(&self, _: LaneID, _: &Map) -> Vec<DrawCarInput> {
900        Vec::new()
901    }
902
903    fn get_draw_cars_in_lots(&self, _: LaneID, _: &Map) -> Vec<DrawCarInput> {
904        Vec::new()
905    }
906
907    fn get_draw_car(&self, _: CarID, _: &Map) -> Option<DrawCarInput> {
908        None
909    }
910
911    fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D> {
912        let p = self.parked_cars.get(&id)?;
913        match p.spot {
914            ParkingSpot::Offstreet(b, _) => Some(map.get_b(b).label_center),
915            _ => unreachable!(),
916        }
917    }
918
919    fn get_all_draw_cars(&self, _: &Map) -> Vec<DrawCarInput> {
920        Vec::new()
921    }
922
923    fn is_free(&self, spot: ParkingSpot) -> bool {
924        !self.occupants.contains_key(&spot) && !self.reserved_spots.contains_key(&spot)
925    }
926
927    fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar> {
928        let car = self.occupants.get(&spot)?;
929        Some(&self.parked_cars[car])
930    }
931
932    fn get_all_free_spots(
933        &self,
934        driving_pos: Position,
935        vehicle: &Vehicle,
936        target: BuildingID,
937        map: &Map,
938    ) -> Vec<(ParkingSpot, Position)> {
939        // The target building may be blackholed, so fallback to a building on one of the
940        // penultimate lanes, when the search begins.
941        let mut bldg: Option<BuildingID> = None;
942        for (b, bldg_dist) in self.driving_to_offstreet.get(driving_pos.lane()) {
943            if driving_pos.dist_along() > *bldg_dist {
944                continue;
945            }
946            if target == *b {
947                bldg = Some(target);
948                break;
949            } else if bldg.is_none() {
950                // Backup option
951                bldg = Some(*b);
952            }
953        }
954        if let Some(b) = bldg {
955            let spot = self.get_free_bldg_spot(b);
956            vec![(spot, self.spot_to_driving_pos(spot, vehicle, map))]
957        } else {
958            Vec::new()
959        }
960    }
961
962    fn spot_to_driving_pos(&self, spot: ParkingSpot, _: &Vehicle, map: &Map) -> Position {
963        match spot {
964            ParkingSpot::Offstreet(b, _) => map.get_b(b).driving_connection(map).unwrap().0,
965            _ => unreachable!(),
966        }
967    }
968
969    fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position {
970        match spot {
971            ParkingSpot::Offstreet(b, _) => map.get_b(b).sidewalk_pos,
972            _ => unreachable!(),
973        }
974    }
975
976    fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
977        self.parked_cars.get(&id).and_then(|p| p.vehicle.owner)
978    }
979    fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
980        self.parked_cars.get(&id)
981    }
982
983    fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
984        unreachable!()
985    }
986
987    fn path_to_free_parking_spot(
988        &self,
989        start: LaneID,
990        vehicle: &Vehicle,
991        target: BuildingID,
992        map: &Map,
993    ) -> Option<(Vec<PathStep>, ParkingSpot, Position)> {
994        // TODO This impl is copied from NormalParkingSimState. Instead, we already know the
995        // redirect... could just path to it.
996        let mut backrefs: HashMap<LaneID, TurnID> = HashMap::new();
997        // Don't travel far.
998        // This is a max-heap, so negate all distances. Tie breaker is lane ID, arbitrary but
999        // deterministic.
1000        let mut queue: BinaryHeap<(Distance, LaneID)> = BinaryHeap::new();
1001        queue.push((Distance::ZERO, start));
1002
1003        while !queue.is_empty() {
1004            let (dist_so_far, current) = queue.pop().unwrap();
1005            // If the current lane has a spot open, we wouldn't be asking. This can happen if a spot
1006            // opens up on the 'start' lane, but behind the car.
1007            if current != start {
1008                // Pick the closest to the start of the lane, since that's closest to where we came
1009                // from
1010                if let Some((spot, pos)) = self
1011                    .get_all_free_spots(Position::start(current), vehicle, target, map)
1012                    .into_iter()
1013                    .min_by_key(|(_, pos)| pos.dist_along())
1014                {
1015                    let mut steps = vec![PathStep::Lane(current)];
1016                    let mut current = current;
1017                    loop {
1018                        if current == start {
1019                            // Don't include PathStep::Lane(start)
1020                            steps.pop();
1021                            steps.reverse();
1022                            return Some((steps, spot, pos));
1023                        }
1024                        let turn = backrefs[&current];
1025                        steps.push(PathStep::Turn(turn));
1026                        steps.push(PathStep::Lane(turn.src));
1027                        current = turn.src;
1028                    }
1029                }
1030            }
1031            for turn in map.get_turns_for(current, PathConstraints::Car) {
1032                if let Entry::Vacant(e) = backrefs.entry(turn.id.dst) {
1033                    let dist_this_step = turn.geom.length() + map.get_l(current).length();
1034                    e.insert(turn.id);
1035                    // Remember, keep things negative
1036                    queue.push((dist_so_far - dist_this_step, turn.id.dst));
1037                }
1038            }
1039        }
1040
1041        None
1042    }
1043
1044    fn collect_events(&mut self) -> Vec<Event> {
1045        std::mem::take(&mut self.events)
1046    }
1047
1048    fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)> {
1049        self.parked_cars
1050            .values()
1051            .map(|p| {
1052                (
1053                    self.spot_to_sidewalk_pos(p.spot, map),
1054                    p.vehicle.owner.unwrap(),
1055                )
1056            })
1057            .collect()
1058    }
1059
1060    fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID> {
1061        // TODO This is a very inefficient impl
1062        let mut cars = Vec::new();
1063        for (spot, car) in &self.occupants {
1064            if let ParkingSpot::Offstreet(bldg, _) = spot {
1065                if b == *bldg {
1066                    cars.push(*car);
1067                }
1068            }
1069        }
1070        cars
1071    }
1072}