mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 22:13:27 +03:00
plumb more info in sim events. this will allow for some consolidated pandemic modeling
This commit is contained in:
parent
c12775e5ea
commit
29c86d656d
@ -163,8 +163,8 @@ fn make_timeline(
|
||||
TripPhaseType::Walking => Color::hex("#DF8C3D"),
|
||||
TripPhaseType::Biking => app.cs.get("bike lane"),
|
||||
TripPhaseType::Parking => Color::hex("#4E30A6"),
|
||||
TripPhaseType::WaitingForBus(_) => app.cs.get("bus stop marking"),
|
||||
TripPhaseType::RidingBus(_) => app.cs.get("bus lane"),
|
||||
TripPhaseType::WaitingForBus(_, _) => app.cs.get("bus stop marking"),
|
||||
TripPhaseType::RidingBus(_, _) => app.cs.get("bus lane"),
|
||||
TripPhaseType::Aborted | TripPhaseType::Finished => unreachable!(),
|
||||
}
|
||||
.alpha(0.7);
|
||||
@ -215,10 +215,10 @@ fn make_timeline(
|
||||
TripPhaseType::Walking => "../data/system/assets/timeline/walking.svg",
|
||||
TripPhaseType::Biking => "../data/system/assets/timeline/biking.svg",
|
||||
TripPhaseType::Parking => "../data/system/assets/timeline/parking.svg",
|
||||
TripPhaseType::WaitingForBus(_) => {
|
||||
TripPhaseType::WaitingForBus(_, _) => {
|
||||
"../data/system/assets/timeline/waiting_for_bus.svg"
|
||||
}
|
||||
TripPhaseType::RidingBus(_) => "../data/system/assets/timeline/riding_bus.svg",
|
||||
TripPhaseType::RidingBus(_, _) => "../data/system/assets/timeline/riding_bus.svg",
|
||||
TripPhaseType::Aborted | TripPhaseType::Finished => unreachable!(),
|
||||
},
|
||||
// TODO Hardcoded layouting...
|
||||
|
@ -111,12 +111,14 @@ impl Analytics {
|
||||
}
|
||||
|
||||
// Bus passengers
|
||||
if let Event::PedReachedBusStop(_, stop, route) = ev {
|
||||
self.bus_passengers_waiting.push((time, stop, route));
|
||||
if let Event::TripPhaseStarting(_, _, _, _, ref tpt) = ev {
|
||||
if let TripPhaseType::WaitingForBus(route, stop) = tpt {
|
||||
self.bus_passengers_waiting.push((time, *stop, *route));
|
||||
}
|
||||
}
|
||||
|
||||
// Started trips
|
||||
if let Event::TripPhaseStarting(id, mode, _, _) = ev {
|
||||
if let Event::TripPhaseStarting(id, _, mode, _, _) = ev {
|
||||
// TODO More efficiently
|
||||
if !self.started_trips.contains_key(&id)
|
||||
&& !self
|
||||
@ -148,7 +150,7 @@ impl Analytics {
|
||||
|
||||
// TODO Kinda hacky, but these all consume the event, so kinda bundle em.
|
||||
match ev {
|
||||
Event::TripPhaseStarting(id, _, maybe_req, phase_type) => {
|
||||
Event::TripPhaseStarting(id, _, _, maybe_req, phase_type) => {
|
||||
self.trip_log.push((time, id, maybe_req, phase_type));
|
||||
}
|
||||
Event::TripAborted(id, _) => {
|
||||
|
@ -16,15 +16,11 @@ pub enum Event {
|
||||
BusArrivedAtStop(CarID, BusRouteID, BusStopID),
|
||||
BusDepartedFromStop(CarID, BusRouteID, BusStopID),
|
||||
|
||||
PedEntersBus(PedestrianID, CarID, BusRouteID),
|
||||
PedLeavesBus(PedestrianID, CarID, BusRouteID),
|
||||
|
||||
PersonEntersBuilding(PersonID, BuildingID),
|
||||
PersonLeavesBuilding(PersonID, BuildingID),
|
||||
|
||||
PedReachedParkingSpot(PedestrianID, ParkingSpot),
|
||||
PedReachedBorder(PedestrianID, IntersectionID),
|
||||
PedReachedBusStop(PedestrianID, BusStopID, BusRouteID),
|
||||
|
||||
BikeStoppedAtSidewalk(CarID, LaneID),
|
||||
|
||||
@ -33,7 +29,13 @@ pub enum Event {
|
||||
|
||||
TripFinished(TripID, TripMode, Duration),
|
||||
TripAborted(TripID, TripMode),
|
||||
TripPhaseStarting(TripID, TripMode, Option<PathRequest>, TripPhaseType),
|
||||
TripPhaseStarting(
|
||||
TripID,
|
||||
PersonID,
|
||||
TripMode,
|
||||
Option<PathRequest>,
|
||||
TripPhaseType,
|
||||
),
|
||||
|
||||
// Just use for parking replanning. Not happy about copying the full path in here, but the way
|
||||
// to plumb info into Analytics is Event.
|
||||
@ -46,8 +48,8 @@ pub enum TripPhaseType {
|
||||
Walking,
|
||||
Biking,
|
||||
Parking,
|
||||
WaitingForBus(BusRouteID),
|
||||
RidingBus(BusRouteID),
|
||||
WaitingForBus(BusRouteID, BusStopID),
|
||||
RidingBus(BusRouteID, CarID),
|
||||
Aborted,
|
||||
Finished,
|
||||
}
|
||||
@ -59,8 +61,8 @@ impl TripPhaseType {
|
||||
TripPhaseType::Walking => "walking".to_string(),
|
||||
TripPhaseType::Biking => "biking".to_string(),
|
||||
TripPhaseType::Parking => "parking".to_string(),
|
||||
TripPhaseType::WaitingForBus(r) => format!("waiting for bus {}", map.get_br(r).name),
|
||||
TripPhaseType::RidingBus(r) => format!("riding bus {}", map.get_br(r).name),
|
||||
TripPhaseType::WaitingForBus(r, _) => format!("waiting for bus {}", map.get_br(r).name),
|
||||
TripPhaseType::RidingBus(r, _) => format!("riding bus {}", map.get_br(r).name),
|
||||
TripPhaseType::Aborted => "trip aborted due to some bug".to_string(),
|
||||
TripPhaseType::Finished => "trip finished".to_string(),
|
||||
}
|
||||
|
@ -11,7 +11,8 @@ mod transit;
|
||||
mod trips;
|
||||
|
||||
pub use self::analytics::{Analytics, TripPhase};
|
||||
pub use self::events::{Event, TripPhaseType};
|
||||
pub(crate) use self::events::Event;
|
||||
pub use self::events::TripPhaseType;
|
||||
pub use self::make::{
|
||||
ABTest, BorderSpawnOverTime, IndividTrip, OriginDestination, PersonSpec, Scenario,
|
||||
ScenarioGenerator, SeedParkedCars, SimFlags, SpawnOverTime, SpawnTrip, TripSpawner, TripSpec,
|
||||
@ -490,8 +491,7 @@ pub struct CreateCar {
|
||||
pub start_dist: Distance,
|
||||
pub maybe_parked_car: Option<ParkedCar>,
|
||||
// None for buses
|
||||
pub trip: Option<TripID>,
|
||||
pub person: Option<PersonID>,
|
||||
pub trip_and_person: Option<(TripID, PersonID)>,
|
||||
}
|
||||
|
||||
impl CreateCar {
|
||||
@ -509,8 +509,7 @@ impl CreateCar {
|
||||
req,
|
||||
start_dist: start_pos.dist_along(),
|
||||
maybe_parked_car: None,
|
||||
trip: Some(trip),
|
||||
person: Some(person),
|
||||
trip_and_person: Some((trip, person)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,8 +528,7 @@ impl CreateCar {
|
||||
req,
|
||||
start_dist,
|
||||
maybe_parked_car: Some(parked_car),
|
||||
trip: Some(trip),
|
||||
person: Some(person),
|
||||
trip_and_person: Some((trip, person)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ pub struct Car {
|
||||
pub state: CarState,
|
||||
pub router: Router,
|
||||
// None for buses
|
||||
pub trip: Option<TripID>,
|
||||
pub person: Option<PersonID>,
|
||||
pub trip_and_person: Option<(TripID, PersonID)>,
|
||||
pub started_at: Time,
|
||||
pub total_blocked_time: Duration,
|
||||
|
||||
|
@ -97,8 +97,7 @@ impl DrivingSimState {
|
||||
last_steps: VecDeque::new(),
|
||||
started_at: now,
|
||||
total_blocked_time: Duration::ZERO,
|
||||
trip: params.trip,
|
||||
person: params.person,
|
||||
trip_and_person: params.trip_and_person,
|
||||
};
|
||||
if let Some(p) = params.maybe_parked_car {
|
||||
car.state = CarState::Unparking(
|
||||
@ -114,7 +113,7 @@ impl DrivingSimState {
|
||||
&car.vehicle,
|
||||
parking,
|
||||
map,
|
||||
car.trip,
|
||||
car.trip_and_person,
|
||||
&mut self.events,
|
||||
) {
|
||||
None | Some(ActionAtEnd::GotoLaneEnd) => {}
|
||||
@ -275,7 +274,7 @@ impl DrivingSimState {
|
||||
&car.vehicle,
|
||||
parking,
|
||||
map,
|
||||
car.trip,
|
||||
car.trip_and_person,
|
||||
&mut self.events,
|
||||
);
|
||||
}
|
||||
@ -365,9 +364,13 @@ impl DrivingSimState {
|
||||
// We do NOT need to update the follower. If they were Queued, they'll remain that
|
||||
// way, until laggy_head is None.
|
||||
|
||||
let last_step =
|
||||
car.router
|
||||
.advance(&car.vehicle, parking, map, car.trip, &mut self.events);
|
||||
let last_step = car.router.advance(
|
||||
&car.vehicle,
|
||||
parking,
|
||||
map,
|
||||
car.trip_and_person,
|
||||
&mut self.events,
|
||||
);
|
||||
car.total_blocked_time += now - blocked_since;
|
||||
car.state = car.crossing_state(Distance::ZERO, now, map);
|
||||
scheduler.push(car.state.get_end_time(), Command::UpdateCar(car.vehicle.id));
|
||||
@ -442,7 +445,7 @@ impl DrivingSimState {
|
||||
&car.vehicle,
|
||||
parking,
|
||||
map,
|
||||
car.trip,
|
||||
car.trip_and_person,
|
||||
&mut self.events,
|
||||
) {
|
||||
Some(ActionAtEnd::VanishAtBorder(i)) => {
|
||||
@ -783,7 +786,7 @@ impl DrivingSimState {
|
||||
result.push(UnzoomedAgent {
|
||||
vehicle_type: Some(car.vehicle.vehicle_type),
|
||||
pos: queue.id.dist_along(dist, map).0,
|
||||
person: car.person,
|
||||
person: car.trip_and_person.map(|(_, p)| p),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -804,7 +807,7 @@ impl DrivingSimState {
|
||||
for (car, dist) in
|
||||
queue.get_car_positions(trip_positions.time, &self.cars, &self.queues)
|
||||
{
|
||||
if let Some(trip) = self.cars[&car].trip {
|
||||
if let Some((trip, _)) = self.cars[&car].trip_and_person {
|
||||
trip_positions
|
||||
.canonical_pt_per_trip
|
||||
.insert(trip, queue.id.dist_along(dist, map).0);
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::mechanics::Queue;
|
||||
use crate::{
|
||||
Event, ParkingSimState, ParkingSpot, SidewalkSpot, TripID, TripMode, TripPhaseType, Vehicle,
|
||||
Event, ParkingSimState, ParkingSpot, PersonID, SidewalkSpot, TripID, TripMode, TripPhaseType,
|
||||
Vehicle,
|
||||
};
|
||||
use geom::Distance;
|
||||
use map_model::{
|
||||
@ -127,13 +128,20 @@ impl Router {
|
||||
vehicle: &Vehicle,
|
||||
parking: &ParkingSimState,
|
||||
map: &Map,
|
||||
trip: Option<TripID>,
|
||||
trip_and_person: Option<(TripID, PersonID)>,
|
||||
events: &mut Vec<Event>,
|
||||
) -> Traversable {
|
||||
let prev = self.path.shift(map).as_traversable();
|
||||
if self.last_step() {
|
||||
// Do this to trigger the side-effect of looking for parking.
|
||||
self.maybe_handle_end(Distance::ZERO, vehicle, parking, map, trip, events);
|
||||
self.maybe_handle_end(
|
||||
Distance::ZERO,
|
||||
vehicle,
|
||||
parking,
|
||||
map,
|
||||
trip_and_person,
|
||||
events,
|
||||
);
|
||||
}
|
||||
|
||||
// Sanity check laws haven't been broken
|
||||
@ -159,7 +167,7 @@ impl Router {
|
||||
parking: &ParkingSimState,
|
||||
map: &Map,
|
||||
// TODO Not so nice to plumb all of this here
|
||||
trip: Option<TripID>,
|
||||
trip_and_person: Option<(TripID, PersonID)>,
|
||||
events: &mut Vec<Event>,
|
||||
) -> Option<ActionAtEnd> {
|
||||
match self.goal {
|
||||
@ -194,9 +202,10 @@ impl Router {
|
||||
vehicle,
|
||||
map,
|
||||
) {
|
||||
if let Some(t) = trip {
|
||||
if let Some((t, p)) = trip_and_person {
|
||||
events.push(Event::TripPhaseStarting(
|
||||
t,
|
||||
p,
|
||||
TripMode::Drive,
|
||||
Some(PathRequest {
|
||||
start: Position::new(current_lane, front),
|
||||
@ -217,9 +226,10 @@ impl Router {
|
||||
}
|
||||
events.push(Event::PathAmended(self.path.clone()));
|
||||
// TODO This path might not be the same as the one found here...
|
||||
if let Some(t) = trip {
|
||||
if let Some((t, p)) = trip_and_person {
|
||||
events.push(Event::TripPhaseStarting(
|
||||
t,
|
||||
p,
|
||||
TripMode::Drive,
|
||||
Some(PathRequest {
|
||||
start: Position::new(current_lane, front),
|
||||
|
@ -269,8 +269,7 @@ impl Sim {
|
||||
req: req.clone(),
|
||||
router: Router::follow_bus_route(path.clone(), end_dist),
|
||||
maybe_parked_car: None,
|
||||
trip: None,
|
||||
person: None,
|
||||
trip_and_person: None,
|
||||
},
|
||||
map,
|
||||
&self.intersections,
|
||||
@ -409,7 +408,7 @@ impl Sim {
|
||||
&self.parking,
|
||||
&mut self.scheduler,
|
||||
) {
|
||||
if let Some(trip) = create_car.trip {
|
||||
if let Some((trip, _)) = create_car.trip_and_person {
|
||||
self.trips
|
||||
.agent_starting_trip_leg(AgentID::Car(create_car.vehicle.id), trip);
|
||||
}
|
||||
@ -417,15 +416,16 @@ impl Sim {
|
||||
if let ParkingSpot::Offstreet(b, _) = parked_car.spot {
|
||||
// Buses don't start in parking garages, so trip must exist
|
||||
events.push(Event::PersonLeavesBuilding(
|
||||
self.trip_to_person(create_car.trip.unwrap()),
|
||||
create_car.trip_and_person.unwrap().1,
|
||||
b,
|
||||
));
|
||||
}
|
||||
self.parking.remove_parked_car(parked_car);
|
||||
}
|
||||
if let Some(trip) = create_car.trip {
|
||||
if let Some((trip, person)) = create_car.trip_and_person {
|
||||
events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
person,
|
||||
// TODO sketchy...
|
||||
if create_car.vehicle.id.1 == VehicleType::Car {
|
||||
TripMode::Drive
|
||||
@ -449,7 +449,7 @@ impl Sim {
|
||||
Command::SpawnCar(create_car, retry_if_no_room),
|
||||
);
|
||||
} else {
|
||||
if let Some(trip) = create_car.trip {
|
||||
if let Some((trip, _)) = create_car.trip_and_person {
|
||||
println!("No room to spawn car for {}. Not retrying!", trip);
|
||||
self.trips.abort_trip_failed_start(trip);
|
||||
} else {
|
||||
@ -518,6 +518,7 @@ impl Sim {
|
||||
);
|
||||
events.push(Event::TripPhaseStarting(
|
||||
create_ped.trip,
|
||||
create_ped.person,
|
||||
TripMode::Walk,
|
||||
Some(create_ped.req.clone()),
|
||||
TripPhaseType::Walking,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
CarID, Event, PedestrianID, Router, Scheduler, TripManager, TripMode, TripPhaseType,
|
||||
WalkingSimState,
|
||||
CarID, Event, PedestrianID, PersonID, Router, Scheduler, TripID, TripManager, TripMode,
|
||||
TripPhaseType, WalkingSimState,
|
||||
};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap};
|
||||
use geom::{Distance, Time};
|
||||
@ -168,7 +168,6 @@ impl TransitSimState {
|
||||
let mut still_riding = Vec::new();
|
||||
for (ped, stop2) in bus.passengers.drain(..) {
|
||||
if stop1 == stop2 {
|
||||
self.events.push(Event::PedLeavesBus(ped, id, bus.route));
|
||||
trips.ped_left_bus(now, ped, map, scheduler);
|
||||
} else {
|
||||
still_riding.push((ped, stop2));
|
||||
@ -183,17 +182,17 @@ impl TransitSimState {
|
||||
{
|
||||
if bus.route == route {
|
||||
bus.passengers.push((ped, stop2));
|
||||
self.events.push(Event::PedEntersBus(ped, id, route));
|
||||
let trip = trips.ped_boarded_bus(now, ped, walking);
|
||||
let (trip, person) = trips.ped_boarded_bus(now, ped, walking);
|
||||
self.events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
person,
|
||||
TripMode::Transit,
|
||||
Some(PathRequest {
|
||||
start: map.get_bs(stop1).driving_pos,
|
||||
end: map.get_bs(stop2).driving_pos,
|
||||
constraints: PathConstraints::Bus,
|
||||
}),
|
||||
TripPhaseType::RidingBus(route),
|
||||
TripPhaseType::RidingBus(route, bus.car),
|
||||
));
|
||||
} else {
|
||||
still_waiting.push((ped, route, stop2, started_waiting));
|
||||
@ -229,9 +228,12 @@ impl TransitSimState {
|
||||
&mut self,
|
||||
now: Time,
|
||||
ped: PedestrianID,
|
||||
trip: TripID,
|
||||
person: PersonID,
|
||||
stop1: BusStopID,
|
||||
route_id: BusRouteID,
|
||||
stop2: BusStopID,
|
||||
map: &Map,
|
||||
) -> bool {
|
||||
assert!(stop1 != stop2);
|
||||
if let Some(route) = self.routes.get(&route_id) {
|
||||
@ -243,8 +245,17 @@ impl TransitSimState {
|
||||
.unwrap()
|
||||
.passengers
|
||||
.push((ped, stop2));
|
||||
// TODO shift trips
|
||||
self.events.push(Event::PedEntersBus(ped, *bus, route_id));
|
||||
self.events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
person,
|
||||
TripMode::Transit,
|
||||
Some(PathRequest {
|
||||
start: map.get_bs(stop1).driving_pos,
|
||||
end: map.get_bs(stop2).driving_pos,
|
||||
constraints: PathConstraints::Bus,
|
||||
}),
|
||||
TripPhaseType::RidingBus(route_id, *bus),
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -390,14 +390,23 @@ impl TripManager {
|
||||
}
|
||||
match trip.legs[1] {
|
||||
TripLeg::RideBus(_, route, stop2) => {
|
||||
self.events.push(Event::PedReachedBusStop(ped, stop, route));
|
||||
self.events.push(Event::TripPhaseStarting(
|
||||
trip.id,
|
||||
trip.person,
|
||||
trip.mode,
|
||||
None,
|
||||
TripPhaseType::WaitingForBus(route),
|
||||
TripPhaseType::WaitingForBus(route, stop),
|
||||
));
|
||||
if transit.ped_waiting_for_bus(now, ped, stop, route, stop2) {
|
||||
if transit.ped_waiting_for_bus(
|
||||
now,
|
||||
ped,
|
||||
trip.id,
|
||||
trip.person,
|
||||
stop,
|
||||
route,
|
||||
stop2,
|
||||
map,
|
||||
) {
|
||||
trip.legs.pop_front();
|
||||
None
|
||||
} else {
|
||||
@ -413,12 +422,12 @@ impl TripManager {
|
||||
now: Time,
|
||||
ped: PedestrianID,
|
||||
walking: &mut WalkingSimState,
|
||||
) -> TripID {
|
||||
) -> (TripID, PersonID) {
|
||||
// TODO Make sure canonical pt is the bus while the ped is riding it
|
||||
let trip = &mut self.trips[self.active_trip_mode[&AgentID::Pedestrian(ped)].0];
|
||||
trip.legs.pop_front();
|
||||
walking.ped_boarded_bus(now, ped);
|
||||
trip.id
|
||||
(trip.id, trip.person)
|
||||
}
|
||||
|
||||
pub fn ped_left_bus(
|
||||
|
Loading…
Reference in New Issue
Block a user