mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
PathRequest instead of massive confusing tuples. also can now use bike lanes from spawn layer
This commit is contained in:
parent
0b53b2e44f
commit
9084f0060b
@ -50,14 +50,13 @@ minimal. Alternate idea for another branch:
|
||||
- lastly: rename. Car -> Vehicle? Vehicle -> VehicleParams? DrivingSim -> QueuedSim?
|
||||
|
||||
- etc
|
||||
= calculate_paths in spawn needs plumbing. introduce a PathfindingRequest struct, avoid those bools.
|
||||
|
||||
- stats; driving.count and trip score
|
||||
- vehicle enum instead of is_bus, is_bike
|
||||
- put this in vehicle properties, not on the main
|
||||
car... then dont need it in Command::DriveFromBorder.
|
||||
- spawn commands getting to have lots of similarish cases
|
||||
- reusing DrivingGoal to mean bike start point too?
|
||||
|
||||
- calculate_paths in spawn needs plumbing. introduce a PathfindingRequest struct, avoid those bools.
|
||||
|
||||
- remove the sim helpers that do specific stuff... think of
|
||||
another way to set up tests, similar to tutorial mode?
|
||||
|
@ -44,7 +44,7 @@ pub use lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH};
|
||||
pub use make::RoadSpec;
|
||||
pub use map::Map;
|
||||
pub use parcel::{Parcel, ParcelID};
|
||||
pub use pathfind::{Path, PathStep, Pathfinder, Trace};
|
||||
pub use pathfind::{Path, PathRequest, PathStep, Pathfinder, Trace};
|
||||
pub use road::{Road, RoadID};
|
||||
pub use traversable::Traversable;
|
||||
pub use turn::{Turn, TurnID, TurnType};
|
||||
|
@ -7,7 +7,7 @@ use multimap::MultiMap;
|
||||
use ordered_float::NotNaN;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::iter;
|
||||
use {BusRoute, BusStop, BusStopID, Lane, LaneID, Map, Pathfinder, Road};
|
||||
use {BusRoute, BusStop, BusStopID, Lane, LaneID, Map, PathRequest, Pathfinder, Road};
|
||||
|
||||
pub fn make_bus_stops(
|
||||
lanes: &mut Vec<Lane>,
|
||||
@ -130,12 +130,14 @@ pub fn verify_bus_routes(map: &Map, routes: Vec<BusRoute>, timer: &mut Timer) ->
|
||||
|
||||
if Pathfinder::shortest_distance(
|
||||
map,
|
||||
bs1.driving_lane,
|
||||
bs1.dist_along,
|
||||
bs2.driving_lane,
|
||||
bs2.dist_along,
|
||||
false,
|
||||
true,
|
||||
PathRequest {
|
||||
start: bs1.driving_lane,
|
||||
start_dist: bs1.dist_along,
|
||||
end: bs2.driving_lane,
|
||||
end_dist: bs2.dist_along,
|
||||
can_use_bike_lanes: false,
|
||||
can_use_bus_lanes: true,
|
||||
},
|
||||
).is_none()
|
||||
{
|
||||
warn!(
|
||||
|
@ -203,6 +203,16 @@ impl Path {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PathRequest {
|
||||
pub start: LaneID,
|
||||
pub start_dist: si::Meter<f64>,
|
||||
pub end: LaneID,
|
||||
pub end_dist: si::Meter<f64>,
|
||||
pub can_use_bike_lanes: bool,
|
||||
pub can_use_bus_lanes: bool,
|
||||
}
|
||||
|
||||
pub enum Pathfinder {
|
||||
ShortestDistance {
|
||||
goal_pt: Pt2D,
|
||||
@ -214,24 +224,15 @@ pub enum Pathfinder {
|
||||
|
||||
impl Pathfinder {
|
||||
// Returns an inclusive path, aka, [start, ..., end]
|
||||
pub fn shortest_distance(
|
||||
map: &Map,
|
||||
start: LaneID,
|
||||
start_dist: si::Meter<f64>,
|
||||
end: LaneID,
|
||||
end_dist: si::Meter<f64>,
|
||||
// TODO ew, bools.
|
||||
can_use_bike_lanes: bool,
|
||||
can_use_bus_lanes: bool,
|
||||
) -> Option<Path> {
|
||||
pub fn shortest_distance(map: &Map, req: PathRequest) -> Option<Path> {
|
||||
// TODO using first_pt here and in heuristic_dist is particularly bad for walking
|
||||
// directions
|
||||
let goal_pt = map.get_l(end).dist_along(end_dist).0;
|
||||
let goal_pt = map.get_l(req.end).dist_along(req.end_dist).0;
|
||||
Pathfinder::ShortestDistance {
|
||||
goal_pt,
|
||||
can_use_bike_lanes,
|
||||
can_use_bus_lanes,
|
||||
}.pathfind(map, start, start_dist, end, end_dist)
|
||||
can_use_bike_lanes: req.can_use_bike_lanes,
|
||||
can_use_bus_lanes: req.can_use_bus_lanes,
|
||||
}.pathfind(map, req.start, req.start_dist, req.end, req.end_dist)
|
||||
}
|
||||
|
||||
// Returns the cost of the potential next step, plus an optional heuristic to the goal
|
||||
|
111
sim/src/spawn.rs
111
sim/src/spawn.rs
@ -2,7 +2,9 @@ use abstutil::{elapsed_seconds, fork_rng, WeightedUsizeChoice};
|
||||
use dimensioned::si;
|
||||
use driving::{CreateCar, DrivingGoal, DrivingSimState};
|
||||
use kinematics::Vehicle;
|
||||
use map_model::{BuildingID, BusRoute, BusStopID, LaneID, LaneType, Map, Path, Pathfinder, RoadID};
|
||||
use map_model::{
|
||||
BuildingID, BusRoute, BusStopID, LaneID, LaneType, Map, Path, PathRequest, Pathfinder, RoadID,
|
||||
};
|
||||
use parking::ParkingSimState;
|
||||
use rand::{Rng, XorShiftRng};
|
||||
use router::Router;
|
||||
@ -50,30 +52,32 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pathfinding_request(
|
||||
&self,
|
||||
map: &Map,
|
||||
parking_sim: &ParkingSimState,
|
||||
) -> (LaneID, Distance, LaneID, Distance) {
|
||||
fn get_pathfinding_request(&self, map: &Map, parking_sim: &ParkingSimState) -> PathRequest {
|
||||
match self {
|
||||
Command::Walk(_, _, _, start, goal) => (
|
||||
start.sidewalk,
|
||||
start.dist_along,
|
||||
goal.sidewalk,
|
||||
goal.dist_along,
|
||||
),
|
||||
Command::Walk(_, _, _, start, goal) => PathRequest {
|
||||
start: start.sidewalk,
|
||||
start_dist: start.dist_along,
|
||||
end: goal.sidewalk,
|
||||
end_dist: goal.dist_along,
|
||||
can_use_bike_lanes: false,
|
||||
can_use_bus_lanes: false,
|
||||
},
|
||||
Command::Drive(_, _, parked_car, goal) => {
|
||||
let goal_lane = match goal {
|
||||
DrivingGoal::ParkNear(b) => find_driving_lane_near_building(*b, map),
|
||||
DrivingGoal::Border(_, l) => *l,
|
||||
};
|
||||
(
|
||||
map.get_driving_lane_from_parking(parked_car.spot.lane)
|
||||
PathRequest {
|
||||
start: map
|
||||
.get_driving_lane_from_parking(parked_car.spot.lane)
|
||||
.unwrap(),
|
||||
parking_sim.dist_along_for_car(parked_car.spot, &parked_car.vehicle),
|
||||
goal_lane,
|
||||
map.get_l(goal_lane).length(),
|
||||
)
|
||||
start_dist: parking_sim
|
||||
.dist_along_for_car(parked_car.spot, &parked_car.vehicle),
|
||||
end: goal_lane,
|
||||
end_dist: map.get_l(goal_lane).length(),
|
||||
can_use_bike_lanes: false,
|
||||
can_use_bus_lanes: false,
|
||||
}
|
||||
}
|
||||
Command::Bike {
|
||||
start_sidewalk,
|
||||
@ -85,24 +89,33 @@ impl Command {
|
||||
DrivingGoal::ParkNear(b) => find_biking_goal_near_building(*b, map),
|
||||
DrivingGoal::Border(_, l) => (*l, map.get_l(*l).length()),
|
||||
};
|
||||
(
|
||||
map.get_driving_lane_from_sidewalk(*start_sidewalk).unwrap(),
|
||||
*start_dist,
|
||||
goal_lane,
|
||||
goal_dist,
|
||||
)
|
||||
PathRequest {
|
||||
start: map.get_driving_lane_from_sidewalk(*start_sidewalk).unwrap(),
|
||||
start_dist: *start_dist,
|
||||
end: goal_lane,
|
||||
end_dist: goal_dist,
|
||||
can_use_bus_lanes: false,
|
||||
can_use_bike_lanes: true,
|
||||
}
|
||||
}
|
||||
Command::DriveFromBorder { start, goal, .. } => {
|
||||
Command::DriveFromBorder {
|
||||
start,
|
||||
goal,
|
||||
is_bike,
|
||||
..
|
||||
} => {
|
||||
let goal_lane = match goal {
|
||||
DrivingGoal::ParkNear(b) => find_driving_lane_near_building(*b, map),
|
||||
DrivingGoal::Border(_, l) => *l,
|
||||
};
|
||||
(
|
||||
*start,
|
||||
0.0 * si::M,
|
||||
goal_lane,
|
||||
map.get_l(goal_lane).length(),
|
||||
)
|
||||
PathRequest {
|
||||
start: *start,
|
||||
start_dist: 0.0 * si::M,
|
||||
end: goal_lane,
|
||||
end_dist: map.get_l(goal_lane).length(),
|
||||
can_use_bus_lanes: false,
|
||||
can_use_bike_lanes: *is_bike,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,7 +194,7 @@ impl Spawner {
|
||||
trips: &mut TripManager,
|
||||
) {
|
||||
let mut commands: Vec<Command> = Vec::new();
|
||||
let mut requested_paths: Vec<(LaneID, Distance, LaneID, Distance)> = Vec::new();
|
||||
let mut requests: Vec<PathRequest> = Vec::new();
|
||||
loop {
|
||||
if self
|
||||
.commands
|
||||
@ -190,7 +203,7 @@ impl Spawner {
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let cmd = self.commands.pop().unwrap();
|
||||
requested_paths.push(cmd.get_pathfinding_request(map, parking_sim));
|
||||
requests.push(cmd.get_pathfinding_request(map, parking_sim));
|
||||
commands.push(cmd);
|
||||
} else {
|
||||
break;
|
||||
@ -199,11 +212,10 @@ impl Spawner {
|
||||
if commands.is_empty() {
|
||||
return;
|
||||
}
|
||||
let paths = calculate_paths(&requested_paths, map);
|
||||
let paths = calculate_paths(map, &requests);
|
||||
|
||||
let mut spawned_agents = 0;
|
||||
for (cmd, (req, maybe_path)) in commands.into_iter().zip(requested_paths.iter().zip(paths))
|
||||
{
|
||||
for (cmd, (req, maybe_path)) in commands.into_iter().zip(requests.iter().zip(paths)) {
|
||||
if let Some(path) = maybe_path {
|
||||
match cmd {
|
||||
Command::Drive(_, trip, ref parked_car, ref goal) => {
|
||||
@ -301,11 +313,11 @@ impl Spawner {
|
||||
owner: None,
|
||||
maybe_parked_car: None,
|
||||
vehicle: vehicle.clone(),
|
||||
start: req.0,
|
||||
dist_along: req.1,
|
||||
start: req.start,
|
||||
dist_along: req.start_dist,
|
||||
router: match goal {
|
||||
DrivingGoal::ParkNear(_) => {
|
||||
Router::make_bike_router(path, req.3)
|
||||
Router::make_bike_router(path, req.end_dist)
|
||||
}
|
||||
DrivingGoal::Border(_, _) => {
|
||||
Router::make_router_to_border(path)
|
||||
@ -330,14 +342,14 @@ impl Spawner {
|
||||
} else {
|
||||
error!(
|
||||
"Couldn't find path from {} to {} for {:?}",
|
||||
req.0, req.2, cmd
|
||||
req.start, req.end, cmd
|
||||
);
|
||||
}
|
||||
}
|
||||
debug!(
|
||||
"Spawned {} agents of requested {}",
|
||||
spawned_agents,
|
||||
requested_paths.len()
|
||||
requests.len()
|
||||
);
|
||||
}
|
||||
|
||||
@ -788,23 +800,16 @@ impl Spawner {
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_paths(
|
||||
requested_paths: &Vec<(LaneID, Distance, LaneID, Distance)>,
|
||||
map: &Map,
|
||||
) -> Vec<Option<Path>> {
|
||||
fn calculate_paths(map: &Map, requests: &Vec<PathRequest>) -> Vec<Option<Path>> {
|
||||
use rayon::prelude::*;
|
||||
|
||||
debug!("Calculating {} paths", requested_paths.len());
|
||||
debug!("Calculating {} paths", requests.len());
|
||||
// TODO better timer macro
|
||||
let timer = Instant::now();
|
||||
let paths: Vec<Option<Path>> = requested_paths
|
||||
let paths: Vec<Option<Path>> = requests
|
||||
.par_iter()
|
||||
// TODO No bikes yet, so never use the bike lanes
|
||||
// TODO I don't think buses ever use this, so also hardcode false. requested_paths should
|
||||
// be a struct of the required input to shortest_distance, probably.
|
||||
.map(|(start, start_dist, goal, goal_dist)| {
|
||||
Pathfinder::shortest_distance(map, *start, *start_dist, *goal, *goal_dist, false, false)
|
||||
}).collect();
|
||||
.map(|req| Pathfinder::shortest_distance(map, req.clone()))
|
||||
.collect();
|
||||
|
||||
debug!(
|
||||
"Calculating {} paths took {}s",
|
||||
|
@ -2,7 +2,7 @@ use abstutil::{deserialize_btreemap, serialize_btreemap};
|
||||
use dimensioned::si;
|
||||
use events::Event;
|
||||
use instrument::capture_backtrace;
|
||||
use map_model::{BusRoute, BusStop, LaneID, Map, Path, Pathfinder};
|
||||
use map_model::{BusRoute, BusStop, LaneID, Map, Path, PathRequest, Pathfinder};
|
||||
use spawn::Spawner;
|
||||
use std::collections::BTreeMap;
|
||||
use trips::TripManager;
|
||||
@ -97,12 +97,14 @@ impl TransitSimState {
|
||||
let stop2 = &route.stops[next_stop];
|
||||
let path = Pathfinder::shortest_distance(
|
||||
map,
|
||||
stop1.driving_lane,
|
||||
stop1.dist_along,
|
||||
stop2.driving_lane,
|
||||
stop2.dist_along,
|
||||
false,
|
||||
true,
|
||||
PathRequest {
|
||||
start: stop1.driving_lane,
|
||||
start_dist: stop1.dist_along,
|
||||
end: stop2.driving_lane,
|
||||
end_dist: stop2.dist_along,
|
||||
can_use_bike_lanes: false,
|
||||
can_use_bus_lanes: true,
|
||||
},
|
||||
).expect(&format!(
|
||||
"No route between bus stops {:?} and {:?}",
|
||||
stop1, stop2
|
||||
@ -168,12 +170,14 @@ impl TransitSimState {
|
||||
|
||||
let new_path = Pathfinder::shortest_distance(
|
||||
map,
|
||||
stop.driving_lane,
|
||||
stop.dist_along,
|
||||
route.stops[next_stop].driving_lane,
|
||||
route.stops[next_stop].dist_along,
|
||||
false,
|
||||
true,
|
||||
PathRequest {
|
||||
start: stop.driving_lane,
|
||||
start_dist: stop.dist_along,
|
||||
end: route.stops[next_stop].driving_lane,
|
||||
end_dist: route.stops[next_stop].dist_along,
|
||||
can_use_bike_lanes: false,
|
||||
can_use_bus_lanes: true,
|
||||
},
|
||||
).expect(&format!(
|
||||
"No route between bus stops {:?} and {:?}",
|
||||
stop, route.stops[next_stop]
|
||||
|
Loading…
Reference in New Issue
Block a user