Skip to content

Commit 9d8ce86

Browse files
authored
Merge pull request #89 from Janekdererste/routing_enhancements
enhanced routing (changes from #70)
2 parents 1de769b + 39e47e9 commit 9d8ce86

13 files changed

+547
-197
lines changed

src/simulation/controller.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ pub fn run(world: SystemCommunicator, config: Config) {
6767
&network,
6868
config.routing_mode,
6969
);
70+
71+
let mut vehicle_definitions: Option<VehicleDefinitions> = None;
72+
if let Some(vehicle_definitions_file_path) = &config.vehicle_definitions_file {
73+
let io_vehicle_definitions =
74+
IOVehicleDefinitions::from_file(vehicle_definitions_file_path.as_ref());
75+
vehicle_definitions = Some(VehicleDefinitions::from_io(io_vehicle_definitions));
76+
}
77+
78+
let routing_kit_network_by_mode =
79+
TravelTimesCollectingRoadRouter::get_routing_kit_network_by_mode(
80+
&network,
81+
vehicle_definitions.as_ref(),
82+
);
83+
7084
let network_partition = network.partitions.remove(rank as usize);
7185
info!(
7286
"Partition #{rank} network has: {} nodes and {} links. Population has {} agents",
@@ -94,23 +108,15 @@ pub fn run(world: SystemCommunicator, config: Config) {
94108
events.add_subscriber(travel_time_collector);
95109
//events.add_subscriber(Box::new(EventsLogger {}));
96110

97-
let mut vehicle_definitions: Option<VehicleDefinitions> = None;
98-
if let Some(vehicle_definitions_file_path) = &config.vehicle_definitions_file {
99-
let io_vehicle_definitions =
100-
IOVehicleDefinitions::from_file(vehicle_definitions_file_path.as_ref());
101-
vehicle_definitions = Some(VehicleDefinitions::from_io(io_vehicle_definitions));
102-
}
103-
104111
let mut router: Option<Box<dyn Router>> = None;
105112
let mut walk_leg_finder: Option<Box<dyn WalkLegUpdater>> = None;
106113
if config.routing_mode == RoutingMode::AdHoc {
107114
router = Some(Box::new(TravelTimesCollectingRoadRouter::new(
108-
io_network,
109-
Some(&id_mappings),
115+
routing_kit_network_by_mode,
110116
world.clone(),
111117
rank,
112118
get_temp_output_folder(&output_path, rank),
113-
vehicle_definitions.clone(),
119+
network_partition.get_link_ids(),
114120
)));
115121

116122
let walking_speed_in_m_per_sec = 1.2;

src/simulation/io/vehicle_definitions.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::simulation::io::xml_reader;
2+
use log::debug;
23
use serde::{Deserialize, Serialize};
34

45
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
@@ -25,6 +26,8 @@ pub enum IOVehicleAttribute {
2526
EgressTime(IOEgressTime),
2627
DoorOperation(IODoorOperation),
2728
PassengerCarEquivalents(IOPassengerCarEquivalents),
29+
NetworkMode(IONetworkMode),
30+
FlowEfficiencyFactor(IOFlowEfficiencyFactor),
2831
}
2932

3033
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
@@ -69,10 +72,23 @@ pub struct IOPassengerCarEquivalents {
6972
pce: f32,
7073
}
7174

75+
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
76+
#[serde(rename_all = "camelCase")]
77+
pub struct IONetworkMode {
78+
network_mode: String,
79+
}
80+
81+
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
82+
#[serde(rename_all = "camelCase")]
83+
pub struct IOFlowEfficiencyFactor {
84+
network_mode: f32,
85+
}
86+
7287
#[derive(Debug, PartialEq, Clone)]
7388
pub struct VehicleType {
7489
pub id: String,
7590
pub maximum_velocity: Option<f32>,
91+
pub network_mode: String,
7692
}
7793

7894
#[derive(Debug, PartialEq, Clone)]
@@ -97,10 +113,12 @@ impl VehicleDefinitions {
97113
mut self,
98114
id: String,
99115
maximum_velocity: Option<f32>,
116+
network_mode: String,
100117
) -> VehicleDefinitions {
101118
self.vehicle_types.push(VehicleType {
102119
id,
103120
maximum_velocity,
121+
network_mode,
104122
});
105123
self
106124
}
@@ -115,28 +133,45 @@ impl VehicleDefinitions {
115133
}
116134

117135
fn convert_io_vehicle_type(io: IOVehicleType) -> VehicleType {
118-
let maximum_velocity = io
119-
.attributes
136+
VehicleType {
137+
id: io.id.clone(),
138+
maximum_velocity: Self::extract_maximum_velocity(&io),
139+
network_mode: Self::extract_network_mode(&io).unwrap_or_else(|| {
140+
debug!("There was no specific network mode for vehicle type {}. Using id as network mode.", io.id);
141+
io.id
142+
}),
143+
}
144+
}
145+
146+
fn extract_maximum_velocity(io: &IOVehicleType) -> Option<f32> {
147+
io.attributes
120148
.iter()
121149
.filter_map(|a| match a {
122150
IOVehicleAttribute::MaximumVelocity(v) => Some(v.meter_per_second),
123151
_ => None,
124152
})
125153
.collect::<Vec<f32>>()
126154
.get(0)
127-
.cloned();
155+
.cloned()
156+
}
128157

129-
VehicleType {
130-
id: io.id,
131-
maximum_velocity,
132-
}
158+
fn extract_network_mode(io: &IOVehicleType) -> Option<String> {
159+
io.attributes
160+
.iter()
161+
.filter_map(|a| match a {
162+
IOVehicleAttribute::NetworkMode(m) => Some(m.network_mode.clone()),
163+
_ => None,
164+
})
165+
.collect::<Vec<String>>()
166+
.get(0)
167+
.cloned()
133168
}
134169

135170
pub fn get_max_speed_for_mode(&self, mode: &str) -> Option<f32> {
136171
let mode_vehicle_type = self
137172
.vehicle_types
138173
.iter()
139-
.filter(|&v| v.id.eq(mode))
174+
.filter(|&v| v.network_mode.eq(mode))
140175
.collect::<Vec<&VehicleType>>();
141176

142177
if mode_vehicle_type.len() == 0 {
@@ -172,6 +207,7 @@ mod test {
172207
<egressTime secondsPerPerson="1.0"/>
173208
<doorOperation mode="serial"/>
174209
<passengerCarEquivalents pce="1.0"/>
210+
<networkMode networkMode="car"/>
175211
</vehicleType>
176212
<vehicleType id="bicycle">
177213
<length meter="7.5"/>
@@ -194,10 +230,12 @@ mod test {
194230
VehicleType {
195231
id: "car".to_string(),
196232
maximum_velocity: Some(16.67),
233+
network_mode: "car".to_string()
197234
},
198235
VehicleType {
199236
id: "bicycle".to_string(),
200-
maximum_velocity: Some(4.17)
237+
maximum_velocity: Some(4.17),
238+
network_mode: "bicycle".to_string()
201239
}
202240
],
203241
}

src/simulation/messaging/messages.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::cmp::Ordering;
22
use std::collections::HashMap;
33
use std::io::Cursor;
44

5+
use log::debug;
56
use prost::Message;
67

78
use crate::simulation::config::RoutingMode;
@@ -172,6 +173,18 @@ impl Agent {
172173
routing_mode: RoutingMode,
173174
) -> Agent {
174175
let plan = Plan::from_io(io_person.selected_plan(), id_mappings, routing_mode);
176+
177+
if plan.acts.is_empty() {
178+
debug!("There is an empty plan for person {:?}", io_person.id);
179+
}
180+
181+
if plan.acts.len() == 1 {
182+
debug!(
183+
"There is a plan with one activity only for person {:?}",
184+
io_person.id
185+
);
186+
}
187+
175188
let id = *id_mappings.agents.get_internal(io_person.id()).unwrap();
176189
Agent {
177190
id: id as u64,
@@ -422,6 +435,21 @@ impl Plan {
422435
}
423436

424437
fn get_full_plan_for_routing(io_plan: &IOPlan, id_mappings: &MatsimIdMappings) -> Plan {
438+
if io_plan.elements.is_empty() {
439+
return Plan::new();
440+
}
441+
442+
if io_plan.elements.len() == 1 {
443+
let mut plan = Plan::new();
444+
if let IOPlanElement::Activity(io_activity) = io_plan.elements.get(0).unwrap() {
445+
plan.acts
446+
.push(Activity::from_io(io_activity, &id_mappings.links));
447+
} else {
448+
panic!("The first element of a plan has to be an activity.")
449+
}
450+
return plan;
451+
}
452+
425453
let plan_type = Plan::get_plan_type(io_plan);
426454
let window_size = plan_type.window_size();
427455
let step_size = plan_type.step_size();

src/simulation/messaging/travel_time_collector.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
use crate::simulation::messaging::events::proto::event::Type;
2-
use crate::simulation::messaging::events::proto::{Event, LinkEnterEvent, LinkLeaveEvent};
2+
use crate::simulation::messaging::events::proto::{
3+
Event, LinkEnterEvent, LinkLeaveEvent, PersonLeavesVehicleEvent,
4+
};
35
use crate::simulation::messaging::events::EventsSubscriber;
46
use std::any::Any;
57
use std::collections::HashMap;
68

79
pub struct TravelTimeCollector {
810
travel_times_by_link: HashMap<u64, Vec<u32>>,
911
cache_traffic_information_by_link: HashMap<u64, Vec<TrafficInformation>>,
12+
current_link_by_vehicle: HashMap<u64, u64>,
1013
}
1114

1215
#[derive(Debug, PartialEq, Clone)]
@@ -20,6 +23,7 @@ impl TravelTimeCollector {
2023
TravelTimeCollector {
2124
travel_times_by_link: HashMap::new(),
2225
cache_traffic_information_by_link: HashMap::new(),
26+
current_link_by_vehicle: HashMap::new(),
2327
}
2428
}
2529

@@ -32,6 +36,9 @@ impl TravelTimeCollector {
3236
time,
3337
vehicle: event.vehicle,
3438
});
39+
40+
self.current_link_by_vehicle
41+
.insert(event.vehicle, event.link);
3542
}
3643

3744
fn process_link_leave_event(&mut self, time: u32, event: &LinkLeaveEvent) {
@@ -59,6 +66,33 @@ impl TravelTimeCollector {
5966
}
6067
}
6168

69+
fn process_person_leaves_vehicle_event(&mut self, time: u32, event: &PersonLeavesVehicleEvent) {
70+
// if there is no current link id of vehicle of link enter event, cache doesn't have to be cleaned up
71+
let link_id = self.current_link_by_vehicle.get(&event.vehicle).copied();
72+
if link_id.is_none() {
73+
return;
74+
}
75+
76+
let index_of_link_enter =
77+
self.get_index_of_link_enter_event(link_id.unwrap(), event.vehicle);
78+
if index_of_link_enter.is_none() {
79+
return;
80+
}
81+
82+
self.cache_traffic_information_by_link
83+
.get_mut(&link_id.unwrap())
84+
.unwrap()
85+
.remove(index_of_link_enter.unwrap());
86+
}
87+
88+
fn get_index_of_link_enter_event(&mut self, link: u64, vehicle: u64) -> Option<usize> {
89+
self.cache_traffic_information_by_link
90+
.entry(link)
91+
.or_insert(Vec::new())
92+
.iter()
93+
.position(|t| t.vehicle == vehicle)
94+
}
95+
6296
pub fn get_travel_time_of_link(&self, link: u64) -> Option<u32> {
6397
match self.travel_times_by_link.get(&link) {
6498
None => None,
@@ -92,6 +126,7 @@ impl EventsSubscriber for TravelTimeCollector {
92126
match event.r#type.as_ref().unwrap() {
93127
Type::LinkEnter(e) => self.process_link_enter_event(time, e),
94128
Type::LinkLeave(e) => self.process_link_leave_event(time, e),
129+
Type::PersonLeavesVeh(e) => self.process_person_leaves_vehicle_event(time, e),
95130
_ => {}
96131
}
97132
}
@@ -179,4 +214,53 @@ mod test {
179214
})
180215
);
181216
}
217+
218+
#[test]
219+
/// Tests whether PersonLeavesVehicleEvent discards travel time
220+
fn test_with_person_leaves_vehicle() {
221+
let mut collector = TravelTimeCollector::new();
222+
collector.receive_event(0, &Event::new_link_enter(1, 1));
223+
collector.receive_event(2, &Event::new_person_leaves_veh(1, 1));
224+
collector.receive_event(4, &Event::new_link_leave(1, 1));
225+
226+
assert_eq!(collector.get_travel_time_of_link(1), None);
227+
assert_eq!(
228+
collector
229+
.cache_traffic_information_by_link
230+
.get(&1)
231+
.unwrap()
232+
.len(),
233+
0
234+
);
235+
}
236+
237+
#[test]
238+
/// Tests whether PersonLeavesVehicleEvent discards travel time
239+
fn test_with_person_leaves_vehicle_complex() {
240+
let mut collector = TravelTimeCollector::new();
241+
collector.receive_event(0, &Event::new_link_enter(1, 1));
242+
243+
//intermediate veh 2 enters link 1
244+
collector.receive_event(1, &Event::new_link_enter(1, 2));
245+
246+
collector.receive_event(2, &Event::new_person_leaves_veh(1, 1));
247+
248+
//intermediate veh 2 leaves link 1
249+
collector.receive_event(3, &Event::new_link_leave(1, 2));
250+
251+
collector.receive_event(10, &Event::new_link_leave(1, 1));
252+
collector.receive_event(10, &Event::new_link_enter(2, 1));
253+
collector.receive_event(20, &Event::new_link_leave(2, 1));
254+
255+
assert_eq!(collector.get_travel_time_of_link(1), Some(2));
256+
assert_eq!(collector.get_travel_time_of_link(2), Some(10));
257+
assert_eq!(
258+
collector
259+
.cache_traffic_information_by_link
260+
.get(&1)
261+
.unwrap()
262+
.len(),
263+
0
264+
);
265+
}
182266
}

0 commit comments

Comments
 (0)