slightly different speed limits

This commit is contained in:
Dustin Carlino 2018-08-09 13:01:47 -07:00
parent 6d70605355
commit 432c9644fc
6 changed files with 54 additions and 35 deletions

View File

@ -13,6 +13,7 @@
- better visualization
- draw moving / blocked colors (gradually more red as they wait longer)
- make lookahead buffer follow the shape of the road and extend into other lanes and stuff
- start implementing a second AORTAish driving model
- then make cars park/unpark at the correct position

View File

@ -1,3 +1,4 @@
use dimensioned::si;
use geom::PolyLine;
use std::collections::BTreeMap;
use std::fmt;
@ -135,4 +136,15 @@ impl Road {
}
panic!("{} doesn't contain {}", self.id, lane);
}
pub fn get_speed_limit(&self) -> si::MeterPerSecond<f64> {
if self.osm_tags.get("highway") == Some(&"primary".to_string())
|| self.osm_tags.get("highway") == Some(&"secondary".to_string())
{
// 40mph
return 17.8816 * si::MPS;
}
// 20mph
8.9408 * si::MPS
}
}

View File

@ -10,10 +10,7 @@ use models::{choose_turn, FOLLOWING_DISTANCE};
use multimap::MultiMap;
use ordered_float::NotNaN;
use std::collections::{BTreeMap, VecDeque};
use {
Acceleration, AgentID, CarID, CarState, Distance, InvariantViolated, On, Speed, Tick,
SPEED_LIMIT,
};
use {Acceleration, AgentID, CarID, CarState, Distance, InvariantViolated, On, Speed, Tick};
// This represents an actively driving car, not a parked one
#[derive(Clone, Serialize, Deserialize)]
@ -59,7 +56,8 @@ impl Car {
let vehicle = Vehicle::typical_car();
// TODO could wrap this state up
let mut dist_to_lookahead = vehicle.max_lookahead_dist(self.speed, SPEED_LIMIT);
let mut current_speed_limit = self.on.speed_limit(map);
let mut dist_to_lookahead = vehicle.max_lookahead_dist(self.speed, current_speed_limit);
// TODO when we add stuff here, optionally log stuff?
let mut constraints: Vec<Acceleration> = Vec::new();
let mut requests: Vec<Request> = Vec::new();
@ -77,9 +75,9 @@ impl Car {
}
// Don't exceed the speed limit
// TODO speed limit per road
{
let accel = vehicle.accel_to_achieve_speed_in_one_tick(self.speed, SPEED_LIMIT);
let accel =
vehicle.accel_to_achieve_speed_in_one_tick(self.speed, current_speed_limit);
constraints.push(accel);
if self.debug {
println!(" {} needs {} to match speed limit", self.id, accel);
@ -96,7 +94,7 @@ impl Car {
if dist_to_lookahead + FOLLOWING_DISTANCE >= dist_behind_other {
let accel = vehicle.accel_to_follow(
self.speed,
SPEED_LIMIT,
current_speed_limit,
&vehicle,
dist_behind_other,
other.speed,
@ -157,6 +155,7 @@ impl Car {
}
On::Lane(l) => On::Turn(choose_turn(&current_path, &None, l, map)),
};
current_speed_limit = current_on.speed_limit(map);
current_dist_along = 0.0 * si::M;
dist_scanned_ahead += dist_this_step;
}
@ -331,7 +330,7 @@ impl DrivingSimState {
s
}
pub fn populate_info_for_intersections(&self, info: &mut AgentInfo) {
pub fn populate_info_for_intersections(&self, info: &mut AgentInfo, _map: &Map) {
for c in self.cars.values() {
let id = AgentID::Car(c.id);
info.speeds.insert(id, c.speed);
@ -498,6 +497,7 @@ impl DrivingSimState {
_time: Tick,
car: CarID,
mut path: VecDeque<LaneID>,
_map: &Map,
) -> bool {
let start = path.pop_front().unwrap();

View File

@ -67,10 +67,6 @@ pub const TIMESTEP: Time = si::Second {
value_unsafe: 0.1,
_marker: std::marker::PhantomData,
};
pub const SPEED_LIMIT: Speed = si::MeterPerSecond {
value_unsafe: 8.9408,
_marker: std::marker::PhantomData,
};
// Represents a moment in time, not a duration/delta
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -122,14 +118,14 @@ pub(crate) enum On {
}
impl On {
pub(crate) fn as_lane(&self) -> LaneID {
pub fn as_lane(&self) -> LaneID {
match self {
&On::Lane(id) => id,
&On::Turn(_) => panic!("not a lane"),
}
}
pub(crate) fn as_turn(&self) -> TurnID {
pub fn as_turn(&self) -> TurnID {
match self {
&On::Turn(id) => id,
&On::Lane(_) => panic!("not a turn"),
@ -156,6 +152,13 @@ impl On {
&On::Turn(id) => map.get_t(id).dist_along(dist),
}
}
fn speed_limit(&self, map: &Map) -> Speed {
match self {
&On::Lane(id) => map.get_lane_and_parent(id).1.get_speed_limit(),
&On::Turn(id) => map.get_lane_and_parent(id.dst).1.get_speed_limit(),
}
}
}
pub enum CarState {

View File

@ -14,7 +14,7 @@ use map_model::{LaneID, LaneType, Map, TurnID};
use models::{choose_turn, Action, FOLLOWING_DISTANCE};
use multimap::MultiMap;
use std::collections::{BTreeMap, HashSet, VecDeque};
use {AgentID, CarID, CarState, Distance, InvariantViolated, On, Tick, SPEED_LIMIT};
use {AgentID, CarID, CarState, Distance, InvariantViolated, On, Tick};
// This represents an actively driving car, not a parked one
#[derive(Clone, Serialize, Deserialize)]
@ -51,7 +51,7 @@ impl Car {
if let Some(on) = self.waiting_for {
on
} else {
let dist = SPEED_LIMIT * (time - self.started_at).as_time();
let dist = self.on.speed_limit(map) * (time - self.started_at).as_time();
if dist < self.on.length(map) {
return Action::Continue;
}
@ -71,8 +71,8 @@ impl Car {
// Can we actually go there right now?
// In a more detailed driving model, this would do things like lookahead.
let has_room_now = match desired_on {
On::Lane(id) => sim.lanes[id.0].room_at_end(time, &sim.cars),
On::Turn(id) => sim.turns[&id].room_at_end(time, &sim.cars),
On::Lane(id) => sim.lanes[id.0].room_at_end(time, &sim.cars, map),
On::Turn(id) => sim.turns[&id].room_at_end(time, &sim.cars, map),
};
let is_lead_vehicle = match self.on {
On::Lane(id) => sim.lanes[id.0].cars_queue[0] == self.id,
@ -115,7 +115,7 @@ impl Car {
// Returns the angle and the dist along the lane/turn too
fn get_best_case_pos(&self, time: Tick, map: &Map) -> (Pt2D, Angle, Distance) {
let mut dist = SPEED_LIMIT * (time - self.started_at).as_time();
let mut dist = self.on.speed_limit(map) * (time - self.started_at).as_time();
if self.waiting_for.is_some() {
dist = self.on.length(map);
}
@ -143,7 +143,7 @@ impl SimQueue {
// TODO it'd be cool to contribute tooltips (like number of cars currently here, capacity) to
// tooltip
fn room_at_end(&self, time: Tick, cars: &BTreeMap<CarID, Car>) -> bool {
fn room_at_end(&self, time: Tick, cars: &BTreeMap<CarID, Car>, map: &Map) -> bool {
if self.cars_queue.is_empty() {
return true;
}
@ -154,13 +154,14 @@ impl SimQueue {
// isn't filled, then we know for sure that there's room, because in this model, we assume
// none of the cars just arbitrarily slow down or stop without reason.
(time - cars[self.cars_queue.last().unwrap()].started_at).as_time()
>= FOLLOWING_DISTANCE / SPEED_LIMIT
>= FOLLOWING_DISTANCE / self.id.speed_limit(map)
}
fn reset(
&mut self,
ids: &Vec<CarID>,
cars: &BTreeMap<CarID, Car>,
map: &Map,
) -> Result<(), InvariantViolated> {
let old_queue = self.cars_queue.clone();
@ -170,7 +171,7 @@ impl SimQueue {
self.cars_queue.sort_by_key(|id| cars[id].started_at);
// assert here we're not squished together too much
let min_dt = FOLLOWING_DISTANCE / SPEED_LIMIT;
let min_dt = FOLLOWING_DISTANCE / self.id.speed_limit(map);
for slice in self.cars_queue.windows(2) {
let (c1, c2) = (slice[0], slice[1]);
let (t1, t2) = (
@ -196,7 +197,7 @@ impl SimQueue {
}
// TODO base this on actual speed ;)
let stopping_dist = Vehicle::typical_car().stopping_distance(SPEED_LIMIT);
let stopping_dist = Vehicle::typical_car().stopping_distance(self.id.speed_limit(map));
let mut results = Vec::new();
let (pos1, angle1, dist_along1) =
@ -277,7 +278,7 @@ impl DrivingSimState {
s
}
pub fn populate_info_for_intersections(&self, info: &mut AgentInfo) {
pub fn populate_info_for_intersections(&self, info: &mut AgentInfo, map: &Map) {
for c in self.cars.values() {
let id = AgentID::Car(c.id);
info.speeds.insert(
@ -285,7 +286,7 @@ impl DrivingSimState {
if c.waiting_for.is_some() {
0.0 * si::MPS
} else {
SPEED_LIMIT
c.on.speed_limit(map)
},
);
info.leaders.insert(id);
@ -433,17 +434,17 @@ impl DrivingSimState {
// Reset all queues
for l in &mut self.lanes {
if let Some(v) = cars_per_lane.get_vec(&l.id.as_lane()) {
l.reset(v, &self.cars)?;
l.reset(v, &self.cars, map)?;
} else {
l.reset(&Vec::new(), &self.cars)?;
l.reset(&Vec::new(), &self.cars, map)?;
}
//l.reset(cars_per_lane.get_vec(&l.id).unwrap_or_else(|| &Vec::new()), &self.cars);
}
for t in self.turns.values_mut() {
if let Some(v) = cars_per_turn.get_vec(&t.id.as_turn()) {
t.reset(v, &self.cars)?;
t.reset(v, &self.cars, map)?;
} else {
t.reset(&Vec::new(), &self.cars)?;
t.reset(&Vec::new(), &self.cars, map)?;
}
}
@ -459,10 +460,11 @@ impl DrivingSimState {
time: Tick,
car: CarID,
mut path: VecDeque<LaneID>,
map: &Map,
) -> bool {
let start = path.pop_front().unwrap();
if !self.lanes[start.0].room_at_end(time, &self.cars) {
if !self.lanes[start.0].room_at_end(time, &self.cars, map) {
// TODO car should enter Unparking state and wait for room
println!("No room for {} to start driving on {}", car, start);
return false;

View File

@ -76,7 +76,7 @@ macro_rules! delegate {
}
impl DrivingModel {
delegate!(fn populate_info_for_intersections(&self, info: &mut AgentInfo));
delegate!(fn populate_info_for_intersections(&self, info: &mut AgentInfo, map: &Map));
delegate!(fn get_car_state(&self, c: CarID) -> CarState);
delegate!(fn get_active_and_waiting_count(&self) -> (usize, usize));
delegate!(fn tooltip_lines(&self, id: CarID) -> Option<Vec<String>>);
@ -90,7 +90,8 @@ impl DrivingModel {
&mut self,
time: Tick,
car: CarID,
path: VecDeque<LaneID>
path: VecDeque<LaneID>,
map: &Map
) -> bool);
delegate!(fn get_empty_lanes(&self, map: &Map) -> Vec<LaneID>);
delegate!(fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCar>);
@ -226,7 +227,7 @@ impl Sim {
{
if let Some(car) = self.parking_state.get_last_parked_car(parking_lane) {
if self.driving_state
.start_car_on_lane(self.time, car, VecDeque::from(steps))
.start_car_on_lane(self.time, car, VecDeque::from(steps), map)
{
self.parking_state.remove_last_parked_car(parking_lane, car);
return true;
@ -343,7 +344,7 @@ impl Sim {
leaders: HashSet::new(),
};
self.driving_state
.populate_info_for_intersections(&mut info);
.populate_info_for_intersections(&mut info, map);
self.walking_state
.populate_info_for_intersections(&mut info);