mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 16:02:23 +03:00
spawning buses at 0.01m on a non-border lane can break, because other cars approach, and the buffer distance gets broken. instead, spawn the buses a few lanes away, if needed. fixes #260
now only ~400 agents left in lakeslice by end!
This commit is contained in:
parent
b7ed2615b1
commit
940d2265c0
@ -34,29 +34,29 @@ data/input/seattle/osm/south_seattle.osm,1107f8b545b09731c4619fde63bdbaed,https:
|
||||
data/input/seattle/osm/udistrict.osm,ed26f2405c07c63161e902bcb5049fab,https://www.dropbox.com/s/ozqk7lb5nn0wace/udistrict.osm.zip?dl=0
|
||||
data/input/seattle/osm/washington-latest.osm.pbf,332c0bbd80621a52e3765381718f3454,https://www.dropbox.com/s/iitat4cnhj5dop8/washington-latest.osm.pbf.zip?dl=0
|
||||
data/input/seattle/osm/west_seattle.osm,f829d6a1c87e782fafbc1552acc5a523,https://www.dropbox.com/s/3vlyve59lfo9s99/west_seattle.osm.zip?dl=0
|
||||
data/input/seattle/parcels.bin,97e8be05694e2f4a1f5194dbc7523c40,https://www.dropbox.com/s/pue16ui1bq4s17w/parcels.bin.zip?dl=0
|
||||
data/input/seattle/parcels.bin,f30df790f1f3d00ad92f255045958920,https://www.dropbox.com/s/rdmtdcfntflgi31/parcels.bin.zip?dl=0
|
||||
data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0
|
||||
data/input/seattle/popdat.bin,0fd10698d2c6bf41da3d57804c617d15,https://www.dropbox.com/s/iboctakleznvslq/popdat.bin.zip?dl=0
|
||||
data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0
|
||||
data/system/cities/seattle.bin,4ddc0f99d53ae3171f0c4ad2e4c646bd,https://www.dropbox.com/s/m7q6y6w9gw3ubjs/seattle.bin.zip?dl=0
|
||||
data/system/maps/ballard.bin,e27bd39957c52599f70f841114048f7b,https://www.dropbox.com/s/y0d4b9ppeibkljn/ballard.bin.zip?dl=0
|
||||
data/system/maps/berlin_center.bin,548313aaed159d2ebd3c034f09a9b5d0,https://www.dropbox.com/s/o4wqefgcywlvmng/berlin_center.bin.zip?dl=0
|
||||
data/system/maps/downtown.bin,134b2db03a9bdd1eecabb700b3335a35,https://www.dropbox.com/s/8h3nzu0zqpj2kr8/downtown.bin.zip?dl=0
|
||||
data/system/maps/huge_seattle.bin,2e9bdc736ab93e00c986480199be0994,https://www.dropbox.com/s/ui8u1k76avtn70h/huge_seattle.bin.zip?dl=0
|
||||
data/system/maps/krakow_center.bin,9cb4922363683950d99e4f8c466eab99,https://www.dropbox.com/s/fmyw0fkwrnpvcnf/krakow_center.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,f2ee2ed0b5eb8b754dc10d720e18f25f,https://www.dropbox.com/s/bdukilqzhxkicjf/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,a5561eb511d4267c636cbb7b0f47e23f,https://www.dropbox.com/s/cehp7etb10h9xq9/montlake.bin.zip?dl=0
|
||||
data/system/maps/south_seattle.bin,a7543a7724d9db41aa325aafaba1d184,https://www.dropbox.com/s/cdtlva0t547siy0/south_seattle.bin.zip?dl=0
|
||||
data/system/maps/udistrict.bin,efd51f101306b243cd80052d8dfd3828,https://www.dropbox.com/s/nn5opbmncdhou2g/udistrict.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,c7d36900c1f7eec758dbec2ab6dc745c,https://www.dropbox.com/s/oyfvegdlnpwzk43/west_seattle.bin.zip?dl=0
|
||||
data/system/prebaked_results/lakeslice/weekday.bin,9040df55be360864e545d1d69f59796c,https://www.dropbox.com/s/yevdoe50z109sjc/weekday.bin.zip?dl=0
|
||||
data/system/maps/ballard.bin,82ced46cda865fb65bc11e7ff68ff877,https://www.dropbox.com/s/ilwsscuwtdhv2wu/ballard.bin.zip?dl=0
|
||||
data/system/maps/berlin_center.bin,bfb07f2bb165fabcdaf7779c6fc5a71d,https://www.dropbox.com/s/f9m84s5ilcys3ah/berlin_center.bin.zip?dl=0
|
||||
data/system/maps/downtown.bin,8f51a3079520982d61418e3ef8c3ffb3,https://www.dropbox.com/s/rh3netnh4p7qv5w/downtown.bin.zip?dl=0
|
||||
data/system/maps/huge_seattle.bin,2a758381fd5f94417bb5646025842e50,https://www.dropbox.com/s/n5cstox0s8czqhx/huge_seattle.bin.zip?dl=0
|
||||
data/system/maps/krakow_center.bin,ee128d15bd8c65b70b0a4ad090a7e736,https://www.dropbox.com/s/bkri62r9se3s46y/krakow_center.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,10269590012e297df17acf6195770b96,https://www.dropbox.com/s/xcp4s1dvdy414nz/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,34a67457c7411291ff03772fd785c98d,https://www.dropbox.com/s/sjl8j4or361e7bc/montlake.bin.zip?dl=0
|
||||
data/system/maps/south_seattle.bin,97ec71f95acb4db29abe58cee88d2a21,https://www.dropbox.com/s/wa1azyqelse3t1e/south_seattle.bin.zip?dl=0
|
||||
data/system/maps/udistrict.bin,475e177d37876ac1b49f03646e147371,https://www.dropbox.com/s/qcxcqy3xe0m9dv2/udistrict.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,32cd4866c222a56c543ae9a31256f08e,https://www.dropbox.com/s/gw8hjjrl4cahm0j/west_seattle.bin.zip?dl=0
|
||||
data/system/prebaked_results/lakeslice/weekday.bin,872d2c49b63659b2dbe3d9424f5448b5,https://www.dropbox.com/s/dg5lalw3caec0ra/weekday.bin.zip?dl=0
|
||||
data/system/prebaked_results/montlake/car vs bike contention.bin,b0ae18d18936d1ae32e20bfc1afbe726,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
|
||||
data/system/prebaked_results/montlake/weekday.bin,f0002cbb7321dbff62ba47f3d3dfcc4f,https://www.dropbox.com/s/hxjwhzgbgymackt/weekday.bin.zip?dl=0
|
||||
data/system/prebaked_results/montlake/weekday.bin,f32fd37202433a4b6a4515db68e70012,https://www.dropbox.com/s/mus8cpyc1q58tq4/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/ballard/weekday.bin,b5252821a3e5e7b1f5bdb83191e9890b,https://www.dropbox.com/s/wam0a5q0mhzxm6x/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/downtown/weekday.bin,91cd32de750bcfe18af307178be770c3,https://www.dropbox.com/s/glytrwccwuwnctc/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/huge_seattle/weekday.bin,0d66a38e299332a485afd342e03ca0e2,https://www.dropbox.com/s/op07w7s03bjedlv/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/downtown/weekday.bin,bc31ac91a67eaa6d865b507432330f5e,https://www.dropbox.com/s/vrhsp920swdgdgk/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/huge_seattle/weekday.bin,cce3d979adb1126ffc159884858fc900,https://www.dropbox.com/s/3jldfrhmhcbofmw/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/lakeslice/weekday.bin,50fb819b17a145c1bccffaac8d0bd2fa,https://www.dropbox.com/s/aoy3zwm88y7yeyi/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/montlake/weekday.bin,49a9f4ad7b8c051d0a278425d1926976,https://www.dropbox.com/s/828ub49rvcdhibu/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/south_seattle/weekday.bin,01268d0e74e3da44f9dff89cc7a9f86d,https://www.dropbox.com/s/4k0sk5c7rlzi80t/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/south_seattle/weekday.bin,ef98b4b688ee4c6490885896fe0e16ea,https://www.dropbox.com/s/amz9jgx4gp7y7pw/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/udistrict/weekday.bin,1065f846a26222f4c12553d3c7116904,https://www.dropbox.com/s/qrm5veac663ni7v/weekday.bin.zip?dl=0
|
||||
data/system/scenarios/west_seattle/weekday.bin,f8a7b2bbe88e952a5e7e3c4a4b998174,https://www.dropbox.com/s/2ryk24mofqdyxaq/weekday.bin.zip?dl=0
|
||||
|
@ -231,8 +231,8 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
|
||||
);
|
||||
|
||||
rows.push(format!("{} stops", route.stops.len()).draw_text(ctx));
|
||||
if let Some(l) = route.start_border {
|
||||
let i = map.get_i(map.get_l(l).src_i);
|
||||
{
|
||||
let i = map.get_i(map.get_l(route.start).src_i);
|
||||
let name = format!("Starts at {}", i.name(map));
|
||||
rows.push(Widget::row(vec![
|
||||
Btn::svg(
|
||||
|
@ -200,7 +200,8 @@ impl Map {
|
||||
.osm_tags
|
||||
.get(osm::HIGHWAY)
|
||||
.map(|x| x.ends_with("_link"))
|
||||
.unwrap_or(false))
|
||||
.unwrap_or(false)
|
||||
|| road.osm_tags.is("railway", "rail"))
|
||||
{
|
||||
timer.warn(format!(
|
||||
"{} has no name. Tags: {:?}",
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::make::match_points_to_lanes;
|
||||
use crate::raw::{RawBusRoute, RawBusStop};
|
||||
use crate::{BusRoute, BusRouteID, BusStop, BusStopID, LaneType, Map, PathConstraints, Position};
|
||||
use crate::{
|
||||
BusRoute, BusRouteID, BusStop, BusStopID, LaneID, LaneType, Map, PathConstraints, Position,
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use geom::{Distance, HashablePt2D};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||
use std::error::Error;
|
||||
|
||||
pub fn make_stops_and_routes(map: &mut Map, raw_routes: &Vec<RawBusRoute>, timer: &mut Timer) {
|
||||
@ -85,26 +87,28 @@ fn make_route(
|
||||
};
|
||||
|
||||
// Start or end at a border?
|
||||
let mut start_border = None;
|
||||
let mut end_border = None;
|
||||
if let Some(i) = r.border_start {
|
||||
let start = if let Some(i) = r.border_start {
|
||||
let i = map.get_i(map.find_i_by_osm_id(i.osm_node_id).unwrap());
|
||||
if !i.is_border() {
|
||||
panic!("Route starts at {}, but isn't a border?", i.orig_id);
|
||||
}
|
||||
if let Some(l) = i.get_outgoing_lanes(map, route_type).get(0) {
|
||||
start_border = Some(*l);
|
||||
*l
|
||||
} else {
|
||||
// TODO Should panic
|
||||
println!(
|
||||
return Err(format!(
|
||||
"Route {} starts at {} ({}), but no starting lane for a {:?}?",
|
||||
rel_url(r.osm_rel_id),
|
||||
i.id,
|
||||
i.orig_id,
|
||||
route_type
|
||||
);
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not starting at a border. Find a lane at or before the first stop that's at least 13m.
|
||||
pick_start_lane(map.get_bs(stops[0]).driving_pos, route_type, map)?
|
||||
};
|
||||
if let Some(i) = r.border_end {
|
||||
let i = map.get_i(map.find_i_by_osm_id(i.osm_node_id).unwrap());
|
||||
if !i.is_border() {
|
||||
@ -130,7 +134,7 @@ fn make_route(
|
||||
short_name: r.short_name.clone(),
|
||||
stops,
|
||||
route_type,
|
||||
start_border,
|
||||
start,
|
||||
end_border,
|
||||
};
|
||||
|
||||
@ -227,9 +231,6 @@ impl Matcher {
|
||||
stop: &RawBusStop,
|
||||
map: &Map,
|
||||
) -> Result<(Position, Position), Box<dyn Error>> {
|
||||
// Buses are spawned at 0.01m along a lane; make sure a potential first stop is past that.
|
||||
let buffer = Distance::meters(0.1);
|
||||
|
||||
if !is_bus {
|
||||
// Light rail needs explicit platforms.
|
||||
let sidewalk_pt = stop.ped_pos.ok_or("light rail missing platform")?;
|
||||
@ -249,45 +250,76 @@ impl Matcher {
|
||||
// Because the stop is usually mapped on the road center-line, the matched side-of-the-road
|
||||
// is often wrong. If we have the bus stop, actually use that and get the equivalent
|
||||
// position on the closest driving/bus lane.
|
||||
if let Some(pt) = stop.ped_pos {
|
||||
let sidewalk_pos = *self
|
||||
let sidewalk_pos = if let Some(pt) = stop.ped_pos {
|
||||
*self
|
||||
.sidewalk_pts
|
||||
.get(&pt.to_hashable())
|
||||
.ok_or("sidewalk didnt match")?;
|
||||
let lane = map
|
||||
.get_parent(sidewalk_pos.lane())
|
||||
.find_closest_lane(sidewalk_pos.lane(), vec![LaneType::Bus, LaneType::Driving])?;
|
||||
return if let Some(driving_pos) =
|
||||
sidewalk_pos.equiv_pos(lane, map).min_dist(buffer, map)
|
||||
{
|
||||
Ok((sidewalk_pos, driving_pos))
|
||||
} else {
|
||||
Err(format!("Driving position {} is too short", lane).into())
|
||||
};
|
||||
}
|
||||
|
||||
// We only have the vehicle position. First find the sidewalk, then snap it to the
|
||||
// rightmost driving/bus lane.
|
||||
let orig_driving_pos = *self
|
||||
.bus_pts
|
||||
.get(&stop.vehicle_pos.to_hashable())
|
||||
.ok_or("vehicle for bus didnt match")?;
|
||||
let sidewalk = map.get_parent(orig_driving_pos.lane()).find_closest_lane(
|
||||
orig_driving_pos.lane(),
|
||||
vec![LaneType::Sidewalk, LaneType::Shoulder],
|
||||
)?;
|
||||
let sidewalk_pos = orig_driving_pos.equiv_pos(sidewalk, map);
|
||||
.ok_or("sidewalk didnt match")?
|
||||
} else {
|
||||
// We only have the vehicle position. First find the sidewalk, then snap it to the
|
||||
// rightmost driving/bus lane.
|
||||
let orig_driving_pos = *self
|
||||
.bus_pts
|
||||
.get(&stop.vehicle_pos.to_hashable())
|
||||
.ok_or("vehicle for bus didnt match")?;
|
||||
let sidewalk = map.get_parent(orig_driving_pos.lane()).find_closest_lane(
|
||||
orig_driving_pos.lane(),
|
||||
vec![LaneType::Sidewalk, LaneType::Shoulder],
|
||||
)?;
|
||||
orig_driving_pos.equiv_pos(sidewalk, map)
|
||||
};
|
||||
let lane = map
|
||||
.get_parent(sidewalk_pos.lane())
|
||||
.find_closest_lane(sidewalk_pos.lane(), vec![LaneType::Bus, LaneType::Driving])?;
|
||||
if let Some(driving_pos) = sidewalk_pos.equiv_pos(lane, map).min_dist(buffer, map) {
|
||||
Ok((sidewalk_pos, driving_pos))
|
||||
} else {
|
||||
Err(format!("Driving position {} is too short", lane).into())
|
||||
let mut driving_pos = sidewalk_pos.equiv_pos(lane, map);
|
||||
// If we're a stop right at an incoming border, make sure to be at least past where the bus
|
||||
// will spawn from the border. pick_start_lane() can't do anything for borders.
|
||||
if map
|
||||
.get_i(map.get_l(driving_pos.lane()).src_i)
|
||||
.is_incoming_border()
|
||||
{
|
||||
if let Some(pos) = driving_pos.min_dist(Distance::meters(1.0), map) {
|
||||
driving_pos = pos;
|
||||
} else {
|
||||
return Err(
|
||||
format!("too close to start of a border {}", driving_pos.lane()).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok((sidewalk_pos, driving_pos))
|
||||
}
|
||||
}
|
||||
|
||||
fn rel_url(id: i64) -> String {
|
||||
format!("https://www.openstreetmap.org/relation/{}", id)
|
||||
}
|
||||
|
||||
fn pick_start_lane(
|
||||
first_stop: Position,
|
||||
constraints: PathConstraints,
|
||||
map: &Map,
|
||||
) -> Result<LaneID, String> {
|
||||
let min_len = Distance::meters(13.0);
|
||||
if first_stop.dist_along() >= min_len {
|
||||
return Ok(first_stop.lane());
|
||||
}
|
||||
|
||||
// Flood backwards until we find a long enough lane
|
||||
let mut queue = VecDeque::new();
|
||||
queue.push_back(first_stop.lane());
|
||||
while !queue.is_empty() {
|
||||
let current = queue.pop_front().unwrap();
|
||||
if current != first_stop.lane() && map.get_l(current).length() >= min_len {
|
||||
return Ok(current);
|
||||
}
|
||||
for t in map.get_turns_to_lane(current) {
|
||||
if constraints.can_use(map.get_l(t.id.src), map) {
|
||||
queue.push_back(t.id.src);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(format!(
|
||||
"couldn't find any lanes leading to {} that're long enough for a bus to spawn",
|
||||
first_stop.lane()
|
||||
))
|
||||
}
|
||||
|
@ -49,7 +49,8 @@ pub struct BusRoute {
|
||||
pub full_name: String,
|
||||
pub short_name: String,
|
||||
pub stops: Vec<BusStopID>,
|
||||
pub start_border: Option<LaneID>,
|
||||
// May be a border or not. If not, is long enough for buses to spawn fully.
|
||||
pub start: LaneID,
|
||||
pub end_border: Option<LaneID>,
|
||||
pub route_type: PathConstraints,
|
||||
}
|
||||
@ -57,13 +58,11 @@ pub struct BusRoute {
|
||||
impl BusRoute {
|
||||
pub fn all_steps(&self, map: &Map) -> Vec<PathRequest> {
|
||||
let mut steps = Vec::new();
|
||||
if let Some(start) = self.start_border {
|
||||
steps.push(PathRequest {
|
||||
start: Position::start(start),
|
||||
end: map.get_bs(self.stops[0]).driving_pos,
|
||||
constraints: self.route_type,
|
||||
});
|
||||
}
|
||||
steps.push(PathRequest {
|
||||
start: Position::start(self.start),
|
||||
end: map.get_bs(self.stops[0]).driving_pos,
|
||||
constraints: self.route_type,
|
||||
});
|
||||
for pair in self.stops.windows(2) {
|
||||
steps.push(PathRequest {
|
||||
start: map.get_bs(pair[0]).driving_pos,
|
||||
|
@ -104,8 +104,11 @@ impl Car {
|
||||
|
||||
if result.len() < 2 {
|
||||
panic!(
|
||||
"{} at {} has front at {}. Didn't even wind up with two points",
|
||||
self.vehicle.id, now, front
|
||||
"{} at {} has front at {} of {:?}. Didn't even wind up with two points",
|
||||
self.vehicle.id,
|
||||
now,
|
||||
front,
|
||||
self.router.head()
|
||||
);
|
||||
}
|
||||
match PolyLine::new(result) {
|
||||
|
@ -245,12 +245,19 @@ impl Sim {
|
||||
max_speed: None,
|
||||
}
|
||||
.make(CarID(self.trips.new_car_id(), vehicle_type), None);
|
||||
let start_lane = map.get_l(path.current_step().as_lane());
|
||||
let start_dist = if map.get_i(start_lane.src_i).is_incoming_border() {
|
||||
EPSILON_DIST
|
||||
} else {
|
||||
assert!(start_lane.length() > vehicle.length);
|
||||
vehicle.length
|
||||
};
|
||||
|
||||
self.scheduler.push(
|
||||
self.time,
|
||||
Command::SpawnCar(
|
||||
CreateCar {
|
||||
start_dist: EPSILON_DIST,
|
||||
start_dist,
|
||||
router: Router::follow_bus_route(
|
||||
vehicle.id,
|
||||
path.clone(),
|
||||
|
@ -116,11 +116,7 @@ impl TransitSimState {
|
||||
}
|
||||
}
|
||||
let start_req = PathRequest {
|
||||
start: Position::start(
|
||||
bus_route
|
||||
.start_border
|
||||
.unwrap_or(stops[0].driving_pos.lane()),
|
||||
),
|
||||
start: Position::start(bus_route.start),
|
||||
end: map.get_bs(bus_route.stops[0]).driving_pos,
|
||||
constraints: bus_route.route_type,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user