basic impl of crossing entire long lane and waiting at the end

This commit is contained in:
Dustin Carlino 2019-02-07 14:17:02 -08:00
parent 409de8ea83
commit b547db43b6
3 changed files with 54 additions and 5 deletions

View File

@ -43,9 +43,11 @@
## Discrete-event model
- make space toggle play for time travel or sim or simple model
- Make cars cover an entire lane when it's short or long
- avoid impossible accel/deaccel
- Handle lead car being faster
- The speed stated in the middle of intervals is clearly wrong for the follower car
- Prototype alternate driving model
- branch or forked code?

View File

@ -1,5 +1,5 @@
use geom::{Acceleration, Distance, Duration, Speed};
use map_model::{LaneID, Map, Traversable};
use map_model::{Lane, LaneID, Map, Traversable};
use sim::{CarID, CarState, DrawCarInput, VehicleType};
const FOLLOWING_DISTANCE: Distance = Distance::const_meters(1.0);
@ -24,9 +24,11 @@ impl World {
start_dist: Distance::meters(5.0),
start_time: Duration::ZERO,
};
leader.accel_from_rest_to_speed_limit(0.5 * speed_limit);
leader.stop_at_end_of_lane(lane, 0.5 * speed_limit);
/*leader.accel_from_rest_to_speed_limit(0.5 * speed_limit);
leader.freeflow(Duration::seconds(10.0));
leader.deaccel_to_rest();
leader.deaccel_to_rest();*/
leader.wait(Duration::seconds(5.0));
let mut follower = Car {
id: CarID::tmp_new(1, VehicleType::Car),
@ -125,7 +127,7 @@ impl Interval {
) -> Interval {
assert!(start_dist >= Distance::ZERO);
assert!(start_time >= Duration::ZERO);
assert!(start_dist < end_dist);
assert!(start_dist <= end_dist);
assert!(start_time < end_time);
assert!(start_speed >= Speed::ZERO);
assert!(end_speed >= Speed::ZERO);
@ -311,6 +313,13 @@ impl Car {
self.next_state(speed * time, speed, time);
}
fn freeflow_to_cross(&mut self, dist: Distance) {
let speed = self.last_state().1;
assert_ne!(dist, Distance::ZERO);
self.next_state(dist, speed, dist / speed);
}
fn deaccel_to_rest(&mut self) {
let speed = self.last_state().1;
assert_ne!(speed, Speed::ZERO);
@ -328,6 +337,16 @@ impl Car {
self.next_state(dist_covered, Speed::ZERO, time_needed);
}
fn stopping_distance(&self, from_speed: Speed) -> Distance {
// TODO Copies partly from deaccel_to_rest
let time_needed = -from_speed / self.max_deaccel;
from_speed * time_needed
+ Distance::meters(
0.5 * self.max_deaccel.inner_meters_per_second_squared()
* time_needed.inner_seconds().powi(2),
)
}
// Returns interval indices too.
fn find_earliest_hit(&self, other: &Car) -> Option<(Duration, Distance, usize, usize)> {
// TODO Do we ever have to worry about having the same intervals? I think this should
@ -360,7 +379,7 @@ impl Car {
self.intervals.split_off(idx1 + 1);
// Option 1: Might be too sharp.
if false {
if true {
{
let mut our_adjusted_last = self.intervals.pop().unwrap();
our_adjusted_last.end_speed = our_adjusted_last.speed(hit_time);
@ -429,6 +448,23 @@ impl Car {
}
}
}
fn stop_at_end_of_lane(&mut self, lane: &Lane, speed_limit: Speed) {
// TODO Argh, this code is awkward.
// TODO Handle shorter lanes.
self.accel_from_rest_to_speed_limit(speed_limit);
let stopping_dist = self.stopping_distance(speed_limit);
self.freeflow_to_cross(
lane.length() - self.intervals.last().as_ref().unwrap().end_dist - stopping_dist,
);
self.deaccel_to_rest();
}
fn wait(&mut self, time: Duration) {
let speed = self.last_state().1;
assert_eq!(speed, Speed::ZERO);
self.next_state(Distance::ZERO, Speed::ZERO, time);
}
}
fn overlap<A: PartialOrd>((a_start, a_end): (A, A), (b_start, b_end): (A, A)) -> bool {

View File

@ -137,6 +137,17 @@ impl ops::Div<f64> for Distance {
}
}
impl ops::Div<Speed> for Distance {
type Output = Duration;
fn div(self, other: Speed) -> Duration {
if other == Speed::ZERO {
panic!("Can't divide {} / {}", self, other);
}
Duration::seconds(self.0 / other.0)
}
}
// In seconds. Can be negative.
// TODO Naming is awkward. Can represent a moment in time or a duration.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]