port scheduler. use it for spawning peds.

This commit is contained in:
Dustin Carlino 2019-02-23 14:49:30 -08:00
parent 661b486870
commit 2e37d673b8
8 changed files with 198 additions and 37 deletions

View File

@ -341,7 +341,6 @@ fn random_ped_near(
new_des_model::SidewalkSpot::bike_rack(pos1, map), new_des_model::SidewalkSpot::bike_rack(pos1, map),
new_des_model::SidewalkSpot::bike_rack(pos2, map), new_des_model::SidewalkSpot::bike_rack(pos2, map),
path, path,
map,
); );
*counter += 1 *counter += 1
} }

View File

@ -1,8 +1,8 @@
use crate::plugins::sim::new_des_model::mechanics::car::{Car, CarState}; 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::mechanics::queue::Queue;
use crate::plugins::sim::new_des_model::{ use crate::plugins::sim::new_des_model::{
ActionAtEnd, IntersectionSimState, ParkedCar, ParkingSimState, Router, TimeInterval, Vehicle, ActionAtEnd, CreateCar, IntersectionSimState, ParkedCar, ParkingSimState, Router, TimeInterval,
FOLLOWING_DISTANCE, MAX_VEHICLE_LENGTH, Vehicle, FOLLOWING_DISTANCE, MAX_VEHICLE_LENGTH,
}; };
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Distance, Duration}; 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( pub fn spawn_car(
&mut self, &mut self,
vehicle: Vehicle, vehicle: Vehicle,

View File

@ -1,5 +1,6 @@
use crate::plugins::sim::new_des_model::{ 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 abstutil::{deserialize_multimap, serialize_multimap};
use geom::{Distance, Duration, Speed}; use geom::{Distance, Duration, Speed};
@ -31,46 +32,40 @@ impl WalkingSimState {
} }
} }
pub fn spawn_ped( pub fn spawn_ped(&mut self, time: Duration, params: CreatePedestrian, map: &Map) {
&mut self, let start_lane = params.start.sidewalk_pos.lane();
id: PedestrianID,
start_time: Duration,
start: SidewalkSpot,
goal: SidewalkSpot,
path: Path,
map: &Map,
) {
let start_lane = start.sidewalk_pos.lane();
assert_eq!( assert_eq!(
path.current_step().as_traversable(), params.path.current_step().as_traversable(),
Traversable::Lane(start_lane) Traversable::Lane(start_lane)
); );
assert_eq!( assert_eq!(
path.last_step().as_traversable(), params.path.last_step().as_traversable(),
Traversable::Lane(goal.sidewalk_pos.lane()) Traversable::Lane(params.goal.sidewalk_pos.lane())
); );
let mut ped = Pedestrian { let mut ped = Pedestrian {
id, id: params.id,
// Temporary bogus thing // Temporary bogus thing
state: PedState::Crossing( state: PedState::Crossing(
DistanceInterval::new_walking(Distance::ZERO, Distance::meters(1.0)), DistanceInterval::new_walking(Distance::ZERO, Distance::meters(1.0)),
TimeInterval::new(Duration::ZERO, Duration::seconds(1.0)), TimeInterval::new(Duration::ZERO, Duration::seconds(1.0)),
true, true,
), ),
path, path: params.path,
goal, goal: params.goal,
}; };
ped.state = match start.connection { ped.state = match params.start.connection {
SidewalkPOI::BikeRack => { 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.insert(params.id, ped);
self.peds_per_traversable self.peds_per_traversable.insert(
.insert(Traversable::Lane(start.sidewalk_pos.lane()), id); Traversable::Lane(params.start.sidewalk_pos.lane()),
params.id,
);
} }
pub fn get_all_draw_peds(&self, time: Duration, map: &Map) -> Vec<DrawPedestrianInput> { pub fn get_all_draw_peds(&self, time: Duration, map: &Map) -> Vec<DrawPedestrianInput> {

View File

@ -1,5 +1,6 @@
mod mechanics; mod mechanics;
mod router; mod router;
mod scheduler;
mod sim; mod sim;
mod trips; mod trips;
@ -7,11 +8,12 @@ pub use self::mechanics::{
DrivingSimState, IntersectionSimState, ParkingSimState, WalkingSimState, DrivingSimState, IntersectionSimState, ParkingSimState, WalkingSimState,
}; };
pub use self::router::{ActionAtEnd, Router}; pub use self::router::{ActionAtEnd, Router};
pub use self::scheduler::{Command, Scheduler};
pub use self::sim::Sim; pub use self::sim::Sim;
pub use self::trips::TripManager; pub use self::trips::TripManager;
use ::sim::{CarID, VehicleType}; use ::sim::{CarID, PedestrianID, TripID, VehicleType};
use geom::{Distance, Duration, Speed}; 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}; use serde_derive::{Deserialize, Serialize};
pub const MIN_VEHICLE_LENGTH: Distance = Distance::const_meters(2.0); pub const MIN_VEHICLE_LENGTH: Distance = Distance::const_meters(2.0);
@ -202,3 +204,22 @@ impl DistanceInterval {
(self.end - self.start).abs() (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,
}

View File

@ -1,9 +1,10 @@
use crate::plugins::sim::new_des_model::{ParkingSimState, ParkingSpot, Vehicle}; use crate::plugins::sim::new_des_model::{ParkingSimState, ParkingSpot, Vehicle};
use geom::Distance; use geom::Distance;
use map_model::{BuildingID, LaneType, Map, Position, Traversable}; use map_model::{BuildingID, LaneType, Map, Position, Traversable};
use serde_derive::{Deserialize, Serialize};
use std::collections::VecDeque; use std::collections::VecDeque;
#[derive(Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Router { pub struct Router {
// Front is always the current step // Front is always the current step
path: VecDeque<Traversable>, path: VecDeque<Traversable>,
@ -16,7 +17,7 @@ pub enum ActionAtEnd {
GotoLaneEnd, GotoLaneEnd,
} }
#[derive(Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
enum Goal { enum Goal {
// Spot and distance along the last driving lane // Spot and distance along the last driving lane
// TODO Right now, the building is ignored. // TODO Right now, the building is ignored.

View 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();
}
}

View File

@ -1,11 +1,11 @@
use crate::plugins::sim::new_des_model::{ use crate::plugins::sim::new_des_model::{
DrivingSimState, IntersectionSimState, ParkedCar, ParkingSimState, ParkingSpot, Router, Command, CreatePedestrian, DrivingSimState, IntersectionSimState, ParkedCar, ParkingSimState,
SidewalkSpot, TripManager, Vehicle, WalkingSimState, ParkingSpot, Router, Scheduler, SidewalkSpot, TripManager, Vehicle, WalkingSimState,
}; };
use ezgui::GfxCtx; use ezgui::GfxCtx;
use geom::{Distance, Duration}; use geom::{Distance, Duration};
use map_model::{LaneID, Map, Path, Position, Traversable}; use map_model::{LaneID, Map, Path, Position, Traversable};
use sim::{DrawCarInput, DrawPedestrianInput, PedestrianID}; use sim::{DrawCarInput, DrawPedestrianInput, PedestrianID, TripID};
pub struct Sim { pub struct Sim {
driving: DrivingSimState, driving: DrivingSimState,
@ -13,6 +13,7 @@ pub struct Sim {
walking: WalkingSimState, walking: WalkingSimState,
intersections: IntersectionSimState, intersections: IntersectionSimState,
trips: TripManager, trips: TripManager,
scheduler: Scheduler,
} }
impl Sim { impl Sim {
@ -23,6 +24,7 @@ impl Sim {
walking: WalkingSimState::new(), walking: WalkingSimState::new(),
intersections: IntersectionSimState::new(map), intersections: IntersectionSimState::new(map),
trips: TripManager::new(), trips: TripManager::new(),
scheduler: Scheduler::new(),
} }
} }
@ -63,6 +65,7 @@ impl Sim {
self.walking.get_draw_peds(time, on, map) self.walking.get_draw_peds(time, on, map)
} }
// TODO Many of these should go away
pub fn spawn_car( pub fn spawn_car(
&mut self, &mut self,
vehicle: Vehicle, vehicle: Vehicle,
@ -89,11 +92,17 @@ impl Sim {
start: SidewalkSpot, start: SidewalkSpot,
goal: SidewalkSpot, goal: SidewalkSpot,
path: Path, path: Path,
map: &Map,
) { ) {
let start_time = Duration::ZERO; self.scheduler.enqueue_command(Command::SpawnPed(
self.walking Duration::ZERO,
.spawn_ped(id, start_time, start, goal, path, map); CreatePedestrian {
id,
start,
goal,
path,
trip: TripID(0),
},
));
} }
pub fn get_free_spots(&self, l: LaneID) -> Vec<ParkingSpot> { 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); .step_if_needed(time, map, &mut self.parking, &mut self.intersections);
self.walking self.walking
.step_if_needed(time, map, &mut self.intersections); .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,
);
} }
} }

View File

@ -155,6 +155,14 @@ impl ops::Div<Speed> for Distance {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Duration(f64); 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 { impl Duration {
pub const ZERO: Duration = Duration::const_seconds(0.0); pub const ZERO: Duration = Duration::const_seconds(0.0);
pub const EPSILON: Duration = Duration::const_seconds(0.0001); pub const EPSILON: Duration = Duration::const_seconds(0.0001);