start to simplify the dynamic nabbing of parked cars

This commit is contained in:
Dustin Carlino 2020-04-22 14:39:02 -07:00
parent 98b76c0759
commit 6ef3a180a3
10 changed files with 167 additions and 191 deletions

View File

@ -294,8 +294,8 @@ fn describe(person: &PersonSpec, trip: &IndividTrip, home: OD) -> String {
i, i,
driving_goal(goal) driving_goal(goal)
), ),
SpawnTrip::MaybeUsingParkedCar(start_bldg, goal) => format!( SpawnTrip::UsingParkedCar(start_bldg, goal) => format!(
"{} at {}: try to drive from {} to {}", "{} at {}: drive from {} to {}",
person.id, person.id,
trip.depart, trip.depart,
if OD::Bldg(*start_bldg) == home { if OD::Bldg(*start_bldg) == home {
@ -347,7 +347,7 @@ fn other_endpt(trip: &IndividTrip, home: OD, map: &Map) -> ID {
driving_goal(goal), driving_goal(goal),
), ),
SpawnTrip::FromBorder { i, goal, .. } => (ID::Intersection(*i), driving_goal(goal)), SpawnTrip::FromBorder { i, goal, .. } => (ID::Intersection(*i), driving_goal(goal)),
SpawnTrip::MaybeUsingParkedCar(start_bldg, goal) => { SpawnTrip::UsingParkedCar(start_bldg, goal) => {
(ID::Building(*start_bldg), driving_goal(goal)) (ID::Building(*start_bldg), driving_goal(goal))
} }
SpawnTrip::UsingBike(start, goal) => (sidewalk_spot(start), driving_goal(goal)), SpawnTrip::UsingBike(start, goal) => (sidewalk_spot(start), driving_goal(goal)),
@ -463,7 +463,7 @@ impl DotMap {
SpawnTrip::FromBorder { i, goal, .. } => { SpawnTrip::FromBorder { i, goal, .. } => {
(map.get_i(*i).polygon.center(), goal.pt(map)) (map.get_i(*i).polygon.center(), goal.pt(map))
} }
SpawnTrip::MaybeUsingParkedCar(b, goal) => { SpawnTrip::UsingParkedCar(b, goal) => {
(map.get_b(*b).polygon.center(), goal.pt(map)) (map.get_b(*b).polygon.center(), goal.pt(map))
} }
SpawnTrip::UsingBike(start, goal) => { SpawnTrip::UsingBike(start, goal) => {

View File

@ -30,10 +30,9 @@ impl Trip {
goal: self.to.driving_goal(PathConstraints::Car, map), goal: self.to.driving_goal(PathConstraints::Car, map),
is_bike: false, is_bike: false,
}, },
TripEndpt::Building(b) => SpawnTrip::MaybeUsingParkedCar( TripEndpt::Building(b) => {
b, SpawnTrip::UsingParkedCar(b, self.to.driving_goal(PathConstraints::Car, map))
self.to.driving_goal(PathConstraints::Car, map), }
),
}, },
Mode::Bike => match self.from { Mode::Bike => match self.from {
TripEndpt::Building(b) => SpawnTrip::UsingBike( TripEndpt::Building(b) => SpawnTrip::UsingBike(

View File

@ -202,7 +202,7 @@ impl SpawnOverTime {
orig_id: (0, 0), orig_id: (0, 0),
trips: vec![IndividTrip { trips: vec![IndividTrip {
depart, depart,
trip: SpawnTrip::MaybeUsingParkedCar(from_bldg, goal), trip: SpawnTrip::UsingParkedCar(from_bldg, goal),
}], }],
}); });
return; return;

View File

@ -52,7 +52,7 @@ pub enum SpawnTrip {
// For bikes starting at a border, use FromBorder. UsingBike implies a walk->bike trip. // For bikes starting at a border, use FromBorder. UsingBike implies a walk->bike trip.
is_bike: bool, is_bike: bool,
}, },
MaybeUsingParkedCar(BuildingID, DrivingGoal), UsingParkedCar(BuildingID, DrivingGoal),
UsingBike(SidewalkSpot, DrivingGoal), UsingBike(SidewalkSpot, DrivingGoal),
JustWalking(SidewalkSpot, SidewalkSpot), JustWalking(SidewalkSpot, SidewalkSpot),
UsingTransit(SidewalkSpot, SidewalkSpot, BusRouteID, BusStopID, BusStopID), UsingTransit(SidewalkSpot, SidewalkSpot, BusRouteID, BusStopID, BusStopID),
@ -378,13 +378,11 @@ impl SpawnTrip {
}, },
ped_speed: Scenario::rand_ped_speed(rng), ped_speed: Scenario::rand_ped_speed(rng),
}), }),
SpawnTrip::MaybeUsingParkedCar(start_bldg, goal) => { SpawnTrip::UsingParkedCar(start_bldg, goal) => Some(TripSpec::UsingParkedCar {
Some(TripSpec::MaybeUsingParkedCar { start_bldg,
start_bldg, goal,
goal, ped_speed: Scenario::rand_ped_speed(rng),
ped_speed: Scenario::rand_ped_speed(rng), }),
})
}
SpawnTrip::UsingBike(start, goal) => Some(TripSpec::UsingBike { SpawnTrip::UsingBike(start, goal) => Some(TripSpec::UsingBike {
start, start,
goal, goal,
@ -415,7 +413,7 @@ impl SpawnTrip {
TripEndpoint::Border(map.get_l(start.lane()).src_i) TripEndpoint::Border(map.get_l(start.lane()).src_i)
} }
SpawnTrip::FromBorder { i, .. } => TripEndpoint::Border(*i), SpawnTrip::FromBorder { i, .. } => TripEndpoint::Border(*i),
SpawnTrip::MaybeUsingParkedCar(b, _) => TripEndpoint::Bldg(*b), SpawnTrip::UsingParkedCar(b, _) => TripEndpoint::Bldg(*b),
SpawnTrip::UsingBike(ref spot, _) SpawnTrip::UsingBike(ref spot, _)
| SpawnTrip::JustWalking(ref spot, _) | SpawnTrip::JustWalking(ref spot, _)
| SpawnTrip::UsingTransit(ref spot, _, _, _, _) => match spot.connection { | SpawnTrip::UsingTransit(ref spot, _, _, _, _) => match spot.connection {
@ -430,7 +428,7 @@ impl SpawnTrip {
match self { match self {
SpawnTrip::CarAppearing { ref goal, .. } SpawnTrip::CarAppearing { ref goal, .. }
| SpawnTrip::FromBorder { ref goal, .. } | SpawnTrip::FromBorder { ref goal, .. }
| SpawnTrip::MaybeUsingParkedCar(_, ref goal) | SpawnTrip::UsingParkedCar(_, ref goal)
| SpawnTrip::UsingBike(_, ref goal) => match goal { | SpawnTrip::UsingBike(_, ref goal) => match goal {
DrivingGoal::ParkNear(b) => TripEndpoint::Bldg(*b), DrivingGoal::ParkNear(b) => TripEndpoint::Bldg(*b),
DrivingGoal::Border(i, _) => TripEndpoint::Border(*i), DrivingGoal::Border(i, _) => TripEndpoint::Border(*i),
@ -460,7 +458,7 @@ impl PersonSpec {
has_car = true; has_car = true;
} }
} }
SpawnTrip::MaybeUsingParkedCar(b, _) => { SpawnTrip::UsingParkedCar(b, _) => {
if !has_car { if !has_car {
has_car = true; has_car = true;
car_initially_parked_at = Some(b); car_initially_parked_at = Some(b);

View File

@ -16,7 +16,7 @@ pub enum TripSpec {
vehicle_spec: VehicleSpec, vehicle_spec: VehicleSpec,
ped_speed: Speed, ped_speed: Speed,
}, },
MaybeUsingParkedCar { UsingParkedCar {
start_bldg: BuildingID, start_bldg: BuildingID,
goal: DrivingGoal, goal: DrivingGoal,
ped_speed: Speed, ped_speed: Speed,
@ -90,7 +90,7 @@ impl TripSpawner {
DrivingGoal::ParkNear(_) => {} DrivingGoal::ParkNear(_) => {}
} }
} }
TripSpec::MaybeUsingParkedCar { .. } => {} TripSpec::UsingParkedCar { .. } => {}
TripSpec::JustWalking { start, goal, .. } => { TripSpec::JustWalking { start, goal, .. } => {
if start == goal { if start == goal {
panic!( panic!(
@ -202,7 +202,7 @@ impl TripSpawner {
let trip_start = TripEndpoint::Border(map.get_l(start_pos.lane()).src_i); let trip_start = TripEndpoint::Border(map.get_l(start_pos.lane()).src_i);
trips.new_trip(person.id, start_time, trip_start, legs) trips.new_trip(person.id, start_time, trip_start, legs)
} }
TripSpec::MaybeUsingParkedCar { TripSpec::UsingParkedCar {
start_bldg, start_bldg,
goal, goal,
ped_speed, ped_speed,
@ -337,7 +337,7 @@ impl TripSpec {
}) })
} }
// We don't know where the parked car will be // We don't know where the parked car will be
TripSpec::MaybeUsingParkedCar { .. } => None, TripSpec::UsingParkedCar { .. } => None,
TripSpec::JustWalking { start, goal, .. } => Some(PathRequest { TripSpec::JustWalking { start, goal, .. } => Some(PathRequest {
start: start.sidewalk_pos, start: start.sidewalk_pos,
end: goal.sidewalk_pos, end: goal.sidewalk_pos,

View File

@ -443,13 +443,21 @@ impl DrivingSimState {
i, i,
car.total_blocked_time, car.total_blocked_time,
map, map,
parking,
scheduler, scheduler,
); );
false false
} }
Some(ActionAtEnd::GiveUpOnParkingAt(b)) => { Some(ActionAtEnd::GiveUpOnParkingAt(b)) => {
car.total_blocked_time += now - blocked_since; car.total_blocked_time += now - blocked_since;
trips.abort_trip_impossible_parking(now, car.vehicle.id, b, map, scheduler); trips.abort_trip_impossible_parking(
now,
car.vehicle.id,
b,
map,
parking,
scheduler,
);
false false
} }
Some(ActionAtEnd::StartParking(spot)) => { Some(ActionAtEnd::StartParking(spot)) => {

View File

@ -25,8 +25,6 @@ pub struct ParkingSimState {
)] )]
occupants: BTreeMap<ParkingSpot, CarID>, occupants: BTreeMap<ParkingSpot, CarID>,
reserved_spots: BTreeSet<ParkingSpot>, reserved_spots: BTreeSet<ParkingSpot>,
// TODO I think we can almost get rid of this
dynamically_reserved_cars: BTreeSet<CarID>,
#[serde( #[serde(
serialize_with = "serialize_btreemap", serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap" deserialize_with = "deserialize_btreemap"
@ -60,7 +58,6 @@ impl ParkingSimState {
let mut sim = ParkingSimState { let mut sim = ParkingSimState {
parked_cars: BTreeMap::new(), parked_cars: BTreeMap::new(),
occupants: BTreeMap::new(), occupants: BTreeMap::new(),
dynamically_reserved_cars: BTreeSet::new(),
reserved_spots: BTreeSet::new(), reserved_spots: BTreeSet::new(),
owner_to_car: BTreeMap::new(), owner_to_car: BTreeMap::new(),
@ -130,7 +127,6 @@ impl ParkingSimState {
if let Some(id) = p.vehicle.owner { if let Some(id) = p.vehicle.owner {
self.owner_to_car.remove(&id); self.owner_to_car.remove(&id);
} }
self.dynamically_reserved_cars.remove(&p.vehicle.id);
self.events self.events
.push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot)); .push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot));
} }
@ -154,19 +150,6 @@ impl ParkingSimState {
self.parked_cars.insert(p.vehicle.id, p); self.parked_cars.insert(p.vehicle.id, p);
} }
pub fn dynamically_reserve_car(&mut self, p: PersonID) -> Option<ParkedCar> {
let car = self.owner_to_car.get(&p)?;
if self.dynamically_reserved_cars.contains(car) {
return None;
}
self.dynamically_reserved_cars.insert(*car);
Some(self.parked_cars[car].clone())
}
pub fn dynamically_return_car(&mut self, p: ParkedCar) {
self.dynamically_reserved_cars.remove(&p.vehicle.id);
}
pub fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> { pub fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> {
let mut cars = Vec::new(); let mut cars = Vec::new();
if let Some(ref lane) = self.onstreet_lanes.get(&id) { if let Some(ref lane) = self.onstreet_lanes.get(&id) {
@ -328,8 +311,9 @@ impl ParkingSimState {
pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> { pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
self.parked_cars.get(&id).and_then(|p| p.vehicle.owner) self.parked_cars.get(&id).and_then(|p| p.vehicle.owner)
} }
pub fn get_car_owned_by(&self, id: PersonID) -> Option<CarID> { pub fn get_parked_car_owned_by(&self, id: PersonID) -> Option<ParkedCar> {
self.owner_to_car.get(&id).cloned() let car = self.owner_to_car.get(&id)?;
Some(self.parked_cars[car].clone())
} }
// (Filled, available) // (Filled, available)

View File

@ -170,6 +170,7 @@ impl WalkingSimState {
i, i,
ped.total_blocked_time, ped.total_blocked_time,
map, map,
parking,
scheduler, scheduler,
); );
self.peds.remove(&id); self.peds.remove(&id);
@ -241,6 +242,7 @@ impl WalkingSimState {
bldg, bldg,
ped.total_blocked_time, ped.total_blocked_time,
map, map,
parking,
scheduler, scheduler,
); );
self.peds.remove(&id); self.peds.remove(&id);
@ -254,6 +256,7 @@ impl WalkingSimState {
spot.clone(), spot.clone(),
ped.total_blocked_time, ped.total_blocked_time,
map, map,
parking,
scheduler, scheduler,
); );
self.peds.remove(&id); self.peds.remove(&id);

View File

@ -1,9 +1,9 @@
use crate::{ use crate::{
AgentID, Analytics, CarID, Command, CreateCar, DrawCarInput, DrawPedCrowdInput, AgentID, Analytics, CarID, Command, CreateCar, DrawCarInput, DrawPedCrowdInput,
DrawPedestrianInput, DrivingGoal, DrivingSimState, Event, GetDrawAgents, IntersectionSimState, DrawPedestrianInput, DrivingSimState, Event, GetDrawAgents, IntersectionSimState,
PandemicModel, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, Person, PersonID, PandemicModel, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, Person, PersonID,
PersonState, Router, Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripCount, PersonState, Router, Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripCount,
TripEndpoint, TripID, TripLeg, TripManager, TripMode, TripPhaseType, TripPositions, TripResult, TripEndpoint, TripID, TripManager, TripMode, TripPhaseType, TripPositions, TripResult,
TripSpawner, UnzoomedAgent, Vehicle, VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH, TripSpawner, UnzoomedAgent, Vehicle, VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH,
MIN_CAR_LENGTH, MIN_CAR_LENGTH,
}; };
@ -407,6 +407,7 @@ impl Sim {
trip_spec, trip_spec,
maybe_req, maybe_req,
maybe_path, maybe_path,
&self.parking,
&mut self.scheduler, &mut self.scheduler,
map, map,
); );
@ -467,114 +468,55 @@ impl Sim {
"No room to spawn car for {} by {}. Not retrying!", "No room to spawn car for {} by {}. Not retrying!",
trip, person trip, person
); );
self.trips
.abort_trip_failed_start(self.time, trip, map, &mut self.scheduler);
}
}
Command::SpawnPed(mut create_ped) => {
let ok = if let SidewalkPOI::DeferredParkingSpot(b, driving_goal) =
create_ped.goal.connection.clone()
{
if let Some(parked_car) =
self.parking.dynamically_reserve_car(create_ped.person)
{
create_ped.goal =
SidewalkSpot::parking_spot(parked_car.spot, map, &self.parking);
create_ped.req = PathRequest {
start: create_ped.start.sidewalk_pos,
end: create_ped.goal.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
if let Some(path) = map.pathfind(create_ped.req.clone()) {
create_ped.path = path;
let mut legs = vec![
TripLeg::Walk(
create_ped.id,
create_ped.speed,
create_ped.goal.clone(),
),
TripLeg::Drive(parked_car.vehicle.clone(), driving_goal.clone()),
];
match driving_goal {
DrivingGoal::ParkNear(b) => {
legs.push(TripLeg::Walk(
create_ped.id,
create_ped.speed,
SidewalkSpot::building(b, map),
));
}
DrivingGoal::Border(_, _) => {}
}
self.trips.dynamically_override_legs(create_ped.trip, legs);
true
} else {
println!(
"WARNING: At {}, {} giving up because no path from {} to {:?}",
self.time, create_ped.id, b, create_ped.goal.connection
);
self.parking.dynamically_return_car(parked_car);
false
}
} else {
println!(
"WARNING: At {}, no free car for {} spawning at {}",
self.time, create_ped.id, b
);
false
}
} else {
true
};
if ok {
// Do the order a bit backwards so we don't have to clone the
// CreatePedestrian. spawn_ped can't fail.
self.trips.agent_starting_trip_leg(
AgentID::Pedestrian(create_ped.id),
create_ped.trip,
);
events.push(Event::TripPhaseStarting(
create_ped.trip,
create_ped.person,
TripMode::Walk,
Some(create_ped.req.clone()),
TripPhaseType::Walking,
));
self.analytics.record_demand(&create_ped.path, map);
// Maybe there's actually no work to do!
match (&create_ped.start.connection, &create_ped.goal.connection) {
(
SidewalkPOI::Building(b1),
SidewalkPOI::ParkingSpot(ParkingSpot::Offstreet(b2, idx)),
) if b1 == b2 => {
self.trips.ped_reached_parking_spot(
self.time,
create_ped.id,
ParkingSpot::Offstreet(*b2, *idx),
Duration::ZERO,
map,
&self.parking,
&mut self.scheduler,
);
}
_ => {
if let SidewalkPOI::Building(b) = &create_ped.start.connection {
events.push(Event::PersonLeavesBuilding(create_ped.person, *b));
}
self.walking
.spawn_ped(self.time, create_ped, map, &mut self.scheduler);
}
}
} else {
self.trips.abort_trip_failed_start( self.trips.abort_trip_failed_start(
self.time, self.time,
create_ped.trip, trip,
map, map,
&self.parking,
&mut self.scheduler, &mut self.scheduler,
); );
} }
} }
Command::SpawnPed(create_ped) => {
// Do the order a bit backwards so we don't have to clone the
// CreatePedestrian. spawn_ped can't fail.
self.trips
.agent_starting_trip_leg(AgentID::Pedestrian(create_ped.id), create_ped.trip);
events.push(Event::TripPhaseStarting(
create_ped.trip,
create_ped.person,
TripMode::Walk,
Some(create_ped.req.clone()),
TripPhaseType::Walking,
));
self.analytics.record_demand(&create_ped.path, map);
// Maybe there's actually no work to do!
match (&create_ped.start.connection, &create_ped.goal.connection) {
(
SidewalkPOI::Building(b1),
SidewalkPOI::ParkingSpot(ParkingSpot::Offstreet(b2, idx)),
) if b1 == b2 => {
self.trips.ped_reached_parking_spot(
self.time,
create_ped.id,
ParkingSpot::Offstreet(*b2, *idx),
Duration::ZERO,
map,
&self.parking,
&mut self.scheduler,
);
}
_ => {
if let SidewalkPOI::Building(b) = &create_ped.start.connection {
events.push(Event::PersonLeavesBuilding(create_ped.person, *b));
}
self.walking
.spawn_ped(self.time, create_ped, map, &mut self.scheduler);
}
}
}
Command::UpdateCar(car) => { Command::UpdateCar(car) => {
self.driving.update_car( self.driving.update_car(
car, car,
@ -1015,7 +957,8 @@ impl Sim {
} }
// Only currently parked cars // Only currently parked cars
pub fn get_parked_car_owned_by(&self, id: PersonID) -> Option<CarID> { pub fn get_parked_car_owned_by(&self, id: PersonID) -> Option<CarID> {
self.parking.get_car_owned_by(id) let p = self.parking.get_parked_car_owned_by(id)?;
Some(p.vehicle.id)
} }
pub fn lookup_person(&self, id: PersonID) -> Option<&Person> { pub fn lookup_person(&self, id: PersonID) -> Option<&Person> {
@ -1186,8 +1129,13 @@ impl Sim {
impl Sim { impl Sim {
pub fn kill_stuck_car(&mut self, id: CarID, map: &Map) { pub fn kill_stuck_car(&mut self, id: CarID, map: &Map) {
if let Some(trip) = self.agent_to_trip(AgentID::Car(id)) { if let Some(trip) = self.agent_to_trip(AgentID::Car(id)) {
self.trips self.trips.abort_trip_failed_start(
.abort_trip_failed_start(self.time, trip, map, &mut self.scheduler); self.time,
trip,
map,
&self.parking,
&mut self.scheduler,
);
self.driving.kill_stuck_car( self.driving.kill_stuck_car(
id, id,
self.time, self.time,

View File

@ -161,13 +161,6 @@ impl TripManager {
id id
} }
pub fn dynamically_override_legs(&mut self, id: TripID, legs: Vec<TripLeg>) {
let trip = &mut self.trips[id.0];
trip.legs = VecDeque::from(legs);
// This is only for peds using a previously unknown parked car
trip.mode = TripMode::Drive;
}
pub fn agent_starting_trip_leg(&mut self, agent: AgentID, t: TripID) { pub fn agent_starting_trip_leg(&mut self, agent: AgentID, t: TripID) {
assert!(!self.active_trip_mode.contains_key(&agent)); assert!(!self.active_trip_mode.contains_key(&agent));
// TODO ensure a trip only has one active agent (aka, not walking and driving at the same // TODO ensure a trip only has one active agent (aka, not walking and driving at the same
@ -212,7 +205,7 @@ impl TripManager {
let person = trip.person; let person = trip.person;
self.people[person.0].state = PersonState::Inside(b1); self.people[person.0].state = PersonState::Inside(b1);
self.events.push(Event::PersonEntersBuilding(person, b1)); self.events.push(Event::PersonEntersBuilding(person, b1));
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
return; return;
} }
_ => {} _ => {}
@ -282,7 +275,7 @@ impl TripManager {
DrivingGoal::ParkNear(b) => PersonState::Inside(b), DrivingGoal::ParkNear(b) => PersonState::Inside(b),
DrivingGoal::Border(_, _) => PersonState::OffMap, DrivingGoal::Border(_, _) => PersonState::OffMap,
}; };
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
return; return;
}; };
@ -312,6 +305,7 @@ impl TripManager {
spot: SidewalkSpot, spot: SidewalkSpot,
blocked_time: Duration, blocked_time: Duration,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
let trip = &mut self.trips[self let trip = &mut self.trips[self
@ -369,7 +363,7 @@ impl TripManager {
DrivingGoal::ParkNear(b) => PersonState::Inside(b), DrivingGoal::ParkNear(b) => PersonState::Inside(b),
DrivingGoal::Border(_, _) => PersonState::OffMap, DrivingGoal::Border(_, _) => PersonState::OffMap,
}; };
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
} }
@ -406,6 +400,7 @@ impl TripManager {
bldg: BuildingID, bldg: BuildingID,
blocked_time: Duration, blocked_time: Duration,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
let trip = &mut self.trips[self let trip = &mut self.trips[self
@ -429,7 +424,7 @@ impl TripManager {
let person = trip.person; let person = trip.person;
self.people[person.0].state = PersonState::Inside(bldg); self.people[person.0].state = PersonState::Inside(bldg);
self.events.push(Event::PersonEntersBuilding(person, bldg)); self.events.push(Event::PersonEntersBuilding(person, bldg));
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
// If no route is returned, the pedestrian boarded a bus immediately. // If no route is returned, the pedestrian boarded a bus immediately.
@ -527,6 +522,7 @@ impl TripManager {
i: IntersectionID, i: IntersectionID,
blocked_time: Duration, blocked_time: Duration,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
self.events.push(Event::PedReachedBorder(ped, i)); self.events.push(Event::PedReachedBorder(ped, i));
@ -550,7 +546,7 @@ impl TripManager {
}); });
let person = trip.person; let person = trip.person;
self.people[person.0].state = PersonState::OffMap; self.people[person.0].state = PersonState::OffMap;
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
pub fn car_or_bike_reached_border( pub fn car_or_bike_reached_border(
@ -560,6 +556,7 @@ impl TripManager {
i: IntersectionID, i: IntersectionID,
blocked_time: Duration, blocked_time: Duration,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
self.events.push(Event::CarOrBikeReachedBorder(car, i)); self.events.push(Event::CarOrBikeReachedBorder(car, i));
@ -582,7 +579,7 @@ impl TripManager {
}); });
let person = trip.person; let person = trip.person;
self.people[person.0].state = PersonState::OffMap; self.people[person.0].state = PersonState::OffMap;
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
pub fn abort_trip_failed_start( pub fn abort_trip_failed_start(
@ -590,6 +587,7 @@ impl TripManager {
now: Time, now: Time,
id: TripID, id: TripID,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
let trip = &mut self.trips[id.0]; let trip = &mut self.trips[id.0];
@ -602,7 +600,7 @@ impl TripManager {
TripEndpoint::Border(_) => PersonState::OffMap, TripEndpoint::Border(_) => PersonState::OffMap,
}; };
self.events.push(Event::TripAborted(id, trip.mode)); self.events.push(Event::TripAborted(id, trip.mode));
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
pub fn abort_trip_impossible_parking( pub fn abort_trip_impossible_parking(
@ -611,6 +609,7 @@ impl TripManager {
car: CarID, car: CarID,
goal: BuildingID, goal: BuildingID,
map: &Map, map: &Map,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
) { ) {
let id = self.active_trip_mode.remove(&AgentID::Car(car)).unwrap(); let id = self.active_trip_mode.remove(&AgentID::Car(car)).unwrap();
@ -620,7 +619,7 @@ impl TripManager {
self.events.push(Event::TripAborted(trip.id, trip.mode)); self.events.push(Event::TripAborted(trip.id, trip.mode));
let person = trip.person; let person = trip.person;
self.people[person.0].state = PersonState::Inside(goal); self.people[person.0].state = PersonState::Inside(goal);
self.person_finished_trip(now, person, scheduler, map); self.person_finished_trip(now, person, parking, scheduler, map);
} }
pub fn active_agents(&self) -> Vec<AgentID> { pub fn active_agents(&self) -> Vec<AgentID> {
@ -806,6 +805,7 @@ impl TripManager {
&mut self, &mut self,
now: Time, now: Time,
person: PersonID, person: PersonID,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
map: &Map, map: &Map,
) { ) {
@ -818,7 +818,9 @@ impl TripManager {
"At {}, {} just freed up, so starting delayed trip {}", "At {}, {} just freed up, so starting delayed trip {}",
now, person.id, trip now, person.id, trip
); );
self.start_trip(now, trip, spec, maybe_req, maybe_path, scheduler, map); self.start_trip(
now, trip, spec, maybe_req, maybe_path, parking, scheduler, map,
);
} }
pub fn start_trip( pub fn start_trip(
@ -828,6 +830,7 @@ impl TripManager {
spec: TripSpec, spec: TripSpec,
maybe_req: Option<PathRequest>, maybe_req: Option<PathRequest>,
maybe_path: Option<Path>, maybe_path: Option<Path>,
parking: &ParkingSimState,
scheduler: &mut Scheduler, scheduler: &mut Scheduler,
map: &Map, map: &Map,
) { ) {
@ -873,35 +876,68 @@ impl TripManager {
connection at the end): {}", connection at the end): {}",
req req
); );
self.abort_trip_failed_start(now, trip, map, scheduler); self.abort_trip_failed_start(now, trip, map, parking, scheduler);
} }
} }
TripSpec::MaybeUsingParkedCar { TripSpec::UsingParkedCar {
start_bldg, start_bldg,
goal, goal,
ped_speed, ped_speed,
} => { } => {
assert_eq!(person.state, PersonState::Inside(start_bldg)); assert_eq!(person.state, PersonState::Inside(start_bldg));
// TODO First step: could move the handling here
let walk_to = SidewalkSpot::deferred_parking_spot(start_bldg, goal, map); if let Some(parked_car) = parking.get_parked_car_owned_by(person.id) {
let dummy_pos = walk_to.sidewalk_pos; let start = SidewalkSpot::building(start_bldg, map);
scheduler.push( let walking_goal = SidewalkSpot::parking_spot(parked_car.spot, map, parking);
now, let req = PathRequest {
Command::SpawnPed(CreatePedestrian { start: start.sidewalk_pos,
id: person.ped, end: walking_goal.sidewalk_pos,
speed: ped_speed, constraints: PathConstraints::Pedestrian,
start: SidewalkSpot::building(start_bldg, map), };
goal: walk_to, if let Some(path) = map.pathfind(req.clone()) {
path: Path::dummy(), // TODO Can get rid of this once VehicleSpec is tied to a Person
req: PathRequest { let mut legs = vec![
start: dummy_pos, TripLeg::Walk(person.ped, ped_speed, walking_goal.clone()),
end: dummy_pos, TripLeg::Drive(parked_car.vehicle.clone(), goal.clone()),
constraints: PathConstraints::Pedestrian, ];
}, match goal {
trip, DrivingGoal::ParkNear(b) => {
person: person.id, legs.push(TripLeg::Walk(
}), person.ped,
); ped_speed,
SidewalkSpot::building(b, map),
));
}
DrivingGoal::Border(_, _) => {}
}
self.trips[trip.0].legs = VecDeque::from(legs);
scheduler.push(
now,
Command::SpawnPed(CreatePedestrian {
id: person.ped,
speed: ped_speed,
start,
goal: walking_goal,
path,
req,
trip,
person: person.id,
}),
);
} else {
println!("UsingParkedCar trip couldn't find the walking path {}", req);
self.abort_trip_failed_start(now, trip, map, parking, scheduler);
}
} else {
// This should only happen when a driving trip has been aborted and there was
// absolutely no room to warp the car.
println!(
"{} doesn't have a parked car free at {}, aborting trip {}",
person.id, now, trip
);
self.abort_trip_failed_start(now, trip, map, parking, scheduler);
}
} }
TripSpec::JustWalking { TripSpec::JustWalking {
start, start,
@ -934,7 +970,7 @@ impl TripManager {
); );
} else { } else {
println!("JustWalking trip couldn't find the first path {}", req); println!("JustWalking trip couldn't find the first path {}", req);
self.abort_trip_failed_start(now, trip, map, scheduler); self.abort_trip_failed_start(now, trip, map, parking, scheduler);
} }
} }
TripSpec::UsingBike { TripSpec::UsingBike {
@ -968,7 +1004,7 @@ impl TripManager {
); );
} else { } else {
println!("UsingBike trip couldn't find the first path {}", req); println!("UsingBike trip couldn't find the first path {}", req);
self.abort_trip_failed_start(now, trip, map, scheduler); self.abort_trip_failed_start(now, trip, map, parking, scheduler);
} }
} }
TripSpec::UsingTransit { TripSpec::UsingTransit {
@ -1004,7 +1040,7 @@ impl TripManager {
); );
} else { } else {
println!("UsingTransit trip couldn't find the first path {}", req); println!("UsingTransit trip couldn't find the first path {}", req);
self.abort_trip_failed_start(now, trip, map, scheduler); self.abort_trip_failed_start(now, trip, map, parking, scheduler);
} }
} }
} }