mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
Import GTFS for São Paulo
This commit is contained in:
parent
9ffab3c976
commit
d386948a13
@ -529,13 +529,15 @@ fn finish_app_setup(
|
||||
}
|
||||
}
|
||||
Mode::SomethingElse => {
|
||||
let start_time = setup.start_time.unwrap_or(Duration::hours(6));
|
||||
|
||||
// Not attempting to keep the primary and secondary simulations synchronized at the
|
||||
// same time yet. Just handle this one startup case, so we can switch maps without
|
||||
// constantly flopping day/night mode.
|
||||
if let Some(ref mut secondary) = app.secondary {
|
||||
secondary.sim.timed_step(
|
||||
&secondary.map,
|
||||
Duration::hours(6),
|
||||
start_time,
|
||||
&mut None,
|
||||
&mut Timer::throwaway(),
|
||||
);
|
||||
@ -546,7 +548,7 @@ fn finish_app_setup(
|
||||
SandboxMode::async_new(
|
||||
app,
|
||||
GameplayMode::Freeform(app.primary.map.get_name().clone()),
|
||||
jump_to_time_upon_startup(Duration::hours(6)),
|
||||
jump_to_time_upon_startup(start_time),
|
||||
)
|
||||
}
|
||||
Mode::TutorialIntro => sandbox::gameplay::Tutorial::start(ctx, app),
|
||||
|
@ -34,7 +34,7 @@ impl PlayScenario {
|
||||
modifiers: Vec<ScenarioModifier>,
|
||||
) -> Box<dyn GameplayState> {
|
||||
URLManager::update_url_free_param(
|
||||
// For dynamiclly generated scenarios like "random" and "home_to_work", this winds up
|
||||
// For dynamically generated scenarios like "random" and "home_to_work", this winds up
|
||||
// making up a filename that doesn't actually exist. But if you pass that in, it winds
|
||||
// up working, because we call abstio::parse_scenario_path() on the other side.
|
||||
abstio::path_scenario(app.primary.map.get_name(), name)
|
||||
|
@ -50,6 +50,10 @@ pub fn import(map: &mut RawMap) -> Result<()> {
|
||||
}
|
||||
|
||||
// Scrape all shape data. Map from shape_id to points and the sequence number
|
||||
//
|
||||
// If this file is missing, one idea is to just draw straight lines between stops. We only use
|
||||
// the shape currently to pick an entry/exit border, so this could be a half-reasonable
|
||||
// workaround.
|
||||
let mut raw_shapes: HashMap<ShapeID, Vec<(Pt2D, usize)>> = HashMap::new();
|
||||
for rec in csv::Reader::from_reader(File::open(map.name.city.input_path("gtfs/shapes.txt"))?)
|
||||
.deserialize()
|
||||
@ -189,6 +193,8 @@ struct Route {
|
||||
route_id: RouteID,
|
||||
route_short_name: String,
|
||||
route_long_name: String,
|
||||
// Missing from São Paulo
|
||||
#[serde(default)]
|
||||
route_desc: String,
|
||||
route_type: usize,
|
||||
}
|
||||
|
@ -70,6 +70,56 @@
|
||||
"uncompressed_size_bytes": 5608139,
|
||||
"compressed_size_bytes": 1056533
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/agency.txt": {
|
||||
"checksum": "3dd694b14c7bacfa33d8ad774db99100",
|
||||
"uncompressed_size_bytes": 155,
|
||||
"compressed_size_bytes": 139
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/calendar.txt": {
|
||||
"checksum": "21622d9185a6a3e5d0775712640f222c",
|
||||
"uncompressed_size_bytes": 451,
|
||||
"compressed_size_bytes": 150
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/fare_attributes.txt": {
|
||||
"checksum": "9e8ca239a9545d1b75cf87b7af027efc",
|
||||
"uncompressed_size_bytes": 371,
|
||||
"compressed_size_bytes": 169
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/fare_rules.txt": {
|
||||
"checksum": "04104cc98ef5504e37717a7cab49edf4",
|
||||
"uncompressed_size_bytes": 206440,
|
||||
"compressed_size_bytes": 16286
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/frequencies.txt": {
|
||||
"checksum": "d92632062fa60f01449c5091fd45398f",
|
||||
"uncompressed_size_bytes": 1651443,
|
||||
"compressed_size_bytes": 140539
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/routes.txt": {
|
||||
"checksum": "cb359e55a553bc9a462fbcbb08ae5574",
|
||||
"uncompressed_size_bytes": 111291,
|
||||
"compressed_size_bytes": 18029
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/shapes.txt": {
|
||||
"checksum": "a1f5500e7a79f96776589f4f4fbcd38e",
|
||||
"uncompressed_size_bytes": 58972562,
|
||||
"compressed_size_bytes": 15500119
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/stop_times.txt": {
|
||||
"checksum": "11ef62b51bb8d23aac88cba96a8def7b",
|
||||
"uncompressed_size_bytes": 4900105,
|
||||
"compressed_size_bytes": 958512
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/stops.txt": {
|
||||
"checksum": "5191a36f2d3f8ef45b435b380e890921",
|
||||
"uncompressed_size_bytes": 2133889,
|
||||
"compressed_size_bytes": 594221
|
||||
},
|
||||
"data/input/br/sao_paulo/gtfs/trips.txt": {
|
||||
"checksum": "f2eb999c99e5ae82a4cfc3f7ed6a0121",
|
||||
"uncompressed_size_bytes": 130243,
|
||||
"compressed_size_bytes": 26310
|
||||
},
|
||||
"data/input/br/sao_paulo/osm/aricanduva.osm": {
|
||||
"checksum": "3708fb4be649c4f16d1de7f7c99369b6",
|
||||
"uncompressed_size_bytes": 128106393,
|
||||
@ -91,19 +141,19 @@
|
||||
"compressed_size_bytes": 649718446
|
||||
},
|
||||
"data/input/br/sao_paulo/raw_maps/aricanduva.bin": {
|
||||
"checksum": "a7443e903c5ebb8a9ef7eebbf3a625b1",
|
||||
"uncompressed_size_bytes": 34483916,
|
||||
"compressed_size_bytes": 8619214
|
||||
"checksum": "27dff0b36d49f5fed136e794ad9ed258",
|
||||
"uncompressed_size_bytes": 34864623,
|
||||
"compressed_size_bytes": 8850565
|
||||
},
|
||||
"data/input/br/sao_paulo/raw_maps/center.bin": {
|
||||
"checksum": "accfa249216653e27a47d13e1f1fd7e4",
|
||||
"uncompressed_size_bytes": 9473758,
|
||||
"compressed_size_bytes": 2496742
|
||||
"checksum": "1344afc8a37b52cffc81b79c32e99506",
|
||||
"uncompressed_size_bytes": 10230115,
|
||||
"compressed_size_bytes": 2926542
|
||||
},
|
||||
"data/input/br/sao_paulo/raw_maps/sao_miguel_paulista.bin": {
|
||||
"checksum": "3fe087174603b33c01b10cca95c516c5",
|
||||
"uncompressed_size_bytes": 591404,
|
||||
"compressed_size_bytes": 145386
|
||||
"checksum": "befa29b3a81ff1e63c2d817044efeff4",
|
||||
"uncompressed_size_bytes": 798773,
|
||||
"compressed_size_bytes": 246669
|
||||
},
|
||||
"data/input/ca/ca/osm/plateau.osm": {
|
||||
"checksum": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
@ -3106,24 +3156,24 @@
|
||||
"compressed_size_bytes": 9015011
|
||||
},
|
||||
"data/system/br/sao_paulo/maps/aricanduva.bin": {
|
||||
"checksum": "ddd45366409816df6c0c581d14055559",
|
||||
"uncompressed_size_bytes": 54363220,
|
||||
"compressed_size_bytes": 20757520
|
||||
"checksum": "3cda5656c2d6969d2c9fadd6657038ca",
|
||||
"uncompressed_size_bytes": 54515170,
|
||||
"compressed_size_bytes": 20816515
|
||||
},
|
||||
"data/system/br/sao_paulo/maps/center.bin": {
|
||||
"checksum": "69b08ea00b97339ddc3d79745dd5cd2d",
|
||||
"uncompressed_size_bytes": 18742932,
|
||||
"compressed_size_bytes": 7122663
|
||||
"checksum": "209300c85a3095771b09647e67f560fa",
|
||||
"uncompressed_size_bytes": 18882279,
|
||||
"compressed_size_bytes": 7158757
|
||||
},
|
||||
"data/system/br/sao_paulo/maps/sao_miguel_paulista.bin": {
|
||||
"checksum": "9144373938117fe60b0db641bda5ecf2",
|
||||
"uncompressed_size_bytes": 958882,
|
||||
"compressed_size_bytes": 326208
|
||||
"checksum": "441e7c85870d58d54b415d4a0688e727",
|
||||
"uncompressed_size_bytes": 986925,
|
||||
"compressed_size_bytes": 335105
|
||||
},
|
||||
"data/system/br/sao_paulo/prebaked_results/sao_miguel_paulista/Full.bin": {
|
||||
"checksum": "565cc8549ce2b275cab59ccb2189532e",
|
||||
"uncompressed_size_bytes": 27726150,
|
||||
"compressed_size_bytes": 9401792
|
||||
"checksum": "ccea922412a35fa314392b26eb269337",
|
||||
"uncompressed_size_bytes": 30436191,
|
||||
"compressed_size_bytes": 9398838
|
||||
},
|
||||
"data/system/br/sao_paulo/scenarios/sao_miguel_paulista/Full.bin": {
|
||||
"checksum": "541fdf1f2ba80b4b6cb88f36b186a707",
|
||||
|
@ -77,6 +77,8 @@ pub fn config_for_map(name: &MapName) -> convert_osm::Options {
|
||||
Some("http://metro.kingcounty.gov/GTFS/google_transit.zip".to_string())
|
||||
} else if name.city == CityName::new("us", "san_francisco") {
|
||||
Some("https://gtfs.sfmta.com/transitdata/google_transit.zip".to_string())
|
||||
} else if name.city == CityName::new("br", "sao_paulo") {
|
||||
Some("https://github.com/transitland/gtfs-archives-not-hosted-elsewhere/blob/master/sao-paulo-sptrans.zip?raw=true".to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
@ -23,7 +23,7 @@ pub async fn download(config: &ImporterConfiguration, output: String, url: &str)
|
||||
println!("- Missing {}, so downloading {}", output, url);
|
||||
abstio::download_to_file(url, None, tmp).await.unwrap();
|
||||
|
||||
if url.ends_with(".zip") {
|
||||
if url.contains(".zip") {
|
||||
let unzip_to = if output.ends_with('/') {
|
||||
output
|
||||
} else {
|
||||
@ -34,7 +34,7 @@ pub async fn download(config: &ImporterConfiguration, output: String, url: &str)
|
||||
println!("- Unzipping into {}", unzip_to);
|
||||
must_run_cmd(Command::new(&config.unzip).arg(tmp).arg("-d").arg(unzip_to));
|
||||
fs_err::remove_file(tmp).unwrap();
|
||||
} else if url.ends_with(".gz") {
|
||||
} else if url.contains(".gz") {
|
||||
println!("- Gunzipping");
|
||||
fs_err::rename(tmp, format!("{}.gz", output)).unwrap();
|
||||
|
||||
|
@ -200,7 +200,16 @@ fn create_route(
|
||||
&snapper.train_outgoing_borders
|
||||
};
|
||||
match borders.closest_pt(exit_pt, border_snap_threshold) {
|
||||
Some((l, _)) => Some(l),
|
||||
Some((lane, _)) => {
|
||||
// Edge case: the last stop is on the same road as the border. We can't lane-change
|
||||
// suddenly, so match the lane in that case.
|
||||
let last_stop_lane = map.get_ts(*stops.last().unwrap()).driving_pos.lane();
|
||||
Some(if lane.road == last_stop_lane.road {
|
||||
last_stop_lane
|
||||
} else {
|
||||
lane
|
||||
})
|
||||
}
|
||||
None => bail!(
|
||||
"Couldn't find a {:?} border near end {}",
|
||||
route.route_type,
|
||||
@ -238,6 +247,15 @@ fn create_route(
|
||||
req
|
||||
);
|
||||
}
|
||||
if req.start.lane().road == req.end.lane().road
|
||||
&& req.start.dist_along() > req.end.dist_along()
|
||||
{
|
||||
bail!(
|
||||
"Two consecutive stops are on the same road, but they travel backwards: {}",
|
||||
req
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(err) = map.pathfind(req) {
|
||||
bail!("Created the route, but pathfinding failed: {}", err);
|
||||
}
|
||||
|
@ -158,6 +158,9 @@ impl PathV2 {
|
||||
// At the simulation layer, we may need to block intermediate lanes to exit a driveway,
|
||||
// so reflect that cost here. The high cost should only be worth it when the v2 path
|
||||
// requires that up-front turn from certain lanes.
|
||||
//
|
||||
// TODO This is only valid if we were leaving from a driveway! This is making some
|
||||
// buses warp after making a stop.
|
||||
let idx_dist = (start_lane_idx - (l.offset as isize)).abs();
|
||||
let cost = 100 * idx_dist as usize;
|
||||
let fake_turn = TurnID {
|
||||
|
@ -34,14 +34,19 @@ pub(crate) struct Car {
|
||||
impl Car {
|
||||
/// Assumes the current head of the path is the thing to cross.
|
||||
pub fn crossing_state(&self, start_dist: Distance, start_time: Time, map: &Map) -> CarState {
|
||||
let dist_int = DistanceInterval::new_driving(
|
||||
start_dist,
|
||||
if self.router.last_step() {
|
||||
self.router.get_end_dist()
|
||||
} else {
|
||||
self.router.head().get_polyline(map).length()
|
||||
},
|
||||
);
|
||||
let end_dist = if self.router.last_step() {
|
||||
self.router.get_end_dist()
|
||||
} else {
|
||||
self.router.head().get_polyline(map).length()
|
||||
};
|
||||
if end_dist < start_dist {
|
||||
panic!(
|
||||
"{} trying to make a crossing_state from {} to {} at {}. Something's very wrong",
|
||||
self.vehicle.id, start_dist, end_dist, start_time
|
||||
);
|
||||
}
|
||||
|
||||
let dist_int = DistanceInterval::new_driving(start_dist, end_dist);
|
||||
self.crossing_state_with_end_dist(dist_int, start_time, map)
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,8 @@ impl TransitSimState {
|
||||
});
|
||||
continue;
|
||||
}
|
||||
// TODO Why're we calculating these again? Use bus_route.all_path_requests(), so
|
||||
// that all the nice checks in the map_model layer are preserved here
|
||||
let req = PathRequest::vehicle(
|
||||
stop1.driving_pos,
|
||||
map.get_ts(bus_route.stops[idx + 1]).driving_pos,
|
||||
@ -112,6 +114,15 @@ impl TransitSimState {
|
||||
if path.is_empty() {
|
||||
panic!("Empty path between stops?! {}", path.get_req());
|
||||
}
|
||||
if stop1.driving_pos != path.get_req().start {
|
||||
panic!(
|
||||
"{} will warp from {} to {}",
|
||||
bus_route.long_name,
|
||||
stop1.driving_pos,
|
||||
path.get_req().start,
|
||||
);
|
||||
}
|
||||
|
||||
stops.push(Stop {
|
||||
id: stop1.id,
|
||||
driving_pos: stop1.driving_pos,
|
||||
|
Loading…
Reference in New Issue
Block a user