mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +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",
|
" 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",
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user