sim/sim/
queries.rs

1//! All sorts of read-only queries about a simulation
2
3use anyhow::Result;
4use serde::Serialize;
5use std::collections::{BTreeMap, BTreeSet};
6
7use abstutil::Counter;
8use geom::{Distance, Duration, PolyLine, Pt2D, Time};
9use map_model::{
10    BuildingID, IntersectionID, Lane, LaneID, Map, Path, Position, RoadID, TransitRouteID,
11    TransitStopID, Traversable, TurnID,
12};
13use synthpop::{OrigPersonID, Scenario, TripMode};
14
15use crate::analytics::SlidingWindow;
16use crate::{
17    AgentID, AgentType, Analytics, CarID, CommutersVehiclesCounts, DrawCarInput, DrawPedCrowdInput,
18    DrawPedestrianInput, PandemicModel, ParkedCar, ParkingSim, PedestrianID, Person, PersonID,
19    PersonState, Sim, TripEndpoint, TripID, TripInfo, TripResult, UnzoomedAgent, VehicleType,
20};
21
22// TODO Many of these just delegate to an inner piece. This is unorganized and hard to maintain.
23impl Sim {
24    pub fn time(&self) -> Time {
25        self.time
26    }
27
28    pub fn is_done(&self) -> bool {
29        self.trips.is_done()
30    }
31
32    pub fn is_empty(&self) -> bool {
33        self.time == Time::START_OF_DAY && self.is_done()
34    }
35
36    /// (number of finished trips, number of unfinished trips)
37    pub fn num_trips(&self) -> (usize, usize) {
38        self.trips.num_trips()
39    }
40    pub fn num_agents(&self) -> Counter<AgentType> {
41        self.trips.num_agents(&self.transit)
42    }
43    pub fn num_commuters_vehicles(&self) -> CommutersVehiclesCounts {
44        self.trips
45            .num_commuters_vehicles(&self.transit, &self.walking)
46    }
47    /// (total number of people, just in buildings, just off map)
48    pub fn num_ppl(&self) -> (usize, usize, usize) {
49        self.trips.num_ppl()
50    }
51
52    pub fn debug_ped(&self, id: PedestrianID) {
53        println!("{}", self.walking.debug_ped_json(id));
54        self.trips.debug_trip(AgentID::Pedestrian(id));
55    }
56
57    pub fn debug_car(&self, id: CarID) {
58        println!("{}", self.driving.debug_car_json(id));
59        self.trips.debug_trip(AgentID::Car(id));
60    }
61
62    /// Return a short string to debug a car in the UI.
63    pub fn debug_car_ui(&self, id: CarID) -> String {
64        self.driving.debug_car_ui(id)
65    }
66
67    pub fn debug_agent_json(&self, id: AgentID) -> String {
68        match id {
69            AgentID::Car(id) => self.driving.debug_car_json(id),
70            AgentID::Pedestrian(id) => self.walking.debug_ped_json(id),
71            AgentID::BusPassenger(_, id) => self.driving.debug_car_json(id),
72        }
73    }
74
75    pub fn debug_intersection_json(&self, id: IntersectionID, map: &Map) -> String {
76        self.intersections.debug_json(id, map)
77    }
78
79    pub fn debug_lane(&self, id: LaneID) {
80        self.driving.debug_lane(id);
81    }
82
83    /// Only call for active agents, will panic otherwise
84    pub fn agent_properties(&self, map: &Map, id: AgentID) -> AgentProperties {
85        match id {
86            AgentID::Pedestrian(id) => self.walking.agent_properties(map, id, self.time),
87            AgentID::Car(id) => self.driving.agent_properties(id, self.time),
88            // TODO Harder to measure some of this stuff
89            AgentID::BusPassenger(_, _) => AgentProperties {
90                total_time: Duration::ZERO,
91                waiting_here: Duration::ZERO,
92                total_waiting: Duration::ZERO,
93                dist_crossed: Distance::ZERO,
94                total_dist: Distance::meters(0.1),
95            },
96        }
97    }
98
99    pub fn num_transit_passengers(&self, car: CarID) -> usize {
100        self.transit.get_passengers(car).len()
101    }
102
103    pub fn bus_route_id(&self, maybe_bus: CarID) -> Option<TransitRouteID> {
104        if maybe_bus.vehicle_type == VehicleType::Bus
105            || maybe_bus.vehicle_type == VehicleType::Train
106        {
107            Some(self.transit.bus_route(maybe_bus))
108        } else {
109            None
110        }
111    }
112
113    pub fn active_agents(&self) -> Vec<AgentID> {
114        self.trips.active_agents()
115    }
116    pub fn num_active_agents(&self) -> usize {
117        self.trips.num_active_agents()
118    }
119
120    pub fn agent_to_trip(&self, id: AgentID) -> Option<TripID> {
121        self.trips.agent_to_trip(id)
122    }
123
124    pub fn trip_to_agent(&self, id: TripID) -> TripResult<AgentID> {
125        self.trips.trip_to_agent(id)
126    }
127
128    pub fn trip_info(&self, id: TripID) -> TripInfo {
129        self.trips.trip_info(id)
130    }
131    pub fn all_trip_info(&self) -> Vec<(TripID, TripInfo)> {
132        self.trips.all_trip_info()
133    }
134    /// If trip is finished, returns (total time, total waiting time, total distance)
135    pub fn finished_trip_details(&self, id: TripID) -> Option<(Duration, Duration, Distance)> {
136        self.trips.finished_trip_details(id)
137    }
138    // Returns the total time a trip was blocked for
139    pub fn trip_blocked_time(&self, id: TripID) -> Duration {
140        self.trips.trip_blocked_time(id)
141    }
142
143    pub fn trip_to_person(&self, id: TripID) -> Option<PersonID> {
144        self.trips.trip_to_person(id)
145    }
146    // TODO This returns None for parked cars owned by people! That's confusing. Dedupe with
147    // get_owner_of_car.
148    pub fn agent_to_person(&self, id: AgentID) -> Option<PersonID> {
149        self.agent_to_trip(id)
150            .map(|t| self.trip_to_person(t).unwrap())
151    }
152    pub fn person_to_agent(&self, id: PersonID) -> Option<AgentID> {
153        if let PersonState::Trip(t) = self.trips.get_person(id)?.state {
154            self.trip_to_agent(t).ok()
155        } else {
156            None
157        }
158    }
159    pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
160        self.driving
161            .get_owner_of_car(id)
162            .or_else(|| self.parking.get_owner_of_car(id))
163    }
164    pub fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
165        self.parking.lookup_parked_car(id)
166    }
167    /// For every parked car, (position of parking spot, position of owner)
168    pub fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, Position)> {
169        self.parking
170            .all_parked_car_positions(map)
171            .into_iter()
172            .filter_map(|(car_pos, owner)| {
173                // TODO Should include people off-map and in the middle of a non-car trip too
174                match self.trips.get_person(owner)?.state {
175                    PersonState::Inside(b) => Some((car_pos, map.get_b(b).sidewalk_pos)),
176                    PersonState::Trip(_) => None,
177                    PersonState::OffMap => None,
178                }
179            })
180            .collect()
181    }
182
183    pub fn lookup_person(&self, id: PersonID) -> Option<&Person> {
184        self.trips.get_person(id)
185    }
186    pub fn get_person(&self, id: PersonID) -> &Person {
187        self.trips.get_person(id).unwrap()
188    }
189    pub fn find_person_by_orig_id(&self, id: OrigPersonID) -> Option<PersonID> {
190        for p in self.get_all_people() {
191            if p.orig_id == Some(id) {
192                return Some(p.id);
193            }
194        }
195        None
196    }
197    pub fn get_all_people(&self) -> &Vec<Person> {
198        self.trips.get_all_people()
199    }
200
201    pub fn lookup_car_id(&self, idx: usize) -> Option<CarID> {
202        for vehicle_type in [
203            VehicleType::Car,
204            VehicleType::Bike,
205            VehicleType::Bus,
206            VehicleType::Train,
207        ] {
208            let id = CarID {
209                id: idx,
210                vehicle_type,
211            };
212            if self.driving.does_car_exist(id) {
213                return Some(id);
214            }
215        }
216
217        let id = CarID {
218            id: idx,
219            vehicle_type: VehicleType::Car,
220        };
221        // Only cars can be parked.
222        if self.parking.lookup_parked_car(id).is_some() {
223            return Some(id);
224        }
225
226        None
227    }
228
229    pub fn get_path(&self, id: AgentID) -> Option<&Path> {
230        match id {
231            AgentID::Car(car) => self.driving.get_path(car),
232            AgentID::Pedestrian(ped) => self.walking.get_path(ped),
233            AgentID::BusPassenger(_, _) => None,
234        }
235    }
236    pub fn get_all_driving_paths(&self) -> Vec<&Path> {
237        self.driving.get_all_driving_paths()
238    }
239
240    pub fn trace_route(&self, id: AgentID, map: &Map) -> Option<PolyLine> {
241        match id {
242            AgentID::Car(car) => self.driving.trace_route(self.time, car, map),
243            AgentID::Pedestrian(ped) => self.walking.trace_route(self.time, ped, map),
244            AgentID::BusPassenger(_, _) => None,
245        }
246    }
247
248    pub fn get_canonical_pt_per_trip(&self, trip: TripID, map: &Map) -> TripResult<Pt2D> {
249        let agent = match self.trips.trip_to_agent(trip) {
250            TripResult::Ok(a) => a,
251            x => {
252                return x.propagate_error();
253            }
254        };
255        if let Some(pt) = self.canonical_pt_for_agent(agent, map) {
256            return TripResult::Ok(pt);
257        }
258        TripResult::ModeChange
259    }
260    pub fn get_canonical_pt_per_person(&self, p: PersonID, map: &Map) -> Option<Pt2D> {
261        match self.trips.get_person(p)?.state {
262            PersonState::Inside(b) => Some(map.get_b(b).polygon.center()),
263            PersonState::Trip(t) => self.get_canonical_pt_per_trip(t, map).ok(),
264            PersonState::OffMap => None,
265        }
266    }
267
268    pub fn canonical_pt_for_agent(&self, id: AgentID, map: &Map) -> Option<Pt2D> {
269        match id {
270            AgentID::Car(id) => self
271                .parking
272                .canonical_pt(id, map)
273                .or_else(|| Some(self.get_draw_car(id, map)?.body.last_pt())),
274            AgentID::Pedestrian(id) => Some(self.get_draw_ped(id, map)?.pos),
275            AgentID::BusPassenger(_, bus) => Some(self.get_draw_car(bus, map)?.body.last_pt()),
276        }
277    }
278
279    pub fn get_accepted_agents(&self, id: IntersectionID) -> Vec<(AgentID, TurnID)> {
280        self.intersections.get_accepted_agents(id)
281    }
282    pub fn get_waiting_agents(&self, id: IntersectionID) -> Vec<(AgentID, TurnID, Time)> {
283        self.intersections.get_waiting_agents(id)
284    }
285
286    /// For every agent that's currently not moving, figure out how long they've been waiting and
287    /// why they're blocked.
288    pub fn get_blocked_by_graph(&self, map: &Map) -> BTreeMap<AgentID, (Duration, DelayCause)> {
289        // Pedestrians can only be blocked at intersections, which is handled inside this call
290        self.driving
291            .get_blocked_by_graph(self.time, map, &self.intersections)
292    }
293
294    /// (bus, stop index it's coming from, percent to next stop, location)
295    pub fn status_of_buses(
296        &self,
297        route: TransitRouteID,
298        map: &Map,
299    ) -> Vec<(CarID, Option<usize>, f64, Pt2D)> {
300        let mut results = Vec::new();
301        for (bus, stop_idx) in self.transit.buses_for_route(route) {
302            results.push((
303                bus,
304                stop_idx,
305                self.driving.percent_along_route(bus),
306                self.canonical_pt_for_agent(AgentID::Car(bus), map).unwrap(),
307            ));
308        }
309        results
310    }
311
312    pub fn get_analytics(&self) -> &Analytics {
313        &self.analytics
314    }
315
316    /// For intersections with an agent waiting beyond some threshold, return when they started
317    /// waiting. Sorted by earliest waiting (likely the root cause of gridlock).
318    pub fn delayed_intersections(&self, threshold: Duration) -> Vec<(IntersectionID, Time)> {
319        self.intersections
320            .delayed_intersections(self.time, threshold)
321    }
322
323    pub fn bldg_to_people(&self, b: BuildingID) -> Vec<PersonID> {
324        self.trips.bldg_to_people(b)
325    }
326
327    pub fn get_pandemic_model(&self) -> Option<&PandemicModel> {
328        self.pandemic.as_ref()
329    }
330
331    pub fn get_end_of_day(&self) -> Time {
332        // Always count at least 24 hours
333        // TODO This should be min()? Also, the end of the day will keep shifting every time we run
334        // this query, since the trips near the end of the day will schedule more events as they
335        // progress.
336        self.scheduler
337            .get_last_time()
338            .max(Time::START_OF_DAY + Duration::hours(24))
339    }
340
341    pub fn current_stage_and_remaining_time(&self, i: IntersectionID) -> (usize, Duration) {
342        self.intersections
343            .current_stage_and_remaining_time(self.time, i)
344    }
345
346    // TODO This is an awkward copy of raw_throughput
347    // TODO And it does NOT count buses/trains spawning
348    pub fn all_arrivals_at_border(
349        &self,
350        i: IntersectionID,
351    ) -> Vec<(AgentType, Vec<(Time, usize)>)> {
352        let window_size = Duration::hours(1);
353        let mut pts_per_type: BTreeMap<AgentType, Vec<(Time, usize)>> = BTreeMap::new();
354        let mut windows_per_type: BTreeMap<AgentType, SlidingWindow> = BTreeMap::new();
355        for agent_type in AgentType::all() {
356            pts_per_type.insert(agent_type, vec![(Time::START_OF_DAY, 0)]);
357            windows_per_type.insert(agent_type, SlidingWindow::new(window_size));
358        }
359
360        for (t, agent_type) in self.trips.all_arrivals_at_border(i) {
361            let count = windows_per_type.get_mut(&agent_type).unwrap().add(t);
362            pts_per_type.get_mut(&agent_type).unwrap().push((t, count));
363        }
364
365        for (agent_type, pts) in pts_per_type.iter_mut() {
366            let mut window = windows_per_type.remove(agent_type).unwrap();
367            window.close_off_pts(pts, self.get_end_of_day());
368        }
369
370        pts_per_type.into_iter().collect()
371    }
372
373    /// (number of vehicles in the lane, penalty if a bike or other slow vehicle is present)
374    pub fn target_lane_penalty(&self, lane: &Lane) -> (usize, usize) {
375        if lane.is_walkable() {
376            (0, 0)
377        } else {
378            self.driving.target_lane_penalty(lane.id)
379        }
380    }
381
382    pub fn get_people_waiting_at_stop(
383        &self,
384        at: TransitStopID,
385    ) -> &Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)> {
386        self.transit.get_people_waiting_at_stop(at)
387    }
388
389    pub fn generate_scenario(&self, map: &Map, name: String) -> Scenario {
390        self.trips.generate_scenario(map, name)
391    }
392
393    pub fn infinite_parking(&self) -> bool {
394        self.parking.is_infinite()
395    }
396
397    pub fn all_waiting_people(&self) -> BTreeMap<PersonID, Duration> {
398        let mut delays = BTreeMap::new();
399        self.walking.all_waiting_people(self.time, &mut delays);
400        self.driving.all_waiting_people(self.time, &mut delays);
401        delays
402    }
403
404    pub fn describe_internal_stats(&self) -> Vec<String> {
405        let mut stats = self.scheduler.describe_stats();
406        stats.push(String::new());
407        stats.extend(self.intersections.describe_stats());
408        stats
409    }
410
411    pub fn debug_queue_lengths(&self, l: LaneID) -> Option<(Distance, Distance)> {
412        self.driving.debug_queue_lengths(l)
413    }
414
415    /// Returns the best-case time for a trip in a world with no traffic or intersection delays.
416    /// Might fail in some cases where the real trip succeeds, but the single-mode path can't be
417    /// found. Assumes the TripID exists.
418    pub fn get_trip_time_lower_bound(&self, map: &Map, id: TripID) -> Result<Duration> {
419        let info = self.trips.trip_info(id);
420        match TripEndpoint::path_req(info.start, info.end, info.mode, map) {
421            Some(req) => {
422                let path = map.pathfind(req)?;
423                let person = self
424                    .trips
425                    .get_person(self.trips.trip_to_person(id).unwrap())
426                    .unwrap();
427                let max_speed = match info.mode {
428                    TripMode::Walk | TripMode::Transit => Some(person.ped_speed),
429                    // TODO We should really search the vehicles and grab it from there
430                    TripMode::Drive => None,
431                    // Assume just one bike
432                    TripMode::Bike => {
433                        person
434                            .vehicles
435                            .iter()
436                            .find(|v| v.vehicle_type == VehicleType::Bike)
437                            .unwrap()
438                            .max_speed
439                    }
440                };
441                Ok(path.estimate_duration(map, max_speed))
442            }
443            None => bail!(
444                "can't figure out PathRequest from {:?} to {:?} via {}",
445                info.start,
446                info.end,
447                info.mode.ongoing_verb()
448            ),
449        }
450    }
451
452    pub fn get_highlighted_people(&self) -> &Option<BTreeSet<PersonID>> {
453        &self.highlighted_people
454    }
455
456    /// Returns people / m^2. Roads have up to two sidewalks and intersections have many crossings
457    /// -- take the max density along any one.
458    pub fn get_pedestrian_density(
459        &self,
460        map: &Map,
461    ) -> (BTreeMap<RoadID, f64>, BTreeMap<IntersectionID, f64>) {
462        self.walking.get_pedestrian_density(map)
463    }
464}
465
466// Drawing
467impl Sim {
468    pub fn step_count(&self) -> usize {
469        self.step_count
470    }
471
472    pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
473        self.parking.get_draw_car(id, map).or_else(|| {
474            self.driving
475                .get_single_draw_car(id, self.time, map, &self.transit)
476        })
477    }
478
479    pub fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
480        self.walking.get_draw_ped(id, self.time, map)
481    }
482
483    pub fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput> {
484        let mut results = Vec::new();
485        if let Traversable::Lane(l) = on {
486            if map.get_l(l).is_parking() {
487                return self.parking.get_draw_cars(l, map);
488            }
489            results.extend(self.parking.get_draw_cars_in_lots(l, map));
490        }
491        results.extend(
492            self.driving
493                .get_draw_cars_on(self.time, on, map, &self.transit),
494        );
495        results
496    }
497
498    pub fn get_draw_peds(
499        &self,
500        on: Traversable,
501        map: &Map,
502    ) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
503        self.walking.get_draw_peds_on(self.time, on, map)
504    }
505
506    pub fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
507        let mut result = self
508            .driving
509            .get_all_draw_cars(self.time, map, &self.transit);
510        result.extend(self.parking.get_all_draw_cars(map));
511        result
512    }
513
514    pub fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput> {
515        self.walking.get_all_draw_peds(self.time, map)
516    }
517
518    /// This does not include transit riders. Some callers need those in addition, but the
519    /// rendering ones don't.
520    pub fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent> {
521        let mut result = self.driving.get_unzoomed_agents(self.time, map);
522        result.extend(self.walking.get_unzoomed_agents(self.time, map));
523        result
524    }
525    pub fn get_unzoomed_transit_riders(&self, map: &Map) -> Vec<UnzoomedAgent> {
526        self.transit
527            .get_unzoomed_transit_riders(self.time, &self.driving, map)
528    }
529}
530
531pub struct AgentProperties {
532    // TODO Of this leg of the trip only!
533    pub total_time: Duration,
534    pub waiting_here: Duration,
535    pub total_waiting: Duration,
536
537    pub dist_crossed: Distance,
538    pub total_dist: Distance,
539}
540
541/// Why is an agent delayed? If there are multiple reasons, arbitrarily pick one -- ie, somebody
542/// could be blocked by two conflicting turns.
543#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize)]
544pub enum DelayCause {
545    /// Queued behind someone, or someone's doing a conflicting turn, or someone's eating up space
546    /// in a target queue
547    Agent(AgentID),
548    /// Waiting on a traffic signal to change, or pausing at a stop sign before proceeding
549    Intersection(IntersectionID),
550}