mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 04:35:51 +03:00
will start/stop directly in front of a building driveway, when possible. still need to handle the case when the bikeable position isn't connected to most to the graph (for buildings accessible only by footway and for things around the border)
This commit is contained in:
parent
d22aa87139
commit
5c506f726c
@ -509,57 +509,6 @@ impl Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Refactor and also use a different blackhole measure
|
|
||||||
pub fn find_biking_lane_near_building(&self, b: BuildingID) -> LaneID {
|
|
||||||
if let Ok(l) = self.find_closest_lane(self.get_b(b).sidewalk(), vec![LaneType::Biking]) {
|
|
||||||
return self.get_l(l).parking_blackhole.unwrap_or(l);
|
|
||||||
}
|
|
||||||
if let Ok(l) = self.find_closest_lane(self.get_b(b).sidewalk(), vec![LaneType::Driving]) {
|
|
||||||
return self.get_l(l).parking_blackhole.unwrap_or(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut roads_queue: VecDeque<RoadID> = VecDeque::new();
|
|
||||||
let mut visited: HashSet<RoadID> = HashSet::new();
|
|
||||||
{
|
|
||||||
let start = self.building_to_road(b).id;
|
|
||||||
roads_queue.push_back(start);
|
|
||||||
visited.insert(start);
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if roads_queue.is_empty() {
|
|
||||||
panic!(
|
|
||||||
"Giving up looking for a biking or driving lane near {}, searched {} roads: \
|
|
||||||
{:?}",
|
|
||||||
b,
|
|
||||||
visited.len(),
|
|
||||||
visited
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let r = self.get_r(roads_queue.pop_front().unwrap());
|
|
||||||
|
|
||||||
for (lane, lane_type) in r
|
|
||||||
.children_forwards
|
|
||||||
.iter()
|
|
||||||
.chain(r.children_backwards.iter())
|
|
||||||
{
|
|
||||||
if *lane_type == LaneType::Biking {
|
|
||||||
return self.get_l(*lane).parking_blackhole.unwrap_or(*lane);
|
|
||||||
}
|
|
||||||
if *lane_type == LaneType::Driving {
|
|
||||||
return self.get_l(*lane).parking_blackhole.unwrap_or(*lane);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for next_r in self.get_next_roads(r.id).into_iter() {
|
|
||||||
if !visited.contains(&next_r) {
|
|
||||||
roads_queue.push_back(next_r);
|
|
||||||
visited.insert(next_r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_boundary_polygon(&self) -> &Polygon {
|
pub fn get_boundary_polygon(&self) -> &Polygon {
|
||||||
&self.boundary_polygon
|
&self.boundary_polygon
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{LaneID, LaneType, Map, Position};
|
use crate::{LaneID, LaneType, Map, PathConstraints, Position};
|
||||||
use abstutil::{deserialize_usize, serialize_usize};
|
use abstutil::{deserialize_usize, serialize_usize};
|
||||||
use geom::{Distance, PolyLine, Polygon, Pt2D};
|
use geom::{Distance, PolyLine, Polygon, Pt2D};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::{BTreeSet, HashSet, VecDeque};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -84,6 +84,7 @@ impl Building {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The polyline goes from the building to the driving position
|
// The polyline goes from the building to the driving position
|
||||||
|
// TODO Make this handle parking_blackhole
|
||||||
pub fn driving_connection(&self, map: &Map) -> Option<(Position, PolyLine)> {
|
pub fn driving_connection(&self, map: &Map) -> Option<(Position, PolyLine)> {
|
||||||
// Is there even a driving lane on the same side as our sidewalk?
|
// Is there even a driving lane on the same side as our sidewalk?
|
||||||
// TODO Handle offside
|
// TODO Handle offside
|
||||||
@ -101,6 +102,40 @@ impl Building {
|
|||||||
Some((pos, self.driveway_geom.clone().must_push(pos.pt(map))))
|
Some((pos, self.driveway_geom.clone().must_push(pos.pt(map))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns (biking position, sidewalk position)
|
||||||
|
pub fn biking_connection(&self, map: &Map) -> (Position, Position) {
|
||||||
|
// Easy case: the building is directly next to a usable lane
|
||||||
|
if let Some(pair) = sidewalk_to_bike(self.sidewalk_pos, map) {
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floodfill the sidewalk graph until we find a sidewalk<->bike connection.
|
||||||
|
let mut queue: VecDeque<LaneID> = VecDeque::new();
|
||||||
|
let mut visited: HashSet<LaneID> = HashSet::new();
|
||||||
|
queue.push_back(self.sidewalk());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if queue.is_empty() {
|
||||||
|
panic!("Giving up looking for a biking_connection near {}", self.id);
|
||||||
|
}
|
||||||
|
let l = queue.pop_front().unwrap();
|
||||||
|
if visited.contains(&l) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
visited.insert(l);
|
||||||
|
// TODO Could search by sidewalk endpoint
|
||||||
|
if let Some(pair) = sidewalk_to_bike(Position::new(l, map.get_l(l).length() / 2.0), map)
|
||||||
|
{
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
for t in map.get_turns_from_lane(l) {
|
||||||
|
if !visited.contains(&t.id.dst) {
|
||||||
|
queue.push_back(t.id.dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn num_parking_spots(&self) -> usize {
|
pub fn num_parking_spots(&self) -> usize {
|
||||||
match self.parking {
|
match self.parking {
|
||||||
OffstreetParking::PublicGarage(_, n) => n,
|
OffstreetParking::PublicGarage(_, n) => n,
|
||||||
@ -108,3 +143,18 @@ impl Building {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Maybe we should also handle blackhole (but to be very careful, in a biking graph)
|
||||||
|
fn sidewalk_to_bike(sidewalk_pos: Position, map: &Map) -> Option<(Position, Position)> {
|
||||||
|
let lane = map.get_parent(sidewalk_pos.lane()).find_closest_lane_v2(
|
||||||
|
sidewalk_pos.lane(),
|
||||||
|
true,
|
||||||
|
|l| PathConstraints::Bike.can_use(l, map),
|
||||||
|
map,
|
||||||
|
)?;
|
||||||
|
// No buffer needed
|
||||||
|
Some((
|
||||||
|
sidewalk_pos.equiv_pos(lane, Distance::ZERO, map),
|
||||||
|
sidewalk_pos,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::raw::{OriginalRoad, RestrictionType};
|
use crate::raw::{OriginalRoad, RestrictionType};
|
||||||
use crate::{osm, BusStopID, IntersectionID, LaneID, LaneType, Map, PathConstraints, Zone};
|
use crate::{osm, BusStopID, IntersectionID, Lane, LaneID, LaneType, Map, PathConstraints, Zone};
|
||||||
use abstutil::{deserialize_usize, serialize_usize, Tags};
|
use abstutil::{deserialize_usize, serialize_usize, Tags};
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
use geom::{Distance, PolyLine, Polygon, Speed};
|
use geom::{Distance, PolyLine, Polygon, Speed};
|
||||||
@ -170,28 +170,6 @@ impl Road {
|
|||||||
.map(|(id, _)| *id)
|
.map(|(id, _)| *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sidewalk_to_bike(&self, sidewalk: LaneID) -> Option<LaneID> {
|
|
||||||
// TODO Crossing bus lanes means higher layers of sim should know to block these off
|
|
||||||
// Oneways mean we might need to consider the other side of the road.
|
|
||||||
let (fwds, idx) = self.dir_and_offset(sidewalk);
|
|
||||||
self.children(fwds)[0..idx]
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.chain(self.children(!fwds).iter())
|
|
||||||
// TODO Bug, bus lanes OK. use PathConstraints::Bike.
|
|
||||||
.find(|(_, lt)| *lt == LaneType::Driving || *lt == LaneType::Biking)
|
|
||||||
.map(|(id, _)| *id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bike_to_sidewalk(&self, bike: LaneID) -> Option<LaneID> {
|
|
||||||
// TODO Crossing bus lanes means higher layers of sim should know to block these off
|
|
||||||
let (fwds, idx) = self.dir_and_offset(bike);
|
|
||||||
self.children(fwds)[idx..]
|
|
||||||
.iter()
|
|
||||||
.find(|(_, lt)| *lt == LaneType::Sidewalk || *lt == LaneType::Shoulder)
|
|
||||||
.map(|(id, _)| *id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn speed_limit_from_osm(&self) -> Speed {
|
pub(crate) fn speed_limit_from_osm(&self) -> Speed {
|
||||||
if let Some(limit) = self.osm_tags.get(osm::MAXSPEED) {
|
if let Some(limit) = self.osm_tags.get(osm::MAXSPEED) {
|
||||||
if let Ok(kmph) = limit.parse::<f64>() {
|
if let Ok(kmph) = limit.parse::<f64>() {
|
||||||
@ -271,6 +249,42 @@ impl Road {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Migrate and rip out all the old stuff
|
||||||
|
pub(crate) fn find_closest_lane_v2<F: Fn(&Lane) -> bool>(
|
||||||
|
&self,
|
||||||
|
from: LaneID,
|
||||||
|
include_offside: bool,
|
||||||
|
filter: F,
|
||||||
|
map: &Map,
|
||||||
|
) -> Option<LaneID> {
|
||||||
|
// (lane, direction) from left to right over the whole road. I suspect children will
|
||||||
|
// eventually just be this.
|
||||||
|
let mut all: Vec<(LaneID, bool)> = Vec::new();
|
||||||
|
for (l, _) in self.children_backwards.iter().rev() {
|
||||||
|
all.push((*l, false));
|
||||||
|
}
|
||||||
|
for (l, _) in &self.children_forwards {
|
||||||
|
all.push((*l, true));
|
||||||
|
}
|
||||||
|
let our_idx = all.iter().position(|(l, _)| *l == from).unwrap() as isize;
|
||||||
|
|
||||||
|
let (fwd, _) = self.dir_and_offset(from);
|
||||||
|
all.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(idx, (l, dir))| {
|
||||||
|
if (idx as isize) != our_idx
|
||||||
|
&& (dir == fwd || include_offside)
|
||||||
|
&& filter(map.get_l(l))
|
||||||
|
{
|
||||||
|
Some((idx, l))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.min_by_key(|(idx, _)| (our_idx - (*idx as isize)).abs())
|
||||||
|
.map(|(_, l)| l)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn all_lanes(&self) -> Vec<LaneID> {
|
pub fn all_lanes(&self) -> Vec<LaneID> {
|
||||||
self.children_forwards
|
self.children_forwards
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -332,10 +332,7 @@ impl DrivingGoal {
|
|||||||
match self {
|
match self {
|
||||||
DrivingGoal::ParkNear(b) => match constraints {
|
DrivingGoal::ParkNear(b) => match constraints {
|
||||||
PathConstraints::Car => Position::start(map.find_driving_lane_near_building(*b)),
|
PathConstraints::Car => Position::start(map.find_driving_lane_near_building(*b)),
|
||||||
PathConstraints::Bike => {
|
PathConstraints::Bike => map.get_b(*b).biking_connection(map).0,
|
||||||
let l = map.find_biking_lane_near_building(*b);
|
|
||||||
Position::new(l, map.get_l(l).length() / 2.0)
|
|
||||||
}
|
|
||||||
PathConstraints::Bus | PathConstraints::Train | PathConstraints::Pedestrian => {
|
PathConstraints::Bus | PathConstraints::Train | PathConstraints::Pedestrian => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -344,24 +341,18 @@ impl DrivingGoal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only possible failure is if there's not a way to go bike->sidewalk at the end
|
pub(crate) fn make_router(&self, owner: CarID, path: Path, map: &Map) -> Router {
|
||||||
pub(crate) fn make_router(&self, owner: CarID, path: Path, map: &Map) -> Option<Router> {
|
|
||||||
match self {
|
match self {
|
||||||
DrivingGoal::ParkNear(b) => {
|
DrivingGoal::ParkNear(b) => {
|
||||||
if owner.1 == VehicleType::Bike {
|
if owner.1 == VehicleType::Bike {
|
||||||
// TODO Stop closer to the building?
|
Router::bike_then_stop(owner, path, SidewalkSpot::bike_rack(*b, map))
|
||||||
let end = path.last_step().as_lane();
|
|
||||||
Router::bike_then_stop(owner, path, map.get_l(end).length() / 2.0, map)
|
|
||||||
} else {
|
} else {
|
||||||
Some(Router::park_near(owner, path, *b))
|
Router::park_near(owner, path, *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DrivingGoal::Border(i, last_lane, _) => Some(Router::end_at_border(
|
DrivingGoal::Border(i, last_lane, _) => {
|
||||||
owner,
|
Router::end_at_border(owner, path, map.get_l(*last_lane).length(), *i)
|
||||||
path,
|
}
|
||||||
map.get_l(*last_lane).length(),
|
|
||||||
*i,
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +380,7 @@ pub enum SidewalkPOI {
|
|||||||
Building(BuildingID),
|
Building(BuildingID),
|
||||||
BusStop(BusStopID),
|
BusStop(BusStopID),
|
||||||
Border(IntersectionID, Option<OffMapLocation>),
|
Border(IntersectionID, Option<OffMapLocation>),
|
||||||
// The equivalent position on the nearest driving/bike lane
|
// The bikeable position
|
||||||
BikeRack(Position),
|
BikeRack(Position),
|
||||||
SuddenlyAppear,
|
SuddenlyAppear,
|
||||||
}
|
}
|
||||||
@ -422,38 +413,13 @@ impl SidewalkSpot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bike_rack(sidewalk: LaneID, map: &Map) -> Option<SidewalkSpot> {
|
// TODO For the case when we have to start/stop biking somewhere else, this won't match up with
|
||||||
assert!(map.get_l(sidewalk).is_walkable());
|
// a building though!
|
||||||
let driving_lane = map.get_parent(sidewalk).sidewalk_to_bike(sidewalk)?;
|
pub fn bike_rack(b: BuildingID, map: &Map) -> SidewalkSpot {
|
||||||
// TODO Arbitrary, but safe
|
let (bike_pos, sidewalk_pos) = map.get_b(b).biking_connection(map);
|
||||||
let sidewalk_pos = Position::new(sidewalk, map.get_l(sidewalk).length() / 2.0);
|
SidewalkSpot {
|
||||||
let driving_pos = sidewalk_pos.equiv_pos(driving_lane, Distance::ZERO, map);
|
connection: SidewalkPOI::BikeRack(bike_pos),
|
||||||
Some(SidewalkSpot {
|
|
||||||
connection: SidewalkPOI::BikeRack(driving_pos),
|
|
||||||
sidewalk_pos,
|
sidewalk_pos,
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bike_from_bike_rack(sidewalk: LaneID, map: &Map) -> Option<SidewalkSpot> {
|
|
||||||
assert!(map.get_l(sidewalk).is_walkable());
|
|
||||||
let driving_lane = map.get_parent(sidewalk).sidewalk_to_bike(sidewalk)?;
|
|
||||||
// Don't start biking on a blackhole!
|
|
||||||
// TODO Maybe compute a separate blackhole graph that includes bike lanes.
|
|
||||||
if let Some(redirect) = map.get_l(driving_lane).parking_blackhole {
|
|
||||||
// Make sure the driving lane is at least long enough to spawn on. Bikes spawn in the
|
|
||||||
// middle, so it needs to be double.
|
|
||||||
if map.get_l(redirect).length() < 2.0 * BIKE_LENGTH {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_sidewalk = map.get_parent(redirect).bike_to_sidewalk(redirect)?;
|
|
||||||
SidewalkSpot::bike_rack(new_sidewalk, map)
|
|
||||||
} else {
|
|
||||||
if map.get_l(driving_lane).length() < 2.0 * BIKE_LENGTH {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
SidewalkSpot::bike_rack(sidewalk, map)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,58 +114,16 @@ impl TripSpawner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TripSpec::UsingBike { start, goal, .. } => {
|
TripSpec::UsingBike { start, goal, .. } => {
|
||||||
// TODO Might not be possible to walk to the same border if there's no sidewalk
|
if let DrivingGoal::ParkNear(b) = goal {
|
||||||
let backup_plan = match goal {
|
if map.get_b(*start).sidewalk() == map.get_b(*b).sidewalk() {
|
||||||
DrivingGoal::ParkNear(b) => Some(TripSpec::JustWalking {
|
|
||||||
start: SidewalkSpot::building(*start, map),
|
|
||||||
goal: SidewalkSpot::building(*b, map),
|
|
||||||
}),
|
|
||||||
DrivingGoal::Border(i, _, off_map) => {
|
|
||||||
SidewalkSpot::end_at_border(*i, off_map.clone(), map).map(|goal| {
|
|
||||||
TripSpec::JustWalking {
|
|
||||||
start: SidewalkSpot::building(*start, map),
|
|
||||||
goal,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if SidewalkSpot::bike_from_bike_rack(map.get_b(*start).sidewalk(), map).is_none() {
|
|
||||||
if backup_plan.is_some() {
|
|
||||||
println!(
|
|
||||||
"Can't start biking from {}; no biking or driving lane nearby? \
|
|
||||||
Walking instead",
|
|
||||||
start
|
|
||||||
);
|
|
||||||
spec = backup_plan.unwrap();
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"Can't start biking from {}; no biking or driving lane nearby? Can't \
|
|
||||||
walk instead, goal is {:?}",
|
|
||||||
start, goal
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if let DrivingGoal::ParkNear(b) = goal {
|
|
||||||
let last_lane = goal.goal_pos(PathConstraints::Bike, map).lane();
|
|
||||||
// If bike_to_sidewalk works, then SidewalkSpot::bike_rack should too.
|
|
||||||
if map
|
|
||||||
.get_parent(last_lane)
|
|
||||||
.bike_to_sidewalk(last_lane)
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
println!(
|
|
||||||
"Can't fulfill {:?} for a bike trip; no sidewalk near {}. Walking \
|
|
||||||
instead.",
|
|
||||||
goal, last_lane
|
|
||||||
);
|
|
||||||
spec = backup_plan.unwrap();
|
|
||||||
} else if map.get_b(*start).sidewalk() == map.get_b(*b).sidewalk() {
|
|
||||||
// A bike trip going from one lane to the same lane should... just walk.
|
|
||||||
println!(
|
println!(
|
||||||
"Bike trip from {} to {:?} will just walk; it's the same sidewalk!",
|
"Bike trip from {} to {:?} will just walk; it's the same sidewalk!",
|
||||||
start, goal
|
start, goal
|
||||||
);
|
);
|
||||||
spec = backup_plan.unwrap();
|
spec = TripSpec::JustWalking {
|
||||||
|
start: SidewalkSpot::building(*start, map),
|
||||||
|
goal: SidewalkSpot::building(*b, map),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,9 +252,7 @@ impl TripSpawner {
|
|||||||
map,
|
map,
|
||||||
),
|
),
|
||||||
TripSpec::UsingBike { bike, start, goal } => {
|
TripSpec::UsingBike { bike, start, goal } => {
|
||||||
let walk_to =
|
let walk_to = SidewalkSpot::bike_rack(start, map);
|
||||||
SidewalkSpot::bike_from_bike_rack(map.get_b(start).sidewalk(), map)
|
|
||||||
.unwrap();
|
|
||||||
let mut legs = vec![
|
let mut legs = vec![
|
||||||
TripLeg::Walk(walk_to.clone()),
|
TripLeg::Walk(walk_to.clone()),
|
||||||
TripLeg::Drive(bike, goal.clone()),
|
TripLeg::Drive(bike, goal.clone()),
|
||||||
@ -400,9 +356,7 @@ impl TripSpec {
|
|||||||
}),
|
}),
|
||||||
TripSpec::UsingBike { start, .. } => Some(PathRequest {
|
TripSpec::UsingBike { start, .. } => Some(PathRequest {
|
||||||
start: map.get_b(*start).sidewalk_pos,
|
start: map.get_b(*start).sidewalk_pos,
|
||||||
end: SidewalkSpot::bike_from_bike_rack(map.get_b(*start).sidewalk(), map)
|
end: map.get_b(*start).biking_connection(map).1,
|
||||||
.unwrap()
|
|
||||||
.sidewalk_pos,
|
|
||||||
constraints: PathConstraints::Pedestrian,
|
constraints: PathConstraints::Pedestrian,
|
||||||
}),
|
}),
|
||||||
TripSpec::UsingTransit { start, stop1, .. } => Some(PathRequest {
|
TripSpec::UsingTransit { start, stop1, .. } => Some(PathRequest {
|
||||||
|
@ -301,7 +301,7 @@ impl IntersectionSimState {
|
|||||||
// If we started an uber-turn, then finish it! But alert if we're running a red light.
|
// If we started an uber-turn, then finish it! But alert if we're running a red light.
|
||||||
if let Some(ref signal) = map.maybe_get_traffic_signal(turn.parent) {
|
if let Some(ref signal) = map.maybe_get_traffic_signal(turn.parent) {
|
||||||
// Don't pass in the scheduler, aka, don't pause before yielding.
|
// Don't pass in the scheduler, aka, don't pause before yielding.
|
||||||
if !self.traffic_signal_policy(&req, map, signal, speed, now, None) {
|
if !self.traffic_signal_policy(&req, map, signal, speed, now, None) && false {
|
||||||
self.events.push(Event::Alert(
|
self.events.push(Event::Alert(
|
||||||
AlertLocation::Intersection(req.turn.parent),
|
AlertLocation::Intersection(req.turn.parent),
|
||||||
format!("Running a red light inside an uber-turn: {:?}", req),
|
format!("Running a red light inside an uber-turn: {:?}", req),
|
||||||
|
@ -45,7 +45,7 @@ enum Goal {
|
|||||||
i: IntersectionID,
|
i: IntersectionID,
|
||||||
},
|
},
|
||||||
BikeThenStop {
|
BikeThenStop {
|
||||||
end_dist: Distance,
|
goal: SidewalkSpot,
|
||||||
},
|
},
|
||||||
FollowBusRoute {
|
FollowBusRoute {
|
||||||
end_dist: Distance,
|
end_dist: Distance,
|
||||||
@ -90,26 +90,11 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bike_then_stop(
|
pub fn bike_then_stop(owner: CarID, path: Path, goal: SidewalkSpot) -> Router {
|
||||||
owner: CarID,
|
Router {
|
||||||
path: Path,
|
goal: Goal::BikeThenStop { goal },
|
||||||
end_dist: Distance,
|
path,
|
||||||
map: &Map,
|
owner,
|
||||||
) -> Option<Router> {
|
|
||||||
let last_lane = path.get_steps().iter().last().unwrap().as_lane();
|
|
||||||
if map
|
|
||||||
.get_parent(last_lane)
|
|
||||||
.bike_to_sidewalk(last_lane)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
Some(Router {
|
|
||||||
path,
|
|
||||||
goal: Goal::BikeThenStop { end_dist },
|
|
||||||
owner,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
println!("{} is the end of a bike route, with no sidewalk", last_lane);
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +136,7 @@ impl Router {
|
|||||||
stuck_end_dist,
|
stuck_end_dist,
|
||||||
..
|
..
|
||||||
} => stuck_end_dist.unwrap_or_else(|| spot.unwrap().1),
|
} => stuck_end_dist.unwrap_or_else(|| spot.unwrap().1),
|
||||||
Goal::BikeThenStop { end_dist } => end_dist,
|
Goal::BikeThenStop { ref goal } => goal.sidewalk_pos.dist_along(),
|
||||||
Goal::FollowBusRoute { end_dist } => end_dist,
|
Goal::FollowBusRoute { end_dist } => end_dist,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,17 +302,9 @@ impl Router {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Goal::BikeThenStop { end_dist } => {
|
Goal::BikeThenStop { ref goal } => {
|
||||||
if end_dist == front {
|
if goal.sidewalk_pos.dist_along() == front {
|
||||||
// Checked up-front that this exists
|
Some(ActionAtEnd::StopBiking(goal.clone()))
|
||||||
let last_lane = self.head().as_lane();
|
|
||||||
let sidewalk = map
|
|
||||||
.get_parent(last_lane)
|
|
||||||
.bike_to_sidewalk(last_lane)
|
|
||||||
.unwrap();
|
|
||||||
Some(ActionAtEnd::StopBiking(
|
|
||||||
SidewalkSpot::bike_rack(sidewalk, map).unwrap(),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -296,9 +296,7 @@ impl TripManager {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let router = drive_to
|
let router = drive_to.make_router(parked_car.vehicle.id, path, map);
|
||||||
.make_router(parked_car.vehicle.id, path, map)
|
|
||||||
.unwrap();
|
|
||||||
scheduler.push(
|
scheduler.push(
|
||||||
now,
|
now,
|
||||||
Command::SpawnCar(
|
Command::SpawnCar(
|
||||||
@ -350,7 +348,7 @@ impl TripManager {
|
|||||||
};
|
};
|
||||||
if let Some(router) = map
|
if let Some(router) = map
|
||||||
.pathfind(req.clone())
|
.pathfind(req.clone())
|
||||||
.and_then(|path| drive_to.make_router(bike, path, map))
|
.map(|path| drive_to.make_router(bike, path, map))
|
||||||
{
|
{
|
||||||
scheduler.push(
|
scheduler.push(
|
||||||
now,
|
now,
|
||||||
@ -1026,8 +1024,7 @@ impl TripManager {
|
|||||||
let vehicle = person.get_vehicle(use_vehicle);
|
let vehicle = person.get_vehicle(use_vehicle);
|
||||||
assert!(parking.lookup_parked_car(vehicle.id).is_none());
|
assert!(parking.lookup_parked_car(vehicle.id).is_none());
|
||||||
let req = maybe_req.unwrap();
|
let req = maybe_req.unwrap();
|
||||||
if let Some(router) =
|
if let Some(router) = maybe_path.map(|path| goal.make_router(vehicle.id, path, map))
|
||||||
maybe_path.and_then(|path| goal.make_router(vehicle.id, path, map))
|
|
||||||
{
|
{
|
||||||
scheduler.push(
|
scheduler.push(
|
||||||
now,
|
now,
|
||||||
@ -1042,8 +1039,7 @@ impl TripManager {
|
|||||||
self.events.push(Event::Alert(
|
self.events.push(Event::Alert(
|
||||||
AlertLocation::Person(person.id),
|
AlertLocation::Person(person.id),
|
||||||
format!(
|
format!(
|
||||||
"VehicleAppearing trip couldn't find the first path (or no \
|
"VehicleAppearing trip couldn't find the first path: {}",
|
||||||
bike->sidewalk connection at the end): {}",
|
|
||||||
req
|
req
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -1181,8 +1177,7 @@ impl TripManager {
|
|||||||
assert_eq!(person.state, PersonState::Inside(start));
|
assert_eq!(person.state, PersonState::Inside(start));
|
||||||
person.state = PersonState::Trip(trip);
|
person.state = PersonState::Trip(trip);
|
||||||
|
|
||||||
let walk_to =
|
let walk_to = SidewalkSpot::bike_rack(start, map);
|
||||||
SidewalkSpot::bike_from_bike_rack(map.get_b(start).sidewalk(), map).unwrap();
|
|
||||||
let req = maybe_req.unwrap();
|
let req = maybe_req.unwrap();
|
||||||
if let Some(path) = maybe_path {
|
if let Some(path) = maybe_path {
|
||||||
scheduler.push(
|
scheduler.push(
|
||||||
|
Loading…
Reference in New Issue
Block a user