I have created a train simulation in simpy, but to keep a track of the trains ahead, I plan to use a dictionary, where key values can act as 'Signal' status. The keys are basically signal numbers. The preceding trains can check if the next signal is green or vice versa. However, the code seems to be working fine for rest of the signals, but I want to check for Signal 0 and Signal 1 so that the train does not generate or does not depart.
I am not entering the entire code, as it would just make it verbose. It is just to give an idea of what I am trying to do.
Here is the sample code -
signal_dict={}
def switchSignal(self,signal):
if signal == 1 or signal == 0:
signal_dict[signal]= False
return signal_dict
else:
s[signal-1] = False
return signal_dict
def switchSignal_2(self,signal):
if signal == 1 or signal == 0:
signal_dict[signal]= True
return signal_dict
else:
signal_dict[signal-1] = True
return signal_dict
class Train(object):
def __init__(self,xxxx):
xxxxxxx
xxxxxxx
def engagelock(self, car, drivetime,signals):
with self.machine.request() as request:
yield request
for signal in range(0,signals):
switchSignal(self,signal)
while signal_dict.get(signal+1) is False :
print(f"{now():s} {self.name:s} is waiting for Signal {signal+1} to turn GREEN")
yield env.timeout(60)
else:
if isdelay()[0] == True:
switchSignal(self,signal)
time_delay=round(delay()[0],2)
print(f"\n{now():s} {self.name:s} is experiencing a delay of {round((time_delay*10)/60,2)} min at Signal {signal}")
print(signal_dict)
yield env.timeout(round(time_delay*10,2))
switchSignal_2(self,signal)
def process(self,k):
here = 'London Old Oak Commons'
dest = 'Birmingham Interchange'
t1=env.now
print(f"{now():s} {self.name:s} Departed from {here:s}")
drivetime=timeTo(self.accel, self.maxV, d)
yield env.process(self.engagelock(self.name,drivetime,k))
yield env.process(self.releaselock(self.name))
yield env.timeout(drivetime)
print(f"{now():s} {self.name:s} has arrived at {dest:s}, Travelling time {round((env.now-t1)/60,2)} mins")
for i in range(int((stop-start)/timing)):
print(signal_dict)
while signal_dict.get(0) is False:
print(f"Train waiting to depart, congestion ahead!")
yield env.timeout(60)
else:
t = Train(i)
env.process(t.process(k,timing))
yield env.timeout(timing)
env = simpy.Environment()
env.process(trainGenerator(start=8*3600, stop=12*3600, timing=1500))
env.run()
When I am trying to trace the global dictionary signal_dict, it seems that the train generator is unable to see the updated values in it.
Total number of Signal Blocks 6
Distance Between signalling blocks is 25.17km
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:00:00 [Train 0] Departed from London Old Oak Commons
08:00:00 [Train 0] is experiencing a delay of 3.37 min at Signal 5
{0: True, 1: True, 2: True, 3: True, 4: False}
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:05:00 [Train 1] Departed from London Old Oak Commons
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:10:00 [Train 2] Departed from London Old Oak Commons
08:10:00 [Train 2] is experiencing a delay of 14.46 min at Signal 3
{0: True, 1: True, 2: False, 3: True, 4: True}
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
I got this working, instead of a doubly-linked list, I just created a Global Dictionary and kept a flag of the trains for a signal ahead and a signal behind. In this way, every train would check the next signal, if it is red, it would decelerate upto the next signal. The link to the entire project could be found here -
https://github.com/abhiray92/train_simulation_simpy/blob/main/Simulation.ipynb