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(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
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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> {
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
|
@ -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.
|
||||||
|
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::{
|
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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user