mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 20:29:04 +03:00
constructing traces way more directly. still broken for peds. :(
This commit is contained in:
parent
88ac5267d2
commit
dcbf373896
@ -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?
|
||||
|
@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
|
Loading…
Reference in New Issue
Block a user