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 "size_bytes": 59144729
}, },
"data/system/seattle/prebaked_results/lakeslice/weekday.bin": { "data/system/seattle/prebaked_results/lakeslice/weekday.bin": {
"checksum": "4c4c942ed0f791eabf4389985098fc54", "checksum": "dab9c56147f1e3e66ca60d7dcd946ee0",
"size_bytes": 66439671 "size_bytes": 66439671
}, },
"data/system/seattle/prebaked_results/montlake/car vs bike contention.bin": { "data/system/seattle/prebaked_results/montlake/car vs bike contention.bin": {
@ -645,7 +645,7 @@
"size_bytes": 5277 "size_bytes": 5277
}, },
"data/system/seattle/prebaked_results/montlake/weekday.bin": { "data/system/seattle/prebaked_results/montlake/weekday.bin": {
"checksum": "ea42c12f997bddc31d147038a0105418", "checksum": "30027ab5ae12145c50102824f4bfaed4",
"size_bytes": 8533785 "size_bytes": 8533785
}, },
"data/system/seattle/scenarios/ballard/weekday.bin": { "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 .primary
.sim .sim
.walking_path_to_nearest_parking_spot(&app.primary.map, id) .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; let color = app.cs.parking_trip;
// TODO But this color doesn't show up well against the info panel... // 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(( self.goal = Some((
to, 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)), .map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
)); ));
} else { } else {
@ -387,7 +387,7 @@ impl State<App> for AgentSpawner {
{ {
self.goal = Some(( self.goal = Some((
hovering, 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)), .map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
)); ));
} else { } else {

View File

@ -102,7 +102,7 @@ impl Zone {
} }
steps.push(PathStep::Lane(req.end.lane())); steps.push(PathStep::Lane(req.end.lane()));
assert_eq!(steps[0], PathStep::Lane(req.start.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 // 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())); steps.push(PathStep::Lane(req.end.lane()));
assert_eq!(steps[0], PathStep::Lane(req.start.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 // TODO Not happy this works so differently

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use geom::{Duration, Time}; 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::mechanics::IntersectionSimState;
use crate::{CarID, SimOptions, VehicleType}; use crate::{CarID, SimOptions, VehicleType};
@ -79,7 +79,6 @@ impl CapSimState {
/// dynamic limits. /// dynamic limits.
pub fn maybe_cap_path( pub fn maybe_cap_path(
&mut self, &mut self,
req: &PathRequest,
path: Path, path: Path,
now: Time, now: Time,
car: CarID, car: CarID,
@ -112,14 +111,14 @@ impl CapSimState {
avoid_lanes.insert(*l); 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), Some(path) => CapResult::Reroute(path),
None => { None => {
if let Some(delay) = self.delay_trips_instead_of_cancelling { if let Some(delay) = self.delay_trips_instead_of_cancelling {
CapResult::Delay(delay) CapResult::Delay(delay)
} else { } else {
CapResult::Cancel { 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 start: SidewalkSpot,
pub speed: Speed, pub speed: Speed,
pub goal: SidewalkSpot, pub goal: SidewalkSpot,
pub req: PathRequest,
pub path: Path, pub path: Path,
pub trip: TripID, pub trip: TripID,
pub person: PersonID, pub person: PersonID,

View File

@ -70,10 +70,17 @@ impl Router {
owner, owner,
} }
} }
pub fn vanish_bus(owner: CarID, l: LaneID, map: &Map) -> Router { pub fn vanish_bus(owner: CarID, start: Position, map: &Map) -> Router {
let lane = map.get_l(l); let lane = map.get_l(start.lane());
Router { 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 { goal: Goal::EndAtBorder {
end_dist: lane.length(), end_dist: lane.length(),
i: lane.dst_i, i: lane.dst_i,

View File

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

View File

@ -287,7 +287,6 @@ impl TransitSimState {
bus.state = BusState::DrivingOffMap; bus.state = BusState::DrivingOffMap;
Router::follow_bus_route(id, path, req.end.dist_along()) Router::follow_bus_route(id, path, req.end.dist_along())
} else { } else {
let on = stop.driving_pos.lane();
route.active_vehicles.remove(&id); route.active_vehicles.remove(&id);
for (person, stop2) in &bus.passengers { for (person, stop2) in &bus.passengers {
panic!( panic!(
@ -297,7 +296,7 @@ impl TransitSimState {
); );
} }
bus.state = BusState::Done; 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, end: walking_goal.sidewalk_pos,
constraints: PathConstraints::Pedestrian, constraints: PathConstraints::Pedestrian,
}; };
match ctx.map.pathfind(req.clone()) { match ctx.map.pathfind(req) {
Ok(path) => { Ok(path) => {
ctx.scheduler.push( ctx.scheduler.push(
now, now,
@ -235,7 +235,6 @@ impl TripManager {
start, start,
goal: walking_goal, goal: walking_goal,
path, path,
req,
trip, trip,
person: person.id, person: person.id,
}), }),
@ -292,7 +291,7 @@ impl TripManager {
end: goal.sidewalk_pos, end: goal.sidewalk_pos,
constraints: PathConstraints::Pedestrian, constraints: PathConstraints::Pedestrian,
}; };
match ctx.map.pathfind(req.clone()) { match ctx.map.pathfind(req) {
Ok(path) => { Ok(path) => {
ctx.scheduler.push( ctx.scheduler.push(
now, now,
@ -302,7 +301,6 @@ impl TripManager {
start, start,
goal, goal,
path, path,
req,
trip, trip,
person: person.id, person: person.id,
}), }),
@ -323,7 +321,7 @@ impl TripManager {
end: walk_to.sidewalk_pos, end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian, constraints: PathConstraints::Pedestrian,
}; };
match ctx.map.pathfind(req.clone()) { match ctx.map.pathfind(req) {
Ok(path) => { Ok(path) => {
// Where we start biking may have slightly changed due to live map // Where we start biking may have slightly changed due to live map
// edits! // edits!
@ -345,7 +343,6 @@ impl TripManager {
start: SidewalkSpot::building(start, ctx.map), start: SidewalkSpot::building(start, ctx.map),
goal: walk_to, goal: walk_to,
path, path,
req,
trip, trip,
person: person.id, person: person.id,
}), }),
@ -402,7 +399,7 @@ impl TripManager {
end: walk_to.sidewalk_pos, end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian, constraints: PathConstraints::Pedestrian,
}; };
match ctx.map.pathfind(req.clone()) { match ctx.map.pathfind(req) {
Ok(path) => { Ok(path) => {
ctx.scheduler.push( ctx.scheduler.push(
now, now,
@ -412,7 +409,6 @@ impl TripManager {
start, start,
goal: walk_to, goal: walk_to,
path, path,
req,
trip, trip,
person: person.id, person: person.id,
}), }),
@ -946,7 +942,7 @@ impl TripManager {
end: walk_to.sidewalk_pos, end: walk_to.sidewalk_pos,
constraints: PathConstraints::Pedestrian, constraints: PathConstraints::Pedestrian,
}; };
match ctx.map.pathfind(req.clone()) { match ctx.map.pathfind(req) {
Ok(path) => { Ok(path) => {
let person = &self.people[trip.person.0]; let person = &self.people[trip.person.0];
ctx.scheduler.push( ctx.scheduler.push(
@ -957,7 +953,6 @@ impl TripManager {
start, start,
goal: walk_to, goal: walk_to,
path, path,
req,
trip: id, trip: id,
person: person.id, person: person.id,
}), }),
@ -979,10 +974,10 @@ impl TripManager {
req: PathRequest, req: PathRequest,
car: CarID, car: CarID,
) -> Result<Path, String> { ) -> Result<Path, String> {
let path = ctx.map.pathfind(req.clone())?; let path = ctx.map.pathfind(req)?;
match ctx match ctx
.cap .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::OK(path) => Ok(path),
CapResult::Reroute(path) => { CapResult::Reroute(path) => {