mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
Refactor starting trips -- caller passes in TripInfo. Stop inferring
TripEndpoints from TripLegs. #258 NOW regenerate scenarios. I'm confident this sweeping refactor didn't break behavior, because prebaked data didn't budge. huge_seattle scenario went from 147MB to 129MB. Not bad!
This commit is contained in:
parent
8d80668a56
commit
7741ea79b5
@ -481,36 +481,36 @@
|
||||
"size_bytes": 9004723
|
||||
},
|
||||
"data/system/seattle/scenarios/ballard/weekday.bin": {
|
||||
"checksum": "f014c2bdce9768f63ab32d24c332dcbe",
|
||||
"size_bytes": 29686654
|
||||
"checksum": "b85c1f2649d9f5653a6892530f531bd5",
|
||||
"size_bytes": 25996430
|
||||
},
|
||||
"data/system/seattle/scenarios/downtown/weekday.bin": {
|
||||
"checksum": "6d7c71d64774b5ae53d17b7e4a494a5a",
|
||||
"size_bytes": 57831457
|
||||
"checksum": "c4fa49791d9044953357646547d44c94",
|
||||
"size_bytes": 46149242
|
||||
},
|
||||
"data/system/seattle/scenarios/huge_seattle/weekday.bin": {
|
||||
"checksum": "de9bedc7ebe58af8f17485ea4a01af49",
|
||||
"size_bytes": 153841978
|
||||
"checksum": "838e4da4ecde804e189ae1a723aac875",
|
||||
"size_bytes": 134353259
|
||||
},
|
||||
"data/system/seattle/scenarios/lakeslice/weekday.bin": {
|
||||
"checksum": "e2037dc1a2059ac9021c0d2b53a53fbb",
|
||||
"size_bytes": 12677894
|
||||
"checksum": "ab537ab45dc0696203a7795693d50d75",
|
||||
"size_bytes": 10936762
|
||||
},
|
||||
"data/system/seattle/scenarios/montlake/weekday.bin": {
|
||||
"checksum": "18e44a3556f382c928e5a35896963133",
|
||||
"size_bytes": 1762819
|
||||
"checksum": "56a8d73b8ed7c961399ae1e86ba7d9ba",
|
||||
"size_bytes": 1536335
|
||||
},
|
||||
"data/system/seattle/scenarios/south_seattle/weekday.bin": {
|
||||
"checksum": "fea36775a87e95fcc810df2faf7be78a",
|
||||
"size_bytes": 37663645
|
||||
"checksum": "493bb5cc11b2814e4a3b0fe547b8d356",
|
||||
"size_bytes": 33451749
|
||||
},
|
||||
"data/system/seattle/scenarios/udistrict/weekday.bin": {
|
||||
"checksum": "0d62a92263ef91b3e9ad36312cd8b9df",
|
||||
"size_bytes": 13137921
|
||||
"checksum": "f8fb713f39b4054704560c0c65db2b22",
|
||||
"size_bytes": 11070560
|
||||
},
|
||||
"data/system/seattle/scenarios/west_seattle/weekday.bin": {
|
||||
"checksum": "e1d0df68c84091ee6e0a6dd22b1235f2",
|
||||
"size_bytes": 27282051
|
||||
"checksum": "9ebd16bc8f33a4d539b91ff762c3888d",
|
||||
"size_bytes": 24859939
|
||||
},
|
||||
"data/system/tel_aviv/maps/center.bin": {
|
||||
"checksum": "d395118f968b001898aba749d20cac02",
|
||||
|
@ -3,9 +3,7 @@ use std::collections::HashMap;
|
||||
use abstutil::{prettyprint_usize, MultiMap, Parallelism, Timer};
|
||||
use geom::LonLat;
|
||||
use map_model::{osm, BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep};
|
||||
use sim::{
|
||||
IndividTrip, OrigPersonID, PersonID, PersonSpec, Scenario, SpawnTrip, TripEndpoint, TripMode,
|
||||
};
|
||||
use sim::{IndividTrip, OrigPersonID, PersonID, PersonSpec, Scenario, TripEndpoint, TripMode};
|
||||
|
||||
use crate::soundcast::popdat::{Endpoint, OrigTrip, PopDat};
|
||||
|
||||
@ -244,36 +242,23 @@ pub fn make_weekday_scenario(
|
||||
huge_map: &Map,
|
||||
timer: &mut Timer,
|
||||
) -> Scenario {
|
||||
let trips = clip_trips(map, popdat, huge_map, timer);
|
||||
let orig_trips = trips.len();
|
||||
|
||||
let mut individ_trips: Vec<Option<IndividTrip>> = Vec::new();
|
||||
// person -> (trip seq, index into individ_trips)
|
||||
let mut trips_per_person: MultiMap<OrigPersonID, ((usize, bool, usize), usize)> =
|
||||
MultiMap::new();
|
||||
for (trip, depart, person, seq, purpose) in timer.parallelize(
|
||||
"turn Soundcast trips into SpawnTrips",
|
||||
Parallelism::Polite,
|
||||
trips,
|
||||
|trip| {
|
||||
(
|
||||
SpawnTrip::new(trip.from, trip.to, trip.orig.mode, map),
|
||||
trip.orig.depart_at,
|
||||
trip.orig.person,
|
||||
trip.orig.seq,
|
||||
trip.orig.purpose,
|
||||
)
|
||||
},
|
||||
) {
|
||||
if let Some(trip) = trip {
|
||||
let idx = individ_trips.len();
|
||||
individ_trips.push(Some(IndividTrip::new(depart, purpose, trip)));
|
||||
trips_per_person.insert(person, (seq, idx));
|
||||
}
|
||||
for trip in clip_trips(map, popdat, huge_map, timer) {
|
||||
let idx = individ_trips.len();
|
||||
individ_trips.push(Some(IndividTrip::new(
|
||||
trip.orig.depart_at,
|
||||
trip.orig.purpose,
|
||||
trip.from,
|
||||
trip.to,
|
||||
trip.orig.mode,
|
||||
)));
|
||||
trips_per_person.insert(trip.orig.person, (trip.orig.seq, idx));
|
||||
}
|
||||
timer.note(format!(
|
||||
"{} clipped trips down to {}, over {} people",
|
||||
prettyprint_usize(orig_trips),
|
||||
"{} clipped trips, over {} people",
|
||||
prettyprint_usize(individ_trips.len()),
|
||||
prettyprint_usize(trips_per_person.len())
|
||||
));
|
||||
@ -307,5 +292,5 @@ pub fn make_weekday_scenario(
|
||||
people,
|
||||
only_seed_buses: None,
|
||||
}
|
||||
.remove_weird_schedules(map)
|
||||
.remove_weird_schedules()
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use map_model::{
|
||||
use crate::make::fork_rng;
|
||||
use crate::{
|
||||
CarID, DrivingGoal, OrigPersonID, ParkingSpot, PersonID, SidewalkSpot, Sim, TripEndpoint,
|
||||
TripMode, TripSpawner, TripSpec, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH,
|
||||
TripInfo, TripMode, TripSpawner, TripSpec, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH,
|
||||
MAX_CAR_LENGTH, MIN_CAR_LENGTH, SPAWN_DIST,
|
||||
};
|
||||
|
||||
@ -210,13 +210,21 @@ impl Scenario {
|
||||
};
|
||||
schedule_trips.push((
|
||||
person.id,
|
||||
t.depart,
|
||||
spec,
|
||||
t.from.clone(),
|
||||
t.purpose,
|
||||
t.cancelled,
|
||||
t.modified,
|
||||
map,
|
||||
TripInfo {
|
||||
departure: t.depart,
|
||||
mode: t.mode,
|
||||
start: t.from.clone(),
|
||||
end: t.to.clone(),
|
||||
purpose: t.purpose,
|
||||
modified: t.modified,
|
||||
capped: false,
|
||||
cancellation_reason: if t.cancelled {
|
||||
Some(format!("cancelled by ScenarioModifier"))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -226,11 +234,7 @@ impl Scenario {
|
||||
"schedule trips",
|
||||
Parallelism::Fastest,
|
||||
schedule_trips,
|
||||
|tuple| {
|
||||
spawner.schedule_trip(
|
||||
tuple.0, tuple.1, tuple.2, tuple.3, tuple.4, tuple.5, tuple.6, tuple.7,
|
||||
)
|
||||
},
|
||||
|tuple| spawner.schedule_trip(tuple.0, tuple.1, tuple.2, map),
|
||||
);
|
||||
spawner.schedule_trips(results);
|
||||
|
||||
|
@ -4,12 +4,11 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use abstutil::Timer;
|
||||
use geom::Time;
|
||||
use map_model::{BuildingID, BusRouteID, BusStopID, Map, PathConstraints, PathRequest, Position};
|
||||
|
||||
use crate::{
|
||||
CarID, Command, DrivingGoal, PersonID, Scheduler, SidewalkSpot, TripEndpoint, TripLeg,
|
||||
TripManager, TripMode, TripPurpose, VehicleType,
|
||||
CarID, Command, DrivingGoal, PersonID, Scheduler, SidewalkSpot, TripInfo, TripLeg, TripManager,
|
||||
VehicleType,
|
||||
};
|
||||
|
||||
// TODO Some of these fields are unused now that we separately pass TripEndpoint
|
||||
@ -52,15 +51,7 @@ pub enum TripSpec {
|
||||
},
|
||||
}
|
||||
|
||||
type TripSpawnPlan = (
|
||||
PersonID,
|
||||
Time,
|
||||
TripSpec,
|
||||
TripEndpoint,
|
||||
TripPurpose,
|
||||
bool,
|
||||
bool,
|
||||
);
|
||||
type TripSpawnPlan = (PersonID, TripSpec, TripInfo);
|
||||
|
||||
/// This structure is created temporarily by a Scenario or to interactively spawn agents.
|
||||
pub struct TripSpawner {
|
||||
@ -77,12 +68,8 @@ impl TripSpawner {
|
||||
pub fn schedule_trip(
|
||||
&self,
|
||||
person: PersonID,
|
||||
start_time: Time,
|
||||
mut spec: TripSpec,
|
||||
trip_start: TripEndpoint,
|
||||
purpose: TripPurpose,
|
||||
cancelled: bool,
|
||||
modified: bool,
|
||||
info: TripInfo,
|
||||
map: &Map,
|
||||
) -> TripSpawnPlan {
|
||||
// TODO We'll want to repeat this validation when we spawn stuff later for a second leg...
|
||||
@ -179,9 +166,7 @@ impl TripSpawner {
|
||||
TripSpec::UsingTransit { .. } => {}
|
||||
};
|
||||
|
||||
(
|
||||
person, start_time, spec, trip_start, purpose, cancelled, modified,
|
||||
)
|
||||
(person, spec, info)
|
||||
}
|
||||
|
||||
pub fn schedule_trips(&mut self, trips: Vec<TripSpawnPlan>) {
|
||||
@ -196,13 +181,14 @@ impl TripSpawner {
|
||||
timer: &mut Timer,
|
||||
) {
|
||||
timer.start_iter("spawn trips", self.trips.len());
|
||||
for (p, start_time, spec, trip_start, purpose, cancelled, modified) in self.trips.drain(..)
|
||||
{
|
||||
for (p, spec, info) in self.trips.drain(..) {
|
||||
timer.next();
|
||||
|
||||
// TODO clone() is super weird to do here, but we just need to make the borrow checker
|
||||
// happy. All we're doing is grabbing IDs off this.
|
||||
let person = trips.get_person(p).unwrap().clone();
|
||||
let departure = info.departure;
|
||||
let cancellation_reason = info.cancellation_reason.clone();
|
||||
// Just create the trip for each case.
|
||||
// TODO Not happy about this clone()
|
||||
let trip = match spec.clone() {
|
||||
@ -213,42 +199,13 @@ impl TripSpawner {
|
||||
if let DrivingGoal::ParkNear(b) = goal {
|
||||
legs.push(TripLeg::Walk(SidewalkSpot::building(b, map)));
|
||||
}
|
||||
trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
if use_vehicle.1 == VehicleType::Bike {
|
||||
TripMode::Bike
|
||||
} else {
|
||||
TripMode::Drive
|
||||
},
|
||||
purpose,
|
||||
modified,
|
||||
legs,
|
||||
map,
|
||||
)
|
||||
trips.new_trip(person.id, info, legs)
|
||||
}
|
||||
TripSpec::SpawningFailure { use_vehicle, .. } => {
|
||||
// TODO Need to plumb TripInfo into here
|
||||
todo!()
|
||||
/*let mut legs = vec![TripLeg::Drive(use_vehicle, goal.clone())];
|
||||
if let DrivingGoal::ParkNear(b) = goal {
|
||||
legs.push(TripLeg::Walk(SidewalkSpot::building(b, map)));
|
||||
}
|
||||
trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
if use_vehicle.1 == VehicleType::Bike {
|
||||
TripMode::Bike
|
||||
} else {
|
||||
TripMode::Drive
|
||||
},
|
||||
purpose,
|
||||
modified,
|
||||
legs,
|
||||
map,
|
||||
)*/
|
||||
TripSpec::SpawningFailure { .. } => {
|
||||
// TODO Is it OK to have empty trip legs?
|
||||
// TODO Do we have to cancel the trip or move the vehicle here?
|
||||
let legs = Vec::new();
|
||||
trips.new_trip(person.id, info, legs)
|
||||
}
|
||||
TripSpec::UsingParkedCar { car, goal, .. } => {
|
||||
let mut legs = vec![
|
||||
@ -261,27 +218,11 @@ impl TripSpawner {
|
||||
}
|
||||
DrivingGoal::Border(_, _) => {}
|
||||
}
|
||||
trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
TripMode::Drive,
|
||||
purpose,
|
||||
modified,
|
||||
legs,
|
||||
map,
|
||||
)
|
||||
trips.new_trip(person.id, info, legs)
|
||||
}
|
||||
TripSpec::JustWalking { goal, .. } => {
|
||||
trips.new_trip(person.id, info, vec![TripLeg::Walk(goal.clone())])
|
||||
}
|
||||
TripSpec::JustWalking { goal, .. } => trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
TripMode::Walk,
|
||||
purpose,
|
||||
modified,
|
||||
vec![TripLeg::Walk(goal.clone())],
|
||||
map,
|
||||
),
|
||||
TripSpec::UsingBike { bike, start, goal } => {
|
||||
let walk_to = SidewalkSpot::bike_rack(start, map).unwrap();
|
||||
let mut legs = vec![
|
||||
@ -294,16 +235,7 @@ impl TripSpawner {
|
||||
}
|
||||
DrivingGoal::Border(_, _) => {}
|
||||
};
|
||||
trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
TripMode::Bike,
|
||||
purpose,
|
||||
modified,
|
||||
legs,
|
||||
map,
|
||||
)
|
||||
trips.new_trip(person.id, info, legs)
|
||||
}
|
||||
TripSpec::UsingTransit {
|
||||
route,
|
||||
@ -325,26 +257,14 @@ impl TripSpawner {
|
||||
TripLeg::RideBus(route, None),
|
||||
]
|
||||
};
|
||||
trips.new_trip(
|
||||
person.id,
|
||||
start_time,
|
||||
trip_start,
|
||||
TripMode::Transit,
|
||||
purpose,
|
||||
modified,
|
||||
legs,
|
||||
map,
|
||||
)
|
||||
trips.new_trip(person.id, info, legs)
|
||||
}
|
||||
};
|
||||
|
||||
if cancelled {
|
||||
trips.cancel_unstarted_trip(
|
||||
trip,
|
||||
format!("traffic pattern modifier cancelled this trip"),
|
||||
);
|
||||
if let Some(msg) = cancellation_reason {
|
||||
trips.cancel_unstarted_trip(trip, msg);
|
||||
} else {
|
||||
scheduler.push(start_time, Command::StartTrip(trip, spec));
|
||||
scheduler.push(departure, Command::StartTrip(trip, spec));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,49 +87,14 @@ impl TripManager {
|
||||
id
|
||||
}
|
||||
|
||||
pub fn new_trip(
|
||||
&mut self,
|
||||
person: PersonID,
|
||||
departure: Time,
|
||||
start: TripEndpoint,
|
||||
mode: TripMode,
|
||||
purpose: TripPurpose,
|
||||
modified: bool,
|
||||
legs: Vec<TripLeg>,
|
||||
map: &Map,
|
||||
) -> TripID {
|
||||
pub fn new_trip(&mut self, person: PersonID, info: TripInfo, legs: Vec<TripLeg>) -> TripID {
|
||||
assert!(!legs.is_empty());
|
||||
// TODO Make sure the legs constitute a valid state machine.
|
||||
|
||||
let id = TripID(self.trips.len());
|
||||
let end = match legs.last() {
|
||||
Some(TripLeg::Walk(ref spot)) => match spot.connection {
|
||||
SidewalkPOI::Building(b) => TripEndpoint::Bldg(b),
|
||||
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Some(TripLeg::Drive(_, ref goal)) => match goal {
|
||||
DrivingGoal::ParkNear(b) => TripEndpoint::Bldg(*b),
|
||||
DrivingGoal::Border(i, _) => TripEndpoint::Border(*i),
|
||||
},
|
||||
Some(TripLeg::RideBus(r, ref maybe_stop2)) => {
|
||||
assert!(maybe_stop2.is_none());
|
||||
TripEndpoint::Border(map.get_l(map.get_br(*r).end_border.unwrap()).dst_i)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let trip = Trip {
|
||||
id,
|
||||
info: TripInfo {
|
||||
departure,
|
||||
mode,
|
||||
start,
|
||||
end,
|
||||
purpose,
|
||||
modified,
|
||||
capped: false,
|
||||
cancellation_reason: None,
|
||||
},
|
||||
info,
|
||||
person,
|
||||
started: false,
|
||||
finished_at: None,
|
||||
|
Loading…
Reference in New Issue
Block a user