1
2
3 """State-machine steering example: people destinations selected by p_state-machine
4 - routed movement
5 - steered by p_state machine
6 - some people go to work and go home for sleeping afterwards
7 - other people go to work and then first have a drink
8 """
9
10 import sys
11 sys.path.append("..")
12
13 from SimPy.SimulationRT import initialize, now, activate, Process, simulate, hold
14
15 from mosp.core import Simulation, Person
16 from mosp.geo import osm
17 from mosp.impl import movement
18 from mosp.monitors import ChildprocessPlayerChamplainMonitor, SocketPlayerMonitor
19
20 __author__ = "B. Henne, F. Ludwig, P. Tute"
21 __contact__ = "henne@dcsec.uni-hannover.de"
22 __copyright__ = "(c) 2010-2012, DCSec, Leibniz Universitaet Hannover, Germany"
23 __license__ = "GPLv3"
24
25
26 WORKPLACES = [2679, 2418, 2217, 1799, 1962]
27 BARS = [2213, 1171, 2464, 2459, 2528, 1987]
28
29
31 """The WorkWiggler wakes up between 6 and 8 o'clock and goes to work. He comes home for sleeping after 16 o'clock.
32
33 Home place is randomly chosen from all way_nodes. Workplace is randomly chosen from
34 hard coded node ids selected using node_finder.py. Waking up time and going home
35 time is random between a start and an end time. 1000 ticks = 1 hour.
36 @author: P. Tute
37 @author: F. Ludwig"""
38
40 """Inits the working man."""
41 Person.__init__(self, *args)
42
43 w_id = self._random.choice(WORKPLACES)
44 for node in self.sim.geo.way_nodes:
45 if node.id == w_id:
46 self.p_workplace_node = node
47 break
48 else:
49 raise Exception('No workplace found')
50
51 self.p_wakeup_time = self._random.randint(6000, 8000)
52 self.p_home_time = self._random.randint(16000, 18000)
53
54 self.dest_node = self.next_node
55 self.home_node = self.last_node
56 self.p_state = 'SLEEP'
57 self.p_color = 2
58 self.p_color_rgba = (0.1, 1.0, 0.1, 1.0)
59
61 """Time until. Used to calculate day events. Here: 1 day = 24000 ticks."""
62 n = self.sim.now() % 24000
63 if t >= n:
64 return t - n
65 else:
66 return (24000 - n) + t
67
69 """Decide what to do (sleep, work, walk) based on daytime and state."""
70 if self.p_state == 'SLEEP':
71 if self.sim.now() % 24000 == self.p_wakeup_time:
72 self.p_state = 'GO_WORK'
73 else:
74 duration = self.time_until(self.p_wakeup_time)
75 self.pause_movement(duration)
76 return 1
77
78 if self.p_state == 'GO_WORK':
79 self.dest_node = self.p_workplace_node
80 if self.next_node == self.p_workplace_node:
81 self.p_state = 'WORK'
82 else:
83 self.need_next_target = True
84
85 if self.p_state == 'WORK':
86 if self.sim.now() % 24000 == self.p_home_time:
87 self.p_state = 'GO_SLEEP'
88 else:
89 duration = self.time_until(self.p_home_time)
90 self.pause_movement(duration)
91 return 1
92
93 if self.p_state == 'GO_SLEEP':
94 self.dest_node = self.home_node
95 if self.next_node == self.home_node:
96 self.p_state = 'SLEEP'
97 return 1
98 else:
99 self.need_next_target = True
100 return -1
101
103 """Sets next next_node an route to destination for next_target()."""
104 self.last_node = self.next_node
105 next = self.last_node.get_route(self.dest_node)
106 if not next:
107 self.dest_node = self.next_node
108 self._duration = 1
109 else:
110 self.next_node = next
111
112
114 """The DrunkWiggler wakes up between 8 and 10 o'clock and goes to work, then drinking ...
115
116 Home place is randomly chosen from all way_nodes. Workplace is randomly chosen from
117 hard coded node ids selected using node_finder.py. Same with the favorite bar.
118 Waking up time and going home time is random between a start and an end time.
119 1000 ticks = 1 hour.
120 @author: P. Tute
121 @author: F. Ludwig"""
122
124 """Inits the drinking man."""
125 WorkWiggler.__init__(self, *args)
126 self.p_wakeup_time = self._random.randint(8000, 10000)
127 self.alcoholism = self._random.randint(21000, 23500)
128 bar_id = self._random.choice(BARS)
129 for node in self.sim.geo.way_nodes:
130 if node.id == bar_id:
131 self.bar_node = node
132 break
133 else:
134 raise Exception('No workplace found')
135
136
137
138 self.p_color = 0
139 self.p_color_rgba = (0.1, 0.1, 1.0, 1.0)
140
141 random_movement = movement.person_next_target_random
142
144 """Decide what to do (sleep, work, drink, walk) based on daytime and state.
145
146 Uses and extends same method of parent WorkWiggler."""
147 sleep = -1
148 if not 'DRINK' in self.p_state:
149 sleep = WorkWiggler.think(self)
150
151 if self.p_state == 'GO_SLEEP':
152 if self.p_wakeup_time < self.sim.now() % 24000 < self.alcoholism:
153 self.p_state = 'GO_DRINK'
154
155 if self.p_state == 'GO_DRINK':
156 self.dest_node = self.bar_node
157 if self.last_node == self.bar_node:
158 self.p_state = 'DRINK'
159 else:
160 self.need_next_target = True
161
162 if self.p_state == 'DRINK':
163 if self.sim.now() % 24000 == self.alcoholism:
164 self.p_state = 'GO_SLEEP'
165
166 if self._random.uniform(0,1) > 0.9:
167 self.next_target = self.random_movement
168 self.p_color = 1
169 self.p_color_rgba = (1.0, 0.1, 0.1, 1.0)
170 self.p_state = 'CONFUSED'
171 sleep = 1
172 else:
173 duration = self.time_until(self.alcoholism)
174 self.pause_movement(duration)
175 sleep = 1
176
177 if self.p_state == 'CONFUSED':
178 self.need_next_target = True
179
180 return sleep
181
182
187
188
190 """A minimal clock for viewing in the SocketPlayerMonitor viewer"""
191 - def __init__(self, name, sim, tick, playerMonitor):
192 """Inits the clock."""
193 Process.__init__(self, name=name, sim=sim)
194 self.playerMonitor = playerMonitor
195 self.tick = tick
196
198 """Draws the clock to the monitor."""
199 id = 999999
200 size = 12
201 x = 10
202 y = (size + 10) * -1
203 while 42:
204 self.playerMonitor.draw_text_to_screen(id, x, y, size, 'black', "%.1f o'clock" % (self.sim.now()/1000.0), ttl=0)
205 yield hold, self, self.tick
206
207
209 """Defines the simulation, map, monitor, different people.
210
211 Combines 20 WorkWigglers, 20 DrunkWigglers and 5 RandomWigglers."""
212 s = Simulation(geo=osm.OSMModel('../data/kl0.osm'), rel_speed=300)
213 m = s.add_monitor(SocketPlayerMonitor, 30)
214 s.add_persons(WorkWiggler, 20, monitor=m)
215 s.add_persons(DrunkWiggler, 20, monitor=m)
216 s.add_persons(RandomWiggler, 1, monitor=m, args={'speed':0.5})
217 clock = SocketPlayerClock('clock', s, 300, m)
218 s.activate(clock, clock.run(), 0)
219 s.run(until=48000, real_time=True, monitor=True)
220
221
222 if __name__ == '__main__':
223 main()
224