Refactor uses of biking speed between the sim and pathfinding, in preparation for incorporating incline. #82

(This was a bigger mess than I expected, so worth doing separately.)
This commit is contained in:
Dustin Carlino 2021-04-01 11:52:25 -07:00
parent 3c601b50c1
commit 892afddcd5
8 changed files with 77 additions and 55 deletions

View File

@ -237,9 +237,10 @@ impl TuneRelative {
" about {} for a car if there's no congestion", " about {} for a car if there's no congestion",
car_dt car_dt
)), )),
// TODO We could calculate a full path and incorporate incline
Line(format!( Line(format!(
" about {} for a bike", " about {} for a bike",
dist_btwn / Scenario::max_bike_speed() dist_btwn / map_model::MAX_BIKE_SPEED
)), )),
Line(format!( Line(format!(
" about {} for a pedestrian", " about {} for a pedestrian",

View File

@ -57,7 +57,7 @@ pub use crate::objects::zone::{AccessRestrictions, Zone};
pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn, UberTurnGroup}; pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn, UberTurnGroup};
use crate::pathfind::Pathfinder; use crate::pathfind::Pathfinder;
pub use crate::pathfind::{Path, PathConstraints, PathRequest, PathStep, RoutingParams}; pub use crate::pathfind::{Path, PathConstraints, PathRequest, PathStep, RoutingParams};
pub use crate::traversable::{Position, Traversable}; pub use crate::traversable::{Position, Traversable, MAX_BIKE_SPEED};
mod city; mod city;
pub mod connectivity; pub mod connectivity;

View File

@ -422,15 +422,9 @@ impl Path {
let mut total = Duration::ZERO; let mut total = Duration::ZERO;
for step in &self.steps { for step in &self.steps {
let dist = self.dist_crossed_from_step(map, step); let dist = self.dist_crossed_from_step(map, step);
let speed_limit = step.as_traversable().speed_limit(map); let speed = step
let speed = if constraints == PathConstraints::Pedestrian { .as_traversable()
// Pedestrians don't care about the road's speed limit .max_speed_along(max_speed, constraints, map);
max_speed.unwrap()
} else if let Some(max) = max_speed {
speed_limit.min(max)
} else {
speed_limit
};
total += dist / speed; total += dist / speed;
} }
total total

View File

@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use thread_local::ThreadLocal; use thread_local::ThreadLocal;
use abstutil::MultiMap; use abstutil::MultiMap;
use geom::{Duration, Speed}; use geom::Duration;
use crate::pathfind::ch::round; use crate::pathfind::ch::round;
use crate::pathfind::node_map::{deserialize_nodemap, NodeMap}; use crate::pathfind::node_map::{deserialize_nodemap, NodeMap};
@ -15,7 +15,7 @@ use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn};
use crate::pathfind::zone_cost; use crate::pathfind::zone_cost;
use crate::{ use crate::{
DrivingSide, Lane, LaneID, Map, Path, PathConstraints, PathRequest, PathStep, RoutingParams, DrivingSide, Lane, LaneID, Map, Path, PathConstraints, PathRequest, PathStep, RoutingParams,
Turn, TurnID, TurnType, Traversable, Turn, TurnID, TurnType,
}; };
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -253,14 +253,13 @@ pub fn vehicle_cost(
t1 + t2 t1 + t2
} }
PathConstraints::Bike => { PathConstraints::Bike => {
// TODO Copied from sim. Probably move to map_model. // We assume MAX_BIKE_SPEED for pathfinding.
let max_bike_speed = Speed::miles_per_hour(10.0); let max_speed = Some(crate::MAX_BIKE_SPEED);
// Usually the bike's speed limit matters, not the road's. let t1 = lane.length()
let t1 = lane.length() / map.get_r(lane.parent).speed_limit.min(max_bike_speed); / Traversable::Lane(lane.id).max_speed_along(max_speed, constraints, map);
let t2 = let t2 = turn.geom.length()
turn.geom.length() / map.get_parent(turn.id.dst).speed_limit.min(max_bike_speed); / Traversable::Turn(turn.id).max_speed_along(max_speed, constraints, map);
// TODO Elevation gain is bad, loss is good.
// TODO If we're on a driving lane, higher speed limit is worse. // TODO If we're on a driving lane, higher speed limit is worse.
// TODO Bike lanes next to parking is dangerous. // TODO Bike lanes next to parking is dangerous.

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use geom::{Angle, Distance, PolyLine, Pt2D, Speed}; use geom::{Angle, Distance, PolyLine, Pt2D, Speed};
use crate::{LaneID, Map, TurnID}; use crate::{LaneID, Map, PathConstraints, TurnID};
/// Represents a specific point some distance along a lane. /// Represents a specific point some distance along a lane.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
@ -197,17 +197,51 @@ impl Traversable {
} }
} }
pub fn speed_limit(&self, map: &Map) -> Speed {
match *self {
Traversable::Lane(id) => map.get_parent(id).speed_limit,
Traversable::Turn(id) => map.get_parent(id.dst).speed_limit,
}
}
pub fn get_zorder(&self, map: &Map) -> isize { pub fn get_zorder(&self, map: &Map) -> isize {
match *self { match *self {
Traversable::Lane(id) => map.get_parent(id).zorder, Traversable::Lane(id) => map.get_parent(id).zorder,
Traversable::Turn(id) => map.get_i(id.parent).get_zorder(map), Traversable::Turn(id) => map.get_i(id.parent).get_zorder(map),
} }
} }
/// The single definitive place to determine how fast somebody could go along a single road or
/// turn. This should be used for pathfinding and simulation.
pub fn max_speed_along(
&self,
max_speed_on_flat_ground: Option<Speed>,
constraints: PathConstraints,
map: &Map,
) -> Speed {
let base = match self {
Traversable::Lane(l) => {
if constraints == PathConstraints::Bike {
// We assume every bike has a max_speed defined.
bike_speed_on_incline(
max_speed_on_flat_ground.unwrap(),
map.get_parent(*l).percent_incline,
)
} else {
map.get_parent(*l).speed_limit
}
}
// TODO Ignore elevation on turns?
Traversable::Turn(t) => map
.get_parent(t.src)
.speed_limit
.min(map.get_parent(t.dst).speed_limit),
};
if let Some(s) = max_speed_on_flat_ground {
base.min(s)
} else {
base
}
}
}
// 10mph
pub const MAX_BIKE_SPEED: Speed = Speed::const_meters_per_second(4.4704);
fn bike_speed_on_incline(max_speed: Speed, _percent_incline: f64) -> Speed {
// TODO Incorporate percent_incline here
max_speed
} }

View File

@ -225,7 +225,7 @@ impl Scenario {
let max_speed = Some(Scenario::rand_speed( let max_speed = Some(Scenario::rand_speed(
rng, rng,
Speed::miles_per_hour(8.0), Speed::miles_per_hour(8.0),
Scenario::max_bike_speed(), map_model::MAX_BIKE_SPEED,
)); ));
VehicleSpec { VehicleSpec {
vehicle_type: VehicleType::Bike, vehicle_type: VehicleType::Bike,
@ -233,9 +233,6 @@ impl Scenario {
max_speed, max_speed,
} }
} }
pub fn max_bike_speed() -> Speed {
Speed::miles_per_hour(10.0)
}
pub fn rand_dist(rng: &mut XorShiftRng, low: Distance, high: Distance) -> Distance { pub fn rand_dist(rng: &mut XorShiftRng, low: Distance, high: Distance) -> Distance {
assert!(high > low); assert!(high > low);

View File

@ -47,11 +47,11 @@ impl Car {
start_time: Time, start_time: Time,
map: &Map, map: &Map,
) -> CarState { ) -> CarState {
let on = self.router.head(); let speed = self.router.head().max_speed_along(
let mut speed = on.speed_limit(map); self.vehicle.max_speed,
if let Some(s) = self.vehicle.max_speed { self.vehicle.vehicle_type.to_constraints(),
speed = speed.min(s); map,
} );
let dt = (dist_int.end - dist_int.start) / speed; let dt = (dist_int.end - dist_int.start) / speed;
CarState::Crossing(TimeInterval::new(start_time, start_time + dt), dist_int) CarState::Crossing(TimeInterval::new(start_time, start_time + dt), dist_int)
} }

View File

@ -273,19 +273,16 @@ impl DrivingSimState {
) -> bool { ) -> bool {
match car.state { match car.state {
CarState::Crossing(time_int, dist_int) => { CarState::Crossing(time_int, dist_int) => {
let time_cross = now - time_int.start; if let Some((trip, _)) = car.trip_and_person {
if time_cross > Duration::ZERO { if let Traversable::Lane(lane) = car.router.head() {
let avg_speed = Speed::from_dist_time(dist_int.length(), time_cross); let time_to_cross = now - time_int.start;
if time_to_cross > Duration::ZERO {
let route = car.router.head(); let avg_speed = Speed::from_dist_time(dist_int.length(), time_to_cross);
let max_speed = route.speed_limit(ctx.map).min( let max_speed = car.router.head().max_speed_along(
car.vehicle car.vehicle.max_speed,
.max_speed car.vehicle.vehicle_type.to_constraints(),
.unwrap_or(Speed::meters_per_second(100.0)), ctx.map,
); );
if let Some((trip, _)) = car.trip_and_person {
if let Traversable::Lane(lane) = route {
self.events self.events
.push(Event::LaneSpeedPercentage(trip, lane, avg_speed, max_speed)); .push(Event::LaneSpeedPercentage(trip, lane, avg_speed, max_speed));
} }
@ -397,14 +394,14 @@ impl DrivingSimState {
assert!(from != goto); assert!(from != goto);
if let Traversable::Turn(t) = goto { if let Traversable::Turn(t) = goto {
let mut speed = goto.speed_limit(ctx.map);
if let Some(s) = car.vehicle.max_speed {
speed = speed.min(s);
}
if !ctx.intersections.maybe_start_turn( if !ctx.intersections.maybe_start_turn(
AgentID::Car(car.vehicle.id), AgentID::Car(car.vehicle.id),
t, t,
speed, goto.max_speed_along(
car.vehicle.max_speed,
car.vehicle.vehicle_type.to_constraints(),
ctx.map,
),
now, now,
ctx.map, ctx.map,
ctx.scheduler, ctx.scheduler,