Abort cars bound to park on edited lanes. #312

This commit is contained in:
Dustin Carlino 2020-09-09 10:47:14 -07:00
parent 53f35f5de1
commit 220f33e2ec
6 changed files with 78 additions and 52 deletions

View File

@ -95,8 +95,7 @@ impl EditMode {
app.primary
.sim
.handle_live_edited_traffic_signals(&app.primary.map);
app.primary.sim.handle_live_edited_lanes(&app.primary.map);
app.primary.sim.handle_live_edited_parking(&app.primary.map);
app.primary.sim.handle_live_edits(&app.primary.map);
Transition::Pop
})
}

View File

@ -4,14 +4,14 @@ use crate::sim::Ctx;
use crate::{
ActionAtEnd, AgentID, AgentProperties, CarID, Command, CreateCar, DistanceInterval,
DrawCarInput, Event, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, PersonID,
Scheduler, TimeInterval, TransitSimState, TripManager, UnzoomedAgent, Vehicle, WalkingSimState,
FOLLOWING_DISTANCE,
Scheduler, TimeInterval, TransitSimState, TripID, TripManager, UnzoomedAgent, Vehicle,
WalkingSimState, FOLLOWING_DISTANCE,
};
use abstutil::{deserialize_btreemap, serialize_btreemap};
use geom::{Distance, Duration, PolyLine, Time};
use map_model::{LaneID, Map, Path, PathStep, Traversable};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet, VecDeque};
use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque};
const TIME_TO_UNPARK_ONSTRET: Duration = Duration::const_seconds(10.0);
const TIME_TO_PARK_ONSTREET: Duration = Duration::const_seconds(15.0);
@ -1024,4 +1024,20 @@ impl DrivingSimState {
pub fn target_lane_penalty(&self, l: LaneID) -> (usize, usize) {
self.queues[&Traversable::Lane(l)].target_lane_penalty()
}
pub fn find_trips_to_edited_parking(
&self,
spots: BTreeSet<ParkingSpot>,
) -> Vec<(AgentID, TripID)> {
let mut affected = Vec::new();
for car in self.cars.values() {
if let Some(spot) = car.router.get_parking_spot_goal() {
if !spots.contains(spot) {
// Buses don't park
affected.push((AgentID::Car(car.vehicle.id), car.trip_and_person.unwrap().0));
}
}
}
affected
}
}

View File

@ -100,7 +100,7 @@ impl ParkingSimState {
}
// Returns any cars that got very abruptly evicted from existence
pub fn handle_map_updates(&mut self, map: &Map, timer: &mut Timer) -> Vec<ParkedCar> {
pub fn handle_live_edits(&mut self, map: &Map, timer: &mut Timer) -> Vec<ParkedCar> {
let (filled_before, _) = self.get_all_parking_spots();
let new = ParkingSimState::new(map, timer);
let (_, avail_after) = new.get_all_parking_spots();

View File

@ -489,25 +489,18 @@ impl WalkingSimState {
std::mem::replace(&mut self.events, Vec::new())
}
pub fn handle_live_edited_parking(
&mut self,
deleted_cars: Vec<ParkedCar>,
scheduler: &mut Scheduler,
) {
let goals: BTreeSet<SidewalkPOI> = deleted_cars
pub fn find_trips_to_parking(&self, evicted_cars: Vec<ParkedCar>) -> Vec<(AgentID, TripID)> {
let goals: BTreeSet<SidewalkPOI> = evicted_cars
.into_iter()
.map(|p| SidewalkPOI::ParkingSpot(p.spot))
.collect();
let mut delete = Vec::new();
let mut affected = Vec::new();
for ped in self.peds.values() {
if goals.contains(&ped.goal.connection) {
delete.push(ped.id);
affected.push((AgentID::Pedestrian(ped.id), ped.trip));
}
}
for id in delete {
self.delete_ped(id, scheduler);
}
affected
}
}

View File

@ -32,7 +32,6 @@ pub enum ActionAtEnd {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
enum Goal {
// Spot and cached distance along the last driving lane
// TODO Right now, the building is ignored when choosing the best spot.
ParkNearBuilding {
target: BuildingID,
spot: Option<(ParkingSpot, Distance)>,
@ -429,4 +428,11 @@ impl Router {
_ => false,
}
}
pub fn get_parking_spot_goal(&self) -> Option<&ParkingSpot> {
match self.goal {
Goal::ParkNearBuilding { ref spot, .. } => spot.as_ref().map(|(s, _)| s),
_ => None,
}
}
}

View File

@ -17,7 +17,7 @@ use map_model::{
};
use rand_xorshift::XorShiftRng;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::panic;
// TODO Do something else.
@ -849,32 +849,8 @@ impl Sim {
.handle_live_edited_traffic_signals(self.time, map, &mut self.scheduler)
}
pub fn handle_live_edited_lanes(&mut self, map: &Map) {
// TODO Handle changes to access restrictions
// Find every active trip whose path crosses a modified lane or closed intersection
let (edited_lanes, _) = map.get_edits().changed_lanes(map);
let mut closed_intersections = HashSet::new();
for i in map.get_edits().original_intersections.keys() {
if map.get_i(*i).is_closed() {
closed_intersections.insert(*i);
}
}
let mut affected = Vec::new();
for (a, trip) in self.trips.active_agents_and_trips() {
if let Some(path) = self.get_path(*a) {
if path
.get_steps()
.iter()
.any(|step| match step.as_traversable() {
Traversable::Lane(l) => edited_lanes.contains(&l),
Traversable::Turn(t) => closed_intersections.contains(&t.parent),
})
{
affected.push((*a, *trip));
}
}
}
pub fn handle_live_edits(&mut self, map: &Map) {
let affected = self.find_trips_affected_by_live_edits(map);
// V1: Just abort every trip crossing an affected area.
// (V2 is probably rerouting everyone, only aborting when that fails)
@ -902,12 +878,48 @@ impl Sim {
}
}
pub fn handle_live_edited_parking(&mut self, map: &Map) {
self.walking.handle_live_edited_parking(
self.parking
.handle_map_updates(map, &mut Timer::throwaway()),
&mut self.scheduler,
);
fn find_trips_affected_by_live_edits(&mut self, map: &Map) -> Vec<(AgentID, TripID)> {
let mut affected: Vec<(AgentID, TripID)> = Vec::new();
// TODO Handle changes to access restrictions
{
// Find every active trip whose path crosses a modified lane or closed intersection
let (edited_lanes, _) = map.get_edits().changed_lanes(map);
let mut closed_intersections = HashSet::new();
for i in map.get_edits().original_intersections.keys() {
if map.get_i(*i).is_closed() {
closed_intersections.insert(*i);
}
}
for (a, trip) in self.trips.active_agents_and_trips() {
if let Some(path) = self.get_path(*a) {
if path
.get_steps()
.iter()
.any(|step| match step.as_traversable() {
Traversable::Lane(l) => edited_lanes.contains(&l),
Traversable::Turn(t) => closed_intersections.contains(&t.parent),
})
{
affected.push((*a, *trip));
}
}
}
}
{
let evicted_cars = self.parking.handle_live_edits(map, &mut Timer::throwaway());
affected.extend(self.walking.find_trips_to_parking(evicted_cars));
let (filled, avail) = self.parking.get_all_parking_spots();
let mut all_spots: BTreeSet<ParkingSpot> = BTreeSet::new();
all_spots.extend(filled);
all_spots.extend(avail);
affected.extend(self.driving.find_trips_to_edited_parking(all_spots));
}
affected
}
}