1use std::collections::HashMap;
5
6use serde::{Deserialize, Serialize};
7
8use geom::Distance;
9use map_model::{
10 BuildingID, IntersectionID, LaneID, Map, Path, PathConstraints, PathRequest, PathStep,
11 Position, Traversable, Turn, TurnID,
12};
13
14use crate::mechanics::Queue;
15use crate::{
16 AlertLocation, CarID, Event, ParkingSim, ParkingSimState, ParkingSpot, PersonID, SidewalkSpot,
17 TripID, TripPhaseType, Vehicle, VehicleType,
18};
19
20#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
21pub(crate) struct Router {
22 path: Path,
24 goal: Goal,
25 owner: CarID,
26}
27
28#[derive(Debug)]
29pub(crate) enum ActionAtEnd {
30 VanishAtBorder(IntersectionID),
31 StartParking(ParkingSpot),
32 GotoLaneEnd,
33 StopBiking(SidewalkSpot),
34 BusAtStop,
35 GiveUpOnParking,
36}
37
38#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
39enum Goal {
40 ParkNearBuilding {
42 target: BuildingID,
43 spot: Option<(ParkingSpot, Distance)>,
44 stuck_end_dist: Option<Distance>,
46 started_looking: bool,
47 },
48 EndAtBorder {
49 end_dist: Distance,
50 i: IntersectionID,
51 },
52 BikeThenStop {
53 goal: SidewalkSpot,
54 },
55 FollowTransitRoute {
56 end_dist: Distance,
57 },
58}
59
60impl Router {
61 pub fn end_at_border(
62 owner: CarID,
63 path: Path,
64 end_dist: Distance,
65 i: IntersectionID,
66 ) -> Router {
67 Router {
68 path,
69 goal: Goal::EndAtBorder { end_dist, i },
70 owner,
71 }
72 }
73
74 pub fn park_near(owner: CarID, path: Path, bldg: BuildingID) -> Router {
75 Router {
76 path,
77 goal: Goal::ParkNearBuilding {
78 target: bldg,
79 spot: None,
80 stuck_end_dist: None,
81 started_looking: false,
82 },
83 owner,
84 }
85 }
86
87 pub fn bike_then_stop(owner: CarID, path: Path, goal: SidewalkSpot) -> Router {
88 Router {
89 goal: Goal::BikeThenStop { goal },
90 path,
91 owner,
92 }
93 }
94
95 pub fn follow_bus_route(owner: CarID, path: Path) -> Router {
96 Router {
97 goal: Goal::FollowTransitRoute {
98 end_dist: path.get_req().end.dist_along(),
99 },
100 path,
101 owner,
102 }
103 }
104
105 pub fn head(&self) -> Traversable {
106 self.path.current_step().as_traversable()
107 }
108
109 pub fn next(&self) -> Traversable {
110 self.path.next_step().as_traversable()
111 }
112
113 pub fn maybe_next(&self) -> Option<Traversable> {
114 self.path.maybe_next_step().map(|s| s.as_traversable())
115 }
116
117 pub fn last_step(&self) -> bool {
118 self.path.is_last_step()
119 }
120
121 pub fn get_end_dist(&self) -> Distance {
122 assert!(self.last_step());
124 match self.goal {
125 Goal::EndAtBorder { end_dist, .. } => end_dist,
126 Goal::ParkNearBuilding {
127 spot,
128 stuck_end_dist,
129 ..
130 } => stuck_end_dist.unwrap_or_else(|| spot.unwrap().1),
131 Goal::BikeThenStop { ref goal } => goal.sidewalk_pos.dist_along(),
132 Goal::FollowTransitRoute { end_dist } => end_dist,
133 }
134 }
135
136 pub fn get_path(&self) -> &Path {
137 &self.path
138 }
139
140 pub fn advance(
142 &mut self,
143 vehicle: &Vehicle,
144 parking: &ParkingSimState,
145 map: &Map,
146 trip_and_person: Option<(TripID, PersonID)>,
147 events: &mut Vec<Event>,
148 ) -> Traversable {
149 let prev = self.path.shift(map).as_traversable();
150 if self.last_step() {
151 self.maybe_handle_end(
153 Distance::ZERO,
154 vehicle,
155 parking,
156 map,
157 trip_and_person,
158 events,
159 );
160 }
161
162 if let Traversable::Lane(l) = self.head() {
164 let lane = map.get_l(l);
165 if !vehicle.vehicle_type.to_constraints().can_use(lane, map) {
166 panic!(
167 "{} just wound up on {}, a {:?} (check the OSM tags)",
168 vehicle.id, l, lane.lane_type
169 );
170 }
171 }
172
173 prev
174 }
175
176 pub fn maybe_handle_end(
179 &mut self,
180 front: Distance,
181 vehicle: &Vehicle,
182 parking: &ParkingSimState,
183 map: &Map,
184 trip_and_person: Option<(TripID, PersonID)>,
186 events: &mut Vec<Event>,
187 ) -> Option<ActionAtEnd> {
188 assert!(self.path.is_last_step());
189
190 match self.goal {
191 Goal::EndAtBorder { end_dist, i } => {
192 if end_dist == front {
193 Some(ActionAtEnd::VanishAtBorder(i))
194 } else {
195 None
196 }
197 }
198 Goal::ParkNearBuilding {
199 ref mut spot,
200 ref mut stuck_end_dist,
201 target,
202 ref mut started_looking,
203 } => {
204 if let Some(d) = stuck_end_dist {
205 if *d == front {
206 return Some(ActionAtEnd::GiveUpOnParking);
207 } else {
208 return None;
209 }
210 }
211
212 let need_new_spot = match spot {
213 Some((s, _)) => !parking.is_free(*s),
214 None => true,
215 };
216 if need_new_spot {
217 *started_looking = true;
218 let current_lane = self.path.current_step().as_lane();
219 let candidates = parking.get_all_free_spots(
220 Position::new(current_lane, front),
221 vehicle,
222 target,
223 map,
224 );
225 let best =
226 if let Some((driving_pos, _)) = map.get_b(target).driving_connection(map) {
227 if driving_pos.lane() == current_lane {
228 let target_dist = driving_pos.dist_along();
229 candidates
231 .into_iter()
232 .min_by_key(|(_, pos)| (pos.dist_along() - target_dist).abs())
233 } else {
234 candidates
236 .into_iter()
237 .min_by_key(|(_, pos)| pos.dist_along())
238 }
239 } else {
240 candidates
242 .into_iter()
243 .min_by_key(|(_, pos)| pos.dist_along())
244 };
245 if let Some((new_spot, new_pos)) = best {
246 if let Some((t, p)) = trip_and_person {
247 events.push(Event::TripPhaseStarting(
248 t,
249 p,
250 Some(PathRequest::vehicle(
251 Position::new(current_lane, front),
252 new_pos,
253 PathConstraints::Car,
254 )),
255 TripPhaseType::Parking,
256 ));
257 }
258 assert_eq!(new_pos.lane(), current_lane);
259 assert!(new_pos.dist_along() >= front);
260 *spot = Some((new_spot, new_pos.dist_along()));
261 } else {
262 if let Some((new_path_steps, new_spot, new_pos)) =
263 parking.path_to_free_parking_spot(current_lane, vehicle, target, map)
264 {
265 assert!(!new_path_steps.is_empty());
266 for step in new_path_steps {
267 self.path.add(step, map);
268 }
269 *spot = Some((new_spot, new_pos.dist_along()));
270 events.push(Event::PathAmended(self.path.clone()));
271 if let Some((t, p)) = trip_and_person {
273 events.push(Event::TripPhaseStarting(
274 t,
275 p,
276 Some(PathRequest::vehicle(
277 Position::new(current_lane, front),
278 new_pos,
279 PathConstraints::Car,
280 )),
281 TripPhaseType::Parking,
282 ));
283 }
284 } else {
285 if let Some((_, p)) = trip_and_person {
286 events.push(Event::Alert(
287 AlertLocation::Person(p),
288 format!(
289 "{} can't find parking on {} or anywhere reachable from \
290 it. Possibly we're just totally out of parking space!",
291 vehicle.id, current_lane
292 ),
293 ));
294 }
295 *stuck_end_dist = Some(map.get_l(current_lane).length());
296 }
297 return Some(ActionAtEnd::GotoLaneEnd);
298 }
299 }
300
301 if spot.unwrap().1 == front {
302 Some(ActionAtEnd::StartParking(spot.unwrap().0))
303 } else {
304 None
305 }
306 }
307 Goal::BikeThenStop { ref goal } => {
308 if goal.sidewalk_pos.dist_along() == front {
309 Some(ActionAtEnd::StopBiking(goal.clone()))
310 } else {
311 None
312 }
313 }
314 Goal::FollowTransitRoute { end_dist } => {
315 if end_dist == front {
316 Some(ActionAtEnd::BusAtStop)
317 } else {
318 None
319 }
320 }
321 }
322 }
323
324 pub fn opportunistically_lanechange(
325 &mut self,
326 queues: &HashMap<Traversable, Queue>,
327 map: &Map,
328 handle_uber_turns: bool,
329 ) {
330 if handle_uber_turns && self.path.currently_inside_ut().is_some() {
333 return;
334 }
335
336 let mut segment = 0;
337 loop {
338 let (current_turn, next_lane) = {
339 let steps = self.path.get_steps();
340 if steps.len() < 5 + segment * 2 {
341 return;
342 }
343 match (steps[1 + segment * 2], steps[4 + segment * 2]) {
344 (PathStep::Turn(t), PathStep::Lane(l)) => (t, l),
345 _ => {
346 return;
347 }
348 }
349 };
350
351 let orig_target_lane = current_turn.dst;
352 let parent = map.get_parent(orig_target_lane);
353 let next_parent = map.get_l(next_lane).src_i;
354 let constraints = self.owner.vehicle_type.to_constraints();
355
356 let compute_cost = |turn1: &Turn, lane: LaneID| {
357 let (lt, lc, mut slow_lane) = turn1.penalty(constraints, map);
358 let (vehicles, mut bike) = queues[&Traversable::Lane(lane)].target_lane_penalty();
359
360 if self.owner.vehicle_type == VehicleType::Bike {
376 bike = 0;
377 } else {
378 slow_lane = 0;
379 }
380
381 (lt, bike, slow_lane, vehicles + lc)
382 };
383
384 let mut original_cost = None;
386 let dir = map.get_l(orig_target_lane).dir;
387 let best = parent
388 .lanes
389 .iter()
390 .filter(|l| l.dir == dir && constraints.can_use(l, map))
391 .filter_map(|l| {
392 let t1 = TurnID {
395 parent: current_turn.parent,
396 src: current_turn.src,
397 dst: l.id,
398 };
399 let turn1 = map.maybe_get_t(t1)?;
400
401 let t2 = TurnID {
402 parent: next_parent,
403 src: l.id,
404 dst: next_lane,
405 };
406 let turn2 = map.maybe_get_t(t2)?;
407
408 Some((turn1, l.id, turn2))
409 })
410 .map(|(turn1, l, turn2)| {
411 let cost = compute_cost(turn1, l);
412 if turn1.id == current_turn {
413 original_cost = Some(cost);
414 }
415 (cost, turn1, l, turn2)
416 })
417 .min_by_key(|(cost, _, _, _)| *cost);
418
419 if best.is_none() {
420 error!("no valid paths found: {:?}", self.owner);
421 return;
422 }
423 let (best_cost, turn1, best_lane, turn2) = best.unwrap();
424
425 if original_cost.is_none() {
426 error!("original_cost was unexpectedly None {:?}", self.owner);
427 return;
428 }
429 let original_cost = original_cost.unwrap();
430
431 if best_cost < original_cost {
434 debug!(
435 "changing lanes {:?} -> {:?}, cost: {:?} -> {:?}",
436 orig_target_lane, best_lane, original_cost, best_cost
437 );
438 self.path
439 .modify_step(1 + segment * 2, PathStep::Turn(turn1.id), map);
440 self.path
441 .modify_step(2 + segment * 2, PathStep::Lane(best_lane), map);
442 self.path
443 .modify_step(3 + segment * 2, PathStep::Turn(turn2.id), map);
444 }
445
446 if self.path.is_upcoming_uber_turn_component(turn2.id) {
447 segment += 1;
448 } else {
449 break;
451 }
452 }
453 }
454
455 pub fn can_lanechange(&self, from: LaneID, to: LaneID, map: &Map) -> bool {
456 let steps = self.path.get_steps();
457 if steps.len() < 3 {
458 return false;
459 }
460 assert_eq!(PathStep::Lane(from), steps[0]);
461 let current_turn = match steps[1] {
462 PathStep::Turn(t) => t,
463 _ => unreachable!(),
464 };
465 let next_lane = current_turn.dst;
466 assert_eq!(PathStep::Lane(next_lane), steps[2]);
467 map.maybe_get_t(TurnID {
468 parent: current_turn.parent,
469 src: to,
470 dst: next_lane,
471 })
472 .is_some()
473 }
474
475 pub fn confirm_lanechange(&mut self, to: LaneID, map: &Map) {
476 self.path.modify_step(0, PathStep::Lane(to), map);
478 let mut turn = match self.path.get_steps()[1] {
479 PathStep::Turn(t) => t,
480 _ => unreachable!(),
481 };
482 turn.src = to;
483 self.path.modify_step(1, PathStep::Turn(turn), map);
484 }
485
486 pub fn is_parking(&self) -> bool {
487 match self.goal {
488 Goal::ParkNearBuilding {
489 started_looking, ..
490 } => started_looking,
491 _ => false,
492 }
493 }
494
495 pub fn get_parking_spot_goal(&self) -> Option<&ParkingSpot> {
496 match self.goal {
497 Goal::ParkNearBuilding { ref spot, .. } => spot.as_ref().map(|(s, _)| s),
498 _ => None,
499 }
500 }
501}