Skip to content

Commit 55eb730

Browse files
authored
Merge pull request #182 from matsim-vsp/167-fix-vehicle-insertion-and-removal
Added WaitingList and Buffer to the Links (Like for MATSim)
2 parents acfce5b + 6abf4bd commit 55eb730

File tree

23 files changed

+1216
-548
lines changed

23 files changed

+1216
-548
lines changed

rust_qsim/assets/equil/equil-1-plan.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<attribute name="routingMode" class="java.lang.String">car</attribute>
2323
</attributes>
2424
<route type="links" start_link="1" end_link="20" trav_time="undefined" distance="25000.0"
25-
vehicleRefId="1_car">1 6 15 20
25+
vehicleRefId="1">1 6 15 20
2626
</route>
2727
</leg>
2828
<activity type="w" link="20" x="3456.0" y="4242.0" max_dur="00:10:00">
@@ -32,7 +32,7 @@
3232
<attribute name="routingMode" class="java.lang.String">car</attribute>
3333
</attributes>
3434
<route type="links" start_link="20" end_link="20" trav_time="undefined" distance="0.0"
35-
vehicleRefId="1_car">20
35+
vehicleRefId="1">20
3636
</route>
3737
</leg>
3838
<activity type="w" link="20" x="10000.0" y="0.0" max_dur="03:30:00">
@@ -42,7 +42,7 @@
4242
<attribute name="routingMode" class="java.lang.String">car</attribute>
4343
</attributes>
4444
<route type="links" start_link="20" end_link="1" trav_time="undefined" distance="65000.0"
45-
vehicleRefId="1_car">20 21 22 23 1
45+
vehicleRefId="1">20 21 22 23 1
4646
</route>
4747
</leg>
4848
<activity type="h" link="1" x="-25000.0" y="0.0">

rust_qsim/assets/equil/equil-vehicles.xml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<vehicleDefinitions xmlns="http://www.matsim.org/files/dtd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:schemaLocation="http://www.matsim.org/files/dtd http://www.matsim.org/files/dtd/vehicleDefinitions_v1.0.xsd">
2+
<vehicleDefinitions xmlns="http://www.matsim.org/files/dtd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.matsim.org/files/dtd http://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd">
43
<vehicleType id="car">
5-
<attributes>
6-
</attributes>
74
<description>abc</description>
85
<length meter="9.5"/>
96
<width meter="3.0"/>
@@ -13,9 +10,6 @@
1310
<flowEfficiencyFactor factor="1.5"/>
1411
</vehicleType>
1512
<vehicleType id="walk">
16-
<attributes>
17-
<attribute name="lod" class="java.lang.String">teleported</attribute>
18-
</attributes>
1913
<description>This is a pair of shoes</description>
2014
<length meter="0.5"/>
2115
<width meter="1.0"/>

rust_qsim/src/generated/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ impl From<&str> for AttributeValue {
225225
}
226226
}
227227

228+
impl From<f64> for AttributeValue {
229+
fn from(value: f64) -> Self {
230+
AttributeValue::new_double(value)
231+
}
232+
}
233+
228234
// we can't tag the enum as non-exhaustive because prost generates it. This is why the warning is manually disabled.
229235
#[allow(unreachable_patterns)]
230236
impl Serialize for AttributeValue {

rust_qsim/src/simulation/agents/agent.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,19 @@ impl SimulationAgentLogic for SimulationAgent {
6868
fn advance_plan(&mut self) {
6969
self.logic.advance_plan();
7070
}
71-
fn wakeup_time(&self, now: u32) -> u32 {
72-
self.logic.wakeup_time(now)
73-
}
7471
fn state(&self) -> SimulationAgentState {
7572
self.logic.state()
7673
}
74+
fn is_wanting_to_arrive_on_current_link(&self) -> bool {
75+
self.logic.is_wanting_to_arrive_on_current_link()
76+
}
7777
fn curr_link_id(&self) -> Option<&Id<Link>> {
7878
self.logic.curr_link_id()
7979
}
8080
fn peek_next_link_id(&self) -> Option<&Id<Link>> {
8181
self.logic.peek_next_link_id()
8282
}
83+
fn wakeup_time(&self, now: u32) -> u32 {
84+
self.logic.wakeup_time(now)
85+
}
8386
}

rust_qsim/src/simulation/agents/agent_logic.rs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,6 @@ impl SimulationAgentLogic for PlanBasedSimulationLogic {
139139
);
140140
}
141141

142-
fn wakeup_time(&self, now: u32) -> u32 {
143-
match self
144-
.basic_agent_delegate
145-
.plan_element_at(self.curr_plan_element)
146-
.unwrap()
147-
{
148-
InternalPlanElement::Activity(a) => a.cmp_end_time(now),
149-
InternalPlanElement::Leg(_) => panic!("Cannot wake up on a leg!"),
150-
}
151-
}
152-
153142
fn state(&self) -> SimulationAgentState {
154143
match self.curr_plan_element % 2 {
155144
0 => SimulationAgentState::ACTIVITY,
@@ -158,6 +147,10 @@ impl SimulationAgentLogic for PlanBasedSimulationLogic {
158147
}
159148
}
160149

150+
fn is_wanting_to_arrive_on_current_link(&self) -> bool {
151+
self.peek_next_link_id().is_none()
152+
}
153+
161154
fn curr_link_id(&self) -> Option<&Id<Link>> {
162155
if self.state() != SimulationAgentState::LEG {
163156
return None;
@@ -192,6 +185,17 @@ impl SimulationAgentLogic for PlanBasedSimulationLogic {
192185
.unwrap()
193186
.route_element_at(next_i)
194187
}
188+
189+
fn wakeup_time(&self, now: u32) -> u32 {
190+
match self
191+
.basic_agent_delegate
192+
.plan_element_at(self.curr_plan_element)
193+
.unwrap()
194+
{
195+
InternalPlanElement::Activity(a) => a.cmp_end_time(now),
196+
InternalPlanElement::Leg(_) => panic!("Cannot wake up on a leg!"),
197+
}
198+
}
195199
}
196200

197201
impl EndTime for PlanBasedSimulationLogic {
@@ -228,6 +232,22 @@ impl SimulationAgentLogic for AdaptivePlanBasedSimulationLogic {
228232
self.delegate.advance_plan();
229233
}
230234

235+
fn state(&self) -> SimulationAgentState {
236+
self.delegate.state()
237+
}
238+
239+
fn is_wanting_to_arrive_on_current_link(&self) -> bool {
240+
self.delegate.is_wanting_to_arrive_on_current_link()
241+
}
242+
243+
fn curr_link_id(&self) -> Option<&Id<Link>> {
244+
self.delegate.curr_link_id()
245+
}
246+
247+
fn peek_next_link_id(&self) -> Option<&Id<Link>> {
248+
self.delegate.peek_next_link_id()
249+
}
250+
231251
fn wakeup_time(&self, now: u32) -> u32 {
232252
let mut end = self.delegate.curr_act().cmp_end_time(now);
233253
if let Some(l) = self.delegate.next_leg() {
@@ -240,18 +260,6 @@ impl SimulationAgentLogic for AdaptivePlanBasedSimulationLogic {
240260
}
241261
end
242262
}
243-
244-
fn state(&self) -> SimulationAgentState {
245-
self.delegate.state()
246-
}
247-
248-
fn curr_link_id(&self) -> Option<&Id<Link>> {
249-
self.delegate.curr_link_id()
250-
}
251-
252-
fn peek_next_link_id(&self) -> Option<&Id<Link>> {
253-
self.delegate.peek_next_link_id()
254-
}
255263
}
256264

257265
impl EndTime for AdaptivePlanBasedSimulationLogic {

rust_qsim/src/simulation/agents/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ pub trait SimulationAgentLogic:
1616
fn curr_leg(&self) -> &InternalLeg;
1717
fn next_leg(&self) -> Option<&InternalLeg>;
1818
fn advance_plan(&mut self);
19-
fn wakeup_time(&self, now: u32) -> u32;
2019
fn state(&self) -> SimulationAgentState;
20+
21+
// Having these functions here is not ideal. See https://github.com/matsim-vsp/parallel_qsim_rust/issues/203 for more details.
22+
fn is_wanting_to_arrive_on_current_link(&self) -> bool;
2123
fn curr_link_id(&self) -> Option<&Id<Link>>;
2224
fn peek_next_link_id(&self) -> Option<&Id<Link>>;
25+
fn wakeup_time(&self, now: u32) -> u32;
2326
}
2427

2528
pub trait EnvironmentalEventObserver {
@@ -28,12 +31,12 @@ pub trait EnvironmentalEventObserver {
2831

2932
#[non_exhaustive]
3033
pub enum AgentEvent<'a> {
31-
// activity related events
34+
// activity-related events
3235
ActivityStarted(),
3336
WokeUp(WokeUpEvent<'a>),
3437
ActivityFinished(),
3538

36-
// teleportation related events
39+
// teleportation-related events
3740
TeleportationStarted(),
3841
TeleportationFinished(),
3942

rust_qsim/src/simulation/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,10 +436,15 @@ pub struct Simulation {
436436
pub start_time: u32,
437437
pub end_time: u32,
438438
pub sample_size: f32,
439+
#[serde(default = "default_to_10")]
439440
pub stuck_threshold: u32,
440441
pub main_modes: Vec<String>,
441442
}
442443

444+
fn default_to_10() -> u32 {
445+
10
446+
}
447+
443448
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
444449
pub struct ComputationalSetup {
445450
pub global_sync: bool,

rust_qsim/src/simulation/engines/leg_engine.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ impl<C: SimCommunicator> LegEngine<C> {
5959
}
6060
}
6161

62+
/// Performs a sim step for the leg engine. Note that vehicles that leave a link and move to another link are always processed one time step later.
63+
/// This is in line with the Java reference implementation. The reason is that the order is:
64+
///
65+
/// 1. `move_nodes`
66+
/// 2. `move_links`
67+
///
68+
/// Let's say, a vehicle's earliest exit time is `x`. The `move_links` call puts it into the buffer
69+
/// at time step `x` (assuming it is free), and the `move_nodes` call at time step `x+1` puts it onto the next link.
70+
/// The corresponding LinkEnter and LinkLeave events have time step `x+1`
6271
#[instrument(level = "trace", skip(self, agents), fields(rank=self.net_message_broker.rank()))]
6372
pub(crate) fn do_step(
6473
&mut self,
@@ -70,14 +79,16 @@ impl<C: SimCommunicator> LegEngine<C> {
7079
}
7180

7281
let teleported_vehicles = self.teleportation_engine.do_step(now);
73-
let network_vehicles = self.network_engine.move_nodes(now);
82+
83+
self.network_engine.move_nodes(now);
84+
let network_vehicles = self
85+
.network_engine
86+
.move_links(now, &mut self.net_message_broker);
7487

7588
let mut agents = vec![];
7689
agents.extend(self.publish_end_events(now, network_vehicles, true));
7790
agents.extend(self.publish_end_events(now, teleported_vehicles, false));
7891

79-
self.network_engine
80-
.move_links(now, &mut self.net_message_broker);
8192
let sync_messages = self.net_message_broker.send_recv(now);
8293

8394
for mut msg in sync_messages {

rust_qsim/src/simulation/engines/network_engine.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,25 @@ impl NetworkEngine {
2929
self.network.send_veh_en_route(vehicle, events, now)
3030
}
3131

32-
pub(super) fn move_nodes(&mut self, now: u32) -> Vec<InternalVehicle> {
32+
pub(super) fn move_nodes(&mut self, now: u32) {
3333
self.network.move_nodes(&mut self.comp_env, now)
3434
}
3535

3636
pub(super) fn move_links<C: SimCommunicator>(
3737
&mut self,
3838
now: u32,
3939
net_message_broker: &mut NetMessageBroker<C>,
40-
) {
41-
let (vehicles, storage_cap_updates) = self.network.move_links(now);
40+
) -> Vec<InternalVehicle> {
41+
let move_links_result = self.network.move_links(&mut self.comp_env, now);
4242

43-
for veh in vehicles {
43+
for veh in move_links_result.vehicles_exit_partition {
4444
net_message_broker.add_veh(veh, now);
4545
}
4646

47-
for cap in storage_cap_updates {
47+
for cap in move_links_result.storage_cap_updates {
4848
net_message_broker.add_cap_update(cap, now);
4949
}
50+
51+
move_links_result.vehicles_end_leg
5052
}
5153
}

rust_qsim/src/simulation/events/mod.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,100 @@ impl EventTrait for LinkLeaveEvent {
325325
}
326326
}
327327

328+
#[derive(Builder, Debug)]
329+
pub struct VehicleEntersTrafficEvent {
330+
pub time: u32,
331+
pub vehicle: Id<InternalVehicle>,
332+
pub link: Id<Link>,
333+
pub driver: Id<InternalPerson>,
334+
pub mode: Id<String>,
335+
#[builder(default = 1.0)]
336+
pub relative_position_on_link: f64,
337+
#[builder(default)]
338+
pub attributes: InternalAttributes,
339+
}
340+
341+
impl VehicleEntersTrafficEvent {
342+
pub const TYPE: &'static str = "vehicle enters traffic";
343+
pub fn from_proto_event(event: &MyEvent, time: u32) -> Self {
344+
let attrs = InternalAttributes::from(&event.attributes);
345+
assert!(event.r#type.eq(Self::TYPE));
346+
VehicleEntersTrafficEventBuilder::default()
347+
.time(time)
348+
.vehicle(Id::create(&event.attributes["vehicle"].as_string()))
349+
.link(Id::create(&event.attributes["link"].as_string()))
350+
.driver(Id::create(&event.attributes["driver"].as_string()))
351+
.mode(Id::create(&event.attributes["mode"].as_string()))
352+
.relative_position_on_link(event.attributes["relative_position_on_link"].as_double())
353+
.attributes(attrs)
354+
.build()
355+
.unwrap()
356+
}
357+
}
358+
359+
impl EventTrait for VehicleEntersTrafficEvent {
360+
fn type_(&self) -> &'static str {
361+
Self::TYPE
362+
}
363+
fn as_any(&self) -> &dyn Any {
364+
self
365+
}
366+
fn time(&self) -> u32 {
367+
self.time
368+
}
369+
370+
fn attributes(&self) -> &InternalAttributes {
371+
&self.attributes
372+
}
373+
}
374+
375+
#[derive(Builder, Debug)]
376+
pub struct VehicleLeavesTrafficEvent {
377+
pub time: u32,
378+
pub vehicle: Id<InternalVehicle>,
379+
pub link: Id<Link>,
380+
pub driver: Id<InternalPerson>,
381+
pub mode: Id<String>,
382+
#[builder(default = 1.0)]
383+
pub relative_position_on_link: f64,
384+
#[builder(default)]
385+
pub attributes: InternalAttributes,
386+
}
387+
388+
impl VehicleLeavesTrafficEvent {
389+
pub const TYPE: &'static str = "vehicle leaves traffic";
390+
pub fn from_proto_event(event: &MyEvent, time: u32) -> Self {
391+
let attrs = InternalAttributes::from(&event.attributes);
392+
assert!(event.r#type.eq(Self::TYPE));
393+
VehicleLeavesTrafficEventBuilder::default()
394+
.time(time)
395+
.vehicle(Id::create(&event.attributes["vehicle"].as_string()))
396+
.link(Id::create(&event.attributes["link"].as_string()))
397+
.driver(Id::create(&event.attributes["driver"].as_string()))
398+
.mode(Id::create(&event.attributes["mode"].as_string()))
399+
.relative_position_on_link(event.attributes["relative_position_on_link"].as_double())
400+
.attributes(attrs)
401+
.build()
402+
.unwrap()
403+
}
404+
}
405+
406+
impl EventTrait for VehicleLeavesTrafficEvent {
407+
fn type_(&self) -> &'static str {
408+
Self::TYPE
409+
}
410+
fn as_any(&self) -> &dyn Any {
411+
self
412+
}
413+
fn time(&self) -> u32 {
414+
self.time
415+
}
416+
417+
fn attributes(&self) -> &InternalAttributes {
418+
&self.attributes
419+
}
420+
}
421+
328422
#[derive(Builder, Debug)]
329423
pub struct PersonEntersVehicleEvent {
330424
pub time: u32,

0 commit comments

Comments
 (0)