mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
ah, there are speeds low enough to round off to zero distance when applied with the timestep. systematically get rid of EPSILON_SPEED.
This commit is contained in:
parent
bfd0465a3d
commit
7b045146da
@ -1,4 +1,4 @@
|
||||
use crate::trim_f64;
|
||||
use crate::{trim_f64, EPSILON_DIST};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{cmp, f64, fmt, ops};
|
||||
|
||||
@ -207,6 +207,12 @@ pub struct Speed(f64);
|
||||
impl Speed {
|
||||
pub const ZERO: Speed = Speed::const_meters_per_second(0.0);
|
||||
|
||||
// Is a speed effectively zero based on the timestep?
|
||||
// TODO Probably better to tweak the rounding so that uselessly tiny speeds round to 0.
|
||||
pub fn is_zero(self, timestep: Duration) -> bool {
|
||||
self * timestep <= EPSILON_DIST
|
||||
}
|
||||
|
||||
pub fn meters_per_second(value: f64) -> Speed {
|
||||
if !value.is_finite() {
|
||||
panic!("Bad Speed {}", value);
|
||||
|
@ -7,7 +7,7 @@ use crate::transit::TransitSimState;
|
||||
use crate::view::{AgentView, WorldView};
|
||||
use crate::{
|
||||
AgentID, CarID, CarState, DrawCarInput, Event, ParkedCar, ParkingSpot, Tick, TripID,
|
||||
VehicleType,
|
||||
VehicleType, TIMESTEP,
|
||||
};
|
||||
use abstutil;
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
|
||||
@ -97,7 +97,7 @@ impl Car {
|
||||
) -> Result<Action, Error> {
|
||||
if self.parking.is_some() {
|
||||
// TODO right place for this check?
|
||||
assert!(self.speed <= kinematics::EPSILON_SPEED);
|
||||
assert!(self.speed.is_zero(TIMESTEP));
|
||||
return Ok(Action::WorkOnParking);
|
||||
}
|
||||
|
||||
@ -377,9 +377,8 @@ impl Car {
|
||||
if self.dist_along > dist {
|
||||
panic!("{} overshot! Wanted to stop at {} along {}, but at {}. Speed is {}. This last step, they chose {}, with their max being {}, and consequently traveled {}", self.id, dist, lane, self.dist_along, self.speed, accel, self.vehicle.max_deaccel, dist_traveled);
|
||||
}
|
||||
if self.dist_along == dist && self.speed > Speed::ZERO {
|
||||
// TODO Don't panic, because some other car did this with no consequence...
|
||||
error!("{} stopped right where they want to, but with a final speed of {}. This last step, they chose {}, with their max being {}", self.id, self.speed, accel, self.vehicle.max_deaccel);
|
||||
if self.dist_along == dist && !self.speed.is_zero(TIMESTEP) {
|
||||
panic!("{} stopped right where they want to, but with a final speed of {}. This last step, they chose {}, with their max being {}", self.id, self.speed, accel, self.vehicle.max_deaccel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -538,7 +537,7 @@ impl DrivingSimState {
|
||||
let waiting = self
|
||||
.cars
|
||||
.values()
|
||||
.filter(|c| c.speed <= kinematics::EPSILON_SPEED)
|
||||
.filter(|c| c.speed.is_zero(TIMESTEP))
|
||||
.count();
|
||||
(waiting, self.cars.len())
|
||||
}
|
||||
@ -906,10 +905,10 @@ impl DrivingSimState {
|
||||
),
|
||||
state: if c.debug {
|
||||
CarState::Debug
|
||||
} else if c.speed > kinematics::EPSILON_SPEED {
|
||||
CarState::Moving
|
||||
} else {
|
||||
} else if c.speed.is_zero(TIMESTEP) {
|
||||
CarState::Stuck
|
||||
} else {
|
||||
CarState::Moving
|
||||
},
|
||||
vehicle_type: c.vehicle.vehicle_type,
|
||||
on: c.on,
|
||||
@ -978,7 +977,7 @@ impl DrivingSimState {
|
||||
if let Some(queue) = self.queues.get(&Traversable::Lane(*l)) {
|
||||
for (_, car) in &queue.cars_queue {
|
||||
let c = &self.cars[car];
|
||||
if c.speed <= kinematics::EPSILON_SPEED {
|
||||
if c.speed.is_zero(TIMESTEP) {
|
||||
stuck_cars += 1;
|
||||
} else {
|
||||
moving_cars += 1;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::kinematics;
|
||||
use crate::view::WorldView;
|
||||
use crate::{AgentID, CarID, Event, PedestrianID, Tick};
|
||||
use crate::{AgentID, CarID, Event, PedestrianID, Tick, TIMESTEP};
|
||||
use abstutil;
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
|
||||
use geom::Duration;
|
||||
@ -257,7 +256,7 @@ impl StopSign {
|
||||
let should_promote = if ss.get_priority(req.turn) == TurnPriority::Stop {
|
||||
// TODO and the agent is at the end? maybe easier than looking at their speed
|
||||
// TODO with lane-changing, somebody could cut in front of them when they're stopped.
|
||||
view.get_speed(req.agent) <= kinematics::EPSILON_SPEED
|
||||
view.get_speed(req.agent).is_zero(TIMESTEP)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
@ -6,8 +6,6 @@ use rand::Rng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
pub const EPSILON_SPEED: Speed = Speed::const_meters_per_second(0.000_1);
|
||||
|
||||
// http://pccsc.net/bicycle-parking-info/ says 68 inches, which is 1.73m
|
||||
const MIN_BIKE_LENGTH: Distance = Distance::const_meters(1.7);
|
||||
const MAX_BIKE_LENGTH: Distance = Distance::const_meters(2.0);
|
||||
@ -308,13 +306,14 @@ pub fn results_of_accel_for_one_tick(
|
||||
* (actual_time.inner_seconds() * actual_time.inner_seconds()),
|
||||
);
|
||||
assert_ge!(dist, Distance::ZERO);
|
||||
let mut new_speed = initial_speed + (accel * actual_time);
|
||||
// Handle some floating point imprecision
|
||||
if new_speed < Speed::ZERO && new_speed >= EPSILON_SPEED * -1.0 {
|
||||
new_speed = Speed::ZERO;
|
||||
let new_speed = initial_speed + (accel * actual_time);
|
||||
// Deal with floating point imprecision.
|
||||
if new_speed < Speed::ZERO && new_speed.is_zero(TIMESTEP) {
|
||||
(dist, Speed::ZERO)
|
||||
} else {
|
||||
assert_ge!(new_speed, Speed::ZERO);
|
||||
(dist, new_speed)
|
||||
}
|
||||
assert_ge!(new_speed, Speed::ZERO);
|
||||
(dist, new_speed)
|
||||
}
|
||||
|
||||
fn accel_to_cover_dist_in_one_tick(dist: Distance, speed: Speed) -> Acceleration {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::driving::{Action, Intent};
|
||||
use crate::kinematics;
|
||||
use crate::kinematics::Vehicle;
|
||||
use crate::parking::ParkingSimState;
|
||||
use crate::transit::TransitSimState;
|
||||
use crate::view::AgentView;
|
||||
use crate::TIMESTEP;
|
||||
use crate::{Event, ParkingSpot, Tick};
|
||||
use geom::{Acceleration, Distance, EPSILON_DIST};
|
||||
use map_model::{
|
||||
@ -78,7 +78,7 @@ impl Router {
|
||||
transit_sim: &mut TransitSimState,
|
||||
rng: &mut XorShiftRng,
|
||||
) -> Option<Action> {
|
||||
if self.path.isnt_last_step() || view.speed > kinematics::EPSILON_SPEED {
|
||||
if self.path.isnt_last_step() || !view.speed.is_zero(TIMESTEP) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::runner::TestRunner;
|
||||
use geom::{Distance, Speed, EPSILON_DIST};
|
||||
use sim::kinematics::{results_of_accel_for_one_tick, Vehicle, EPSILON_SPEED};
|
||||
use sim::Tick;
|
||||
use sim::kinematics::{results_of_accel_for_one_tick, Vehicle};
|
||||
use sim::{Tick, TIMESTEP};
|
||||
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
pub fn run(t: &mut TestRunner) {
|
||||
@ -86,7 +86,7 @@ fn test_accel_to_stop_in_dist(vehicle: Vehicle, orig_dist_left: Distance, orig_s
|
||||
}
|
||||
if dist_left <= EPSILON_DIST {
|
||||
println!(" Result: speed {}, dist_left {}", speed, dist_left);
|
||||
if speed > EPSILON_SPEED {
|
||||
if !speed.is_zero(TIMESTEP) {
|
||||
panic!("Finished, but going too fast");
|
||||
}
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user