mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
instantiate bus routes from GTFS too
This commit is contained in:
parent
143084a8a9
commit
58b01fce9e
@ -34,3 +34,10 @@ pub use parcel::{Parcel, ParcelID};
|
||||
pub use pathfind::pathfind;
|
||||
pub use road::{Road, RoadID};
|
||||
pub use turn::{Turn, TurnID};
|
||||
|
||||
// TODO This sort of doesn't fit in the map layer, but it's quite convenient to store it.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct BusRoute {
|
||||
pub name: String,
|
||||
pub stops: Vec<BusStop>,
|
||||
}
|
||||
|
@ -4,20 +4,23 @@ use gtfs;
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
use multimap::MultiMap;
|
||||
use ordered_float::NotNaN;
|
||||
use std::collections::HashSet;
|
||||
use {BusStop, BusStopDetails, Lane, LaneID, Road};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use {BusRoute, BusStop, BusStopDetails, Lane, LaneID, Road};
|
||||
|
||||
pub fn make_bus_stops(
|
||||
lanes: &mut Vec<Lane>,
|
||||
roads: &Vec<Road>,
|
||||
bus_routes: &Vec<gtfs::Route>,
|
||||
bounds: &Bounds,
|
||||
) {
|
||||
) -> Vec<BusRoute> {
|
||||
let mut bus_stop_pts: HashSet<HashablePt2D> = HashSet::new();
|
||||
let mut route_lookups: MultiMap<String, HashablePt2D> = MultiMap::new();
|
||||
for route in bus_routes {
|
||||
for gps in &route.stops {
|
||||
if bounds.contains(gps.longitude, gps.latitude) {
|
||||
bus_stop_pts.insert(Pt2D::from_gps(&gps, bounds).into());
|
||||
let pt: HashablePt2D = Pt2D::from_gps(&gps, bounds).into();
|
||||
bus_stop_pts.insert(pt);
|
||||
route_lookups.insert(route.name.to_string(), pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,23 +30,39 @@ pub fn make_bus_stops(
|
||||
bus_routes.len()
|
||||
);
|
||||
|
||||
let mut stops_per_sidewalk: MultiMap<LaneID, si::Meter<f64>> = MultiMap::new();
|
||||
for (lane, dist_along) in find_sidewalk_points(bus_stop_pts, lanes).values() {
|
||||
stops_per_sidewalk.insert(*lane, *dist_along);
|
||||
let mut stops_per_sidewalk: MultiMap<LaneID, (si::Meter<f64>, HashablePt2D)> = MultiMap::new();
|
||||
for (pt, (lane, dist_along)) in find_sidewalk_points(bus_stop_pts, lanes).iter() {
|
||||
stops_per_sidewalk.insert(*lane, (*dist_along, *pt));
|
||||
}
|
||||
let mut point_to_stop_idx: HashMap<HashablePt2D, BusStop> = HashMap::new();
|
||||
for (id, dists) in stops_per_sidewalk.iter_all_mut() {
|
||||
// TODO duplicate a little logic from map, and also, this is fragile :)
|
||||
let road = &roads[lanes[id.0].parent.0];
|
||||
let parking = road.find_parking_lane(*id).unwrap();
|
||||
let driving_lane = road.find_driving_lane(parking).unwrap();
|
||||
|
||||
dists.sort_by_key(|dist| NotNaN::new(dist.value_unsafe).unwrap());
|
||||
for (idx, dist_along) in dists.iter().enumerate() {
|
||||
dists.sort_by_key(|(dist, _)| NotNaN::new(dist.value_unsafe).unwrap());
|
||||
for (idx, (dist_along, orig_pt)) in dists.iter().enumerate() {
|
||||
let stop_id = BusStop { sidewalk: *id, idx };
|
||||
point_to_stop_idx.insert(*orig_pt, stop_id);
|
||||
lanes[id.0].bus_stops.push(BusStopDetails {
|
||||
id: BusStop { sidewalk: *id, idx },
|
||||
id: stop_id,
|
||||
driving_lane,
|
||||
dist_along: *dist_along,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut results: Vec<BusRoute> = Vec::new();
|
||||
for (route_name, stop_points) in route_lookups.iter_all() {
|
||||
if stop_points.len() == 1 {
|
||||
//println!("Skipping route {} since it only has 1 stop in the slice of the map", route_name);
|
||||
continue;
|
||||
}
|
||||
results.push(BusRoute {
|
||||
name: route_name.to_string(),
|
||||
stops: stop_points.iter().map(|pt| point_to_stop_idx[pt]).collect(),
|
||||
});
|
||||
}
|
||||
results
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use abstutil;
|
||||
use building::{Building, BuildingID};
|
||||
use edits::Edits;
|
||||
use geom::{Bounds, HashablePt2D, PolyLine, Pt2D};
|
||||
use geometry;
|
||||
use intersection::{Intersection, IntersectionID};
|
||||
use lane::{BusStop, BusStopDetails, Lane, LaneID, LaneType};
|
||||
use make;
|
||||
use parcel::{Parcel, ParcelID};
|
||||
use raw_data;
|
||||
use road::{Road, RoadID};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io::Error;
|
||||
use std::path;
|
||||
use turn::{Turn, TurnID};
|
||||
use {
|
||||
Building, BuildingID, BusRoute, BusStop, BusStopDetails, Intersection, IntersectionID, Lane,
|
||||
LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn, TurnID,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Map {
|
||||
@ -24,6 +22,7 @@ pub struct Map {
|
||||
turns: BTreeMap<TurnID, Turn>,
|
||||
buildings: Vec<Building>,
|
||||
parcels: Vec<Parcel>,
|
||||
bus_routes: Vec<BusRoute>,
|
||||
|
||||
// TODO maybe dont need to retain GPS stuff later
|
||||
bounds: Bounds,
|
||||
@ -57,6 +56,7 @@ impl Map {
|
||||
turns: BTreeMap::new(),
|
||||
buildings: Vec::new(),
|
||||
parcels: Vec::new(),
|
||||
bus_routes: Vec::new(),
|
||||
};
|
||||
|
||||
let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new();
|
||||
@ -152,7 +152,7 @@ impl Map {
|
||||
}
|
||||
}
|
||||
|
||||
make::make_bus_stops(&mut m.lanes, &m.roads, &data.bus_routes, &bounds);
|
||||
m.bus_routes = make::make_bus_stops(&mut m.lanes, &m.roads, &data.bus_routes, &bounds);
|
||||
|
||||
for i in &m.intersections {
|
||||
for t in make::make_all_turns(i, &m) {
|
||||
@ -363,4 +363,8 @@ impl Map {
|
||||
pub fn get_bus_stop(&self, stop: BusStop) -> &BusStopDetails {
|
||||
&self.get_l(stop.sidewalk).bus_stops[stop.idx]
|
||||
}
|
||||
|
||||
pub fn get_all_bus_routes(&self) -> &Vec<BusRoute> {
|
||||
&self.bus_routes
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil;
|
||||
use control::ControlMap;
|
||||
use map_model::{BuildingID, BusStop, Edits, LaneID, Map};
|
||||
use map_model::{BuildingID, BusRoute, BusStop, Edits, LaneID, Map};
|
||||
use rand::Rng;
|
||||
use std::collections::VecDeque;
|
||||
use {CarID, Event, PedestrianID, RouteID, Sim, Tick};
|
||||
@ -94,16 +94,8 @@ impl Sim {
|
||||
self.seed_walking_trips(&map, 100);
|
||||
self.seed_driving_trips(&map, 100);
|
||||
|
||||
if self.seed_bus_route(
|
||||
vec![
|
||||
map.get_l(LaneID(309)).bus_stops[0].id,
|
||||
map.get_l(LaneID(325)).bus_stops[0].id,
|
||||
map.get_l(LaneID(840)).bus_stops[0].id,
|
||||
],
|
||||
map,
|
||||
).len() != 3
|
||||
{
|
||||
panic!("Three buses didn't fit");
|
||||
for route in map.get_all_bus_routes() {
|
||||
self.seed_bus_route(route, map);
|
||||
}
|
||||
// TODO this is introducing nondeterminism, because of slight floating point errors.
|
||||
// fragile that this causes it, but true. :\
|
||||
@ -131,13 +123,13 @@ impl Sim {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seed_bus_route(&mut self, stops: Vec<BusStop>, map: &Map) -> Vec<CarID> {
|
||||
pub fn seed_bus_route(&mut self, route: &BusRoute, map: &Map) -> Vec<CarID> {
|
||||
// TODO throw away the events? :(
|
||||
let mut events: Vec<Event> = Vec::new();
|
||||
let mut result: Vec<CarID> = Vec::new();
|
||||
for v in self.spawner.seed_bus_route(
|
||||
&mut events,
|
||||
stops,
|
||||
route,
|
||||
&mut self.rng,
|
||||
map,
|
||||
&mut self.driving_state,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use driving::DrivingSimState;
|
||||
use kinematics::Vehicle;
|
||||
use map_model;
|
||||
use map_model::{BuildingID, BusStop, LaneID, Map};
|
||||
use map_model::{BuildingID, BusRoute, BusStop, LaneID, Map};
|
||||
use parking::ParkingSimState;
|
||||
use rand::Rng;
|
||||
use router::Router;
|
||||
@ -166,7 +166,7 @@ impl Spawner {
|
||||
pub fn seed_bus_route<R: Rng + ?Sized>(
|
||||
&mut self,
|
||||
events: &mut Vec<Event>,
|
||||
stops: Vec<BusStop>,
|
||||
route: &BusRoute,
|
||||
rng: &mut R,
|
||||
map: &Map,
|
||||
driving_sim: &mut DrivingSimState,
|
||||
@ -174,11 +174,11 @@ impl Spawner {
|
||||
now: Tick,
|
||||
properties: &BTreeMap<CarID, Vehicle>,
|
||||
) -> Vec<Vehicle> {
|
||||
let route = transit_sim.create_empty_route(stops, map);
|
||||
let route_id = transit_sim.create_empty_route(route, map);
|
||||
let mut vehicles: Vec<Vehicle> = Vec::new();
|
||||
// Try to spawn a bus at each stop
|
||||
for (next_stop_idx, start_dist_along, mut path) in
|
||||
transit_sim.get_route_starts(route, map).into_iter()
|
||||
transit_sim.get_route_starts(route_id, map).into_iter()
|
||||
{
|
||||
let id = CarID(self.car_id_counter);
|
||||
self.car_id_counter += 1;
|
||||
@ -196,13 +196,13 @@ impl Spawner {
|
||||
map,
|
||||
properties,
|
||||
) {
|
||||
transit_sim.bus_created(id, route, next_stop_idx);
|
||||
println!("Spawned bus {} for route {}", id, route);
|
||||
transit_sim.bus_created(id, route_id, next_stop_idx);
|
||||
println!("Spawned bus {} for route {} ({})", id, route.name, route_id);
|
||||
vehicles.push(vehicle);
|
||||
} else {
|
||||
println!(
|
||||
"No room for a bus headed towards stop {} of {}, giving up",
|
||||
next_stop_idx, route
|
||||
"No room for a bus headed towards stop {} of {} ({}), giving up",
|
||||
next_stop_idx, route.name, route_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use dimensioned::si;
|
||||
use events::Event;
|
||||
use instrument::capture_backtrace;
|
||||
use map_model;
|
||||
use map_model::{BusStop, BusStopDetails, LaneID, Map};
|
||||
use map_model::{BusRoute, BusStopDetails, LaneID, Map};
|
||||
use spawn::Spawner;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use trips::TripManager;
|
||||
@ -17,6 +17,7 @@ type StopIdx = usize;
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
struct Route {
|
||||
id: RouteID,
|
||||
name: String,
|
||||
buses: Vec<CarID>,
|
||||
stops: Vec<BusStopDetails>,
|
||||
// TODO info on schedules
|
||||
@ -65,17 +66,19 @@ impl TransitSimState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_empty_route(&mut self, stops: Vec<BusStop>, map: &Map) -> RouteID {
|
||||
assert!(stops.len() > 1);
|
||||
pub fn create_empty_route(&mut self, route: &BusRoute, map: &Map) -> RouteID {
|
||||
assert!(route.stops.len() > 1);
|
||||
let id = RouteID(self.routes.len());
|
||||
self.routes.insert(
|
||||
id,
|
||||
Route {
|
||||
id,
|
||||
name: route.name.clone(),
|
||||
buses: Vec::new(),
|
||||
stops: stops
|
||||
.into_iter()
|
||||
.map(|s| map.get_bus_stop(s).clone())
|
||||
stops: route
|
||||
.stops
|
||||
.iter()
|
||||
.map(|s| map.get_bus_stop(*s).clone())
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user