def launch(self): while True: print("Launch at %2.4f; wallclock: %2.4f" % (SimulationRT.now(), time.clock() - startTime)) yield SimulationRT.hold, self, uniform(1, maxFlightTime) print("Boom!!! Aaaah!! at %2.4f; wallclock: %2.4f" % (SimulationRT.now(), time.clock() - startTime))
def _do_embark_pax_finish(self, pax, vehicle, cmd_msg_id): # Error if vehicle is not still parked in berth if not vehicle.is_parked_between(self.start_pos, self.end_pos, self.platform.track_segment): raise VehicleOutOfPositionError(vehicle, cmd_msg_id) # Move passenger's location to the vehicle vehicle.embark(pax) pax.loc = vehicle self.station._pax_departures_count += 1 self.station.remove_passenger(pax) pax.trip_boarded = Sim.now() logging.info( "T=%4.3f %s loaded into Vehicle %s (%d out of %d) at station %s, platform %s, berth %s ", Sim.now(), pax, vehicle.ID, vehicle.get_pax_count(), vehicle.max_pax_capacity, self.station.ID, self.platform.ID, self.ID) # Notify that embark of this passenger is complete end_msg = api.SimNotifyPassengerEmbarkEnd() end_msg.vID = vehicle.ID end_msg.sID = self.station.ID end_msg.platformID = self.platform.ID end_msg.pID = pax.ID end_msg.berthID = self.ID end_msg.time = Sim.now() common.interface.send(api.SIM_NOTIFY_PASSENGER_EMBARK_END, end_msg)
def add_events(self, evts): """PrtEvent objects should be contained in a iterable container.""" self.list.extend(evts) heapq.heapify(self.list) # If adding events during the sim, if self.active() or Sim.now() > 0: Sim.reactivate(self, prior=True)
def _do_disembark_pax_finish(self, pax, vehicle, cmd_msg_id): # Error if vehicle is not still parked in berth if not vehicle.is_parked_between(self.start_pos, self.end_pos, self.platform.track_segment): raise VehicleOutOfPositionError(vehicle, cmd_msg_id) # Move the passenger from the vehicle to the station vehicle.disembark(pax) pax.loc = self.station # Note if the passenger has arrived at final dest (may not be # the case with non-PRT systems) if self.station.ID == pax.dest_station.ID: pax.trip_end = Sim.now() pax.trip_success = True common.delivered_pax.add(pax) self.station._pax_arrivals_count += 1 self.station._all_passengers.append(pax) logging.info( "T=%4.3f %s delivered to platform %s in %s by %s (%d out of %d), disembarked in berth %s", Sim.now(), pax, self.platform.ID, self.station.ID, vehicle.ID, vehicle.get_pax_count(), vehicle.max_pax_capacity, self.ID) else: self.station.add_passenger(pax) self.station._arrivals_count += 1 # Notify that disembark of this passenger is complete end_msg = api.SimNotifyPassengerDisembarkEnd() end_msg.vID = vehicle.ID end_msg.sID = self.station.ID end_msg.platformID = self.platform.ID end_msg.pID = pax.ID end_msg.berthID = self.ID end_msg.time = Sim.now() common.interface.send(api.SIM_NOTIFY_PASSENGER_DISEMBARK_END, end_msg)
def _request_vehicle(self, pos, loc): """Request that a vehicle be moved to pos on loc. The effect takes place immediately. To simulate a delay, see reserve_vehicle. """ v = None if len(self._storage_track.vehicles): v = self._storage_track.vehicles[0] v._move_to(pos, loc) v._operational_times.append((Sim.now(), True)) else: # create a new vehicle v_id = max(vehicle.ID for vehicle in common.vehicles.itervalues()) + 1 v = common.vehicle_models[self.model_name](ID=v_id, loc=loc, position=pos, vel=0) common.vehicles[v_id] = v common.vehicle_list.append(v) Sim.activate(v, v.ctrl_loop()) self._num_pending_exit -= 1 self._num_vehicles -= 1 assert 0 <= self._num_vehicles - self._num_pending_exit <= self.max_capacity return v
def __init__(self, time, payload, *args, **kwargs): super(AlarmClock, self).__init__(name="AlarmClock") self.time = time self.payload = payload self.args = args self.kwargs = kwargs Sim.activate(self, self.ring())
def embark(self, vehicle, passengers, cmd_msg, cmd_msg_id): """If ordering matters, note that passengers at the end of the list are serviced first.""" assert not self._busy self._action = Berth.EMBARK self._fnc_args = (vehicle, passengers, cmd_msg, cmd_msg_id) if self.passive: Sim.reactivate(self, prior=True)
def transmitPacket(self, sample): packet = Packet(txHost=self.source.host, txTime=simpy.now(), \ seqNumber=self.seqNumber, data=sample) self.seqNumber += 1 for i, sink in enumerate(self.source.sinks): newPacket = copy(packet) newPacket.rxHost = sink.host link = self.network.findLink(hostFrom=self.source.host, \ hostTo=sink.host) link.simTransmission(sink.receiver, newPacket) sink.session.transmittedPackets.append(newPacket) print "%7.4f Transmitting packet %1d: %s -> %s" % \ (simpy.now(), newPacket.seqNumber, newPacket.txHost.name, newPacket.rxHost.name)
def update(self): if self._last_update_time == Sim.now(): return self.pax_report.update() self.vehicle_report.update() self.station_report.update() self.power_report.update() self.summary_report.update(self.pax_report, self.vehicle_report, self.station_report, self.power_report) self._last_update_time = Sim.now()
def ride_time(self): # in seconds total = 0 for start, end, vehicle in self._ride_times: if end is None: total += Sim.now() - start else: total += end - start return total
def walk(self, origin_station, dest_station, travel_time, cmd_msg, cmd_id): assert self._loc is origin_station assert travel_time >= 0 assert isinstance(cmd_msg, api.CtrlCmdPassengerWalk) assert isinstance(cmd_id, int) self.loc = None common.AlarmClock(Sim.now() + travel_time, self._post_walk, dest_station, cmd_msg, cmd_id)
def walk_time(self): # in seconds total = 0 for start, end in self._walk_times: if end is None: total += Sim.now() - start else: total += end - start return total
def set_loc(self, loc): """Changes the loc, and keeps track of how much time is spent in each mode of transit: waiting, riding, or walking.""" ### Track time spent in each mode of transit ### if self._loc is None: # Was walking self._walk_times[-1][1] = Sim.now() elif hasattr(self._loc, 'vehicle_mass'): # was in vehicle self._ride_times[-1][1] = Sim.now() elif hasattr(self._loc, 'platforms'): # was at station self._wait_times[-1][1] = Sim.now() else: raise Exception("Unknown loc type") ### Note if trip is completed. ### if loc is self.dest_station: self._end_time = Sim.now() self.trip_success = True ### More time tracking ### if not self.trip_success: if loc is None: self._walk_times.append([Sim.now(), None]) elif hasattr(loc, 'vehicle_mass'): self._ride_times.append([Sim.now(), None, loc]) # isinstance(loc, BaseVehicle) elif hasattr(loc, 'platforms'): self._wait_times.append([Sim.now(), None, loc]) # isinstance(loc, TrackSegment) else: raise Exception("Unknown loc type") self._loc = loc
def _do_exit_storage(self, position, model_name, cmd_msg, cmd_msg_id): storage = self.station._storage_dict[model_name] storage._reserve_vehicle() self._busy = True yield self.station.storage_exit_delay vehicle = storage._request_vehicle(position, self.platform.track_segment) self._busy = False # Notify controller that vehicle exiting storage is done. cmd_complete = api.SimCompleteStorageExit() cmd_complete.msgID = cmd_msg_id cmd_complete.cmd.CopyFrom(cmd_msg) cmd_complete.time = Sim.now() vehicle.fill_VehicleStatus(cmd_complete.v_status) common.interface.send(api.SIM_COMPLETE_STORAGE_EXIT, cmd_complete) logging.info( "T=%4.3f Exit from Storage: Vehicle: %s, Berth: %s, Platform: %s, Station: %s", Sim.now(), vehicle.ID, self.ID, self.platform.ID, self.station.ID)
def pytest_funcarg__sim(request): if request.param == 'default': return Simulation.Simulation() elif request.param == 'step': return SimulationStep.SimulationStep() elif request.param == 'trace': return SimulationTrace.SimulationTrace() elif request.param == 'rt': return SimulationRT.SimulationRT() elif request.param.startswith('global'): if request.param.endswith('default'): Globals.sim = Simulation.Simulation() elif request.param.endswith('step'): Globals.sim = SimulationStep.SimulationStep() elif request.param.endswith('trace'): Globals.sim = SimulationTrace.SimulationTrace() elif request.param.endswith('rt'): Globals.sim = SimulationRT.SimulationRT() return Globals.sim
def run(self, data, txRate): print "%7.4f Starting transmitter: %s" % (simpy.now(), self.name) lastTx = -1000 for sample in data: time = sample[0] if time >= lastTx + txRate: lastTx = time self.transmitPacket(sample) yield simpy.hold, self, txRate
def send(self, msg_type, msg): """Send an outgoing message. Every message sent is prefixed with: msg seperator: 2 bytes, signed -32123 msg type: 2 bytes, signed msg ID: 4 bytes, signed msg time: 4 bytes, signed msg size: 4 bytes, signed The message seperator is always -32123 The msg type is one of the values found in CtrlMsgType or SimMsgType The msg size is the length (in bytes) of the serialized message. These values are transmitted in network byte order (Big Endian). TEMP: Transmits to all clients (no filtering) """ msgID = common.msg_id_widget.next_id() msg_time = ms_now() msg_str = msg.SerializeToString() msg_size = len(msg_str) # big_endian, *std size* and align: short, short, int, int, int # short = 2 bytes, int = 4 bytes header = struct.pack('>hhiii', api.MSG_SEP, msg_type, msgID, msg_time, msg_size) message = header + msg_str # TODO: Only send to consumers that are subscribed to that message type # and/or message target. for q in self.sendQs: q.put(message) if self.passive() and not common.sim_ended: # Reset the resume_list to all False self.resume_list[:] = [False] * len(self.resume_list) # Reactivate the ControlInterface, placing it at the end of the # list of events to run. Sim.reactivate(self, prior=False) if self.log != os.devnull: self.log.write("Now:%s, SENT, %s, MsgType:%d, MsgID:%d, MsgTime:%d\n" %\ (time.time(), msg.DESCRIPTOR.name, msg_type, msgID, msg_time)) text_format.PrintMessage(msg, out=self.log) self.log.write("--\n")
def _post_walk(self, dest_station, cmd_msg, cmd_id): """Updates stats, changes location, and sends a SimCompletePassengerWalk message. To be called once the walk is complete.""" assert self._loc is None self.loc = dest_station msg = api.SimCompletePassengerWalk() msg.msgID = cmd_id msg.cmd.CopyFrom(cmd_msg) msg.time = Sim.now() common.interface.send(api.SIM_COMPLETE_PASSENGER_WALK, msg)
def all_pax_wait_times(self): """Returns a list of wait times for all passengers, not just the current ones.""" times = [] for pax in self._all_passengers: for start, end, loc in pax._wait_times: if loc is self: if end is None: times.append(Sim.now() - start) else: times.append(end - start) return times
def curr_pax_wait_times(self): """Returns a list of wait times for passengers currently waiting in the station.""" times = [] for pax in self._passengers: for start, end, loc in pax._wait_times: if loc is self: if end is None: times.append(Sim.now() - start) else: times.append(end - start) return times
def update_statusbar(self, evt): if not common.sim_ended: # calc some passenger stats pax_waiting = 0 total_wait = 0 max_wait = 0 trip_success = 0 trip_failed = 0 for stat in common.station_list: # collected in 'seconds' for pax in stat._passengers: pax_waiting += 1 pax_wait = pax.wait_time # don't force it to calc the wait time twice total_wait += pax_wait max_wait = max(pax_wait, max_wait) for pax in stat._all_passengers: if pax.trip_success: trip_success += 1 else: trip_failed += 1 if pax_waiting == 0: pax_ave_wait = 0 else: pax_ave_wait = total_wait / pax_waiting # calc some vehicle stats seats_occupied = 0 vehicles_occupied = 0 total_vehicles = len(common.vehicles) total_seats = 0 for vehicle in common.vehicle_list: total_seats += vehicle.max_pax_capacity if vehicle.passengers: vehicles_occupied += 1 seats_occupied += len(vehicle.passengers) v_avail = total_vehicles - vehicles_occupied if total_vehicles > 0: v_pct_utilized = vehicles_occupied / total_vehicles * 100 else: v_pct_utilized = 0 if total_seats > 0: seats_pct_utilized = seats_occupied / total_seats * 100 else: seats_pct_utilized = 0 self.statusbar.SetFields([ 'SimTime: %.3f RealTime: %.3f' % (SimPy.now(), time.time() - self.start_time), # timers 'PAX Waiting: %d Avg: %.1f Max: %.1f Trips: done %d active %d' % (pax_waiting, pax_ave_wait / 60, max_wait / 60, trip_success, trip_failed), # report in minutes 'VEHICLES Avail: %d %%Utilized: %.1f %%Seats Utilized: %.1f' % (v_avail, v_pct_utilized, seats_pct_utilized) ])
def model(): SimulationRT.initialize() for i in range(nrLaunchers): lau = Launcher() SimulationRT.activate(lau, lau.launch()) SimulationRT.simulate(real_time=True, rel_speed=1, until=20) # unit sim time = 1 sec clock
def validate_spline(self, spline): """A simple check that the message data is not malformed. See: vehicle._validate_spline for more thorough testing of the resulting cubic_spline.CubicSpline object. """ assert isinstance(spline, api.Spline) # Check that the times for the spline are in non-decreasing order if len(spline.times) == 0: raise common.InvalidTime(0) for t1, t2 in pairwise(spline.times): if t2 < t1: logging.info("T=%4.3f Spline times are not in non-decreasing order: %s", Sim.now(), spline.times) raise common.InvalidTime(t2)
def spawn_events(self): while True: try: while self.list[0].time <= Sim.now(): evt = heapq.heappop(self.list) if isinstance(evt, Passenger): assert not common.passengers.get(evt.ID) common.passengers[evt.ID] = evt # add to common dict evt.loc = evt.src_station # set pax loc evt.loc.add_passenger(evt) msg = api.SimEventPassengerCreated() evt.fill_PassengerStatus(msg.p_status) msg.time = Sim.now() common.interface.send(api.SIM_EVENT_PASSENGER_CREATED, msg) else: raise NotImplementedError if self.list[0].time > Sim.now(): yield Sim.hold, self, self.list[0].time - Sim.now() except IndexError: yield Sim.passivate, self # will be reactivated if new items added
def _do_embark(self, vehicle, passengers, cmd_msg, cmd_msg_id): self._busy = True while passengers: pax = passengers.pop() self._do_embark_pax_start(pax, vehicle, cmd_msg_id) yield pax.load_delay self._do_embark_pax_finish(pax, vehicle, cmd_msg_id) self._busy = False # Notify controller that all passenger embarkments are done. cmd_complete = api.SimCompletePassengersEmbark() cmd_complete.msgID = cmd_msg_id cmd_complete.cmd.CopyFrom(cmd_msg) cmd_complete.time = Sim.now() common.interface.send(api.SIM_COMPLETE_PASSENGERS_EMBARK, cmd_complete)
def __init__(self, ID, label, track_segments, storage_entrance_delay, storage_exit_delay, storage_dict): traits.HasTraits.__init__(self) self.ID = ID self.label = label self.platforms = [] self.track_segments = track_segments self.storage_entrance_delay = storage_entrance_delay self.storage_exit_delay = storage_exit_delay # Keyed by the VehicleModel name (string) with FIFO queues as the values. self._storage_dict = storage_dict self._pax_arrivals_count = 0 self._pax_departures_count = 0 self._pax_times = [(Sim.now(), len(self._passengers)) ] # elements are (time, num_pax) self._all_passengers = []
def _store_vehicle(self, vehicle): """Request that vehicle be moved into storage. The effect takes place immediately. To simulate a delay, see reserve_slot """ assert vehicle.model_name == self.model_name assert abs(vehicle.vel ) < 0.1 # loose sanity check, vehicle should be stopped. try: pos = self._storage_track.vehicles[ 0].pos + vehicle.length + 1 # arbitrary 1 meter spacing except IndexError: pos = vehicle.length + 1 vehicle._move_to(pos, self._storage_track) vehicle._operational_times.append((Sim.now(), False)) self._num_pending_entry -= 1 self._num_vehicles += 1 assert 0 <= self._num_pending_entry + self._num_vehicles <= self.max_capacity
def _do_disembark_pax_start(self, pax, vehicle, cmd_msg_id): # Error if vehicle not parked in berth if not vehicle.is_parked_between(self.start_pos, self.end_pos, self.platform.track_segment): raise VehicleOutOfPositionError(vehicle, cmd_msg_id) # Error if pax not in the vehicle if pax not in vehicle.passengers: raise PassengerNotAvailableError(pax, vehicle, cmd_msg_id) # Notify controller that disembark of this passenger is starting start_msg = api.SimNotifyPassengerDisembarkStart() start_msg.vID = vehicle.ID start_msg.sID = self.station.ID start_msg.platformID = self.platform.ID start_msg.pID = pax.ID start_msg.berthID = self.ID start_msg.time = Sim.now() common.interface.send(api.SIM_NOTIFY_PASSENGER_DISEMBARK_START, start_msg)
def tick(self, nrTicks): oldratio = ratio for i in range(nrTicks): tLastSim = SimulationRT.now() tLastWallclock = SimulationRT.wallclock() yield SimulationRT.hold, self, 1 diffSim = SimulationRT.now() - tLastSim diffWall = SimulationRT.wallclock() - tLastWallclock print("now(): %s, sim. time elapsed: %s, wall clock elapsed: " "%6.3f, sim/wall time ratio: %6.3f" % (SimulationRT.now(), diffSim, diffWall, diffSim / diffWall)) if not ratio == oldratio: print("At simulation time %s: ratio simulation/wallclock " "time now changed to %s" % (SimulationRT.now(), ratio)) oldratio = ratio
def _do_enter_storage(self, vehicle, cmd_msg, cmd_msg_id): if not vehicle.is_parked_between(self.start_pos, self.end_pos, self.platform.track_segment): raise VehicleOutOfPositionError(vehicle, cmd_msg_id) storage = self.station._storage_dict[vehicle.model_name] storage._reserve_slot() self._busy = True yield self.station.storage_entrance_delay if not vehicle.is_parked_between(self.start_pos, self.end_pos, self.platform.track_segment): raise VehicleOutOfPositionError(vehicle, cmd_msg_id) storage._store_vehicle(vehicle) self._busy = False # Notify controller that vehicle entering storage is done. cmd_complete = api.SimCompleteStorageEnter() cmd_complete.msgID = cmd_msg_id cmd_complete.cmd.CopyFrom(cmd_msg) cmd_complete.time = Sim.now() common.interface.send(api.SIM_COMPLETE_STORAGE_ENTER, cmd_complete)
def test_ticker(): """Tests SimulationRT for degree to which simulation time and wallclock time can be synchronized.""" rel_speed = 10 sim_slow=SimulationRT() t=Ticker(sim=sim_slow) sim_slow.activate(t,t.tick()) sim_slow.simulate(until=10,real_time=True,rel_speed=rel_speed) for tSim, tRT in t.timing: assert tSim/tRT > rel_speed - 1 rel_speed = 20 sim_fast=SimulationRT() sim_fast.initialize() t=Ticker(sim=sim_fast) sim_fast.activate(t,t.tick()) sim_fast.simulate(until=10,real_time=True,rel_speed=rel_speed) for tSim, tRT in t.timing: assert tSim/tRT > rel_speed - 1