Refactor: Store the input PathRequest inside the resulting Path. This

saves lots of callers from cloning the request and separately plumbing
around the requested start/end distance. Also a step towards exposing
more granular distance crossed in a path for #392.

Still a few more places to simplify, but will do in a separate, smaller
change.
This commit is contained in:
Dustin Carlino 2020-12-16 12:55:57 -08:00
parent e8f7e7444c
commit fccc98205c
15 changed files with 66 additions and 80 deletions

View File

@ -637,7 +637,7 @@
"size_bytes": 59144729
},
"data/system/seattle/prebaked_results/lakeslice/weekday.bin": {
"checksum": "4c4c942ed0f791eabf4389985098fc54",
"checksum": "dab9c56147f1e3e66ca60d7dcd946ee0",
"size_bytes": 66439671
},
"data/system/seattle/prebaked_results/montlake/car vs bike contention.bin": {
@ -645,7 +645,7 @@
"size_bytes": 5277
},
"data/system/seattle/prebaked_results/montlake/weekday.bin": {
"checksum": "ea42c12f997bddc31d147038a0105418",
"checksum": "30027ab5ae12145c50102824f4bfaed4",
"size_bytes": 8533785
},
"data/system/seattle/scenarios/ballard/weekday.bin": {

View File

@ -74,7 +74,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID
.primary
.sim
.walking_path_to_nearest_parking_spot(&app.primary.map, id)
.and_then(|(path, start_dist)| path.trace(&app.primary.map, start_dist, None))
.and_then(|path| path.trace(&app.primary.map, path.get_req().start.dist_along(), None))
{
let color = app.cs.parking_trip;
// TODO But this color doesn't show up well against the info panel...

View File

@ -322,7 +322,7 @@ impl State<App> for AgentSpawner {
{
self.goal = Some((
to,
path.trace(&app.primary.map, Distance::ZERO, None)
path.trace(&app.primary.map, path.get_req().start.dist_along(), None)
.map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
));
} else {
@ -387,7 +387,7 @@ impl State<App> for AgentSpawner {
{
self.goal = Some((
hovering,
path.trace(&app.primary.map, Distance::ZERO, None)
path.trace(&app.primary.map, path.get_req().start.dist_along(), None)
.map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
));
} else {

View File

@ -102,7 +102,7 @@ impl Zone {
}
steps.push(PathStep::Lane(req.end.lane()));
assert_eq!(steps[0], PathStep::Lane(req.start.lane()));
Some(Path::new(map, steps, req.end.dist_along(), Vec::new()))
Some(Path::new(map, steps, req, Vec::new()))
}
// TODO Not happy this works so differently

View File

@ -68,7 +68,7 @@ fn calc_path(graph: DiGraphMap<LaneID, TurnID>, req: &PathRequest, map: &Map) ->
}
steps.push(PathStep::Lane(req.end.lane()));
assert_eq!(steps[0], PathStep::Lane(req.start.lane()));
Some(Path::new(map, steps, req.end.dist_along(), Vec::new()))
Some(Path::new(map, steps, req.clone(), Vec::new()))
}
// TODO Not happy this works so differently

View File

@ -116,7 +116,7 @@ impl VehiclePathfinder {
}
steps.push(PathStep::Lane(req.end.lane()));
Some((
Path::new(map, steps, req.end.dist_along(), uber_turns),
Path::new(map, steps, req.clone(), uber_turns),
raw_path.get_weight(),
))
}

View File

@ -102,7 +102,9 @@ impl PathStep {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Path {
steps: VecDeque<PathStep>,
end_dist: Distance,
// The original request used to produce this path. Calling shift(), add(), modify_step(), etc
// will NOT affect this.
orig_req: PathRequest,
// Also track progress along the original path.
total_length: Distance,
@ -119,7 +121,7 @@ impl Path {
pub(crate) fn new(
map: &Map,
steps: Vec<PathStep>,
end_dist: Distance,
orig_req: PathRequest,
uber_turns: Vec<UberTurn>,
) -> Path {
// Haven't seen problems here in a very long time. Noticeably saves some time to skip.
@ -136,7 +138,7 @@ impl Path {
}
Path {
steps: VecDeque::from(steps),
end_dist,
orig_req,
total_length,
crossed_so_far: Distance::ZERO,
uber_turns: uber_turns.into_iter().collect(),
@ -144,25 +146,15 @@ impl Path {
}
}
pub fn one_step(l: LaneID, map: &Map) -> Path {
Path::new(
map,
vec![PathStep::Lane(l)],
map.get_l(l).length(),
Vec::new(),
)
pub fn one_step(req: PathRequest, map: &Map) -> Path {
assert_eq!(req.start.lane(), req.end.lane());
Path::new(map, vec![PathStep::Lane(req.start.lane())], req, Vec::new())
}
/// Only used for weird serialization magic.
pub fn dummy() -> Path {
Path {
steps: VecDeque::new(),
end_dist: Distance::ZERO,
total_length: Distance::ZERO,
crossed_so_far: Distance::ZERO,
uber_turns: VecDeque::new(),
currently_inside_ut: None,
}
/// The original PathRequest used to produce this path. If the path has been modified since
/// creation, the start and end of the request won't match up with the current path steps.
pub fn get_req(&self) -> &PathRequest {
&self.orig_req
}
pub fn crossed_so_far(&self) -> Distance {
@ -293,7 +285,8 @@ impl Path {
self.steps[self.steps.len() - 1]
}
/// dist_ahead is unlimited when None.
/// dist_ahead is unlimited when None. Note this starts at the beginning (or end, for some
/// walking paths) of the first lane, not accounting for the original request's start distance.
pub fn trace(
&self,
map: &Map,
@ -302,12 +295,13 @@ impl Path {
) -> Option<PolyLine> {
let mut pts_so_far: Option<PolyLine> = None;
let mut dist_remaining = dist_ahead;
let orig_end_dist = self.orig_req.end.dist_along();
if self.steps.len() == 1 {
let dist = if start_dist < self.end_dist {
self.end_dist - start_dist
let dist = if start_dist < orig_end_dist {
orig_end_dist - start_dist
} else {
start_dist - self.end_dist
start_dist - orig_end_dist
};
if let Some(d) = dist_remaining {
if dist < d {
@ -346,9 +340,9 @@ impl Path {
if i == self.steps.len() - 1 {
let end_dist = match self.steps[i] {
PathStep::ContraflowLane(l) => {
map.get_l(l).lane_center_pts.reversed().length() - self.end_dist
map.get_l(l).lane_center_pts.reversed().length() - orig_end_dist
}
_ => self.end_dist,
_ => orig_end_dist,
};
if let Some(d) = dist_remaining {
if end_dist < d {

View File

@ -45,7 +45,7 @@ impl Pathfinder {
if req.constraints == PathConstraints::Pedestrian {
let steps =
walking_path_to_steps(z1.pathfind_walking(req.clone(), map)?, map);
return Some(Path::new(map, steps, req.end.dist_along(), Vec::new()));
return Some(Path::new(map, steps, req, Vec::new()));
}
return z1.pathfind(req, map);
}
@ -102,7 +102,7 @@ impl Pathfinder {
return Some(one_step_walking_path(&req, map));
}
let steps = walking_path_to_steps(self.simple_walking_path(&req, map)?, map);
return Some(Path::new(map, steps, req.end.dist_along(), Vec::new()));
return Some(Path::new(map, steps, req, Vec::new()));
}
self.simple_pathfind(&req, map)
}
@ -221,7 +221,7 @@ impl Pathfinder {
};
interior_path.extend(main_path);
let steps = walking_path_to_steps(interior_path, map);
return Some(Path::new(map, steps, req.end.dist_along(), Vec::new()));
return Some(Path::new(map, steps, req, Vec::new()));
}
let mut interior_path = zone.pathfind(interior_req, map)?;
@ -279,7 +279,7 @@ impl Pathfinder {
end: req.end,
constraints: req.constraints,
};
let orig_end_dist = req.end.dist_along();
let orig_req = req.clone();
req.end = if map.get_l(src).dst_i == i.id {
Position::end(src, map)
} else {
@ -301,13 +301,13 @@ impl Pathfinder {
main_path.extend(interior_path);
let steps = walking_path_to_steps(main_path, map);
return Some(Path::new(map, steps, orig_end_dist, Vec::new()));
return Some(Path::new(map, steps, orig_req, Vec::new()));
}
let interior_path = zone.pathfind(interior_req, map)?;
let mut main_path = self.simple_pathfind(&req, map)?;
main_path.append(interior_path, map);
main_path.end_dist = orig_end_dist;
main_path.orig_req = orig_req;
Some(main_path)
}
}

View File

@ -462,21 +462,21 @@ pub fn one_step_walking_path(req: &PathRequest, map: &Map) -> Path {
Path::new(
map,
vec![PathStep::Lane(req.start.lane())],
req.start.dist_along(),
req.clone(),
Vec::new(),
)
} else if req.start.dist_along() < req.end.dist_along() {
Path::new(
map,
vec![PathStep::Lane(req.start.lane())],
req.end.dist_along(),
req.clone(),
Vec::new(),
)
} else {
Path::new(
map,
vec![PathStep::ContraflowLane(req.start.lane())],
req.end.dist_along(),
req.clone(),
Vec::new(),
)
}

View File

@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
use geom::{Duration, Time};
use map_model::{LaneID, Map, Path, PathConstraints, PathRequest, PathStep, TurnID};
use map_model::{LaneID, Map, Path, PathConstraints, PathStep, TurnID};
use crate::mechanics::IntersectionSimState;
use crate::{CarID, SimOptions, VehicleType};
@ -79,7 +79,6 @@ impl CapSimState {
/// dynamic limits.
pub fn maybe_cap_path(
&mut self,
req: &PathRequest,
path: Path,
now: Time,
car: CarID,
@ -112,14 +111,14 @@ impl CapSimState {
avoid_lanes.insert(*l);
}
}
match map.pathfind_avoiding_lanes(req.clone(), avoid_lanes) {
match map.pathfind_avoiding_lanes(path.get_req().clone(), avoid_lanes) {
Some(path) => CapResult::Reroute(path),
None => {
if let Some(delay) = self.delay_trips_instead_of_cancelling {
CapResult::Delay(delay)
} else {
CapResult::Cancel {
reason: format!("no path avoiding caps: {}", req),
reason: format!("no path avoiding caps: {}", path.get_req()),
}
}
}

View File

@ -581,7 +581,6 @@ pub(crate) struct CreatePedestrian {
pub start: SidewalkSpot,
pub speed: Speed,
pub goal: SidewalkSpot,
pub req: PathRequest,
pub path: Path,
pub trip: TripID,
pub person: PersonID,

View File

@ -70,10 +70,17 @@ impl Router {
owner,
}
}
pub fn vanish_bus(owner: CarID, l: LaneID, map: &Map) -> Router {
let lane = map.get_l(l);
pub fn vanish_bus(owner: CarID, start: Position, map: &Map) -> Router {
let lane = map.get_l(start.lane());
Router {
path: Path::one_step(l, map),
path: Path::one_step(
PathRequest {
start,
end: Position::end(lane.id, map),
constraints: PathConstraints::Bus,
},
map,
),
goal: Goal::EndAtBorder {
end_dist: lane.length(),
i: lane.dst_i,

View File

@ -273,12 +273,7 @@ impl Sim {
self.parking.bldg_to_parked_cars(b)
}
/// Also returns the start distance of the building. TODO Do that in the Path properly.
pub fn walking_path_to_nearest_parking_spot(
&self,
map: &Map,
b: BuildingID,
) -> Option<(Path, Distance)> {
pub fn walking_path_to_nearest_parking_spot(&self, map: &Map, b: BuildingID) -> Option<Path> {
let vehicle = Vehicle {
id: CarID(0, VehicleType::Car),
owner: None,
@ -306,14 +301,12 @@ impl Sim {
let start = SidewalkSpot::building(b, map).sidewalk_pos;
let end = SidewalkSpot::parking_spot(spot, map, &self.parking).sidewalk_pos;
let path = map
.pathfind(PathRequest {
start,
end,
constraints: PathConstraints::Pedestrian,
})
.ok()?;
Some((path, start.dist_along()))
map.pathfind(PathRequest {
start,
end,
constraints: PathConstraints::Pedestrian,
})
.ok()
}
pub(crate) fn new_person(
@ -572,7 +565,7 @@ impl Sim {
events.push(Event::TripPhaseStarting(
create_ped.trip,
create_ped.person,
Some(create_ped.req.clone()),
Some(create_ped.path.get_req().clone()),
TripPhaseType::Walking,
));
self.analytics.record_demand(&create_ped.path, map);

View File

@ -287,7 +287,6 @@ impl TransitSimState {
bus.state = BusState::DrivingOffMap;
Router::follow_bus_route(id, path, req.end.dist_along())
} else {
let on = stop.driving_pos.lane();
route.active_vehicles.remove(&id);
for (person, stop2) in &bus.passengers {
panic!(
@ -297,7 +296,7 @@ impl TransitSimState {
);
}
bus.state = BusState::Done;
Router::vanish_bus(id, on, map)
Router::vanish_bus(id, stop.driving_pos, map)
}
}
}

View File

@ -225,7 +225,7 @@ impl TripManager {
end: walking_goal.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
match ctx.map.pathfind(req.clone()) {
match ctx.map.pathfind(req) {
Ok(path) => {
ctx.scheduler.push(
now,
@ -235,7 +235,6 @@ impl TripManager {
start,
goal: walking_goal,
path,
req,
trip,
person: person.id,
}),
@ -292,7 +291,7 @@ impl TripManager {
end: goal.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
match ctx.map.pathfind(req.clone()) {
match ctx.map.pathfind(req) {
Ok(path) => {
ctx.scheduler.push(
now,
@ -302,7 +301,6 @@ impl TripManager {
start,
goal,
path,
req,
trip,
person: person.id,
}),
@ -323,7 +321,7 @@ impl TripManager {
end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
match ctx.map.pathfind(req.clone()) {
match ctx.map.pathfind(req) {
Ok(path) => {
// Where we start biking may have slightly changed due to live map
// edits!
@ -345,7 +343,6 @@ impl TripManager {
start: SidewalkSpot::building(start, ctx.map),
goal: walk_to,
path,
req,
trip,
person: person.id,
}),
@ -402,7 +399,7 @@ impl TripManager {
end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
match ctx.map.pathfind(req.clone()) {
match ctx.map.pathfind(req) {
Ok(path) => {
ctx.scheduler.push(
now,
@ -412,7 +409,6 @@ impl TripManager {
start,
goal: walk_to,
path,
req,
trip,
person: person.id,
}),
@ -946,7 +942,7 @@ impl TripManager {
end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian,
};
match ctx.map.pathfind(req.clone()) {
match ctx.map.pathfind(req) {
Ok(path) => {
let person = &self.people[trip.person.0];
ctx.scheduler.push(
@ -957,7 +953,6 @@ impl TripManager {
start,
goal: walk_to,
path,
req,
trip: id,
person: person.id,
}),
@ -979,10 +974,10 @@ impl TripManager {
req: PathRequest,
car: CarID,
) -> Result<Path, String> {
let path = ctx.map.pathfind(req.clone())?;
let path = ctx.map.pathfind(req)?;
match ctx
.cap
.maybe_cap_path(&req, path, now, car, ctx.intersections, ctx.map)
.maybe_cap_path(path, now, car, ctx.intersections, ctx.map)
{
CapResult::OK(path) => Ok(path),
CapResult::Reroute(path) => {