mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 04:35:51 +03:00
properly update followers that're Crossing and become unblocked
This commit is contained in:
parent
ab52e9ac38
commit
2ac973f245
@ -141,137 +141,134 @@ impl DrivingSimState {
|
|||||||
|
|
||||||
// Handle cars on their last step. Some of them will vanish or finish parking; others will
|
// Handle cars on their last step. Some of them will vanish or finish parking; others will
|
||||||
// start.
|
// start.
|
||||||
// TODO Inside here, need to mutate cars and a single queue. Clone keys to awkwardly work
|
for queue in self.queues.values_mut() {
|
||||||
// with borrow checker.
|
let mut any_last_step = false;
|
||||||
for on in self.queues.keys().cloned().collect::<Vec<Traversable>>() {
|
for id in &queue.cars {
|
||||||
if self.queues[&on]
|
if self.cars[id].router.last_step() {
|
||||||
.cars
|
any_last_step = true;
|
||||||
.iter()
|
break;
|
||||||
.any(|id| self.cars[id].router.last_step())
|
}
|
||||||
{
|
}
|
||||||
// This car might have reached the router's end distance, but maybe not -- might
|
if !any_last_step {
|
||||||
// actually be stuck behind other cars. We have to calculate the distances right
|
continue;
|
||||||
// now to be sure.
|
}
|
||||||
// TODO This calculates distances a little unnecessarily -- might just be a car
|
|
||||||
// parking.
|
// This car might have reached the router's end distance, but maybe not -- might
|
||||||
let mut delete_indices = Vec::new();
|
// actually be stuck behind other cars. We have to calculate the distances right now to
|
||||||
for (idx, (id, dist)) in self.queues[&on]
|
// be sure.
|
||||||
.get_car_positions(time, &self.cars)
|
// TODO This calculates distances a little unnecessarily -- might just be a car
|
||||||
.into_iter()
|
// parking.
|
||||||
.enumerate()
|
let mut delete_indices = Vec::new();
|
||||||
{
|
let dists = queue.get_car_positions(time, &self.cars);
|
||||||
let car = self.cars.get_mut(&id).unwrap();
|
for (idx, (id, dist)) in dists.iter().enumerate() {
|
||||||
if !car.router.last_step() {
|
let car = self.cars.get_mut(id).unwrap();
|
||||||
continue;
|
if !car.router.last_step() {
|
||||||
}
|
continue;
|
||||||
match car.state {
|
}
|
||||||
CarState::Queued => {
|
match car.state {
|
||||||
match car
|
CarState::Crossing(_, _) | CarState::Unparking(_, _) => {}
|
||||||
.router
|
CarState::Queued => {
|
||||||
.maybe_handle_end(dist, &car.vehicle, parking, map)
|
match car
|
||||||
{
|
.router
|
||||||
Some(ActionAtEnd::VanishAtBorder(i)) => {
|
.maybe_handle_end(*dist, &car.vehicle, parking, map)
|
||||||
trips.car_or_bike_reached_border(time, car.vehicle.id, i);
|
{
|
||||||
delete_indices.push((idx, dist));
|
Some(ActionAtEnd::VanishAtBorder(i)) => {
|
||||||
}
|
trips.car_or_bike_reached_border(time, car.vehicle.id, i);
|
||||||
Some(ActionAtEnd::StartParking(spot)) => {
|
delete_indices.push(idx);
|
||||||
car.state = CarState::Parking(
|
|
||||||
dist,
|
|
||||||
spot,
|
|
||||||
TimeInterval::new(time, time + TIME_TO_PARK),
|
|
||||||
);
|
|
||||||
// If we don't do this, then we might have another car creep up
|
|
||||||
// behind, see the spot free, and start parking too. This can
|
|
||||||
// happen with multiple lanes and certain vehicle lengths.
|
|
||||||
parking.reserve_spot(spot);
|
|
||||||
}
|
|
||||||
Some(ActionAtEnd::GotoLaneEnd) => {
|
|
||||||
car.state = car.crossing_state(dist, time, map);
|
|
||||||
}
|
|
||||||
Some(ActionAtEnd::StopBiking(bike_rack)) => {
|
|
||||||
delete_indices.push((idx, dist));
|
|
||||||
trips.bike_reached_end(
|
|
||||||
time,
|
|
||||||
car.vehicle.id,
|
|
||||||
bike_rack,
|
|
||||||
map,
|
|
||||||
scheduler,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Some(ActionAtEnd::BusAtStop) => {
|
|
||||||
transit.bus_arrived_at_stop(
|
|
||||||
time,
|
|
||||||
car.vehicle.id,
|
|
||||||
trips,
|
|
||||||
walking,
|
|
||||||
scheduler,
|
|
||||||
map,
|
|
||||||
);
|
|
||||||
car.state = CarState::Idling(
|
|
||||||
dist,
|
|
||||||
TimeInterval::new(time, time + TIME_TO_WAIT_AT_STOP),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
}
|
Some(ActionAtEnd::StartParking(spot)) => {
|
||||||
CarState::Parking(_, spot, ref time_int) => {
|
car.state = CarState::Parking(
|
||||||
if time > time_int.end {
|
*dist,
|
||||||
delete_indices.push((idx, dist));
|
|
||||||
parking.add_parked_car(ParkedCar {
|
|
||||||
vehicle: car.vehicle.clone(),
|
|
||||||
spot,
|
spot,
|
||||||
});
|
TimeInterval::new(time, time + TIME_TO_PARK),
|
||||||
trips.car_reached_parking_spot(
|
);
|
||||||
|
// If we don't do this, then we might have another car creep up
|
||||||
|
// behind, see the spot free, and start parking too. This can
|
||||||
|
// happen with multiple lanes and certain vehicle lengths.
|
||||||
|
parking.reserve_spot(spot);
|
||||||
|
}
|
||||||
|
Some(ActionAtEnd::GotoLaneEnd) => {
|
||||||
|
car.state = car.crossing_state(*dist, time, map);
|
||||||
|
}
|
||||||
|
Some(ActionAtEnd::StopBiking(bike_rack)) => {
|
||||||
|
delete_indices.push(idx);
|
||||||
|
trips.bike_reached_end(
|
||||||
time,
|
time,
|
||||||
car.vehicle.id,
|
car.vehicle.id,
|
||||||
spot,
|
bike_rack,
|
||||||
map,
|
map,
|
||||||
parking,
|
|
||||||
scheduler,
|
scheduler,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
Some(ActionAtEnd::BusAtStop) => {
|
||||||
CarState::Idling(dist, ref time_int) => {
|
transit.bus_arrived_at_stop(
|
||||||
if time > time_int.end {
|
|
||||||
car.router = transit.bus_departed_from_stop(car.vehicle.id, map);
|
|
||||||
car.state = car.crossing_state(dist, time, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the finished cars starting from the end of the queue, so indices aren't
|
|
||||||
// messed up.
|
|
||||||
delete_indices.reverse();
|
|
||||||
for (idx, leader_dist) in delete_indices {
|
|
||||||
let queue = self.queues.get_mut(&on).unwrap();
|
|
||||||
let leader = self.cars.remove(&queue.cars.remove(idx).unwrap()).unwrap();
|
|
||||||
|
|
||||||
// Update the follower so that they don't suddenly jump forwards.
|
|
||||||
if idx != queue.cars.len() {
|
|
||||||
let mut follower = self.cars.get_mut(&queue.cars[idx]).unwrap();
|
|
||||||
// TODO If the leader vanished at a border node, this still jumps a bit --
|
|
||||||
// the lead car's back is still sticking out. Need to still be bound by
|
|
||||||
// them, even though they don't exist! If the leader just parked, then
|
|
||||||
// we're fine.
|
|
||||||
match follower.state {
|
|
||||||
CarState::Queued => {
|
|
||||||
follower.state = follower.crossing_state(
|
|
||||||
// Since the follower was Queued, this must be where they are
|
|
||||||
leader_dist - leader.vehicle.length - FOLLOWING_DISTANCE,
|
|
||||||
time,
|
time,
|
||||||
|
car.vehicle.id,
|
||||||
|
trips,
|
||||||
|
walking,
|
||||||
|
scheduler,
|
||||||
map,
|
map,
|
||||||
);
|
);
|
||||||
|
car.state = CarState::Idling(
|
||||||
|
*dist,
|
||||||
|
TimeInterval::new(time, time + TIME_TO_WAIT_AT_STOP),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// They weren't blocked
|
None => {}
|
||||||
CarState::Crossing(_, _)
|
|
||||||
| CarState::Unparking(_, _)
|
|
||||||
| CarState::Parking(_, _, _)
|
|
||||||
| CarState::Idling(_, _) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CarState::Parking(_, spot, ref time_int) => {
|
||||||
|
if time > time_int.end {
|
||||||
|
delete_indices.push(idx);
|
||||||
|
parking.add_parked_car(ParkedCar {
|
||||||
|
vehicle: car.vehicle.clone(),
|
||||||
|
spot,
|
||||||
|
});
|
||||||
|
trips.car_reached_parking_spot(
|
||||||
|
time,
|
||||||
|
car.vehicle.id,
|
||||||
|
spot,
|
||||||
|
map,
|
||||||
|
parking,
|
||||||
|
scheduler,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CarState::Idling(dist, ref time_int) => {
|
||||||
|
if time > time_int.end {
|
||||||
|
car.router = transit.bus_departed_from_stop(car.vehicle.id, map);
|
||||||
|
car.state = car.crossing_state(dist, time, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the finished cars starting from the end of the queue (the beginning of the
|
||||||
|
// traversable), so indices aren't messed up.
|
||||||
|
delete_indices.reverse();
|
||||||
|
for idx in delete_indices {
|
||||||
|
self.cars.remove(&queue.cars.remove(idx).unwrap());
|
||||||
|
|
||||||
|
// Update the follower so that they don't suddenly jump forwards.
|
||||||
|
if idx != queue.cars.len() {
|
||||||
|
let (follower_id, follower_dist) = dists[idx + 1];
|
||||||
|
let mut follower = self.cars.get_mut(&follower_id).unwrap();
|
||||||
|
// TODO If the leader vanished at a border node, this still jumps a bit -- the
|
||||||
|
// lead car's back is still sticking out. Need to still be bound by them, even
|
||||||
|
// though they don't exist! If the leader just parked, then we're fine.
|
||||||
|
match follower.state {
|
||||||
|
CarState::Queued | CarState::Crossing(_, _) => {
|
||||||
|
// If the follower was still Crossing, they might not've been blocked
|
||||||
|
// by leader yet. In that case, recalculating their Crossing state is a
|
||||||
|
// no-op. But if they were blocked, then this will prevent them from
|
||||||
|
// jumping forwards.
|
||||||
|
follower.state = follower.crossing_state(follower_dist, time, map);
|
||||||
|
}
|
||||||
|
// They weren't blocked
|
||||||
|
CarState::Unparking(_, _)
|
||||||
|
| CarState::Parking(_, _, _)
|
||||||
|
| CarState::Idling(_, _) => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,7 +320,8 @@ impl DrivingSimState {
|
|||||||
map,
|
map,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// They weren't blocked
|
// They weren't blocked. Note that there's no way the Crossing state could jump
|
||||||
|
// forwards here; the leader vanished from the end of the traversable.
|
||||||
CarState::Crossing(_, _)
|
CarState::Crossing(_, _)
|
||||||
| CarState::Unparking(_, _)
|
| CarState::Unparking(_, _)
|
||||||
| CarState::Parking(_, _, _)
|
| CarState::Parking(_, _, _)
|
||||||
|
Loading…
Reference in New Issue
Block a user