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",
car_dt
)),
// TODO We could calculate a full path and incorporate incline
Line(format!(
" about {} for a bike",
dist_btwn / Scenario::max_bike_speed()
dist_btwn / map_model::MAX_BIKE_SPEED
)),
Line(format!(
" 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};
use crate::pathfind::Pathfinder;
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;
pub mod connectivity;

View File

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

View File

@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use thread_local::ThreadLocal;
use abstutil::MultiMap;
use geom::{Duration, Speed};
use geom::Duration;
use crate::pathfind::ch::round;
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::{
DrivingSide, Lane, LaneID, Map, Path, PathConstraints, PathRequest, PathStep, RoutingParams,
Turn, TurnID, TurnType,
Traversable, Turn, TurnID, TurnType,
};
#[derive(Serialize, Deserialize)]
@ -253,14 +253,13 @@ pub fn vehicle_cost(
t1 + t2
}
PathConstraints::Bike => {
// TODO Copied from sim. Probably move to map_model.
let max_bike_speed = Speed::miles_per_hour(10.0);
// Usually the bike's speed limit matters, not the road's.
let t1 = lane.length() / map.get_r(lane.parent).speed_limit.min(max_bike_speed);
let t2 =
turn.geom.length() / map.get_parent(turn.id.dst).speed_limit.min(max_bike_speed);
// We assume MAX_BIKE_SPEED for pathfinding.
let max_speed = Some(crate::MAX_BIKE_SPEED);
let t1 = lane.length()
/ Traversable::Lane(lane.id).max_speed_along(max_speed, constraints, map);
let t2 = turn.geom.length()
/ 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 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 crate::{LaneID, Map, TurnID};
use crate::{LaneID, Map, PathConstraints, TurnID};
/// Represents a specific point some distance along a lane.
#[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 {
match *self {
Traversable::Lane(id) => map.get_parent(id).zorder,
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(
rng,
Speed::miles_per_hour(8.0),
Scenario::max_bike_speed(),
map_model::MAX_BIKE_SPEED,
));
VehicleSpec {
vehicle_type: VehicleType::Bike,
@ -233,9 +233,6 @@ impl Scenario {
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 {
assert!(high > low);

View File

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

View File

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