mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 23:43:25 +03:00
start to simplify the dynamic nabbing of parked cars
This commit is contained in:
parent
98b76c0759
commit
6ef3a180a3
@ -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) => {
|
||||||
|
@ -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(
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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)) => {
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
160
sim/src/sim.rs
160
sim/src/sim.rs
@ -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,
|
||||||
|
118
sim/src/trips.rs
118
sim/src/trips.rs
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user