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[¤tly_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[¤t_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[¤t_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