diff --git a/editor/src/common/trip_explorer.rs b/editor/src/common/trip_explorer.rs index 209bcc0cea..13849a04ce 100644 --- a/editor/src/common/trip_explorer.rs +++ b/editor/src/common/trip_explorer.rs @@ -21,7 +21,7 @@ impl TripExplorer { .as_ref() .and_then(|id| id.agent_id())?; let trip = ui.primary.sim.agent_to_trip(agent)?; - let status = ui.primary.sim.trip_status(trip)?; + let status = ui.primary.sim.trip_status(trip); if !ctx.input.contextual_action(Key::T, "explore trip") { return None; } @@ -33,6 +33,11 @@ impl TripExplorer { ID::Building(b), Text::from(Line(format!("start at {}", map.get_b(b).get_name()))), ), + TripStart::Border(i) => ( + map.get_i(i).polygon.center(), + ID::Intersection(i), + Text::from(Line(format!("enter map via {}", i))), + ), TripStart::Appearing(pos) => ( pos.pt(map), ID::Lane(pos.lane()), @@ -62,6 +67,15 @@ impl TripExplorer { ID::Intersection(i), Text::from(Line(format!("leave map via {}", i))), ), + TripEnd::ServeBusRoute(br) => { + let route = map.get_br(br); + let stop = map.get_bs(route.stops[0]); + ( + stop.driving_pos.pt(map), + ID::BusStop(stop.id), + Text::from(Line(format!("serve route {} forever", route.name))), + ) + } }, ]; diff --git a/sim/src/make/spawner.rs b/sim/src/make/spawner.rs index 9ed84d373b..f87f2e66a3 100644 --- a/sim/src/make/spawner.rs +++ b/sim/src/make/spawner.rs @@ -5,7 +5,7 @@ use crate::{ }; use abstutil::Timer; use geom::{Duration, Speed, EPSILON_DIST}; -use map_model::{BuildingID, BusRouteID, BusStopID, Map, PathRequest, Position}; +use map_model::{BuildingID, BusRouteID, BusStopID, IntersectionType, Map, PathRequest, Position}; use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeSet; @@ -193,8 +193,15 @@ impl TripSpawner { SidewalkSpot::building(b, map), )); } - let trip = - trips.new_trip(start_time, Some(TripStart::Appearing(start_pos)), legs); + let trip_start = { + let src_i = map.get_i(map.get_l(start_pos.lane()).src_i); + if src_i.intersection_type == IntersectionType::Border { + TripStart::Border(src_i.id) + } else { + TripStart::Appearing(start_pos) + } + }; + let trip = trips.new_trip(start_time, trip_start, legs); let router = goal.make_router(path, map, vehicle.vehicle_type); scheduler.quick_push( start_time, @@ -232,11 +239,8 @@ impl TripSpawner { } DrivingGoal::Border(_, _) => {} } - let trip = trips.new_trip( - start_time, - Some(TripStart::Bldg(vehicle.owner.unwrap())), - legs, - ); + let trip = + trips.new_trip(start_time, TripStart::Bldg(vehicle.owner.unwrap()), legs); scheduler.quick_push( start_time, @@ -259,7 +263,7 @@ impl TripSpawner { // Can't add TripLeg::Drive, because we don't know the vehicle yet! Plumb along // the DrivingGoal, so we can expand the trip later. let legs = vec![TripLeg::Walk(ped_id.unwrap(), ped_speed, walk_to.clone())]; - let trip = trips.new_trip(start_time, Some(TripStart::Bldg(start_bldg)), legs); + let trip = trips.new_trip(start_time, TripStart::Bldg(start_bldg), legs); scheduler.quick_push( start_time, @@ -282,10 +286,9 @@ impl TripSpawner { let trip = trips.new_trip( start_time, match start.connection { - SidewalkPOI::Building(b) => Some(TripStart::Bldg(b)), - SidewalkPOI::SuddenlyAppear | SidewalkPOI::Border(_) => { - Some(TripStart::Appearing(start.sidewalk_pos)) - } + SidewalkPOI::Building(b) => TripStart::Bldg(b), + SidewalkPOI::SuddenlyAppear => TripStart::Appearing(start.sidewalk_pos), + SidewalkPOI::Border(i) => TripStart::Border(i), _ => unreachable!(), }, vec![TripLeg::Walk(ped_id.unwrap(), ped_speed, goal.clone())], @@ -328,10 +331,9 @@ impl TripSpawner { let trip = trips.new_trip( start_time, match start.connection { - SidewalkPOI::Building(b) => Some(TripStart::Bldg(b)), - SidewalkPOI::SuddenlyAppear | SidewalkPOI::Border(_) => { - Some(TripStart::Appearing(start.sidewalk_pos)) - } + SidewalkPOI::Building(b) => TripStart::Bldg(b), + SidewalkPOI::SuddenlyAppear => TripStart::Appearing(start.sidewalk_pos), + SidewalkPOI::Border(i) => TripStart::Border(i), _ => unreachable!(), }, legs, @@ -361,10 +363,9 @@ impl TripSpawner { let trip = trips.new_trip( start_time, match start.connection { - SidewalkPOI::Building(b) => Some(TripStart::Bldg(b)), - SidewalkPOI::SuddenlyAppear | SidewalkPOI::Border(_) => { - Some(TripStart::Appearing(start.sidewalk_pos)) - } + SidewalkPOI::Building(b) => TripStart::Bldg(b), + SidewalkPOI::SuddenlyAppear => TripStart::Appearing(start.sidewalk_pos), + SidewalkPOI::Border(i) => TripStart::Border(i), _ => unreachable!(), }, vec![ diff --git a/sim/src/sim.rs b/sim/src/sim.rs index 8f87b9c172..8ca9d4fe38 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -3,13 +3,15 @@ use crate::{ DrivingGoal, DrivingSimState, Event, FinishedTrips, GetDrawAgents, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, Router, Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripID, TripLeg, TripManager, TripPositions, TripSpawner, - TripSpec, TripStatus, UnzoomedAgent, VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH, + TripSpec, TripStart, TripStatus, UnzoomedAgent, VehicleSpec, VehicleType, WalkingSimState, + BUS_LENGTH, }; use abstutil::{elapsed_seconds, Timer}; use derivative::Derivative; use geom::{Distance, Duration, PolyLine, Pt2D}; use map_model::{ - BuildingID, BusRoute, BusRouteID, IntersectionID, LaneID, Map, Path, PathRequest, Traversable, + BuildingID, BusRoute, BusRouteID, IntersectionID, LaneID, Map, Path, PathRequest, Position, + Traversable, }; use serde_derive::{Deserialize, Serialize}; use std::collections::{HashSet, VecDeque}; @@ -233,9 +235,11 @@ impl Sim { // Bypass some layers of abstraction that don't make sense for buses. - let trip = - self.trips - .new_trip(self.time, None, vec![TripLeg::ServeBusRoute(id, route.id)]); + let trip = self.trips.new_trip( + self.time, + TripStart::Appearing(Position::new(path.current_step().as_lane(), start_dist)), + vec![TripLeg::ServeBusRoute(id, route.id)], + ); if self.driving.start_car_on_lane( self.time, CreateCar { @@ -795,7 +799,7 @@ impl Sim { self.trips.trip_to_agent(id) } - pub fn trip_status(&self, id: TripID) -> Option { + pub fn trip_status(&self, id: TripID) -> TripStatus { self.trips.trip_status(id) } diff --git a/sim/src/trips.rs b/sim/src/trips.rs index ad9a404adf..be331fc90a 100644 --- a/sim/src/trips.rs +++ b/sim/src/trips.rs @@ -38,7 +38,7 @@ impl TripManager { pub fn new_trip( &mut self, spawned_at: Duration, - start: Option, + start: TripStart, legs: Vec, ) -> TripID { assert!(!legs.is_empty()); @@ -62,6 +62,19 @@ impl TripManager { } } } + let end = match legs.last() { + Some(TripLeg::Walk(_, _, ref spot)) => match spot.connection { + SidewalkPOI::Building(b) => TripEnd::Bldg(b), + SidewalkPOI::Border(i) => TripEnd::Border(i), + _ => unreachable!(), + }, + Some(TripLeg::Drive(_, ref goal)) => match goal { + DrivingGoal::ParkNear(b) => TripEnd::Bldg(*b), + DrivingGoal::Border(i, _) => TripEnd::Border(*i), + }, + Some(TripLeg::ServeBusRoute(_, route)) => TripEnd::ServeBusRoute(*route), + _ => unreachable!(), + }; let trip = Trip { id, spawned_at, @@ -70,6 +83,7 @@ impl TripManager { mode, legs: VecDeque::from(legs), start, + end, }; if !trip.is_bus_trip() { self.unfinished_trips += 1; @@ -464,22 +478,12 @@ impl TripManager { self.events.drain(..).collect() } - pub fn trip_status(&self, id: TripID) -> Option { + pub fn trip_status(&self, id: TripID) -> TripStatus { let trip = &self.trips[id.0]; - let start = trip.start.clone()?; - let end = match trip.legs.back() { - Some(TripLeg::Walk(_, _, ref spot)) => match spot.connection { - SidewalkPOI::Building(b) => TripEnd::Bldg(b), - SidewalkPOI::Border(i) => TripEnd::Border(i), - _ => unreachable!(), - }, - Some(TripLeg::Drive(_, ref goal)) => match goal { - DrivingGoal::ParkNear(b) => TripEnd::Bldg(*b), - DrivingGoal::Border(i, _) => TripEnd::Border(*i), - }, - _ => unreachable!(), - }; - Some(TripStatus { start, end }) + TripStatus { + start: trip.start.clone(), + end: trip.end.clone(), + } } } @@ -491,7 +495,8 @@ struct Trip { aborted: bool, legs: VecDeque, mode: TripMode, - start: Option, + start: TripStart, + end: TripEnd, } impl Trip { @@ -586,12 +591,16 @@ pub enum TripMode { #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub enum TripStart { Bldg(BuildingID), + Border(IntersectionID), Appearing(Position), } +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub enum TripEnd { Bldg(BuildingID), Border(IntersectionID), + // No end! + ServeBusRoute(BusRouteID), } pub struct TripStatus {