Skip to content

Commit

Permalink
Merge pull request #89 from Janekdererste/routing_enhancements
Browse files Browse the repository at this point in the history
enhanced routing (changes from #70)
  • Loading branch information
paulheinr authored Jun 12, 2023
2 parents 1de769b + 39e47e9 commit 9d8ce86
Show file tree
Hide file tree
Showing 13 changed files with 547 additions and 197 deletions.
26 changes: 16 additions & 10 deletions src/simulation/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ pub fn run(world: SystemCommunicator, config: Config) {
&network,
config.routing_mode,
);

let mut vehicle_definitions: Option<VehicleDefinitions> = None;
if let Some(vehicle_definitions_file_path) = &config.vehicle_definitions_file {
let io_vehicle_definitions =
IOVehicleDefinitions::from_file(vehicle_definitions_file_path.as_ref());
vehicle_definitions = Some(VehicleDefinitions::from_io(io_vehicle_definitions));
}

let routing_kit_network_by_mode =
TravelTimesCollectingRoadRouter::get_routing_kit_network_by_mode(
&network,
vehicle_definitions.as_ref(),
);

let network_partition = network.partitions.remove(rank as usize);
info!(
"Partition #{rank} network has: {} nodes and {} links. Population has {} agents",
Expand Down Expand Up @@ -94,23 +108,15 @@ pub fn run(world: SystemCommunicator, config: Config) {
events.add_subscriber(travel_time_collector);
//events.add_subscriber(Box::new(EventsLogger {}));

let mut vehicle_definitions: Option<VehicleDefinitions> = None;
if let Some(vehicle_definitions_file_path) = &config.vehicle_definitions_file {
let io_vehicle_definitions =
IOVehicleDefinitions::from_file(vehicle_definitions_file_path.as_ref());
vehicle_definitions = Some(VehicleDefinitions::from_io(io_vehicle_definitions));
}

let mut router: Option<Box<dyn Router>> = None;
let mut walk_leg_finder: Option<Box<dyn WalkLegUpdater>> = None;
if config.routing_mode == RoutingMode::AdHoc {
router = Some(Box::new(TravelTimesCollectingRoadRouter::new(
io_network,
Some(&id_mappings),
routing_kit_network_by_mode,
world.clone(),
rank,
get_temp_output_folder(&output_path, rank),
vehicle_definitions.clone(),
network_partition.get_link_ids(),
)));

let walking_speed_in_m_per_sec = 1.2;
Expand Down
56 changes: 47 additions & 9 deletions src/simulation/io/vehicle_definitions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::simulation::io::xml_reader;
use log::debug;
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
Expand All @@ -25,6 +26,8 @@ pub enum IOVehicleAttribute {
EgressTime(IOEgressTime),
DoorOperation(IODoorOperation),
PassengerCarEquivalents(IOPassengerCarEquivalents),
NetworkMode(IONetworkMode),
FlowEfficiencyFactor(IOFlowEfficiencyFactor),
}

#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
Expand Down Expand Up @@ -69,10 +72,23 @@ pub struct IOPassengerCarEquivalents {
pce: f32,
}

#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct IONetworkMode {
network_mode: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct IOFlowEfficiencyFactor {
network_mode: f32,
}

#[derive(Debug, PartialEq, Clone)]
pub struct VehicleType {
pub id: String,
pub maximum_velocity: Option<f32>,
pub network_mode: String,
}

#[derive(Debug, PartialEq, Clone)]
Expand All @@ -97,10 +113,12 @@ impl VehicleDefinitions {
mut self,
id: String,
maximum_velocity: Option<f32>,
network_mode: String,
) -> VehicleDefinitions {
self.vehicle_types.push(VehicleType {
id,
maximum_velocity,
network_mode,
});
self
}
Expand All @@ -115,28 +133,45 @@ impl VehicleDefinitions {
}

fn convert_io_vehicle_type(io: IOVehicleType) -> VehicleType {
let maximum_velocity = io
.attributes
VehicleType {
id: io.id.clone(),
maximum_velocity: Self::extract_maximum_velocity(&io),
network_mode: Self::extract_network_mode(&io).unwrap_or_else(|| {
debug!("There was no specific network mode for vehicle type {}. Using id as network mode.", io.id);
io.id
}),
}
}

fn extract_maximum_velocity(io: &IOVehicleType) -> Option<f32> {
io.attributes
.iter()
.filter_map(|a| match a {
IOVehicleAttribute::MaximumVelocity(v) => Some(v.meter_per_second),
_ => None,
})
.collect::<Vec<f32>>()
.get(0)
.cloned();
.cloned()
}

VehicleType {
id: io.id,
maximum_velocity,
}
fn extract_network_mode(io: &IOVehicleType) -> Option<String> {
io.attributes
.iter()
.filter_map(|a| match a {
IOVehicleAttribute::NetworkMode(m) => Some(m.network_mode.clone()),
_ => None,
})
.collect::<Vec<String>>()
.get(0)
.cloned()
}

pub fn get_max_speed_for_mode(&self, mode: &str) -> Option<f32> {
let mode_vehicle_type = self
.vehicle_types
.iter()
.filter(|&v| v.id.eq(mode))
.filter(|&v| v.network_mode.eq(mode))
.collect::<Vec<&VehicleType>>();

if mode_vehicle_type.len() == 0 {
Expand Down Expand Up @@ -172,6 +207,7 @@ mod test {
<egressTime secondsPerPerson="1.0"/>
<doorOperation mode="serial"/>
<passengerCarEquivalents pce="1.0"/>
<networkMode networkMode="car"/>
</vehicleType>
<vehicleType id="bicycle">
<length meter="7.5"/>
Expand All @@ -194,10 +230,12 @@ mod test {
VehicleType {
id: "car".to_string(),
maximum_velocity: Some(16.67),
network_mode: "car".to_string()
},
VehicleType {
id: "bicycle".to_string(),
maximum_velocity: Some(4.17)
maximum_velocity: Some(4.17),
network_mode: "bicycle".to_string()
}
],
}
Expand Down
28 changes: 28 additions & 0 deletions src/simulation/messaging/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::cmp::Ordering;
use std::collections::HashMap;
use std::io::Cursor;

use log::debug;
use prost::Message;

use crate::simulation::config::RoutingMode;
Expand Down Expand Up @@ -172,6 +173,18 @@ impl Agent {
routing_mode: RoutingMode,
) -> Agent {
let plan = Plan::from_io(io_person.selected_plan(), id_mappings, routing_mode);

if plan.acts.is_empty() {
debug!("There is an empty plan for person {:?}", io_person.id);
}

if plan.acts.len() == 1 {
debug!(
"There is a plan with one activity only for person {:?}",
io_person.id
);
}

let id = *id_mappings.agents.get_internal(io_person.id()).unwrap();
Agent {
id: id as u64,
Expand Down Expand Up @@ -422,6 +435,21 @@ impl Plan {
}

fn get_full_plan_for_routing(io_plan: &IOPlan, id_mappings: &MatsimIdMappings) -> Plan {
if io_plan.elements.is_empty() {
return Plan::new();
}

if io_plan.elements.len() == 1 {
let mut plan = Plan::new();
if let IOPlanElement::Activity(io_activity) = io_plan.elements.get(0).unwrap() {
plan.acts
.push(Activity::from_io(io_activity, &id_mappings.links));
} else {
panic!("The first element of a plan has to be an activity.")
}
return plan;
}

let plan_type = Plan::get_plan_type(io_plan);
let window_size = plan_type.window_size();
let step_size = plan_type.step_size();
Expand Down
86 changes: 85 additions & 1 deletion src/simulation/messaging/travel_time_collector.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::simulation::messaging::events::proto::event::Type;
use crate::simulation::messaging::events::proto::{Event, LinkEnterEvent, LinkLeaveEvent};
use crate::simulation::messaging::events::proto::{
Event, LinkEnterEvent, LinkLeaveEvent, PersonLeavesVehicleEvent,
};
use crate::simulation::messaging::events::EventsSubscriber;
use std::any::Any;
use std::collections::HashMap;

pub struct TravelTimeCollector {
travel_times_by_link: HashMap<u64, Vec<u32>>,
cache_traffic_information_by_link: HashMap<u64, Vec<TrafficInformation>>,
current_link_by_vehicle: HashMap<u64, u64>,
}

#[derive(Debug, PartialEq, Clone)]
Expand All @@ -20,6 +23,7 @@ impl TravelTimeCollector {
TravelTimeCollector {
travel_times_by_link: HashMap::new(),
cache_traffic_information_by_link: HashMap::new(),
current_link_by_vehicle: HashMap::new(),
}
}

Expand All @@ -32,6 +36,9 @@ impl TravelTimeCollector {
time,
vehicle: event.vehicle,
});

self.current_link_by_vehicle
.insert(event.vehicle, event.link);
}

fn process_link_leave_event(&mut self, time: u32, event: &LinkLeaveEvent) {
Expand Down Expand Up @@ -59,6 +66,33 @@ impl TravelTimeCollector {
}
}

fn process_person_leaves_vehicle_event(&mut self, time: u32, event: &PersonLeavesVehicleEvent) {
// if there is no current link id of vehicle of link enter event, cache doesn't have to be cleaned up
let link_id = self.current_link_by_vehicle.get(&event.vehicle).copied();
if link_id.is_none() {
return;
}

let index_of_link_enter =
self.get_index_of_link_enter_event(link_id.unwrap(), event.vehicle);
if index_of_link_enter.is_none() {
return;
}

self.cache_traffic_information_by_link
.get_mut(&link_id.unwrap())
.unwrap()
.remove(index_of_link_enter.unwrap());
}

fn get_index_of_link_enter_event(&mut self, link: u64, vehicle: u64) -> Option<usize> {
self.cache_traffic_information_by_link
.entry(link)
.or_insert(Vec::new())
.iter()
.position(|t| t.vehicle == vehicle)
}

pub fn get_travel_time_of_link(&self, link: u64) -> Option<u32> {
match self.travel_times_by_link.get(&link) {
None => None,
Expand Down Expand Up @@ -92,6 +126,7 @@ impl EventsSubscriber for TravelTimeCollector {
match event.r#type.as_ref().unwrap() {
Type::LinkEnter(e) => self.process_link_enter_event(time, e),
Type::LinkLeave(e) => self.process_link_leave_event(time, e),
Type::PersonLeavesVeh(e) => self.process_person_leaves_vehicle_event(time, e),
_ => {}
}
}
Expand Down Expand Up @@ -179,4 +214,53 @@ mod test {
})
);
}

#[test]
/// Tests whether PersonLeavesVehicleEvent discards travel time
fn test_with_person_leaves_vehicle() {
let mut collector = TravelTimeCollector::new();
collector.receive_event(0, &Event::new_link_enter(1, 1));
collector.receive_event(2, &Event::new_person_leaves_veh(1, 1));
collector.receive_event(4, &Event::new_link_leave(1, 1));

assert_eq!(collector.get_travel_time_of_link(1), None);
assert_eq!(
collector
.cache_traffic_information_by_link
.get(&1)
.unwrap()
.len(),
0
);
}

#[test]
/// Tests whether PersonLeavesVehicleEvent discards travel time
fn test_with_person_leaves_vehicle_complex() {
let mut collector = TravelTimeCollector::new();
collector.receive_event(0, &Event::new_link_enter(1, 1));

//intermediate veh 2 enters link 1
collector.receive_event(1, &Event::new_link_enter(1, 2));

collector.receive_event(2, &Event::new_person_leaves_veh(1, 1));

//intermediate veh 2 leaves link 1
collector.receive_event(3, &Event::new_link_leave(1, 2));

collector.receive_event(10, &Event::new_link_leave(1, 1));
collector.receive_event(10, &Event::new_link_enter(2, 1));
collector.receive_event(20, &Event::new_link_leave(2, 1));

assert_eq!(collector.get_travel_time_of_link(1), Some(2));
assert_eq!(collector.get_travel_time_of_link(2), Some(10));
assert_eq!(
collector
.cache_traffic_information_by_link
.get(&1)
.unwrap()
.len(),
0
);
}
}
Loading

0 comments on commit 9d8ce86

Please sign in to comment.