mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
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:
parent
3c601b50c1
commit
892afddcd5
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user