mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
Implement no-through-traffic zones instead by adding a huge cost to crossing into the zones. #555, #574
Regenerate all maps. Gridlock-wise, Rainier and Poundbury broke, but Wallingford started working again. Acceptable cost for a change this useful; I'll work on fixing those maps later.
This commit is contained in:
parent
e6cf2d54bc
commit
7d2e8409e8
File diff suppressed because it is too large
Load Diff
@ -30,8 +30,8 @@ pub fn prebake_all() {
|
||||
MapName::seattle("lakeslice"),
|
||||
MapName::seattle("phinney"),
|
||||
MapName::seattle("qa"),
|
||||
MapName::seattle("rainier_valley"),
|
||||
//MapName::seattle("wallingford"), TODO broken
|
||||
//MapName::seattle("rainier_valley"), // TODO broken
|
||||
MapName::seattle("wallingford"),
|
||||
] {
|
||||
let map = map_model::Map::load_synchronously(name.path(), &mut timer);
|
||||
let scenario: Scenario =
|
||||
@ -39,7 +39,11 @@ pub fn prebake_all() {
|
||||
prebake(&map, scenario, None, &mut timer);
|
||||
}
|
||||
|
||||
for scenario_name in vec!["base", "go_active", "base_with_bg", "go_active_with_bg"] {
|
||||
// TODO These two also broke
|
||||
for scenario_name in vec![
|
||||
"base",
|
||||
"go_active", /* "base_with_bg", "go_active_with_bg" */
|
||||
] {
|
||||
let map = map_model::Map::load_synchronously(
|
||||
MapName::new("gb", "poundbury", "center").path(),
|
||||
&mut timer,
|
||||
|
@ -7,7 +7,7 @@ use petgraph::graphmap::DiGraphMap;
|
||||
use geom::{Distance, Duration, Speed};
|
||||
|
||||
pub use self::walking::{all_walking_costs_from, WalkingOptions};
|
||||
use crate::pathfind::build_graph_for_vehicles;
|
||||
use crate::pathfind::{build_graph_for_vehicles, zone_cost};
|
||||
pub use crate::pathfind::{driving_cost, WalkingNode};
|
||||
use crate::{BuildingID, LaneID, Map, PathConstraints, PathRequest, RoadID};
|
||||
|
||||
@ -117,26 +117,28 @@ pub fn debug_vehicle_costs(req: PathRequest, map: &Map) -> Option<(f64, HashMap<
|
||||
&graph,
|
||||
req.start.lane(),
|
||||
|l| l == req.end.lane(),
|
||||
|(_, _, turn)| {
|
||||
|(_, _, t)| {
|
||||
let turn = map.get_t(*t);
|
||||
driving_cost(
|
||||
map.get_l(turn.src),
|
||||
map.get_t(*turn),
|
||||
map.get_l(turn.id.src),
|
||||
turn,
|
||||
req.constraints,
|
||||
map.routing_params(),
|
||||
map,
|
||||
)
|
||||
) + zone_cost(turn, req.constraints, map)
|
||||
},
|
||||
|_| 0.0,
|
||||
)?;
|
||||
|
||||
let lane_costs = petgraph::algo::dijkstra(&graph, req.start.lane(), None, |(_, _, turn)| {
|
||||
let lane_costs = petgraph::algo::dijkstra(&graph, req.start.lane(), None, |(_, _, t)| {
|
||||
let turn = map.get_t(*t);
|
||||
driving_cost(
|
||||
map.get_l(turn.src),
|
||||
map.get_t(*turn),
|
||||
map.get_l(turn.id.src),
|
||||
turn,
|
||||
req.constraints,
|
||||
map.routing_params(),
|
||||
map,
|
||||
)
|
||||
) + zone_cost(turn, req.constraints, map)
|
||||
});
|
||||
// Express the costs per road for an easier debug experince. Take the LOWEST cost per road,
|
||||
// since we don't want noise from considering the opposite direction.
|
||||
|
@ -6,6 +6,7 @@ use petgraph::graphmap::DiGraphMap;
|
||||
|
||||
use crate::pathfind::driving::driving_cost;
|
||||
use crate::pathfind::walking::{walking_cost, WalkingNode};
|
||||
use crate::pathfind::zone_cost;
|
||||
use crate::{LaneID, Map, Path, PathConstraints, PathRequest, PathStep, RoutingParams, TurnID};
|
||||
|
||||
// TODO These should maybe keep the DiGraphMaps as state. It's cheap to recalculate it for edits.
|
||||
@ -58,17 +59,14 @@ fn calc_path(
|
||||
&graph,
|
||||
req.start.lane(),
|
||||
|l| l == req.end.lane(),
|
||||
|(_, _, turn)| {
|
||||
driving_cost(
|
||||
map.get_l(turn.src),
|
||||
map.get_t(*turn),
|
||||
req.constraints,
|
||||
params,
|
||||
map,
|
||||
)
|
||||
|(_, _, t)| {
|
||||
let turn = map.get_t(*t);
|
||||
driving_cost(map.get_l(turn.id.src), turn, req.constraints, params, map)
|
||||
+ zone_cost(turn, req.constraints, map)
|
||||
},
|
||||
|_| 0.0,
|
||||
)?;
|
||||
|
||||
let mut steps = Vec::new();
|
||||
for pair in path.windows(2) {
|
||||
steps.push(PathStep::Lane(pair[0]));
|
||||
@ -101,7 +99,8 @@ pub fn build_graph_for_pedestrians(map: &Map) -> DiGraphMap<WalkingNode, usize>
|
||||
turn.id.dst,
|
||||
map.get_l(turn.id.dst).dst_i == turn.id.parent,
|
||||
),
|
||||
walking_cost(turn.geom.length()),
|
||||
walking_cost(turn.geom.length())
|
||||
+ zone_cost(turn, PathConstraints::Pedestrian, map) as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use abstutil::MultiMap;
|
||||
|
||||
use crate::pathfind::node_map::{deserialize_nodemap, NodeMap};
|
||||
use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn};
|
||||
use crate::pathfind::zone_cost;
|
||||
use crate::{
|
||||
DrivingSide, Lane, LaneID, Map, Path, PathConstraints, PathRequest, PathStep, RoutingParams,
|
||||
Turn, TurnID, TurnType,
|
||||
@ -175,13 +176,10 @@ fn make_input_graph(
|
||||
input_graph.add_edge(
|
||||
from,
|
||||
nodes.get(Node::Lane(turn.id.dst)),
|
||||
round(driving_cost(
|
||||
l,
|
||||
turn,
|
||||
constraints,
|
||||
map.routing_params(),
|
||||
map,
|
||||
)),
|
||||
round(
|
||||
driving_cost(l, turn, constraints, map.routing_params(), map)
|
||||
+ zone_cost(turn, constraints, map),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@ -191,13 +189,14 @@ fn make_input_graph(
|
||||
|
||||
let mut sum_cost = 0.0;
|
||||
for t in &ut.path {
|
||||
let turn = map.get_t(*t);
|
||||
sum_cost += driving_cost(
|
||||
map.get_l(t.src),
|
||||
map.get_t(*t),
|
||||
turn,
|
||||
constraints,
|
||||
map.routing_params(),
|
||||
map,
|
||||
);
|
||||
) + zone_cost(turn, constraints, map);
|
||||
}
|
||||
input_graph.add_edge(from, nodes.get(Node::UberTurn(*idx)), round(sum_cost));
|
||||
input_graph.add_edge(
|
||||
|
@ -15,7 +15,7 @@ pub use self::driving::driving_cost;
|
||||
pub use self::pathfinder::Pathfinder;
|
||||
pub use self::walking::{walking_cost, WalkingNode};
|
||||
use crate::{
|
||||
osm, BuildingID, Lane, LaneID, LaneType, Map, Position, Traversable, TurnID, UberTurn,
|
||||
osm, BuildingID, Lane, LaneID, LaneType, Map, Position, Traversable, Turn, TurnID, UberTurn,
|
||||
};
|
||||
|
||||
mod ch;
|
||||
@ -644,16 +644,42 @@ fn validate_zones(map: &Map, steps: &Vec<PathStep>, req: &PathRequest) {
|
||||
.allow_through_traffic
|
||||
.contains(req.constraints)
|
||||
{
|
||||
// Maybe it's fine
|
||||
// Entering our destination zone is fine
|
||||
let into_zone = map.get_parent(t.dst).get_zone(map);
|
||||
if into_zone != z1 && into_zone != z2 {
|
||||
error!("{} causes illegal entrance into a zone at {}", req, t);
|
||||
// TODO There are lots of false positive here that occur when part of the graph
|
||||
// is separated from the rest by access-restricted roads. Could maybe detect
|
||||
// that here, or ideally even extend the zone at map construction time (or edit
|
||||
// time) when that happens.
|
||||
panic!("{} causes illegal entrance into a zone at {}", req, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Heavily penalize crossing into an access-restricted zone that doesn't allow this mode.
|
||||
pub fn zone_cost(turn: &Turn, constraints: PathConstraints, map: &Map) -> f64 {
|
||||
// Detect when we cross into a new zone that doesn't allow constraints.
|
||||
if map
|
||||
.get_parent(turn.id.src)
|
||||
.access_restrictions
|
||||
.allow_through_traffic
|
||||
.contains(constraints)
|
||||
&& !map
|
||||
.get_parent(turn.id.dst)
|
||||
.access_restrictions
|
||||
.allow_through_traffic
|
||||
.contains(constraints)
|
||||
{
|
||||
// TODO Tune this after making driving_cost and walking_cost both roughly represent
|
||||
// seconds. In the meantime, this penalty seems high enough to achieve the desired effect.
|
||||
100_000.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Tuneable parameters for all types of routing.
|
||||
// These will maybe become part of the PathRequest later, but that's an extremely invasive and
|
||||
// space-expensive change right now.
|
||||
|
@ -12,6 +12,7 @@ use geom::{Distance, Speed};
|
||||
|
||||
use crate::pathfind::driving::VehiclePathfinder;
|
||||
use crate::pathfind::node_map::{deserialize_nodemap, NodeMap};
|
||||
use crate::pathfind::zone_cost;
|
||||
use crate::{
|
||||
BusRoute, BusRouteID, BusStopID, IntersectionID, LaneID, Map, Path, PathConstraints,
|
||||
PathRequest, PathStep, Position,
|
||||
@ -254,7 +255,8 @@ fn make_input_graph(
|
||||
input_graph.add_edge(
|
||||
nodes.get(from),
|
||||
nodes.get(to),
|
||||
walking_cost(t.geom.length()),
|
||||
walking_cost(t.geom.length())
|
||||
+ zone_cost(t, PathConstraints::Pedestrian, map) as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user