making trace handle lanes and turns

This commit is contained in:
Dustin Carlino 2018-10-09 13:10:24 -07:00
parent d3e5fdb7c4
commit 2716a2272b
8 changed files with 82 additions and 35 deletions

View File

@ -1,6 +1,6 @@
use colors::Colors; use colors::Colors;
use ezgui::{Color, UserInput}; use ezgui::{Color, UserInput};
use map_model::LaneID; use map_model::{LaneID, Map};
use objects::{Ctx, ID}; use objects::{Ctx, ID};
use piston::input::Key; use piston::input::Key;
use plugins::Colorizer; use plugins::Colorizer;
@ -14,7 +14,13 @@ pub enum ShowRouteState {
} }
impl ShowRouteState { impl ShowRouteState {
pub fn event(&mut self, input: &mut UserInput, sim: &Sim, selected: Option<ID>) -> bool { pub fn event(
&mut self,
input: &mut UserInput,
sim: &Sim,
map: &Map,
selected: Option<ID>,
) -> bool {
if *self == ShowRouteState::Empty { if *self == ShowRouteState::Empty {
match selected { match selected {
Some(ID::Car(id)) => { Some(ID::Car(id)) => {
@ -39,10 +45,14 @@ impl ShowRouteState {
if input.key_pressed(Key::Return, "stop showing route") { if input.key_pressed(Key::Return, "stop showing route") {
true true
} else { } else {
match sim.get_current_route(*agent) { match sim.get_current_route(*agent, map) {
Some(route) => { Some(route) => {
lanes.clear(); lanes.clear();
lanes.extend(route); for tr in &route {
if let Some(l) = tr.maybe_lane() {
lanes.insert(l);
}
}
false false
} }
None => true, None => true,

View File

@ -164,6 +164,7 @@ impl UIWrapper {
ctx.ui.primary.show_route.event( ctx.ui.primary.show_route.event(
ctx.input, ctx.input,
&ctx.ui.primary.sim, &ctx.ui.primary.sim,
&ctx.ui.primary.map,
ctx.ui.primary.current_selection, ctx.ui.primary.current_selection,
) )
}), }),

View File

@ -1,6 +1,6 @@
use dimensioned::si; use dimensioned::si;
use geom::PolyLine; use geom::PolyLine;
use {LaneID, Map}; use {Map, Traversable};
pub struct Trace { pub struct Trace {
// The rendered form // The rendered form
@ -8,27 +8,21 @@ pub struct Trace {
} }
impl Trace { impl Trace {
// TODO what about when the route is empty and the caller is at the end?
// TODO what about turns?
pub fn new( pub fn new(
start_dist_along: si::Meter<f64>, start_dist_along: si::Meter<f64>,
route: &Vec<LaneID>, // Starting with the current traversable
route: &Vec<Traversable>,
length: si::Meter<f64>, length: si::Meter<f64>,
map: &Map, map: &Map,
) -> Trace { ) -> Trace {
assert!(!route.is_empty()); assert!(!route.is_empty());
let (mut result, mut dist_left) = map let (mut result, mut dist_left) =
.get_l(route[0]) route[0].slice(map, start_dist_along, start_dist_along + length);
.lane_center_pts
.slice(start_dist_along, start_dist_along + length);
let mut idx = 1; let mut idx = 1;
while dist_left > 0.0 * si::M && idx < route.len() { while dist_left > 0.0 * si::M && idx < route.len() {
let (piece, new_dist_left) = map let (piece, new_dist_left) = route[idx].slice(map, 0.0 * si::M, dist_left);
.get_l(route[idx])
.lane_center_pts
.slice(0.0 * si::M, dist_left);
result.extend(piece); result.extend(piece);
dist_left = new_dist_left; dist_left = new_dist_left;

View File

@ -1,5 +1,5 @@
use dimensioned::si; use dimensioned::si;
use geom::{Angle, Pt2D}; use geom::{Angle, PolyLine, Pt2D};
use {LaneID, Map, TurnID}; use {LaneID, Map, TurnID};
// TODO also building paths? // TODO also building paths?
@ -31,6 +31,14 @@ impl Traversable {
} }
} }
pub fn maybe_lane(&self) -> Option<LaneID> {
match self {
&Traversable::Turn(_) => None,
&Traversable::Lane(id) => Some(id),
}
}
// TODO Just expose the PolyLine instead of all these layers of helpers
pub fn length(&self, map: &Map) -> si::Meter<f64> { pub fn length(&self, map: &Map) -> si::Meter<f64> {
match self { match self {
&Traversable::Lane(id) => map.get_l(id).length(), &Traversable::Lane(id) => map.get_l(id).length(),
@ -38,6 +46,21 @@ impl Traversable {
} }
} }
pub fn slice(
&self,
map: &Map,
start: si::Meter<f64>,
end: si::Meter<f64>,
) -> (PolyLine, si::Meter<f64>) {
match self {
&Traversable::Lane(id) => map.get_l(id).lane_center_pts.slice(start, end),
&Traversable::Turn(id) => {
let t = map.get_t(id);
PolyLine::new(vec![t.line.pt1(), t.line.pt2()]).slice(start, end)
}
}
}
pub fn dist_along(&self, dist: si::Meter<f64>, map: &Map) -> (Pt2D, Angle) { pub fn dist_along(&self, dist: si::Meter<f64>, map: &Map) -> (Pt2D, Angle) {
match self { match self {
&Traversable::Lane(id) => map.get_l(id).dist_along(dist), &Traversable::Lane(id) => map.get_l(id).dist_along(dist),

View File

@ -776,7 +776,7 @@ impl DrivingSimState {
// TODO amend the route? // TODO amend the route?
Some(Trace::new( Some(Trace::new(
c.dist_along, c.dist_along,
&self.get_current_route(id).unwrap(), &self.get_current_route(id, map).unwrap(),
stopping_dist, stopping_dist,
map, map,
)) ))
@ -822,7 +822,8 @@ impl DrivingSimState {
} }
} }
pub fn get_current_route(&self, id: CarID) -> Option<Vec<LaneID>> { pub fn get_current_route(&self, id: CarID, map: &Map) -> Option<Vec<Traversable>> {
self.routers.get(&id).map(|r| r.get_current_route()) let r = self.routers.get(&id)?;
Some(r.get_current_route(self.cars[&id].on, map))
} }
} }

View File

@ -124,12 +124,7 @@ impl Router {
} }
pub fn choose_turn(&self, from: LaneID, map: &Map) -> TurnID { pub fn choose_turn(&self, from: LaneID, map: &Map) -> TurnID {
for t in map.get_turns_from_lane(from) { pick_turn(from, self.path[0], map)
if t.dst == self.path[0] {
return t.id;
}
}
panic!("No turn from {} to {}", from, self.path[0]);
} }
pub fn advance_to(&mut self, next_lane: LaneID) { pub fn advance_to(&mut self, next_lane: LaneID) {
@ -165,8 +160,18 @@ impl Router {
None None
} }
pub fn get_current_route(&self) -> Vec<LaneID> { pub fn get_current_route(&self, start: Traversable, map: &Map) -> Vec<Traversable> {
self.path.iter().map(|id| *id).collect() let mut route = vec![start];
let mut last_lane = start.maybe_lane();
for next in &self.path {
if let Some(prev) = last_lane {
route.push(Traversable::Turn(pick_turn(prev, *next, map)));
}
route.push(Traversable::Lane(*next));
last_lane = Some(*next);
}
route
} }
} }
@ -180,3 +185,12 @@ fn find_parking_spot(
.find_parking_lane(driving_lane) .find_parking_lane(driving_lane)
.and_then(|l| parking_sim.get_first_free_spot(l, dist_along)) .and_then(|l| parking_sim.get_first_free_spot(l, dist_along))
} }
fn pick_turn(from: LaneID, to: LaneID, map: &Map) -> TurnID {
for t in map.get_turns_from_lane(from) {
if t.dst == to {
return t.id;
}
}
panic!("No turn from {} to {}", from, to);
}

View File

@ -7,7 +7,7 @@ use driving::DrivingSimState;
use failure::Error; use failure::Error;
use instrument::capture_backtrace; use instrument::capture_backtrace;
use intersections::IntersectionSimState; use intersections::IntersectionSimState;
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID}; use map_model::{IntersectionID, LaneID, LaneType, Map, Traversable, Turn, TurnID};
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::{FromEntropy, SeedableRng, XorShiftRng}; use rand::{FromEntropy, SeedableRng, XorShiftRng};
use spawn::Spawner; use spawn::Spawner;
@ -348,9 +348,9 @@ impl Sim {
} }
} }
pub fn get_current_route(&self, id: AgentID) -> Option<Vec<LaneID>> { pub fn get_current_route(&self, id: AgentID, map: &Map) -> Option<Vec<Traversable>> {
match id { match id {
AgentID::Car(car) => self.driving_state.get_current_route(car), AgentID::Car(car) => self.driving_state.get_current_route(car, map),
AgentID::Pedestrian(ped) => self.walking_state.get_current_route(ped), AgentID::Pedestrian(ped) => self.walking_state.get_current_route(ped),
} }
} }

View File

@ -577,10 +577,14 @@ impl WalkingSimState {
self.peds.is_empty() self.peds.is_empty()
} }
pub fn get_current_route(&self, id: PedestrianID) -> Option<Vec<LaneID>> { pub fn get_current_route(&self, id: PedestrianID) -> Option<Vec<Traversable>> {
self.peds // TODO turns. will be hard because of contraflow.
.get(&id) let p = self.peds.get(&id)?;
.map(|p| p.path.iter().map(|id| *id).collect()) let mut route = vec![p.on];
for l in &p.path {
route.push(Traversable::Lane(*l));
}
Some(route)
} }
pub fn get_peds_waiting_at_stop(&self, stop: BusStopID) -> Vec<PedestrianID> { pub fn get_peds_waiting_at_stop(&self, stop: BusStopID) -> Vec<PedestrianID> {