Package mosp_examples :: Module statemachine_wiggler
[hide private]
[frames] | no frames]

Source Code for Module mosp_examples.statemachine_wiggler

  1  #!/bin/env python 
  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]   #: hard-coded MOSP node ids (no osm ids!) of map selected as workplaces - get them via node_finder.py. 
 27  BARS = [2213, 1171, 2464, 2459, 2528, 1987]  #: hard-coded MOSP node ids (no osm ids!) of map selected as bars - get them via node_finder.py. 
 28   
 29      
30 -class WorkWiggler(Person):
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
39 - def __init__(self, *args):
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
60 - def time_until(self, t):
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
68 - def think(self):
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 # return 1 so the person can react in the next tick after waking up 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 # return 1 so the person can react in the next tick after waking up 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
102 - def next_target(self):
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
113 -class DrunkWiggler(WorkWiggler):
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
123 - def __init__(self, *args):
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 #self.sim.monitors[0].draw_point(self.p_id + 100, self.p_workplace_node.lat, self.p_workplace_node.lon, 5, (1.0, 0.0, 0.0, 1.0), ttl=0) 136 #self.sim.monitors[0].draw_point(self.p_id + 101, self.home_node.lat, self.home_node.lon, 5, (0.0, 0.0, 1.0, 1.0), ttl=0) 137 #self.sim.monitors[0].draw_point(self.p_id + 102, self.bar_node.lat, self.bar_node.lon, 5, (1.0, 0.0, 0.0, 1.0), ttl=0) 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
143 - def think(self):
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 # some drunken people do not find their home again 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 # return 1 so the person can react in the next tick after waking up 176 177 if self.p_state == 'CONFUSED': 178 self.need_next_target = True 179 180 return sleep
181 182
183 -class RandomWiggler(Person):
184 """Implements a person doing random movement the whole day. 185 @author: P. Tute""" 186 next_target = movement.person_next_target_random
187 188
189 -class SocketPlayerClock(Process):
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
197 - def run(self):
198 """Draws the clock to the monitor.""" 199 id = 999999 200 size = 12 201 x = 10 202 y = (size + 10) * -1 #draw top of text 10 pixels below top of screen 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
208 -def main():
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) #: a clock drawer for SocketPlayerMonitor 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