mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
port scheduler. use it for spawning peds.
This commit is contained in:
parent
661b486870
commit
2e37d673b8
@ -341,7 +341,6 @@ fn random_ped_near(
|
||||
new_des_model::SidewalkSpot::bike_rack(pos1, map),
|
||||
new_des_model::SidewalkSpot::bike_rack(pos2, map),
|
||||
path,
|
||||
map,
|
||||
);
|
||||
*counter += 1
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::plugins::sim::new_des_model::mechanics::car::{Car, CarState};
|
||||
use crate::plugins::sim::new_des_model::mechanics::queue::Queue;
|
||||
use crate::plugins::sim::new_des_model::{
|
||||
ActionAtEnd, IntersectionSimState, ParkedCar, ParkingSimState, Router, TimeInterval, Vehicle,
|
||||
FOLLOWING_DISTANCE, MAX_VEHICLE_LENGTH,
|
||||
ActionAtEnd, CreateCar, IntersectionSimState, ParkedCar, ParkingSimState, Router, TimeInterval,
|
||||
Vehicle, FOLLOWING_DISTANCE, MAX_VEHICLE_LENGTH,
|
||||
};
|
||||
use ezgui::{Color, GfxCtx};
|
||||
use geom::{Distance, Duration};
|
||||
@ -127,6 +127,16 @@ impl DrivingSimState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_car_on_lane(
|
||||
&mut self,
|
||||
time: Duration,
|
||||
map: &Map,
|
||||
params: CreateCar,
|
||||
intersections: &IntersectionSimState,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn spawn_car(
|
||||
&mut self,
|
||||
vehicle: Vehicle,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::plugins::sim::new_des_model::{
|
||||
DistanceInterval, IntersectionSimState, SidewalkPOI, SidewalkSpot, TimeInterval,
|
||||
CreatePedestrian, DistanceInterval, IntersectionSimState, SidewalkPOI, SidewalkSpot,
|
||||
TimeInterval,
|
||||
};
|
||||
use abstutil::{deserialize_multimap, serialize_multimap};
|
||||
use geom::{Distance, Duration, Speed};
|
||||
@ -31,46 +32,40 @@ impl WalkingSimState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_ped(
|
||||
&mut self,
|
||||
id: PedestrianID,
|
||||
start_time: Duration,
|
||||
start: SidewalkSpot,
|
||||
goal: SidewalkSpot,
|
||||
path: Path,
|
||||
map: &Map,
|
||||
) {
|
||||
let start_lane = start.sidewalk_pos.lane();
|
||||
pub fn spawn_ped(&mut self, time: Duration, params: CreatePedestrian, map: &Map) {
|
||||
let start_lane = params.start.sidewalk_pos.lane();
|
||||
assert_eq!(
|
||||
path.current_step().as_traversable(),
|
||||
params.path.current_step().as_traversable(),
|
||||
Traversable::Lane(start_lane)
|
||||
);
|
||||
assert_eq!(
|
||||
path.last_step().as_traversable(),
|
||||
Traversable::Lane(goal.sidewalk_pos.lane())
|
||||
params.path.last_step().as_traversable(),
|
||||
Traversable::Lane(params.goal.sidewalk_pos.lane())
|
||||
);
|
||||
|
||||
let mut ped = Pedestrian {
|
||||
id,
|
||||
id: params.id,
|
||||
// Temporary bogus thing
|
||||
state: PedState::Crossing(
|
||||
DistanceInterval::new_walking(Distance::ZERO, Distance::meters(1.0)),
|
||||
TimeInterval::new(Duration::ZERO, Duration::seconds(1.0)),
|
||||
true,
|
||||
),
|
||||
path,
|
||||
goal,
|
||||
path: params.path,
|
||||
goal: params.goal,
|
||||
};
|
||||
ped.state = match start.connection {
|
||||
ped.state = match params.start.connection {
|
||||
SidewalkPOI::BikeRack => {
|
||||
ped.crossing_state(start.sidewalk_pos.dist_along(), start_time, map)
|
||||
ped.crossing_state(params.start.sidewalk_pos.dist_along(), time, map)
|
||||
}
|
||||
_ => panic!("Don't support {:?} yet", start.connection),
|
||||
_ => panic!("Don't support {:?} yet", params.start.connection),
|
||||
};
|
||||
|
||||
self.peds.insert(id, ped);
|
||||
self.peds_per_traversable
|
||||
.insert(Traversable::Lane(start.sidewalk_pos.lane()), id);
|
||||
self.peds.insert(params.id, ped);
|
||||
self.peds_per_traversable.insert(
|
||||
Traversable::Lane(params.start.sidewalk_pos.lane()),
|
||||
params.id,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_all_draw_peds(&self, time: Duration, map: &Map) -> Vec<DrawPedestrianInput> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
mod mechanics;
|
||||
mod router;
|
||||
mod scheduler;
|
||||
mod sim;
|
||||
mod trips;
|
||||
|
||||
@ -7,11 +8,12 @@ pub use self::mechanics::{
|
||||
DrivingSimState, IntersectionSimState, ParkingSimState, WalkingSimState,
|
||||
};
|
||||
pub use self::router::{ActionAtEnd, Router};
|
||||
pub use self::scheduler::{Command, Scheduler};
|
||||
pub use self::sim::Sim;
|
||||
pub use self::trips::TripManager;
|
||||
use ::sim::{CarID, VehicleType};
|
||||
use ::sim::{CarID, PedestrianID, TripID, VehicleType};
|
||||
use geom::{Distance, Duration, Speed};
|
||||
use map_model::{BuildingID, BusStopID, IntersectionID, LaneID, LaneType, Map, Position};
|
||||
use map_model::{BuildingID, BusStopID, IntersectionID, LaneID, LaneType, Map, Path, Position};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
pub const MIN_VEHICLE_LENGTH: Distance = Distance::const_meters(2.0);
|
||||
@ -202,3 +204,22 @@ impl DistanceInterval {
|
||||
(self.end - self.start).abs()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
pub struct CreatePedestrian {
|
||||
pub id: PedestrianID,
|
||||
pub start: SidewalkSpot,
|
||||
pub goal: SidewalkSpot,
|
||||
pub path: Path,
|
||||
pub trip: TripID,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
|
||||
pub struct CreateCar {
|
||||
pub vehicle: Vehicle,
|
||||
pub router: Router,
|
||||
pub start_time: Duration,
|
||||
pub start_dist: Distance,
|
||||
pub maybe_parked_car: Option<ParkedCar>,
|
||||
pub trip: TripID,
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::plugins::sim::new_des_model::{ParkingSimState, ParkingSpot, Vehicle};
|
||||
use geom::Distance;
|
||||
use map_model::{BuildingID, LaneType, Map, Position, Traversable};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
pub struct Router {
|
||||
// Front is always the current step
|
||||
path: VecDeque<Traversable>,
|
||||
@ -16,7 +17,7 @@ pub enum ActionAtEnd {
|
||||
GotoLaneEnd,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
enum Goal {
|
||||
// Spot and distance along the last driving lane
|
||||
// TODO Right now, the building is ignored.
|
||||
|
107
editor/src/plugins/sim/new_des_model/scheduler.rs
Normal file
107
editor/src/plugins/sim/new_des_model/scheduler.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use crate::plugins::sim::new_des_model::{
|
||||
CreateCar, CreatePedestrian, DrivingSimState, IntersectionSimState, ParkingSimState,
|
||||
TripManager, WalkingSimState,
|
||||
};
|
||||
use geom::Duration;
|
||||
use map_model::Map;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use sim::AgentID;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum Command {
|
||||
SpawnCar(Duration, CreateCar),
|
||||
SpawnPed(Duration, CreatePedestrian),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
fn at(&self) -> Duration {
|
||||
match self {
|
||||
Command::SpawnCar(at, _) => *at,
|
||||
Command::SpawnPed(at, _) => *at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq)]
|
||||
pub struct Scheduler {
|
||||
// Ordered descending by time
|
||||
commands: Vec<Command>,
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
pub fn new() -> Scheduler {
|
||||
Scheduler {
|
||||
commands: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step_if_needed(
|
||||
&mut self,
|
||||
now: Duration,
|
||||
map: &Map,
|
||||
parking_sim: &mut ParkingSimState,
|
||||
walking_sim: &mut WalkingSimState,
|
||||
driving_sim: &mut DrivingSimState,
|
||||
intersections: &IntersectionSimState,
|
||||
trips: &mut TripManager,
|
||||
) {
|
||||
let mut this_tick_commands: Vec<Command> = Vec::new();
|
||||
loop {
|
||||
if self
|
||||
.commands
|
||||
.last()
|
||||
// TODO >= just to handle the fact that we dont step on 0
|
||||
.and_then(|cmd| Some(now >= cmd.at()))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
this_tick_commands.push(self.commands.pop().unwrap());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if this_tick_commands.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for cmd in this_tick_commands.into_iter() {
|
||||
match cmd {
|
||||
Command::SpawnCar(_, create_car) => {
|
||||
if driving_sim.start_car_on_lane(now, map, create_car.clone(), intersections) {
|
||||
trips.agent_starting_trip_leg(
|
||||
AgentID::Car(create_car.vehicle.id),
|
||||
create_car.trip,
|
||||
);
|
||||
if let Some(parked_car) = create_car.maybe_parked_car {
|
||||
parking_sim.remove_parked_car(parked_car);
|
||||
}
|
||||
} else {
|
||||
self.enqueue_command(Command::SpawnCar(
|
||||
now + Duration::EPSILON,
|
||||
create_car,
|
||||
));
|
||||
}
|
||||
}
|
||||
Command::SpawnPed(_, create_ped) => {
|
||||
// Do the order a bit backwards so we don't have to clone the CreatePedestrian.
|
||||
// spawn_ped can't fail.
|
||||
trips.agent_starting_trip_leg(
|
||||
AgentID::Pedestrian(create_ped.id),
|
||||
create_ped.trip,
|
||||
);
|
||||
walking_sim.spawn_ped(now, create_ped, map);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_done(&self) -> bool {
|
||||
self.commands.is_empty()
|
||||
}
|
||||
|
||||
pub fn enqueue_command(&mut self, cmd: Command) {
|
||||
// TODO Use some kind of priority queue that's serializable
|
||||
self.commands.push(cmd);
|
||||
self.commands.sort_by_key(|cmd| cmd.at());
|
||||
self.commands.reverse();
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
use crate::plugins::sim::new_des_model::{
|
||||
DrivingSimState, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, Router,
|
||||
SidewalkSpot, TripManager, Vehicle, WalkingSimState,
|
||||
Command, CreatePedestrian, DrivingSimState, IntersectionSimState, ParkedCar, ParkingSimState,
|
||||
ParkingSpot, Router, Scheduler, SidewalkSpot, TripManager, Vehicle, WalkingSimState,
|
||||
};
|
||||
use ezgui::GfxCtx;
|
||||
use geom::{Distance, Duration};
|
||||
use map_model::{LaneID, Map, Path, Position, Traversable};
|
||||
use sim::{DrawCarInput, DrawPedestrianInput, PedestrianID};
|
||||
use sim::{DrawCarInput, DrawPedestrianInput, PedestrianID, TripID};
|
||||
|
||||
pub struct Sim {
|
||||
driving: DrivingSimState,
|
||||
@ -13,6 +13,7 @@ pub struct Sim {
|
||||
walking: WalkingSimState,
|
||||
intersections: IntersectionSimState,
|
||||
trips: TripManager,
|
||||
scheduler: Scheduler,
|
||||
}
|
||||
|
||||
impl Sim {
|
||||
@ -23,6 +24,7 @@ impl Sim {
|
||||
walking: WalkingSimState::new(),
|
||||
intersections: IntersectionSimState::new(map),
|
||||
trips: TripManager::new(),
|
||||
scheduler: Scheduler::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +65,7 @@ impl Sim {
|
||||
self.walking.get_draw_peds(time, on, map)
|
||||
}
|
||||
|
||||
// TODO Many of these should go away
|
||||
pub fn spawn_car(
|
||||
&mut self,
|
||||
vehicle: Vehicle,
|
||||
@ -89,11 +92,17 @@ impl Sim {
|
||||
start: SidewalkSpot,
|
||||
goal: SidewalkSpot,
|
||||
path: Path,
|
||||
map: &Map,
|
||||
) {
|
||||
let start_time = Duration::ZERO;
|
||||
self.walking
|
||||
.spawn_ped(id, start_time, start, goal, path, map);
|
||||
self.scheduler.enqueue_command(Command::SpawnPed(
|
||||
Duration::ZERO,
|
||||
CreatePedestrian {
|
||||
id,
|
||||
start,
|
||||
goal,
|
||||
path,
|
||||
trip: TripID(0),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn get_free_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
|
||||
@ -122,5 +131,16 @@ impl Sim {
|
||||
.step_if_needed(time, map, &mut self.parking, &mut self.intersections);
|
||||
self.walking
|
||||
.step_if_needed(time, map, &mut self.intersections);
|
||||
|
||||
// Spawn stuff at the end, so we can see the correct state of everything else at this time.
|
||||
self.scheduler.step_if_needed(
|
||||
time,
|
||||
map,
|
||||
&mut self.parking,
|
||||
&mut self.walking,
|
||||
&mut self.driving,
|
||||
&self.intersections,
|
||||
&mut self.trips,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +155,14 @@ impl ops::Div<Speed> for Distance {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Duration(f64);
|
||||
|
||||
// By construction, Duration is a finite f64 with trimmed precision.
|
||||
impl Eq for Duration {}
|
||||
impl Ord for Duration {
|
||||
fn cmp(&self, other: &Duration) -> cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Duration {
|
||||
pub const ZERO: Duration = Duration::const_seconds(0.0);
|
||||
pub const EPSILON: Duration = Duration::const_seconds(0.0001);
|
||||
|
Loading…
Reference in New Issue
Block a user