1 use crate::mechanics::car::{Car, CarState};
2 use crate::mechanics::Queue;
3 use crate::sim::Ctx;
4 use crate::{
5     ActionAtEnd, AgentID, AgentProperties, CarID, Command, CreateCar, DistanceInterval,
6     DrawCarInput, Event, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, PersonID,
7     Scheduler, TimeInterval, TransitSimState, TripManager, UnzoomedAgent, Vehicle, WalkingSimState,
8     FOLLOWING_DISTANCE,
9 };
10 use abstutil::{deserialize_btreemap, serialize_btreemap};
11 use geom::{Distance, Duration, PolyLine, Time};
12 use map_model::{LaneID, Map, Path, PathStep, Traversable};
13 use serde::{Deserialize, Serialize};
14 use std::collections::{BTreeMap, HashSet, VecDeque};
15 
16 const TIME_TO_UNPARK_ONSTRET: Duration = Duration::const_seconds(10.0);
17 const TIME_TO_PARK_ONSTREET: Duration = Duration::const_seconds(15.0);
18 const TIME_TO_UNPARK_OFFSTREET: Duration = Duration::const_seconds(5.0);
19 const TIME_TO_PARK_OFFSTREET: Duration = Duration::const_seconds(5.0);
20 const TIME_TO_WAIT_AT_STOP: Duration = Duration::const_seconds(10.0);
21 
22 // TODO Do something else.
23 pub(crate) const BLIND_RETRY_TO_CREEP_FORWARDS: Duration = Duration::const_seconds(0.1);
24 pub(crate) const BLIND_RETRY_TO_REACH_END_DIST: Duration = Duration::const_seconds(5.0);
25 
26 #[derive(Serialize, Deserialize, Clone)]
27 pub struct DrivingSimState {
28     #[serde(
29         serialize_with = "serialize_btreemap",
30         deserialize_with = "deserialize_btreemap"
31     )]
32     cars: BTreeMap<CarID, Car>,
33     #[serde(
34         serialize_with = "serialize_btreemap",
35         deserialize_with = "deserialize_btreemap"
36     )]
37     queues: BTreeMap<Traversable, Queue>,
38     events: Vec<Event>,
39 
40     recalc_lanechanging: bool,
41     handle_uber_turns: bool,
42 }
43 
44 impl DrivingSimState {
new(map: &Map, recalc_lanechanging: bool, handle_uber_turns: bool) -> DrivingSimState45     pub fn new(map: &Map, recalc_lanechanging: bool, handle_uber_turns: bool) -> DrivingSimState {
46         let mut sim = DrivingSimState {
47             cars: BTreeMap::new(),
48             queues: BTreeMap::new(),
49             events: Vec::new(),
50             recalc_lanechanging,
51             handle_uber_turns,
52         };
53 
54         for l in map.all_lanes() {
55             if l.lane_type.is_for_moving_vehicles() {
56                 let q = Queue::new(Traversable::Lane(l.id), map);
57                 sim.queues.insert(q.id, q);
58             }
59         }
60         for t in map.all_turns().values() {
61             if !t.between_sidewalks() {
62                 let q = Queue::new(Traversable::Turn(t.id), map);
63                 sim.queues.insert(q.id, q);
64             }
65         }
66 
67         sim
68     }
69 
70     // True if it worked
start_car_on_lane( &mut self, now: Time, params: CreateCar, map: &Map, intersections: &IntersectionSimState, parking: &ParkingSimState, scheduler: &mut Scheduler, ) -> bool71     pub fn start_car_on_lane(
72         &mut self,
73         now: Time,
74         params: CreateCar,
75         map: &Map,
76         intersections: &IntersectionSimState,
77         parking: &ParkingSimState,
78         scheduler: &mut Scheduler,
79     ) -> bool {
80         let first_lane = params.router.head().as_lane();
81 
82         if !intersections.nobody_headed_towards(first_lane, map.get_l(first_lane).src_i) {
83             return false;
84         }
85         if let Some(idx) = self.queues[&Traversable::Lane(first_lane)].get_idx_to_insert_car(
86             params.start_dist,
87             params.vehicle.length,
88             now,
89             &self.cars,
90             &self.queues,
91         ) {
92             let mut car = Car {
93                 vehicle: params.vehicle,
94                 router: params.router,
95                 // Temporary
96                 state: CarState::Queued { blocked_since: now },
97                 last_steps: VecDeque::new(),
98                 started_at: now,
99                 total_blocked_time: Duration::ZERO,
100                 trip_and_person: params.trip_and_person,
101             };
102             if let Some(p) = params.maybe_parked_car {
103                 let delay = match p.spot {
104                     ParkingSpot::Onstreet(_, _) => TIME_TO_UNPARK_ONSTRET,
105                     ParkingSpot::Offstreet(_, _) | ParkingSpot::Lot(_, _) => {
106                         TIME_TO_UNPARK_OFFSTREET
107                     }
108                 };
109                 car.state = CarState::Unparking(
110                     params.start_dist,
111                     p.spot,
112                     TimeInterval::new(now, now + delay),
113                 );
114             } else {
115                 // Have to do this early
116                 if car.router.last_step() {
117                     match car.router.maybe_handle_end(
118                         params.start_dist,
119                         &car.vehicle,
120                         parking,
121                         map,
122                         car.trip_and_person,
123                         &mut self.events,
124                     ) {
125                         None | Some(ActionAtEnd::GotoLaneEnd) => {}
126                         x => {
127                             panic!(
128                                 "Car with one-step route {:?} had unexpected result from \
129                                  maybe_handle_end: {:?}",
130                                 car.router, x
131                             );
132                         }
133                     }
134                     // We might've decided to go park somewhere farther, so get_end_dist no longer
135                     // makes sense.
136                     if car.router.last_step() && params.start_dist > car.router.get_end_dist() {
137                         println!(
138                             "WARNING: {} wants to spawn at {}, which is past their end of {} on a \
139                              one-step path {}",
140                             car.vehicle.id,
141                             params.start_dist,
142                             car.router.get_end_dist(),
143                             first_lane
144                         );
145                         return false;
146                     }
147                 }
148 
149                 car.state = car.crossing_state(params.start_dist, now, map);
150             }
151             scheduler.push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
152             {
153                 let queue = self.queues.get_mut(&Traversable::Lane(first_lane)).unwrap();
154                 queue.cars.insert(idx, car.vehicle.id);
155                 // Don't use try_to_reserve_entry -- it's overly conservative.
156                 // get_idx_to_insert_car does a more detailed check of the current space usage.
157                 queue.reserved_length += car.vehicle.length + FOLLOWING_DISTANCE;
158             }
159             self.cars.insert(car.vehicle.id, car);
160             return true;
161         }
162         false
163     }
164 
update_car( &mut self, id: CarID, now: Time, ctx: &mut Ctx, trips: &mut TripManager, transit: &mut TransitSimState, walking: &mut WalkingSimState, )165     pub fn update_car(
166         &mut self,
167         id: CarID,
168         now: Time,
169         ctx: &mut Ctx,
170         trips: &mut TripManager,
171         transit: &mut TransitSimState,
172         walking: &mut WalkingSimState,
173     ) {
174         // State transitions for this car:
175         //
176         // Crossing -> Queued or WaitingToAdvance
177         // Unparking -> Crossing
178         // IdlingAtStop -> Crossing
179         // Queued -> last step handling (Parking or done)
180         // WaitingToAdvance -> try to advance to the next step of the path
181         // Parking -> done
182         //
183         // State transitions for other cars:
184         //
185         // Crossing -> Crossing (recalculate dist/time)
186         // Queued -> Crossing
187         //
188         // Why is it safe to process cars in any order, rather than making sure to follow the order
189         // of queues? Because of the invariant that distances should never suddenly jump when a car
190         // has entered/exiting a queue.
191         // This car might have reached the router's end distance, but maybe not -- might
192         // actually be stuck behind other cars. We have to calculate the distances right now to
193         // be sure.
194         let mut need_distances = {
195             let car = &self.cars[&id];
196             match car.state {
197                 CarState::Queued { .. } => car.router.last_step(),
198                 CarState::Parking(_, _, _) => true,
199                 _ => false,
200             }
201         };
202 
203         if !need_distances {
204             // We need to mutate two different cars in one case. To avoid fighting the borrow
205             // checker, temporarily move one of them out of the BTreeMap.
206             let mut car = self.cars.remove(&id).unwrap();
207             // Responsibility of update_car to manage scheduling stuff!
208             need_distances = self.update_car_without_distances(&mut car, now, ctx, transit);
209             self.cars.insert(id, car);
210         }
211 
212         if need_distances {
213             // Do this before removing the car!
214             let dists = self.queues[&self.cars[&id].router.head()].get_car_positions(
215                 now,
216                 &self.cars,
217                 &self.queues,
218             );
219             let idx = dists.iter().position(|(c, _)| *c == id).unwrap();
220 
221             // We need to mutate two different cars in some cases. To avoid fighting the borrow
222             // checker, temporarily move one of them out of the BTreeMap.
223             let mut car = self.cars.remove(&id).unwrap();
224             // Responsibility of update_car_with_distances to manage scheduling stuff!
225             if self
226                 .update_car_with_distances(&mut car, &dists, idx, now, ctx, trips, transit, walking)
227             {
228                 self.cars.insert(id, car);
229             } else {
230                 self.delete_car(
231                     &mut car,
232                     dists,
233                     idx,
234                     now,
235                     ctx.map,
236                     ctx.scheduler,
237                     ctx.intersections,
238                 );
239             }
240         }
241     }
242 
243     // If this returns true, we need to immediately run update_car_with_distances. If we don't,
244     // then the car will briefly be Queued and might immediately become something else, which
245     // affects how leaders update followers.
update_car_without_distances( &mut self, car: &mut Car, now: Time, ctx: &mut Ctx, transit: &mut TransitSimState, ) -> bool246     fn update_car_without_distances(
247         &mut self,
248         car: &mut Car,
249         now: Time,
250         ctx: &mut Ctx,
251         transit: &mut TransitSimState,
252     ) -> bool {
253         match car.state {
254             CarState::Crossing(_, _) => {
255                 car.state = CarState::Queued { blocked_since: now };
256                 if car.router.last_step() {
257                     // Immediately run update_car_with_distances.
258                     return true;
259                 }
260                 let queue = &self.queues[&car.router.head()];
261                 if queue.cars[0] == car.vehicle.id && queue.laggy_head.is_none() {
262                     // Want to re-run, but no urgency about it happening immediately.
263                     car.state = CarState::WaitingToAdvance { blocked_since: now };
264                     if self.recalc_lanechanging {
265                         car.router.opportunistically_lanechange(
266                             &self.queues,
267                             ctx.map,
268                             self.handle_uber_turns,
269                         );
270                     }
271                     ctx.scheduler.push(now, Command::UpdateCar(car.vehicle.id));
272                 }
273             }
274             CarState::Unparking(front, _, _) => {
275                 if car.router.last_step() {
276                     // Actually, we need to do this first. Ignore the answer -- if we're
277                     // doing something weird like vanishing or re-parking immediately
278                     // (quite unlikely), the next loop will pick that up. Just trigger the
279                     // side effect of choosing an end_dist.
280                     car.router.maybe_handle_end(
281                         front,
282                         &car.vehicle,
283                         ctx.parking,
284                         ctx.map,
285                         car.trip_and_person,
286                         &mut self.events,
287                     );
288                 }
289                 car.state = car.crossing_state(front, now, ctx.map);
290                 ctx.scheduler
291                     .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
292             }
293             CarState::IdlingAtStop(dist, _) => {
294                 car.router = transit.bus_departed_from_stop(car.vehicle.id, ctx.map);
295                 self.events
296                     .push(Event::PathAmended(car.router.get_path().clone()));
297                 car.state = car.crossing_state(dist, now, ctx.map);
298                 ctx.scheduler
299                     .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
300 
301                 // Update our follower, so they know we stopped idling.
302                 let queue = &self.queues[&car.router.head()];
303                 let idx = queue
304                     .cars
305                     .iter()
306                     .position(|c| *c == car.vehicle.id)
307                     .unwrap();
308                 if idx != queue.cars.len() - 1 {
309                     let mut follower = self.cars.get_mut(&queue.cars[idx + 1]).unwrap();
310                     match follower.state {
311                         CarState::Queued { blocked_since } => {
312                             // If they're on their last step, they might be ending early and not
313                             // right behind us.
314                             if !follower.router.last_step() {
315                                 follower.total_blocked_time += now - blocked_since;
316                                 follower.state = follower.crossing_state(
317                                     // Since the follower was Queued, this must be where they are.
318                                     dist - car.vehicle.length - FOLLOWING_DISTANCE,
319                                     now,
320                                     ctx.map,
321                                 );
322                                 ctx.scheduler.update(
323                                     follower.state.get_end_time(),
324                                     Command::UpdateCar(follower.vehicle.id),
325                                 );
326                             }
327                         }
328                         CarState::WaitingToAdvance { .. } => unreachable!(),
329                         // They weren't blocked. Note that there's no way the Crossing state could
330                         // jump forwards here; the leader is still in front
331                         // of them.
332                         CarState::Crossing(_, _)
333                         | CarState::Unparking(_, _, _)
334                         | CarState::Parking(_, _, _)
335                         | CarState::IdlingAtStop(_, _) => {}
336                     }
337                 }
338             }
339             CarState::Queued { .. } => unreachable!(),
340             CarState::WaitingToAdvance { blocked_since } => {
341                 // 'car' is the leader.
342                 let from = car.router.head();
343                 let goto = car.router.next();
344                 assert!(from != goto);
345 
346                 match goto {
347                     Traversable::Turn(t) => {
348                         let mut speed = goto.speed_limit(ctx.map);
349                         if let Some(s) = car.vehicle.max_speed {
350                             speed = speed.min(s);
351                         }
352                         if !ctx.intersections.maybe_start_turn(
353                             AgentID::Car(car.vehicle.id),
354                             t,
355                             speed,
356                             now,
357                             ctx.map,
358                             ctx.scheduler,
359                             Some((&car, &self.cars, &mut self.queues)),
360                         ) {
361                             // Don't schedule a retry here.
362                             return false;
363                         }
364                     }
365                     Traversable::Lane(l) => {
366                         ctx.cap.car_entering_lane(now, car.vehicle.id, l);
367                     }
368                 }
369 
370                 {
371                     let mut queue = self.queues.get_mut(&from).unwrap();
372                     assert_eq!(queue.cars.pop_front().unwrap(), car.vehicle.id);
373                     queue.laggy_head = Some(car.vehicle.id);
374                 }
375 
376                 // We do NOT need to update the follower. If they were Queued, they'll remain that
377                 // way, until laggy_head is None.
378 
379                 let last_step = car.router.advance(
380                     &car.vehicle,
381                     ctx.parking,
382                     ctx.map,
383                     car.trip_and_person,
384                     &mut self.events,
385                 );
386                 car.total_blocked_time += now - blocked_since;
387                 car.state = car.crossing_state(Distance::ZERO, now, ctx.map);
388                 ctx.scheduler
389                     .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
390                 self.events.push(Event::AgentEntersTraversable(
391                     AgentID::Car(car.vehicle.id),
392                     goto,
393                     if car.vehicle.vehicle_type.is_transit() {
394                         Some(transit.get_passengers(car.vehicle.id).len())
395                     } else {
396                         None
397                     },
398                 ));
399 
400                 // Don't mark turn_finished until our back is out of the turn.
401                 car.last_steps.push_front(last_step);
402 
403                 // Optimistically assume we'll be out of the way ASAP.
404                 // This is update, not push, because we might've scheduled a blind retry too
405                 // late, and the car actually crosses an entire new traversable in the
406                 // meantime.
407                 ctx.scheduler.update(
408                     car.crossing_state_with_end_dist(
409                         DistanceInterval::new_driving(
410                             Distance::ZERO,
411                             car.vehicle.length + FOLLOWING_DISTANCE,
412                         ),
413                         now,
414                         ctx.map,
415                     )
416                     .get_end_time(),
417                     Command::UpdateLaggyHead(car.vehicle.id),
418                 );
419 
420                 self.queues
421                     .get_mut(&goto)
422                     .unwrap()
423                     .cars
424                     .push_back(car.vehicle.id);
425             }
426             CarState::Parking(_, _, _) => unreachable!(),
427         }
428         false
429     }
430 
431     // Returns true if the car survives.
update_car_with_distances( &mut self, car: &mut Car, dists: &Vec<(CarID, Distance)>, idx: usize, now: Time, ctx: &mut Ctx, trips: &mut TripManager, transit: &mut TransitSimState, walking: &mut WalkingSimState, ) -> bool432     fn update_car_with_distances(
433         &mut self,
434         car: &mut Car,
435         dists: &Vec<(CarID, Distance)>,
436         idx: usize,
437         now: Time,
438         ctx: &mut Ctx,
439         trips: &mut TripManager,
440         transit: &mut TransitSimState,
441         walking: &mut WalkingSimState,
442     ) -> bool {
443         let our_dist = dists[idx].1;
444 
445         match car.state {
446             CarState::Crossing(_, _)
447             | CarState::Unparking(_, _, _)
448             | CarState::IdlingAtStop(_, _)
449             | CarState::WaitingToAdvance { .. } => unreachable!(),
450             CarState::Queued { blocked_since } => {
451                 match car.router.maybe_handle_end(
452                     our_dist,
453                     &car.vehicle,
454                     ctx.parking,
455                     ctx.map,
456                     car.trip_and_person,
457                     &mut self.events,
458                 ) {
459                     Some(ActionAtEnd::VanishAtBorder(i)) => {
460                         car.total_blocked_time += now - blocked_since;
461                         // Don't do this for buses
462                         if car.trip_and_person.is_some() {
463                             trips.car_or_bike_reached_border(
464                                 now,
465                                 car.vehicle.id,
466                                 i,
467                                 car.total_blocked_time,
468                                 ctx,
469                             );
470                         }
471                         false
472                     }
473                     Some(ActionAtEnd::GiveUpOnParking) => {
474                         car.total_blocked_time += now - blocked_since;
475                         trips.abort_trip(
476                             now,
477                             car.trip_and_person.unwrap().0,
478                             // If we couldn't find parking normally, doesn't make sense to warp the
479                             // car to the destination. There's no parking!
480                             None,
481                             ctx,
482                         );
483                         false
484                     }
485                     Some(ActionAtEnd::StartParking(spot)) => {
486                         car.total_blocked_time += now - blocked_since;
487                         let delay = match spot {
488                             ParkingSpot::Onstreet(_, _) => TIME_TO_PARK_ONSTREET,
489                             ParkingSpot::Offstreet(_, _) | ParkingSpot::Lot(_, _) => {
490                                 TIME_TO_PARK_OFFSTREET
491                             }
492                         };
493                         car.state =
494                             CarState::Parking(our_dist, spot, TimeInterval::new(now, now + delay));
495                         // If we don't do this, then we might have another car creep up
496                         // behind, see the spot free, and start parking too. This can
497                         // happen with multiple lanes and certain vehicle lengths.
498                         ctx.parking.reserve_spot(spot);
499                         ctx.scheduler
500                             .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
501                         true
502                     }
503                     Some(ActionAtEnd::GotoLaneEnd) => {
504                         car.total_blocked_time += now - blocked_since;
505                         car.state = car.crossing_state(our_dist, now, ctx.map);
506                         ctx.scheduler
507                             .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
508                         true
509                     }
510                     Some(ActionAtEnd::StopBiking(bike_rack)) => {
511                         car.total_blocked_time += now - blocked_since;
512                         trips.bike_reached_end(
513                             now,
514                             car.vehicle.id,
515                             bike_rack,
516                             car.total_blocked_time,
517                             ctx.map,
518                             ctx.scheduler,
519                         );
520                         false
521                     }
522                     Some(ActionAtEnd::BusAtStop) => {
523                         car.total_blocked_time += now - blocked_since;
524                         if transit.bus_arrived_at_stop(now, car.vehicle.id, trips, walking, ctx) {
525                             car.state = CarState::IdlingAtStop(
526                                 our_dist,
527                                 TimeInterval::new(now, now + TIME_TO_WAIT_AT_STOP),
528                             );
529                             ctx.scheduler
530                                 .push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
531                             true
532                         } else {
533                             // Vanishing at a border
534                             false
535                         }
536                     }
537                     None => {
538                         ctx.scheduler.push(
539                             now + BLIND_RETRY_TO_REACH_END_DIST,
540                             Command::UpdateCar(car.vehicle.id),
541                         );
542 
543                         // TODO For now, always use BLIND_RETRY_TO_REACH_END_DIST. Measured things
544                         // to be slower otherwise. :(
545                         /*
546                         // If this car wasn't blocked at all, when would it reach its goal?
547                         let ideal_end_time = match car.crossing_state(our_dist, now, map) {
548                             CarState::Crossing(time_int, _) => time_int.end,
549                             _ => unreachable!(),
550                         };
551                         if ideal_end_time == now {
552                             // Haha, no such luck. We're super super close to the goal, but not
553                             // quite there yet.
554                             scheduler.push(now + BLIND_RETRY_TO_REACH_END_DIST, Command::UpdateCar(car.vehicle.id));
555                         } else {
556                             scheduler.push(ideal_end_time, Command::UpdateCar(car.vehicle.id));
557                         }
558                         // TODO For cars stuck on their last step, this will spam a fair bit. But
559                         // that should be pretty rare.
560                         */
561 
562                         true
563                     }
564                 }
565             }
566             CarState::Parking(_, spot, _) => {
567                 ctx.parking.add_parked_car(ParkedCar {
568                     vehicle: car.vehicle.clone(),
569                     spot,
570                 });
571                 trips.car_reached_parking_spot(
572                     now,
573                     car.vehicle.id,
574                     spot,
575                     car.total_blocked_time,
576                     ctx,
577                 );
578                 false
579             }
580         }
581     }
582 
kill_stuck_car( &mut self, c: CarID, now: Time, map: &Map, scheduler: &mut Scheduler, intersections: &mut IntersectionSimState, ) -> Vehicle583     pub fn kill_stuck_car(
584         &mut self,
585         c: CarID,
586         now: Time,
587         map: &Map,
588         scheduler: &mut Scheduler,
589         intersections: &mut IntersectionSimState,
590     ) -> Vehicle {
591         let dists = self.queues[&self.cars[&c].router.head()].get_car_positions(
592             now,
593             &self.cars,
594             &self.queues,
595         );
596         let idx = dists.iter().position(|(id, _)| *id == c).unwrap();
597         let mut car = self.cars.remove(&c).unwrap();
598 
599         // Hacks to delete cars that're mid-turn
600         if let Traversable::Turn(_) = car.router.head() {
601             let queue = self.queues.get_mut(&car.router.head()).unwrap();
602             queue.reserved_length += car.vehicle.length + FOLLOWING_DISTANCE;
603         }
604         if let Some(Traversable::Turn(t)) = car.router.maybe_next() {
605             intersections.cancel_request(AgentID::Car(c), t);
606         }
607 
608         self.delete_car(&mut car, dists, idx, now, map, scheduler, intersections);
609         // delete_car cancels UpdateLaggyHead
610         scheduler.cancel(Command::UpdateCar(c));
611         car.vehicle
612     }
613 
delete_car( &mut self, car: &mut Car, dists: Vec<(CarID, Distance)>, idx: usize, now: Time, map: &Map, scheduler: &mut Scheduler, intersections: &mut IntersectionSimState, )614     fn delete_car(
615         &mut self,
616         car: &mut Car,
617         dists: Vec<(CarID, Distance)>,
618         idx: usize,
619         now: Time,
620         map: &Map,
621         scheduler: &mut Scheduler,
622         intersections: &mut IntersectionSimState,
623     ) {
624         {
625             let queue = self.queues.get_mut(&car.router.head()).unwrap();
626             assert_eq!(queue.cars.remove(idx).unwrap(), car.vehicle.id);
627             // trim_last_steps doesn't actually include the current queue!
628             queue.free_reserved_space(car);
629             let i = match queue.id {
630                 Traversable::Lane(l) => map.get_l(l).src_i,
631                 Traversable::Turn(t) => t.parent,
632             };
633             intersections.space_freed(now, i, scheduler, map);
634         }
635 
636         intersections.vehicle_gone(car.vehicle.id);
637 
638         // We might be vanishing while partly clipping into other stuff.
639         self.trim_last_steps(
640             car,
641             now,
642             car.last_steps.len(),
643             map,
644             intersections,
645             scheduler,
646         );
647 
648         // We might've scheduled one of those using BLIND_RETRY_TO_CREEP_FORWARDS.
649         scheduler.cancel(Command::UpdateLaggyHead(car.vehicle.id));
650 
651         // Update the follower so that they don't suddenly jump forwards.
652         if idx != dists.len() - 1 {
653             let (follower_id, follower_dist) = dists[idx + 1];
654             let mut follower = self.cars.get_mut(&follower_id).unwrap();
655             // TODO If the leader vanished at a border node, this still jumps a bit -- the
656             // lead car's back is still sticking out. Need to still be bound by them, even
657             // though they don't exist! If the leader just parked, then we're fine.
658             match follower.state {
659                 CarState::Queued { blocked_since } => {
660                     // Prevent them from jumping forwards.
661                     follower.total_blocked_time += now - blocked_since;
662                     follower.state = follower.crossing_state(follower_dist, now, map);
663                     scheduler.update(
664                         follower.state.get_end_time(),
665                         Command::UpdateCar(follower_id),
666                     );
667                 }
668                 CarState::Crossing(_, _) => {
669                     // If the follower was still Crossing, they might not've been blocked
670                     // by leader yet. In that case, recalculating their Crossing state is a
671                     // no-op.
672                     follower.state = follower.crossing_state(follower_dist, now, map);
673                     scheduler.update(
674                         follower.state.get_end_time(),
675                         Command::UpdateCar(follower_id),
676                     );
677                 }
678                 // They weren't blocked
679                 CarState::Unparking(_, _, _)
680                 | CarState::Parking(_, _, _)
681                 | CarState::IdlingAtStop(_, _) => {}
682                 CarState::WaitingToAdvance { .. } => unreachable!(),
683             }
684         }
685     }
686 
update_laggy_head( &mut self, id: CarID, now: Time, map: &Map, intersections: &mut IntersectionSimState, scheduler: &mut Scheduler, )687     pub fn update_laggy_head(
688         &mut self,
689         id: CarID,
690         now: Time,
691         map: &Map,
692         intersections: &mut IntersectionSimState,
693         scheduler: &mut Scheduler,
694     ) {
695         let currently_on = self.cars[&id].router.head();
696         let current_dists =
697             self.queues[&currently_on].get_car_positions(now, &self.cars, &self.queues);
698         // This car must be the tail.
699         let dist_along_last = {
700             let (last_id, dist) = current_dists.last().unwrap();
701             if id != *last_id {
702                 panic!(
703                     "At {} on {:?}, laggy head {} isn't the last on the lane; it's {}",
704                     now, currently_on, id, last_id
705                 );
706             }
707             *dist
708         };
709 
710         // Trim off as many of the oldest last_steps as we've made distance.
711         let mut dist_left_to_cleanup = self.cars[&id].vehicle.length + FOLLOWING_DISTANCE;
712         dist_left_to_cleanup -= dist_along_last;
713         let mut num_to_trim = None;
714         for (idx, step) in self.cars[&id].last_steps.iter().enumerate() {
715             if dist_left_to_cleanup <= Distance::ZERO {
716                 num_to_trim = Some(self.cars[&id].last_steps.len() - idx);
717                 break;
718             }
719             dist_left_to_cleanup -= step.length(map);
720         }
721 
722         if let Some(n) = num_to_trim {
723             let mut car = self.cars.remove(&id).unwrap();
724             self.trim_last_steps(&mut car, now, n, map, intersections, scheduler);
725             self.cars.insert(id, car);
726         }
727 
728         if !self.cars[&id].last_steps.is_empty() {
729             // Might have to retry again later.
730             let retry_at = self.cars[&id]
731                 .crossing_state_with_end_dist(
732                     // Update again when we've completely cleared all last_steps. We could be more
733                     // precise and do it sooner when we clear the last step, but a little delay is
734                     // fine for correctness.
735                     DistanceInterval::new_driving(
736                         dist_along_last,
737                         self.cars[&id].vehicle.length + FOLLOWING_DISTANCE,
738                     ),
739                     now,
740                     map,
741                 )
742                 .get_end_time();
743             // Sometimes due to rounding, retry_at will be exactly time, but we really need to
744             // wait a bit longer.
745             // TODO Smarter retry based on states and stuckness?
746             if retry_at > now {
747                 scheduler.push(retry_at, Command::UpdateLaggyHead(id));
748             } else {
749                 // If we look up car positions before this retry happens, weird things can
750                 // happen -- the laggy head could be well clear of the old queue by then. Make
751                 // sure to handle that there. Consequences of this retry being long? A follower
752                 // will wait a bit before advancing.
753                 scheduler.push(
754                     now + BLIND_RETRY_TO_CREEP_FORWARDS,
755                     Command::UpdateLaggyHead(id),
756                 );
757             }
758         }
759     }
760 
761     // Caller has to figure out how many steps to trim!
trim_last_steps( &mut self, car: &mut Car, now: Time, n: usize, map: &Map, intersections: &mut IntersectionSimState, scheduler: &mut Scheduler, )762     fn trim_last_steps(
763         &mut self,
764         car: &mut Car,
765         now: Time,
766         n: usize,
767         map: &Map,
768         intersections: &mut IntersectionSimState,
769         scheduler: &mut Scheduler,
770     ) {
771         for i in 0..n {
772             let on = car.last_steps.pop_back().unwrap();
773             let old_queue = self.queues.get_mut(&on).unwrap();
774             assert_eq!(old_queue.laggy_head, Some(car.vehicle.id));
775             old_queue.laggy_head = None;
776             match on {
777                 Traversable::Turn(t) => {
778                     intersections.turn_finished(
779                         now,
780                         AgentID::Car(car.vehicle.id),
781                         t,
782                         scheduler,
783                         map,
784                     );
785                 }
786                 Traversable::Lane(l) => {
787                     old_queue.free_reserved_space(car);
788                     intersections.space_freed(now, map.get_l(l).src_i, scheduler, map);
789                 }
790             }
791 
792             if i == 0 {
793                 // Wake up the follower
794                 if let Some(follower_id) = old_queue.cars.front() {
795                     let mut follower = self.cars.get_mut(&follower_id).unwrap();
796 
797                     match follower.state {
798                         CarState::Queued { blocked_since } => {
799                             // If they're on their last step, they might be ending early and not
800                             // right behind us.
801                             if !follower.router.last_step() {
802                                 // The follower has been smoothly following while the laggy head
803                                 // gets out of the way. So
804                                 // immediately promote them to WaitingToAdvance.
805                                 follower.state = CarState::WaitingToAdvance { blocked_since };
806                                 if self.recalc_lanechanging {
807                                     follower.router.opportunistically_lanechange(
808                                         &self.queues,
809                                         map,
810                                         self.handle_uber_turns,
811                                     );
812                                 }
813                                 scheduler.push(now, Command::UpdateCar(follower.vehicle.id));
814                             }
815                         }
816                         CarState::WaitingToAdvance { .. } => unreachable!(),
817                         // They weren't blocked. Note that there's no way the Crossing state
818                         // could jump forwards here; the leader
819                         // vanished from the end of the traversable.
820                         CarState::Crossing(_, _)
821                         | CarState::Unparking(_, _, _)
822                         | CarState::Parking(_, _, _)
823                         | CarState::IdlingAtStop(_, _) => {}
824                     }
825                 }
826             } else {
827                 // Only the last step we cleared could possibly have cars. Any intermediates,
828                 // this car was previously completely blocking them.
829                 assert!(old_queue.cars.is_empty());
830             }
831         }
832     }
833 
get_unzoomed_agents(&self, now: Time, map: &Map) -> Vec<UnzoomedAgent>834     pub fn get_unzoomed_agents(&self, now: Time, map: &Map) -> Vec<UnzoomedAgent> {
835         let mut result = Vec::new();
836 
837         for queue in self.queues.values() {
838             if queue.cars.is_empty() {
839                 continue;
840             }
841 
842             for (c, dist) in queue.get_car_positions(now, &self.cars, &self.queues) {
843                 let car = &self.cars[&c];
844                 result.push(UnzoomedAgent {
845                     vehicle_type: Some(car.vehicle.vehicle_type),
846                     pos: match queue.id.dist_along(dist, map) {
847                         Ok((pt, _)) => pt,
848                         Err(err) => panic!(
849                             "At {}, invalid dist_along of {} for queue {}: {}",
850                             now, dist, queue.id, err
851                         ),
852                     },
853                     person: car.trip_and_person.map(|(_, p)| p),
854                     parking: car.is_parking(),
855                 });
856             }
857         }
858 
859         result
860     }
861 
does_car_exist(&self, id: CarID) -> bool862     pub fn does_car_exist(&self, id: CarID) -> bool {
863         self.cars.contains_key(&id)
864     }
865 
get_all_draw_cars( &self, now: Time, map: &Map, transit: &TransitSimState, ) -> Vec<DrawCarInput>866     pub fn get_all_draw_cars(
867         &self,
868         now: Time,
869         map: &Map,
870         transit: &TransitSimState,
871     ) -> Vec<DrawCarInput> {
872         let mut result = Vec::new();
873         for queue in self.queues.values() {
874             result.extend(
875                 queue
876                     .get_car_positions(now, &self.cars, &self.queues)
877                     .into_iter()
878                     .map(|(id, dist)| self.cars[&id].get_draw_car(dist, now, map, transit)),
879             );
880         }
881         result
882     }
883 
884     // This is about as expensive as get_draw_cars_on.
get_single_draw_car( &self, id: CarID, now: Time, map: &Map, transit: &TransitSimState, ) -> Option<DrawCarInput>885     pub fn get_single_draw_car(
886         &self,
887         id: CarID,
888         now: Time,
889         map: &Map,
890         transit: &TransitSimState,
891     ) -> Option<DrawCarInput> {
892         let car = self.cars.get(&id)?;
893         self.get_draw_cars_on(now, car.router.head(), map, transit)
894             .into_iter()
895             .find(|d| d.id == id)
896     }
897 
get_draw_cars_on( &self, now: Time, on: Traversable, map: &Map, transit: &TransitSimState, ) -> Vec<DrawCarInput>898     pub fn get_draw_cars_on(
899         &self,
900         now: Time,
901         on: Traversable,
902         map: &Map,
903         transit: &TransitSimState,
904     ) -> Vec<DrawCarInput> {
905         match self.queues.get(&on) {
906             Some(q) => q
907                 .get_car_positions(now, &self.cars, &self.queues)
908                 .into_iter()
909                 .map(|(id, dist)| self.cars[&id].get_draw_car(dist, now, map, transit))
910                 .collect(),
911             None => Vec::new(),
912         }
913     }
914 
debug_car(&self, id: CarID)915     pub fn debug_car(&self, id: CarID) {
916         if let Some(ref car) = self.cars.get(&id) {
917             println!("{}", abstutil::to_json(car));
918             println!("State: {:?}", car.state);
919         } else {
920             println!("{} is parked somewhere", id);
921         }
922     }
923 
debug_lane(&self, id: LaneID)924     pub fn debug_lane(&self, id: LaneID) {
925         if let Some(ref queue) = self.queues.get(&Traversable::Lane(id)) {
926             println!("{}", abstutil::to_json(queue));
927         }
928     }
929 
agent_properties(&self, id: CarID, now: Time) -> AgentProperties930     pub fn agent_properties(&self, id: CarID, now: Time) -> AgentProperties {
931         let car = self.cars.get(&id).unwrap();
932         let path = car.router.get_path();
933 
934         let time_spent_waiting = match car.state {
935             CarState::Queued { blocked_since } | CarState::WaitingToAdvance { blocked_since } => {
936                 now - blocked_since
937             }
938             _ => Duration::ZERO,
939         };
940 
941         AgentProperties {
942             total_time: now - car.started_at,
943             waiting_here: time_spent_waiting,
944             total_waiting: car.total_blocked_time + time_spent_waiting,
945             dist_crossed: path.crossed_so_far(),
946             total_dist: path.total_length(),
947             lanes_crossed: path.lanes_crossed_so_far(),
948             total_lanes: path.total_lanes(),
949         }
950     }
951 
get_path(&self, id: CarID) -> Option<&Path>952     pub fn get_path(&self, id: CarID) -> Option<&Path> {
953         let car = self.cars.get(&id)?;
954         Some(car.router.get_path())
955     }
get_all_driving_paths(&self) -> Vec<&Path>956     pub fn get_all_driving_paths(&self) -> Vec<&Path> {
957         self.cars
958             .values()
959             .map(|car| car.router.get_path())
960             .collect()
961     }
962 
trace_route( &self, now: Time, id: CarID, map: &Map, dist_ahead: Option<Distance>, ) -> Option<PolyLine>963     pub fn trace_route(
964         &self,
965         now: Time,
966         id: CarID,
967         map: &Map,
968         dist_ahead: Option<Distance>,
969     ) -> Option<PolyLine> {
970         let car = self.cars.get(&id)?;
971         let front = self.queues[&car.router.head()]
972             .get_car_positions(now, &self.cars, &self.queues)
973             .into_iter()
974             .find(|(c, _)| *c == id)
975             .unwrap()
976             .1;
977         car.router.get_path().trace(map, front, dist_ahead)
978     }
979 
percent_along_route(&self, id: CarID) -> f64980     pub fn percent_along_route(&self, id: CarID) -> f64 {
981         self.cars[&id].router.get_path().percent_dist_crossed()
982     }
983 
get_owner_of_car(&self, id: CarID) -> Option<PersonID>984     pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
985         let car = self.cars.get(&id)?;
986         car.vehicle.owner
987     }
988 
989     // TODO Clean this up
find_blockage_front( &self, start: CarID, map: &Map, intersections: &IntersectionSimState, ) -> String990     pub fn find_blockage_front(
991         &self,
992         start: CarID,
993         map: &Map,
994         intersections: &IntersectionSimState,
995     ) -> String {
996         let mut seen_intersections = HashSet::new();
997 
998         let mut current_head = start;
999         let mut current_lane = match self.cars[&start].router.head() {
1000             Traversable::Lane(l) => l,
1001             Traversable::Turn(_) => {
1002                 return "TODO Doesn't support starting from a turn yet".to_string();
1003             }
1004         };
1005         loop {
1006             current_head =
1007                 if let Some(c) = self.queues[&Traversable::Lane(current_lane)].cars.get(0) {
1008                     *c
1009                 } else {
1010                     return format!("no gridlock, {}", current_head);
1011                 };
1012 
1013             let i = map.get_l(current_lane).dst_i;
1014             if seen_intersections.contains(&i) {
1015                 return format!("Gridlock near {}! {:?}", i, seen_intersections);
1016             }
1017             seen_intersections.insert(i);
1018 
1019             // Why isn't current_head proceeding? Pedestrians can never get stuck in an
1020             // intersection.
1021             if intersections
1022                 .get_accepted_agents(i)
1023                 .iter()
1024                 .any(|a| matches!(a, AgentID::Car(_)))
1025             {
1026                 return format!("someone's turning in {} still", i);
1027             }
1028 
1029             current_lane = if let Some(PathStep::Lane(l)) = self.cars[&current_head]
1030                 .router
1031                 .get_path()
1032                 .get_steps()
1033                 .get(2)
1034             {
1035                 *l
1036             } else {
1037                 return format!(
1038                     "{} is near end of path, probably tmp blockage",
1039                     current_head
1040                 );
1041             };
1042 
1043             // Lack of capacity?
1044             if self.queues[&Traversable::Lane(current_lane)].room_for_car(&self.cars[&current_head])
1045             {
1046                 return format!("{} is about to proceed, tmp blockage", current_head);
1047             }
1048         }
1049     }
1050 
collect_events(&mut self) -> Vec<Event>1051     pub fn collect_events(&mut self) -> Vec<Event> {
1052         std::mem::replace(&mut self.events, Vec::new())
1053     }
1054 
target_lane_penalty(&self, l: LaneID) -> (usize, usize)1055     pub fn target_lane_penalty(&self, l: LaneID) -> (usize, usize) {
1056         self.queues[&Traversable::Lane(l)].target_lane_penalty()
1057     }
1058 }
1059