constructing traces way more directly. still broken for peds. :(

This commit is contained in:
Dustin Carlino 2018-10-09 15:19:27 -07:00
parent 88ac5267d2
commit dcbf373896
11 changed files with 113 additions and 96 deletions

View File

@ -41,3 +41,10 @@ if we're looking at turns from a road that's a sidewalk, bake in some extra logi
most reasonable sidewalk cases, this is true. Don't need to model more
detailed movement. As a consequence of this, crosswalk turns never conflict.
Assume people can weave.
## Cost of contraflow
Either duplicate sidewalks in both directions (extra rendering and memory, etc)
or have complicated turns and contraflow logic. Making trace_route is example
of time wasted on contraflow mess. Maybe having two directional sides of a
sidewalk is nice anyway?

View File

@ -1,11 +1,11 @@
use colors::{ColorScheme, Colors};
use dimensioned::si;
use ezgui::{GfxCtx, UserInput};
use map_model::{Map, Trace, LANE_THICKNESS};
use map_model::{Map, LANE_THICKNESS};
use objects::ID;
use piston::input::Key;
use plugins::Colorizer;
use sim::{AgentID, Sim};
use sim::{AgentID, Sim, Trace};
use std::f64;
pub enum ShowRouteState {
@ -48,13 +48,10 @@ impl ShowRouteState {
}
};
if let Some(agent) = maybe_agent {
match sim.get_current_route(agent, map) {
Some((route, dist_along)) => {
// Trace along the entire route by passing in max distance
*self = ShowRouteState::Active(
agent,
Trace::new(dist_along, &route, f64::MAX * si::M, map),
);
// Trace along the entire route by passing in max distance
match sim.trace_route(agent, map, f64::MAX * si::M) {
Some(trace) => {
*self = ShowRouteState::Active(agent, trace);
}
None => {
*self = ShowRouteState::Empty;
@ -74,7 +71,7 @@ impl ShowRouteState {
if let ShowRouteState::Active(_, trace) = self {
g.draw_polygon(
cs.get(Colors::Queued),
&trace.polyline.make_polygons_blindly(LANE_THICKNESS),
&trace.make_polygons_blindly(LANE_THICKNESS),
);
}
}

View File

@ -32,7 +32,7 @@ impl DrawCar {
let stopping_buffer = input
.stopping_trace
.map(|t| t.polyline.make_polygons_blindly(CAR_WIDTH));
.map(|t| t.make_polygons_blindly(CAR_WIDTH));
let front_window_length_gap = 0.2;
let front_window_thickness = 0.3;

View File

@ -29,7 +29,6 @@ mod parcel;
mod pathfind;
pub mod raw_data;
mod road;
mod trace;
mod traversable;
mod turn;
@ -43,7 +42,6 @@ pub use map::Map;
pub use parcel::{Parcel, ParcelID};
pub use pathfind::Pathfinder;
pub use road::{Road, RoadID};
pub use trace::Trace;
pub use traversable::Traversable;
pub use turn::{Turn, TurnID};

View File

@ -1,37 +0,0 @@
use dimensioned::si;
use geom::PolyLine;
use {Map, Traversable};
pub struct Trace {
// The rendered form
pub polyline: PolyLine,
}
impl Trace {
pub fn new(
start_dist_along: si::Meter<f64>,
// Starting with the current traversable
route: &Vec<Traversable>,
length: si::Meter<f64>,
map: &Map,
) -> Trace {
assert!(!route.is_empty());
// TODO Assuming we can't ever be called while on a 0-length turn
let (mut result, mut dist_left) = route[0]
.slice(map, start_dist_along, start_dist_along + length)
.unwrap();
let mut idx = 1;
while dist_left > 0.0 * si::M && idx < route.len() {
if let Some((piece, new_dist_left)) = route[idx].slice(map, 0.0 * si::M, dist_left) {
result.extend(piece);
dist_left = new_dist_left;
}
idx += 1;
}
// Excess dist_left is just ignored
Trace { polyline: result }
}
}

View File

@ -49,13 +49,19 @@ impl Traversable {
// Returns None if the traversable is actually 0 length, as some turns are.
pub fn slice(
&self,
reverse: bool,
map: &Map,
start: si::Meter<f64>,
end: si::Meter<f64>,
) -> Option<(PolyLine, si::Meter<f64>)> {
match self {
&Traversable::Lane(id) => Some(map.get_l(id).lane_center_pts.slice(start, end)),
&Traversable::Lane(id) => if reverse {
Some(map.get_l(id).lane_center_pts.reversed().slice(start, end))
} else {
Some(map.get_l(id).lane_center_pts.slice(start, end))
},
&Traversable::Turn(id) => {
assert!(!reverse);
let t = map.get_t(id);
if t.line.length() <= EPSILON_DIST {
None

View File

@ -6,7 +6,7 @@ use geom::EPSILON_DIST;
use intersections::{IntersectionSimState, Request};
use kinematics;
use kinematics::Vehicle;
use map_model::{LaneID, Map, Trace, Traversable, TurnID, LANE_THICKNESS};
use map_model::{LaneID, Map, Traversable, TurnID, LANE_THICKNESS};
use multimap::MultiMap;
use ordered_float::NotNaN;
use parking::ParkingSimState;
@ -18,7 +18,7 @@ use transit::TransitSimState;
use view::{AgentView, WorldView};
use {
Acceleration, AgentID, CarID, CarState, Distance, DrawCarInput, Event, InvariantViolated,
ParkedCar, ParkingSpot, Speed, Tick, Time,
ParkedCar, ParkingSpot, Speed, Tick, Time, Trace,
};
const TIME_TO_PARK_OR_DEPART: Time = si::Second {
@ -769,21 +769,13 @@ impl DrivingSimState {
base_pos
};
let stopping_dist = c.vehicle.stopping_distance(c.speed);
let stopping_trace = if stopping_dist <= EPSILON_DIST {
None
} else {
let (route, dist_along) = self.get_current_route(id, map).unwrap();
Some(Trace::new(dist_along, &route, stopping_dist, map))
};
Some(DrawCarInput {
id: c.id,
vehicle_length: c.vehicle.length,
waiting_for_turn: c.waiting_for.and_then(|on| on.maybe_turn()),
front: pos,
angle,
stopping_trace,
stopping_trace: self.trace_route(id, map, c.vehicle.stopping_distance(c.speed)),
})
}
@ -817,9 +809,12 @@ impl DrivingSimState {
}
}
pub fn get_current_route(&self, id: CarID, map: &Map) -> Option<(Vec<Traversable>, Distance)> {
pub fn trace_route(&self, id: CarID, map: &Map, dist_ahead: Distance) -> Option<Trace> {
if dist_ahead <= EPSILON_DIST {
return None;
}
let r = self.routers.get(&id)?;
let c = &self.cars[&id];
Some((r.get_current_route(c.on, map), c.dist_along))
Some(r.trace_route(c.on, c.dist_along, map, dist_ahead))
}
}

View File

@ -57,10 +57,10 @@ use abstutil::Cloneable;
use dimensioned::si;
pub use edits::MapEdits;
pub use events::Event;
use geom::{Angle, Pt2D};
use geom::{Angle, PolyLine, Pt2D};
pub use helpers::{load, SimFlags};
pub use instrument::save_backtraces;
use map_model::{LaneID, Trace, TurnID};
use map_model::{LaneID, TurnID};
pub use scenario::{Neighborhood, Scenario, SeedParkedCars, SpawnOverTime};
pub use sim::{Benchmark, Sim};
use std::fmt;
@ -338,3 +338,5 @@ impl Cloneable for Scenario {}
impl Cloneable for Tick {}
impl Cloneable for MapEdits {}
impl Cloneable for ABTest {}
pub type Trace = PolyLine;

View File

@ -8,7 +8,7 @@ use rand::Rng;
use std::collections::VecDeque;
use transit::TransitSimState;
use view::AgentView;
use {Distance, Event, ParkingSpot, Tick};
use {Distance, Event, ParkingSpot, Tick, Trace};
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
enum Goal {
@ -160,18 +160,48 @@ impl Router {
None
}
pub fn get_current_route(&self, start: Traversable, map: &Map) -> Vec<Traversable> {
let mut route = vec![start];
pub fn trace_route(
&self,
start: Traversable,
start_dist: Distance,
map: &Map,
dist_along: Distance,
) -> Trace {
// TODO Assuming we can't ever be called while on a 0-length turn
let (mut result, mut dist_left) = start
// TODO will this break if we pass in max for dist_along?
.slice(false, map, start_dist, start_dist + dist_along)
.unwrap();
let mut last_lane = start.maybe_lane();
for next in &self.path {
let mut idx = 0;
while dist_left > 0.0 * si::M && idx < self.path.len() {
let next_lane = self.path[idx];
if let Some(prev) = last_lane {
route.push(Traversable::Turn(pick_turn(prev, *next, map)));
if let Some((piece, new_dist_left)) = Traversable::Turn(pick_turn(
prev, next_lane, map,
)).slice(false, map, 0.0 * si::M, dist_left)
{
result.extend(piece);
dist_left = new_dist_left;
if dist_left <= 0.0 * si::M {
break;
}
}
}
route.push(Traversable::Lane(*next));
last_lane = Some(*next);
let (piece, new_dist_left) = Traversable::Lane(next_lane)
.slice(false, map, 0.0 * si::M, dist_left)
.unwrap();
result.extend(piece);
dist_left = new_dist_left;
last_lane = Some(next_lane);
idx += 1;
}
route
// Excess dist_left is just ignored
result
}
}

View File

@ -7,7 +7,7 @@ use driving::DrivingSimState;
use failure::Error;
use instrument::capture_backtrace;
use intersections::IntersectionSimState;
use map_model::{IntersectionID, LaneID, LaneType, Map, Traversable, Turn, TurnID};
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID};
use parking::ParkingSimState;
use rand::{FromEntropy, SeedableRng, XorShiftRng};
use spawn::Spawner;
@ -21,7 +21,7 @@ use view::WorldView;
use walking::WalkingSimState;
use {
AgentID, CarID, CarState, Distance, DrawCarInput, DrawPedestrianInput, Event, PedestrianID,
ScoreSummary, Tick, TIMESTEP,
ScoreSummary, Tick, Trace, TIMESTEP,
};
#[derive(Serialize, Deserialize, Derivative)]
@ -348,15 +348,10 @@ impl Sim {
}
}
// Also returns current distance along the first element of the route
pub fn get_current_route(
&self,
id: AgentID,
map: &Map,
) -> Option<(Vec<Traversable>, Distance)> {
pub fn trace_route(&self, id: AgentID, map: &Map, dist_ahead: Distance) -> Option<Trace> {
match id {
AgentID::Car(car) => self.driving_state.get_current_route(car, map),
AgentID::Pedestrian(ped) => self.walking_state.get_current_route(ped, map),
AgentID::Car(car) => self.driving_state.trace_route(car, map, dist_ahead),
AgentID::Pedestrian(ped) => self.walking_state.trace_route(ped, map, dist_ahead),
}
}

View File

@ -14,7 +14,7 @@ use trips::TripManager;
use view::{AgentView, WorldView};
use {
AgentID, Distance, DrawPedestrianInput, Event, InvariantViolated, ParkingSpot, PedestrianID,
Speed, Tick, Time, TIMESTEP,
Speed, Tick, Time, Trace, TIMESTEP,
};
// TODO tune these!
@ -563,24 +563,48 @@ impl WalkingSimState {
self.peds.is_empty()
}
pub fn get_current_route(
&self,
id: PedestrianID,
map: &Map,
) -> Option<(Vec<Traversable>, Distance)> {
// TODO share impl with router... contraflow is the only difference
pub fn trace_route(&self, id: PedestrianID, map: &Map, dist_ahead: Distance) -> Option<Trace> {
let p = self.peds.get(&id)?;
let mut route = vec![p.on];
// TODO Assuming we can't ever be called while on a 0-length turn
let (mut result, mut dist_left) = p.on
// TODO will this break if we pass in max for dist_along?
.slice(p.contraflow, map, p.dist_along, p.dist_along + dist_ahead)
.unwrap();
let mut last_lane = p.on.maybe_lane();
for next in &p.path {
let mut idx = 0;
while dist_left > 0.0 * si::M && idx < p.path.len() {
let next_lane = p.path[idx];
if let Some(prev) = last_lane {
route.push(Traversable::Turn(pick_turn(prev, *next, map)));
// Never contraflow on turns
if let Some((piece, new_dist_left)) = Traversable::Turn(pick_turn(
prev, next_lane, map,
)).slice(false, map, 0.0 * si::M, dist_left)
{
result.extend(piece);
dist_left = new_dist_left;
if dist_left <= 0.0 * si::M {
break;
}
}
}
route.push(Traversable::Lane(*next));
last_lane = Some(*next);
// TODO ooh this is _really_ cheating. ;)
let contraflow = *result.points().last().unwrap() != map.get_l(next_lane).first_pt();
let (piece, new_dist_left) = Traversable::Lane(next_lane)
.slice(contraflow, map, 0.0 * si::M, dist_left)
.unwrap();
result.extend(piece);
dist_left = new_dist_left;
last_lane = Some(next_lane);
idx += 1;
}
Some((route, p.dist_along))
// Excess dist_left is just ignored
Some(result)
}
pub fn get_peds_waiting_at_stop(&self, stop: BusStopID) -> Vec<PedestrianID> {