plumb through exact off-map locations from popdat->scenario

This commit is contained in:
Dustin Carlino 2020-04-24 22:05:33 -07:00
parent 65ef5d4149
commit dd1c9f936d
13 changed files with 148 additions and 108 deletions

View File

@ -91,16 +91,16 @@ d14c96851d6289b867e008432f54320d data/input/neighborhoods/caphill/Broadway.json
955835e85d15a2fb6c4a8586b8e5cb73 data/input/neighborhoods/caphill/Montlake.json
19e8073a9f6c807b4492681b2c7570de data/input/blockface.bin
db63d7d606e8702d12f9399e87e6a00f data/input/parcels_urbansim.txt
dc1968d1701598bccf41d1f396ae23e9 data/input/raw_maps/huge_seattle.bin
e59204b20ae17a56e128e4d8b0c3b447 data/input/raw_maps/ballard.bin
5474231e70e6edbf16837a0b54bdf33e data/input/raw_maps/downtown.bin
194e089ea73b6dd383d84ab64661c0f3 data/input/raw_maps/caphill.bin
6ea08ee5c85c302671b569cb3113387d data/input/raw_maps/lakeslice.bin
dd7a37e55ccfb450d87ad3195ba614c9 data/input/raw_maps/montlake.bin
b26a07ee49ec56a5ca80b2e01a56f1b5 data/input/raw_maps/intl_district.bin
14eaa51e2ed5235b2423300fc41b93a3 data/input/raw_maps/23rd.bin
0bea891a45667240ff5d5d0d8b484c1c data/input/raw_maps/huge_seattle.bin
a6f96f5e96b520783684778561a965c6 data/input/raw_maps/ballard.bin
21d44b9ca54677ef0c301e238382e536 data/input/raw_maps/downtown.bin
c80b13eaf83c11fb34a8c92611c33f82 data/input/raw_maps/caphill.bin
556045ed604ac0ff2312b45eef17f3ab data/input/raw_maps/lakeslice.bin
3edecaa20da69f94f920fd6a8252ce45 data/input/raw_maps/montlake.bin
2b34d9513ec0d9782216d8723060eeb3 data/input/raw_maps/intl_district.bin
671b84c17f8137503cba9036fbd71257 data/input/raw_maps/23rd.bin
2bc84e4d194d7cea6007ae3b93f3b11b data/input/neighborhoods.geojson
a0461cb7047fbc6f8f44a284cd6c19a4 data/input/popdat.bin
416bfeea026d52aa8989f496fae5fe29 data/input/popdat.bin
428bc2e92ea02089cedbb614ce1d8f25 data/input/polygons/caphill.poly
4f291bbe84ac32a98d7d100be79ddc4b data/input/polygons/huge_seattle.poly
6b221b5e68a38f16f34e46a208c7ca15 data/input/polygons/lakeslice.poly
@ -110,26 +110,26 @@ a0461cb7047fbc6f8f44a284cd6c19a4 data/input/popdat.bin
0304847f270859fcfc19c8ca122ed793 data/input/polygons/23rd.poly
54f5f16e5ec925cb29b4d1405a89ef94 data/input/polygons/downtown.poly
58485a3bdff2aea9769fffd207e3cf30 data/input/offstreet_parking.bin
139f6e0a688bd07a69a4984495b3f2e5 data/input/screenshots/montlake/02x05_i124.png
87b182b3e4269b955fff61a41198da44 data/input/screenshots/montlake/01x06_i26.png
1717bfb53aa375bd3359de6e7db860ff data/input/screenshots/montlake/01x01_i19.png
7c3927abc1b31191c7c24efeb6e9940f data/input/screenshots/montlake/MANIFEST
b681d564271051e5e60cb63d0ee1d6b1 data/input/screenshots/montlake/03x06_i27.png
89abe949e1a8184a084df873dbace415 data/input/screenshots/montlake/02x03_i1.png
612d5c710d77ae2fcd639fc8c1716dac data/input/screenshots/montlake/02x04_i25.png
2b2fffe66932402f6885865217a13175 data/input/screenshots/montlake/03x02_i8.png
75ea4a81b2371fa1b03d756c8fc0fa54 data/input/screenshots/montlake/01x04_i31.png
7dbf9830b6a37f6e58d3effc54363de7 data/input/screenshots/montlake/02x05_i124.png
244fe61defcf394590775582ef438f17 data/input/screenshots/montlake/01x06_i26.png
e6e912d845568358261fd74576b57f87 data/input/screenshots/montlake/01x01_i19.png
d0720059c524ec65637eb8184a1a41c8 data/input/screenshots/montlake/MANIFEST
d66611b36bd11a567f1b8da95420fc9f data/input/screenshots/montlake/03x06_i27.png
4fdfb67049a6208f6b929154cea457d3 data/input/screenshots/montlake/02x03_i1.png
a84ce197439197750399b91522158c81 data/input/screenshots/montlake/02x04_i25.png
a13baeaa78255c5b14f0cd6826ee6495 data/input/screenshots/montlake/03x02_i8.png
c6f46ce8b497eb1b4fa2823cf99468a7 data/input/screenshots/montlake/01x04_i31.png
4f507c78977c8ff62f4c2a0e011329ee data/input/screenshots/montlake/combine.sh
301fa5745ff7c7e1c43e7300e38add50 data/input/screenshots/montlake/03x01_i0.png
e0f2b904b21fec546372c737bc4872da data/input/screenshots/montlake/01x03_i4.png
482f9da940c8c9ed52aa81fcd04b34bc data/input/screenshots/montlake/01x02_i20.png
b1929464274d34c3bce5040821f7869d data/input/screenshots/montlake/03x04_i112.png
33b3c92b72edd8fd757e2df73eb87a52 data/input/screenshots/montlake/02x02_i288.png
1028e0631bdfcc27913de602356b89e0 data/input/screenshots/montlake/03x03_i59.png
587a29517ab20ebe69c03cc2d0eb6b9e data/input/screenshots/montlake/02x01_i24.png
3a92ad12d5875db4dabb7f04bc684435 data/input/screenshots/montlake/03x05_i2.png
3d3733fb494ca616e4070c9146206ebf data/input/screenshots/montlake/02x06_i85.png
25855b7aa895686d13bd054d3bba7051 data/input/screenshots/montlake/01x05_i40.png
df00e33a986f93e3b33938a927d062a9 data/input/screenshots/montlake/03x01_i0.png
3a4dbcb76ce8853f8414abb5fdb727f1 data/input/screenshots/montlake/01x03_i4.png
ce30a66567ab09cb1c36d731c15cd5e1 data/input/screenshots/montlake/01x02_i20.png
7036b3cf99ed1dfd4e856455f1a4978e data/input/screenshots/montlake/03x04_i112.png
1d5849d54d78c0431a9dcbd000fba25c data/input/screenshots/montlake/02x02_i288.png
83b0e07b42d2c50a1ab70fbf69abb97d data/input/screenshots/montlake/03x03_i59.png
211f6c2a020d2d555574ebaf289d21e9 data/input/screenshots/montlake/02x01_i24.png
9eb0005ac206fba788042e655cfbe300 data/input/screenshots/montlake/03x05_i2.png
d12a9d72fcbf32cb75d2820a78fa5e22 data/input/screenshots/montlake/02x06_i85.png
a7fec0718264a554de0fc282f9737ea0 data/input/screenshots/montlake/01x05_i40.png
129b460f56f5eb41cab3bfd70fb5fde9 data/input/sidewalks.bin
0db4e23e51f7680538b0bbbc72208e07 data/input/N47W122.hgt
51dbf7a263fe5f0ea24e43c3aad3fec2 data/input/google_transit/stop_times.txt
@ -217,27 +217,27 @@ d02d0d103f7b00672a5f1145c5169d8c data/system/fonts/Overpass-Bold.ttf
2a13391023ce8787887331530cac35a7 data/system/fonts/BungeeInline-Regular.ttf
17a1468e62195d0688a6f3bd12da2e92 data/system/fonts/Overpass-SemiBold.ttf
259d4afad7edca07e727ef80f5bbce07 data/system/fonts/Bungee-Regular.ttf
4e0441582b7b913a89176436b5122bf2 data/system/maps/huge_seattle.bin
08d407ab1b9688eee0b83cd65e698560 data/system/maps/ballard.bin
19ae5adf392679c4264069bbca23710c data/system/maps/downtown.bin
2313d5a3805f07e652127d0010668c80 data/system/maps/caphill.bin
a3b5a81b41be4c9f4b0710821c1841bb data/system/maps/lakeslice.bin
81057642bc7981331c3fb920147faa75 data/system/maps/montlake.bin
750b8e4f996f12d4105a771e26e83192 data/system/maps/intl_district.bin
e27d41c916a721b330459ce85a114dbc data/system/maps/23rd.bin
812904abcbdca8f86278205f8af26a3e data/system/maps/huge_seattle.bin
5c0b0d1c83f43d8d71d744eabff512cb data/system/maps/ballard.bin
6a7aead7416ee4ac45899fc6fa2905dd data/system/maps/downtown.bin
27c24479582289a6bb47d4de4e5d0242 data/system/maps/caphill.bin
34ce6777051eda17e54c0ea855400d11 data/system/maps/lakeslice.bin
67712c4d404666a29178e3b7542c1269 data/system/maps/montlake.bin
f3b48a58d5af668f02e899ed2e44ef4a data/system/maps/intl_district.bin
d6722d5d86547f8fc963e80595d922dd data/system/maps/23rd.bin
cc45f42cb24cad1cfdbf5ed7a0cb86d4 data/system/synthetic_maps/signal_double.json
8b949cc34d9a27ace0bd8ecde55a9520 data/system/synthetic_maps/signal_single.json
1cd7be125e1d992613ed3a41e8b25b6a data/system/synthetic_maps/signal_fan_in.json
9f8ab17e0a0c1cf4a0d5964f7e36658e data/system/scenarios/ballard/weekday.bin
70b59885920616c1b1677818f6f89d82 data/system/scenarios/intl_district/weekday.bin
ccb9e7763427b2d8b4fb6b44b2c4e599 data/system/scenarios/23rd/weekday.bin
160825412e11206e8e856cc20920fbf0 data/system/scenarios/lakeslice/weekday.bin
a23157b6bc180c457f93430c0683ff69 data/system/scenarios/downtown/weekday.bin
1ea056fc3afff56db11be283bb23b6fd data/system/scenarios/huge_seattle/weekday.bin
1e9409a0a789de6b22157e3f28ce30bd data/system/scenarios/caphill/weekday.bin
f180a68083c44e0e21b65e3e63be8068 data/system/scenarios/montlake/weekday.bin
29828738af2ba2f81b1ac49dd64587b9 data/system/scenarios/ballard/weekday.bin
23da3f12b1e98f2f531aa121a1a85c04 data/system/scenarios/intl_district/weekday.bin
562a97a406e7502e1defcc122919a8cf data/system/scenarios/23rd/weekday.bin
797f560c130135c6d2e3248a95748af7 data/system/scenarios/lakeslice/weekday.bin
aad8ff309a1b38dc85a5d8a4b37f3c87 data/system/scenarios/downtown/weekday.bin
53baae7739ada8cb7276804c0d480618 data/system/scenarios/huge_seattle/weekday.bin
112a8e8a1f8e41f566a03ab83d14fe22 data/system/scenarios/caphill/weekday.bin
fa8391c0e45db61fabdd466ad81b83fa data/system/scenarios/montlake/weekday.bin
80cb748e090072b559b08bdd4bc8c30c data/system/prebaked_results/signal_single/tutorial lvl1.bin
ec841305a2dbc37649045f31afce09bd data/system/prebaked_results/signal_single/tutorial lvl2.bin
4e26a658e0a9e95859d82d35123b33d5 data/system/prebaked_results/montlake/car vs bike contention.bin
25d1542a7cb3bde030a4e10e542e48df data/system/prebaked_results/montlake/weekday.bin
2da75e16bd2620e8ed1f8db58e852538 data/system/prebaked_results/montlake/car vs bike contention.bin
1faec374216a3afa38e48e29d1317126 data/system/prebaked_results/montlake/weekday.bin
02ae8e1b35219ab4934969c07187842b data/system/prebaked_results/montlake/car vs bus contention.bin

View File

@ -247,7 +247,7 @@ fn describe(person: &PersonSpec, trip: &IndividTrip, home: OD) -> String {
b.to_string()
}
}
DrivingGoal::Border(i, _) => {
DrivingGoal::Border(i, _, _) => {
if OD::Border(*i) == home {
"HERE".to_string()
} else {
@ -263,7 +263,7 @@ fn describe(person: &PersonSpec, trip: &IndividTrip, home: OD) -> String {
b.to_string()
}
}
SidewalkPOI::Border(i) => {
SidewalkPOI::Border(i, _) => {
if OD::Border(*i) == home {
"HERE".to_string()
} else {
@ -286,7 +286,9 @@ fn describe(person: &PersonSpec, trip: &IndividTrip, home: OD) -> String {
start.lane(),
driving_goal(goal)
),
SpawnTrip::FromBorder { i, goal, is_bike } => format!(
SpawnTrip::FromBorder {
i, goal, is_bike, ..
} => format!(
"{} at {}: {} appears at {}, goes to {}",
person.id,
trip.depart,
@ -333,11 +335,11 @@ fn describe(person: &PersonSpec, trip: &IndividTrip, home: OD) -> String {
fn other_endpt(trip: &IndividTrip, home: OD, map: &Map) -> ID {
let driving_goal = |goal: &DrivingGoal| match goal {
DrivingGoal::ParkNear(b) => ID::Building(*b),
DrivingGoal::Border(i, _) => ID::Intersection(*i),
DrivingGoal::Border(i, _, _) => ID::Intersection(*i),
};
let sidewalk_spot = |spot: &SidewalkSpot| match &spot.connection {
SidewalkPOI::Building(b) => ID::Building(*b),
SidewalkPOI::Border(i) => ID::Intersection(*i),
SidewalkPOI::Border(i, _) => ID::Intersection(*i),
x => panic!("other_endpt for {:?}?", x),
};

View File

@ -104,6 +104,7 @@ impl State for AgentSpawner {
if let Some(g) = DrivingGoal::end_at_border(
map.get_i(to).some_incoming_road(map),
constraints,
None,
map,
) {
g.goal_pos(constraints, map)
@ -263,7 +264,7 @@ fn schedule_trip(
let goal = match raw_goal {
Goal::Building(to) => SidewalkSpot::building(to, map),
Goal::Border(to) => {
if let Some(goal) = SidewalkSpot::end_at_border(to, map) {
if let Some(goal) = SidewalkSpot::end_at_border(to, None, map) {
goal
} else {
return Some(format!("Can't end a walking trip at {}; no sidewalks", to));
@ -303,6 +304,7 @@ fn schedule_trip(
if let Some(g) = DrivingGoal::end_at_border(
map.get_i(to).some_incoming_road(map),
PathConstraints::Bike,
None,
map,
) {
g
@ -334,6 +336,7 @@ fn schedule_trip(
if let Some(g) = DrivingGoal::end_at_border(
map.get_i(to).some_incoming_road(map),
PathConstraints::Car,
None,
map,
) {
g

View File

@ -192,6 +192,7 @@ fn import_parcels(
Endpoint {
pos: pt,
osm_building,
parcel_id: id,
},
);
}

View File

@ -21,6 +21,7 @@ pub struct OrigTrip {
pub struct Endpoint {
pub pos: LonLat,
pub osm_building: Option<i64>,
pub parcel_id: usize,
}
#[derive(Serialize, Deserialize)]

View File

@ -1,9 +1,12 @@
use crate::psrc::{Endpoint, Mode, OrigTrip, Parcel};
use crate::PopDat;
use abstutil::{prettyprint_usize, MultiMap, Timer};
use geom::{LonLat, Pt2D};
use geom::LonLat;
use map_model::{BuildingID, IntersectionID, Map, PathConstraints};
use sim::{DrivingGoal, IndividTrip, PersonID, PersonSpec, Scenario, SidewalkSpot, SpawnTrip};
use sim::{
DrivingGoal, IndividTrip, OffMapLocation, PersonID, PersonSpec, Scenario, SidewalkSpot,
SpawnTrip,
};
use std::collections::HashMap;
#[derive(Clone, Debug)]
@ -16,19 +19,18 @@ pub struct Trip {
#[derive(Clone, Debug)]
pub enum TripEndpt {
Building(BuildingID),
// The Pt2D is the original point. It'll be outside the map and likely out-of-bounds entirely,
// maybe even negative.
Border(IntersectionID, Pt2D),
Border(IntersectionID, OffMapLocation),
}
impl Trip {
fn to_spawn_trip(&self, map: &Map) -> SpawnTrip {
match self.orig.mode {
Mode::Drive => match self.from {
TripEndpt::Border(i, _) => SpawnTrip::FromBorder {
TripEndpt::Border(i, ref origin) => SpawnTrip::FromBorder {
i,
goal: self.to.driving_goal(PathConstraints::Car, map),
is_bike: false,
origin: Some(origin.clone()),
},
TripEndpt::Building(b) => {
SpawnTrip::UsingParkedCar(b, self.to.driving_goal(PathConstraints::Car, map))
@ -39,10 +41,11 @@ impl Trip {
SidewalkSpot::building(b, map),
self.to.driving_goal(PathConstraints::Bike, map),
),
TripEndpt::Border(i, _) => SpawnTrip::FromBorder {
TripEndpt::Border(i, ref origin) => SpawnTrip::FromBorder {
i,
goal: self.to.driving_goal(PathConstraints::Bike, map),
is_bike: true,
origin: Some(origin.clone()),
},
},
Mode::Walk => SpawnTrip::JustWalking(
@ -69,7 +72,6 @@ impl Trip {
impl TripEndpt {
fn new(
endpt: &Endpoint,
map: &Map,
osm_id_to_bldg: &HashMap<i64, BuildingID>,
borders: &Vec<(IntersectionID, LonLat)>,
) -> Option<TripEndpt> {
@ -82,7 +84,10 @@ impl TripEndpt {
.map(|(id, _)| {
TripEndpt::Border(
*id,
Pt2D::forcibly_from_gps(endpt.pos, map.get_gps_bounds()),
OffMapLocation {
gps: endpt.pos,
parcel_id: endpt.parcel_id,
},
)
})
}
@ -90,24 +95,31 @@ impl TripEndpt {
fn start_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
match self {
TripEndpt::Building(b) => SidewalkSpot::building(*b, map),
TripEndpt::Border(i, _) => SidewalkSpot::start_at_border(*i, map).unwrap(),
TripEndpt::Border(i, origin) => {
SidewalkSpot::start_at_border(*i, Some(origin.clone()), map).unwrap()
}
}
}
fn end_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
match self {
TripEndpt::Building(b) => SidewalkSpot::building(*b, map),
TripEndpt::Border(i, _) => SidewalkSpot::end_at_border(*i, map).unwrap(),
TripEndpt::Border(i, destination) => {
SidewalkSpot::end_at_border(*i, Some(destination.clone()), map).unwrap()
}
}
}
fn driving_goal(&self, constraints: PathConstraints, map: &Map) -> DrivingGoal {
match self {
TripEndpt::Building(b) => DrivingGoal::ParkNear(*b),
TripEndpt::Border(i, _) => {
DrivingGoal::end_at_border(map.get_i(*i).some_incoming_road(map), constraints, map)
.unwrap()
}
TripEndpt::Border(i, destination) => DrivingGoal::end_at_border(
map.get_i(*i).some_incoming_road(map),
constraints,
Some(destination.clone()),
map,
)
.unwrap(),
}
}
}
@ -168,7 +180,6 @@ pub fn clip_trips(map: &Map, timer: &mut Timer) -> (Vec<Trip>, HashMap<BuildingI
let maybe_results: Vec<Option<Trip>> = timer.parallelize("clip trips", popdat.trips, |orig| {
let from = TripEndpt::new(
&orig.from,
map,
&osm_id_to_bldg,
match orig.mode {
Mode::Walk | Mode::Transit => &incoming_borders_walking,
@ -178,7 +189,6 @@ pub fn clip_trips(map: &Map, timer: &mut Timer) -> (Vec<Trip>, HashMap<BuildingI
)?;
let to = TripEndpt::new(
&orig.to,
map,
&osm_id_to_bldg,
match orig.mode {
Mode::Walk | Mode::Transit => &outgoing_borders_walking,

View File

@ -14,8 +14,8 @@ pub use self::analytics::{Analytics, TripPhase};
pub(crate) use self::events::Event;
pub use self::events::{AlertLocation, TripPhaseType};
pub use self::make::{
ABTest, BorderSpawnOverTime, IndividTrip, OriginDestination, PersonSpec, Scenario,
ScenarioGenerator, SimFlags, SpawnOverTime, SpawnTrip, TripSpawner, TripSpec,
ABTest, BorderSpawnOverTime, IndividTrip, OffMapLocation, OriginDestination, PersonSpec,
Scenario, ScenarioGenerator, SimFlags, SpawnOverTime, SpawnTrip, TripSpawner, TripSpec,
};
pub(crate) use self::mechanics::{
DrivingSimState, IntersectionSimState, ParkingSimState, WalkingSimState,
@ -206,13 +206,14 @@ pub struct ParkedCar {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum DrivingGoal {
ParkNear(BuildingID),
Border(IntersectionID, LaneID),
Border(IntersectionID, LaneID, Option<OffMapLocation>),
}
impl DrivingGoal {
pub fn end_at_border(
dr: DirectedRoadID,
constraints: PathConstraints,
destination: Option<OffMapLocation>,
map: &Map,
) -> Option<DrivingGoal> {
let lanes = dr.lanes(constraints, map);
@ -220,7 +221,7 @@ impl DrivingGoal {
None
} else {
// TODO ideally could use any
Some(DrivingGoal::Border(dr.dst_i(map), lanes[0]))
Some(DrivingGoal::Border(dr.dst_i(map), lanes[0], destination))
}
}
@ -236,7 +237,7 @@ impl DrivingGoal {
}
PathConstraints::Bus | PathConstraints::Pedestrian => unreachable!(),
},
DrivingGoal::Border(_, l) => Position::new(*l, map.get_l(*l).length()),
DrivingGoal::Border(_, l, _) => Position::new(*l, map.get_l(*l).length()),
}
}
@ -252,7 +253,7 @@ impl DrivingGoal {
Some(Router::park_near(path, *b))
}
}
DrivingGoal::Border(i, last_lane) => Some(Router::end_at_border(
DrivingGoal::Border(i, last_lane, _) => Some(Router::end_at_border(
path,
map.get_l(*last_lane).length(),
*i,
@ -263,7 +264,7 @@ impl DrivingGoal {
pub fn pt(&self, map: &Map) -> Pt2D {
match self {
DrivingGoal::ParkNear(b) => map.get_b(*b).polygon.center(),
DrivingGoal::Border(i, _) => map.get_i(*i).polygon.center(),
DrivingGoal::Border(i, _, _) => map.get_i(*i).polygon.center(),
}
}
}
@ -336,14 +337,18 @@ impl SidewalkSpot {
}
// Recall sidewalks are bidirectional.
pub fn start_at_border(i: IntersectionID, map: &Map) -> Option<SidewalkSpot> {
pub fn start_at_border(
i: IntersectionID,
origin: Option<OffMapLocation>,
map: &Map,
) -> Option<SidewalkSpot> {
let lanes = map
.get_i(i)
.get_outgoing_lanes(map, PathConstraints::Pedestrian);
if !lanes.is_empty() {
return Some(SidewalkSpot {
sidewalk_pos: Position::new(lanes[0], Distance::ZERO),
connection: SidewalkPOI::Border(i),
connection: SidewalkPOI::Border(i, origin),
});
}
@ -355,18 +360,22 @@ impl SidewalkSpot {
}
Some(SidewalkSpot {
sidewalk_pos: Position::new(lanes[0], map.get_l(lanes[0]).length()),
connection: SidewalkPOI::Border(i),
connection: SidewalkPOI::Border(i, origin),
})
}
pub fn end_at_border(i: IntersectionID, map: &Map) -> Option<SidewalkSpot> {
pub fn end_at_border(
i: IntersectionID,
destination: Option<OffMapLocation>,
map: &Map,
) -> Option<SidewalkSpot> {
let lanes = map
.get_i(i)
.get_incoming_lanes(map, PathConstraints::Pedestrian);
if !lanes.is_empty() {
return Some(SidewalkSpot {
sidewalk_pos: Position::new(lanes[0], map.get_l(lanes[0]).length()),
connection: SidewalkPOI::Border(i),
connection: SidewalkPOI::Border(i, destination),
});
}
@ -378,7 +387,7 @@ impl SidewalkSpot {
}
Some(SidewalkSpot {
sidewalk_pos: Position::new(lanes[0], Distance::ZERO),
connection: SidewalkPOI::Border(i),
connection: SidewalkPOI::Border(i, destination),
})
}
@ -402,7 +411,7 @@ pub enum SidewalkPOI {
DeferredParkingSpot,
Building(BuildingID),
BusStop(BusStopID),
Border(IntersectionID),
Border(IntersectionID, Option<OffMapLocation>),
// The equivalent position on the nearest driving/bike lane
BikeRack(Position),
SuddenlyAppear,

View File

@ -281,7 +281,7 @@ impl BorderSpawnOverTime {
}
let start = if let Some(s) =
SidewalkSpot::start_at_border(self.start_from_border.src_i(map), map)
SidewalkSpot::start_at_border(self.start_from_border.src_i(map), None, map)
{
s
} else {
@ -358,6 +358,7 @@ impl BorderSpawnOverTime {
i: self.start_from_border.src_i(map),
goal,
is_bike: constraints == PathConstraints::Bike,
origin: None,
},
}],
});
@ -388,7 +389,7 @@ impl OriginDestination {
)),
OriginDestination::GotoBldg(b) => Some(DrivingGoal::ParkNear(*b)),
OriginDestination::EndOfRoad(dr) => {
let goal = DrivingGoal::end_at_border(*dr, constraints, map);
let goal = DrivingGoal::end_at_border(*dr, constraints, None, map);
if goal.is_none() {
timer.warn(format!(
"Can't spawn a {:?} ending at border {}; no appropriate lanes there",
@ -413,7 +414,7 @@ impl OriginDestination {
map,
)),
OriginDestination::EndOfRoad(dr) => {
let goal = SidewalkSpot::end_at_border(dr.dst_i(map), map);
let goal = SidewalkSpot::end_at_border(dr.dst_i(map), None, map);
if goal.is_none() {
timer.warn(format!("Can't end_at_border for {} without a sidewalk", dr));
}

View File

@ -9,5 +9,5 @@ pub use self::generator::{
BorderSpawnOverTime, OriginDestination, ScenarioGenerator, SpawnOverTime,
};
pub use self::load::SimFlags;
pub use self::scenario::{IndividTrip, PersonSpec, Scenario, SpawnTrip};
pub use self::scenario::{IndividTrip, OffMapLocation, PersonSpec, Scenario, SpawnTrip};
pub use self::spawner::{TripSpawner, TripSpec};

View File

@ -3,7 +3,7 @@ use crate::{
TripSpec, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH, MIN_CAR_LENGTH,
};
use abstutil::{prettyprint_usize, Counter, Timer};
use geom::{Distance, Duration, Speed, Time};
use geom::{Distance, Duration, LonLat, Speed, Time};
use map_model::{
BuildingID, BusRouteID, BusStopID, IntersectionID, Map, PathConstraints, Position, RoadID,
};
@ -38,7 +38,7 @@ pub struct IndividTrip {
pub trip: SpawnTrip,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum SpawnTrip {
// Only for interactive / debug trips
VehicleAppearing {
@ -51,6 +51,7 @@ pub enum SpawnTrip {
goal: DrivingGoal,
// For bikes starting at a border, use FromBorder. UsingBike implies a walk->bike trip.
is_bike: bool,
origin: Option<OffMapLocation>,
},
UsingParkedCar(BuildingID, DrivingGoal),
UsingBike(SidewalkSpot, DrivingGoal),
@ -58,6 +59,12 @@ pub enum SpawnTrip {
UsingTransit(SidewalkSpot, SidewalkSpot, BusRouteID, BusStopID, BusStopID),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct OffMapLocation {
pub parcel_id: usize,
pub gps: LonLat,
}
impl Scenario {
// Any case where map edits could change the calls to the RNG, we have to fork.
pub fn instantiate(&self, sim: &mut Sim, map: &Map, rng: &mut XorShiftRng, timer: &mut Timer) {
@ -398,7 +405,7 @@ impl SpawnTrip {
| SpawnTrip::JustWalking(ref spot, _)
| SpawnTrip::UsingTransit(ref spot, _, _, _, _) => match spot.connection {
SidewalkPOI::Building(b) => TripEndpoint::Bldg(b),
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::Border(i, _) => TripEndpoint::Border(i),
_ => unreachable!(),
},
}
@ -411,12 +418,12 @@ impl SpawnTrip {
| SpawnTrip::UsingParkedCar(_, ref goal)
| SpawnTrip::UsingBike(_, ref goal) => match goal {
DrivingGoal::ParkNear(b) => TripEndpoint::Bldg(*b),
DrivingGoal::Border(i, _) => TripEndpoint::Border(*i),
DrivingGoal::Border(i, _, _) => TripEndpoint::Border(*i),
},
SpawnTrip::JustWalking(_, ref spot) | SpawnTrip::UsingTransit(_, ref spot, _, _, _) => {
match spot.connection {
SidewalkPOI::Building(b) => TripEndpoint::Bldg(b),
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::Border(i, _) => TripEndpoint::Border(i),
_ => unreachable!(),
}
}
@ -506,7 +513,7 @@ impl PersonSpec {
DrivingGoal::ParkNear(b) => {
car_locations.push((idx, Some(*b)));
}
DrivingGoal::Border(_, _) => {
DrivingGoal::Border(_, _, _) => {
car_locations.push((idx, None));
}
}
@ -536,7 +543,7 @@ impl PersonSpec {
DrivingGoal::ParkNear(b) => {
car_locations.push((idx, Some(*b)));
}
DrivingGoal::Border(_, _) => {
DrivingGoal::Border(_, _, _) => {
car_locations.push((idx, None));
}
}

View File

@ -86,7 +86,7 @@ impl TripSpawner {
);
}
match goal {
DrivingGoal::Border(_, end_lane) => {
DrivingGoal::Border(_, end_lane, _) => {
if start_pos.lane() == *end_lane
&& start_pos.dist_along() == map.get_l(*end_lane).length()
{
@ -241,7 +241,7 @@ impl TripSpawner {
DrivingGoal::ParkNear(b) => {
legs.push(TripLeg::Walk(SidewalkSpot::building(b, map)));
}
DrivingGoal::Border(_, _) => {}
DrivingGoal::Border(_, _, _) => {}
}
trips.new_trip(
person.id,
@ -259,7 +259,7 @@ impl TripSpawner {
SidewalkPOI::SuddenlyAppear => {
TripEndpoint::Border(map.get_l(start.sidewalk_pos.lane()).src_i)
}
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::Border(i, _) => TripEndpoint::Border(i),
_ => unreachable!(),
},
TripMode::Walk,
@ -276,7 +276,7 @@ impl TripSpawner {
DrivingGoal::ParkNear(b) => {
legs.push(TripLeg::Walk(SidewalkSpot::building(b, map)));
}
DrivingGoal::Border(_, _) => {}
DrivingGoal::Border(_, _, _) => {}
};
trips.new_trip(
person.id,
@ -286,7 +286,7 @@ impl TripSpawner {
SidewalkPOI::SuddenlyAppear => {
TripEndpoint::Border(map.get_l(start.sidewalk_pos.lane()).src_i)
}
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::Border(i, _) => TripEndpoint::Border(i),
_ => unreachable!(),
},
TripMode::Bike,
@ -309,7 +309,7 @@ impl TripSpawner {
SidewalkPOI::SuddenlyAppear => {
TripEndpoint::Border(map.get_l(start.sidewalk_pos.lane()).src_i)
}
SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::Border(i, _) => TripEndpoint::Border(i),
_ => unreachable!(),
},
TripMode::Transit,

View File

@ -161,7 +161,7 @@ impl WalkingSimState {
self.peds.remove(&id);
}
}
SidewalkPOI::Border(i) => {
SidewalkPOI::Border(i, _) => {
self.peds_per_traversable
.remove(ped.path.current_step().as_traversable(), ped.id);
trips.ped_reached_border(

View File

@ -90,12 +90,12 @@ impl TripManager {
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),
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),
DrivingGoal::Border(i, _, _) => TripEndpoint::Border(*i),
},
_ => unreachable!(),
};
@ -524,7 +524,13 @@ impl TripManager {
.0];
trip.total_blocked_time += blocked_time;
trip.assert_walking_leg(SidewalkSpot::end_at_border(i, map).unwrap());
match trip.legs.pop_front() {
Some(TripLeg::Walk(spot)) => match spot.connection {
SidewalkPOI::Border(i2, _) => assert_eq!(i, i2),
_ => unreachable!(),
},
_ => unreachable!(),
}
assert!(trip.legs.is_empty());
assert!(!trip.finished_at.is_some());
trip.finished_at = Some(now);
@ -555,7 +561,7 @@ impl TripManager {
trip.total_blocked_time += blocked_time;
match trip.legs.pop_front().unwrap() {
TripLeg::Drive(c, DrivingGoal::Border(int, _)) => {
TripLeg::Drive(c, DrivingGoal::Border(int, _, _)) => {
assert_eq!(car, c);
assert_eq!(i, int);
}
@ -987,7 +993,7 @@ impl TripManager {
person.state,
match start.connection {
SidewalkPOI::Building(b) => PersonState::Inside(b),
SidewalkPOI::Border(_) => PersonState::OffMap,
SidewalkPOI::Border(_, _) => PersonState::OffMap,
SidewalkPOI::SuddenlyAppear => PersonState::OffMap,
_ => unreachable!(),
}
@ -1022,7 +1028,7 @@ impl TripManager {
person.state,
match start.connection {
SidewalkPOI::Building(b) => PersonState::Inside(b),
SidewalkPOI::Border(_) => PersonState::OffMap,
SidewalkPOI::Border(_, _) => PersonState::OffMap,
SidewalkPOI::SuddenlyAppear => PersonState::OffMap,
_ => unreachable!(),
}
@ -1059,7 +1065,7 @@ impl TripManager {
person.state,
match start.connection {
SidewalkPOI::Building(b) => PersonState::Inside(b),
SidewalkPOI::Border(_) => PersonState::OffMap,
SidewalkPOI::Border(_, _) => PersonState::OffMap,
SidewalkPOI::SuddenlyAppear => PersonState::OffMap,
_ => unreachable!(),
}