def __init__(self, id, xPos, yPos, frequencyBand, sendInterval, initialDelay): super(SendingDevice, self).__init__("Device" + str(id), xPos, yPos, frequencyBand) # initialize a physical layer only self._phy = SimplePhy("phy", self, frequencyBand) mcs = BpskMcs(frequencyBand) def sender(): yield SimMan.timeout(initialDelay) while True: yield SimMan.timeout(sendInterval) packet = Packet( SimpleMacHeader(bytes([0 for _ in range(5)] + [id % 255]), bytes([255 for _ in range(6)]), flag=0), Transmittable("A message to all my homies")) signal = Message(StackMessageTypes.SEND, { "packet": packet, "power": 40.0, "mcs": mcs }) self._phy.gates["macIn"].send(signal) SimMan.process(sender())
def __init__(self): frequencyBand = FrequencyBand([FsplAttenuation]) super(CounterTrafficEnv, self).__init__(frequencyBand, deviceCount=2) # The difference between the lastly received values from both devices # summed up with the COUNTER_BOUND will be the observation. self.observation_space = spaces.Discrete( 2 * CounterTrafficEnv.COUNTER_BOUND) SimMan.init() self.senders: List[self.SenderDevice] = [ CounterTrafficEnv.SenderDevice("Sender 1", 0, 2, self.frequencyBand, 1), CounterTrafficEnv.SenderDevice("Sender 2", 0, -2, self.frequencyBand, 3) ] self.deviceIndexToMacDict: Dict[int, bytes] = { i: s.macAddr for i, s in enumerate(self.senders) } self.senders[0].destinationMac = self.senders[1].macAddr self.senders[1].destinationMac = self.senders[0].macAddr interpreter = self.CounterTrafficInterpreter(self) self.rrm = SimpleRrmDevice("RRM", 0, 0, self.frequencyBand, self.deviceIndexToMacDict, interpreter)
def __init__(self, name: str, frequencyBand: FrequencyBand, plant: SlidingPendulum): super(WagonActuator, self).__init__(name, plant.getWagonPos, 0, frequencyBand) self.plant = plant SimMan.process(self._positionUpdater())
def __init__(self, name): super(TestModule, self).__init__(name) self._addPort("a") self._addPort("b") self.msgReceivedCount = {"a": 0, "b": 0} self.msgVal = None SimMan.process(self.process("a", "b")) SimMan.process(self.process("b", "a"))
def mover(d: NetworkDevice): yield SimMan.timeout(random.uniform(0, MOVE_INTERVAL)) initialPos = d.position while True: xOffset = random.uniform(-.2, .2) yOffset = random.uniform(-.2, .2) d.position.set(initialPos.x + xOffset, initialPos.y + yOffset) yield SimMan.timeout(MOVE_INTERVAL)
def __init__(self, name: str, xPos: float, yPos: float, frequencyBand: FrequencyBand, packetMultiplicity: int): super(CounterTrafficEnv.SenderDevice, self).__init__(name, xPos, yPos, frequencyBand) self.packetMultiplicity = packetMultiplicity self.counter = 1 SimMan.process(self.senderProcess()) self.destinationMac: bytes = None # to be set after construction
def __init__(self, sender: Device, power: float, packet: Packet, mcsHeader: Mcs, mcsPayload: Mcs, startTime: float): self.sender: Device = sender """Device: The device that initiated the transmission""" self.power: float = power """float: The tramsmission power in dBm""" self.mcsHeader: Mcs = mcsHeader """Mcs: The modulation and coding scheme used for the transmitted packet's header""" self.mcsPayload: Mcs = mcsPayload """Mcs: The modulation and coding scheme used for the transmitted packet's payload""" self.packet: Packet = packet """Packet: The packet sent in the transmission""" self.startTime: float = startTime """float: The simulated time at which the transmission started""" self.headerDuration = packet.header.bitSize / mcsHeader.dataRate """float: The time in seconds taken by the transmission of the packet's header""" self.payloadDuration = packet.payload.bitSize / mcsPayload.dataRate """float: The time in seconds taken by the transmission of the packet's payload""" self.duration = self.headerDuration + self.payloadDuration """float: The time in seconds taken by the transmission""" self.stopTime = startTime + self.duration """ float: The moment in simulated time right after the transmission has completed """ self.headerBits = packet.header.bitSize * float(2 - mcsHeader.codeRate) """Transmitted bits for the packet's header (including coding overhead)""" self.payloadBits = packet.payload.bitSize * float(2 - mcsPayload.codeRate) """Transmitted bits for the packet's payload (including coding overhead)""" # SimPy events headerStopTime = self.startTime + self.headerDuration self.eHeaderCompletes: Event = SimMan.timeoutUntil( headerStopTime, self) """ :class:`~simpy.events.Event`: A SimPy event that succeeds at the moment in simulated time right after the packet's header has been transmitted. The transmission object is provided as the value to the :meth:`~simpy.events.Event.succeed` call. """ self.eCompletes: Event = SimMan.timeoutUntil(self.stopTime, self) """
def __init__(self, name: str, frequencyBand: FrequencyBand, plant: SlidingPendulum, controllerAddr: bytes, sampleInterval: float): super(AngleSensor, self).__init__(name, plant.getWagonPos(), 0, frequencyBand) self.plant = plant self.controllerAddr = controllerAddr self.sampleInterval = sampleInterval SimMan.process(self._sensor())
def __init__(self, name: str, xPos: float, yPos: float, frequencyBand: FrequencyBand): super(InvertedPendulumPidController, self).__init__(name, xPos, yPos, frequencyBand) self._angle = 0 self.sensorAddr = None """bytes: The sensor's network address""" self.actuatorAddr = None """bytes: The actuator's network address""" SimMan.process(self.control)
def mobile_device_grid(device_grid): def mover(d: NetworkDevice): yield SimMan.timeout(random.uniform(0, MOVE_INTERVAL)) initialPos = d.position while True: xOffset = random.uniform(-.2, .2) yOffset = random.uniform(-.2, .2) d.position.set(initialPos.x + xOffset, initialPos.y + yOffset) yield SimMan.timeout(MOVE_INTERVAL) for device in device_grid: SimMan.process(mover(device))
def __init__(self, world: ode.World = None): """ Args: world: A py3ode :class:`World` object. If not provided, a new one will be created with gravity ``(0,-9.81,0)``. """ if world is None: world = ode.World() world.setGravity((0, -9.81, 0)) self.world = world self.maxStepSize = 0.05 self._lastUpdateSimTime = SimMan.now SimMan.process(self._stateUpdater())
def step(self, action): assert self.action_space.contains(action) deviceIndex = action["device"] duration = action["duration"] * self.ASSIGNMENT_DURATION_FACTOR # Assign the frequency band assignSignal = self.rrm.assignFrequencyBand(deviceIndex, duration) # Run the simulation until the assignment ends SimMan.runSimulation(assignSignal.eProcessed) # Return (observation, reward, done, info) return self.rrm.interpreter.getFeedback()
def simulation(): # send the test message (a zero) print("sending message") m1.gates["aIn"].send(1) # wait 40 time units yield SimMan.timeout(20) assert m1.msgVal == 19 assert m2.msgVal == 20 yield SimMan.timeout(20) # assertions for m in [m1, m2]: for portName in ["a", "b"]: assert m.msgReceivedCount[portName] == 10
def receiving(self, receiving: bool): if receiving != self._receiving: if receiving: # start receiving if self._receiverProcess is None: self._receiverProcess = SimMan.process(self._receiver()) self._receiving = receiving
def _sendAnnouncement(self, assignMessage: Message): """ Is executed by the `_nAnnouncementReceived` notifier in a blocking and queued way for every assignMessage that is received on the `networkIn` gate. """ destination = assignMessage.args["dest"] duration = assignMessage.args["duration"] announcement = Packet(SimpleMacHeader(self.addr, destination, flag=1), Transmittable(duration)) sendCmd = Message( StackMessageTypes.SEND, { "packet": announcement, "power": self._transmissionPower, "mcs": self._announcementMcs }) logger.debug("%s: Sending announcement: %s", self, announcement) self.gates["phyOut"].send(sendCmd) yield sendCmd.eProcessed yield SimMan.timeout( (duration + 1) * TIME_SLOT_LENGTH) # one extra time slot to prevent collisions # mark the current ASSIGN message as processed assignMessage.setProcessed()
def sender(): yield SimMan.timeout(initialDelay) while True: yield SimMan.timeout(sendInterval) packet = Packet( SimpleMacHeader(bytes([0 for _ in range(5)] + [id % 255]), bytes([255 for _ in range(6)]), flag=0), Transmittable("A message to all my homies")) signal = Message(StackMessageTypes.SEND, { "packet": packet, "power": 40.0, "mcs": mcs }) self._phy.gates["macIn"].send(signal)
def sender(fromMacLayer: SimpleMac, toMacLayer: SimpleMac, payloads: Iterable): # send a bunch of packets from `fromMacLayer` to `toMacLayer` for p in payloads: packet = Packet( SimpleNetworkHeader(fromMacLayer.addr, toMacLayer.addr), p) fromMacLayer.gates["networkIn"].send(packet) yield SimMan.timeout(1e-4)
def _stateUpdater(self): """ A SimPy process that regularly performs ODE time steps when no ODE time step was previously taken within maxStepSize """ while True: yield SimMan.timeout(self.maxStepSize) if self._lastUpdateSimTime <= SimMan.now - self.maxStepSize: self.updateState()
def senderProcess(self): assert self.destinationMac is not None while True: for _ in range(self.packetMultiplicity): data = Transmittable(CounterTrafficEnv.COUNTER_BYTE_LENGTH, self.counter) self.send(data, self.destinationMac) if self.counter < CounterTrafficEnv.COUNTER_BOUND: self.counter += 1 yield SimMan.timeout(CounterTrafficEnv.COUNTER_INTERVAL)
def device_grid(request): """ A parametrized device fixture that sets up SendingDevices in a grid arrangement with 1 m distance between adjacent devices. Tests using this fixture will be run with every specified parameter. """ n = request.param # Number of devices to be created SimMan.init() frequencyBand = FrequencyBand([FsplAttenuation]) devices = [] cols = int(sqrt(n)) for i in range(n): initialDelay = random.uniform(0, SEND_INTERVAL) devices.append( SendingDevice(i, i / cols, i % cols, frequencyBand, SEND_INTERVAL, initialDelay)) return devices
def sending(): # the frequency band should be unused yet assert len(frequencyBand.getActiveTransmissions()) == 0 # setup the message to the physical layer MCS = BpskMcs(frequencyBand.spec) POWER = 0.0 # dBm cmd = Message(StackMessageTypes.SEND, { "packet": packet, "power": POWER, "mcs": MCS }) # send the message to the physical layer senderPhy.gates["macIn"].send(cmd) # wait 8 payload bits yield SimMan.timeout(8 / MCS.dataRate) # assertions for the transmission transmissions = frequencyBand.getActiveTransmissions() assert len(transmissions) == 1 t = transmissions[0] # check the correctness of the transmission created assert t.packet == packet assert t.power == POWER assert t.mcsHeader == MCS assert t.mcsPayload == MCS power = receiverPhy._receivedPower # wait another 64 bits yield SimMan.timeout(64 / MCS.dataRate) # move device 2 setup.device2.position.x = 2 yield SimMan.timeout(16 / MCS.dataRate) assert receiverPhy._receivedPower < power yield SimMan.timeout(1) assert len(frequencyBand.getActiveTransmissions()) == 0
def __init__(self, world: ode.World = None, visualized=False): super(SlidingPendulum, self).__init__(world) # Bodies and joints # Create wagon wagon = ode.Body(self.world) M = ode.Mass() M.setSphere(2500, 0.05) wagon.setMass(M) wagon.setPosition((0, 1, 0)) # Create pendulum pendulum = ode.Body(self.world) M = ode.Mass() M.setSphere(2500, 0.05) pendulum.setMass(M) pendulum.setPosition((0, 2, 0)) # Connect wagon with the static environment using a slider joint slider = ode.SliderJoint(self.world) slider.attach(ode.environment, wagon) slider.setAxis((1, 0, 0)) # Connect pendulum with wagon arm = ode.HingeJoint(self.world) arm.attach(wagon, pendulum) arm.setAnchor(wagon.getPosition()) arm.setAxis((0, 0, 1)) self._wagon = wagon self._pendulum = pendulum self._slider = slider self._arm = arm slider.setParam(ode.ParamVel, 0.1) slider.setParam(ode.ParamFMax, 22) # used to be 22 # visualization self._visualized = visualized if visualized: surface = pygame.display.set_mode((640, 480)) SimMan.process(self._screenUpdater(surface))
def _screenUpdater(self, surface: Surface): """ A SimPy process for regularly redrawing the visualization window. """ fps = 50 stepSize = 1.0 / fps while True: self._drawOnSurface(surface) yield SimMan.timeout(stepSize) self.updateState()
def simple_phy(): # initialize SimPy environment SimMan.init() # create a wireless frequency band with FSPL attenuation frequencyBand = FrequencyBand([FsplAttenuation]) # create two network devices device1 = Device("1", 0, 0) device2 = Device("2", 1, 1) # create the SimplePhy network stack layers device1Phy = SimplePhy("Phy", device1, frequencyBand) device2Phy = SimplePhy("Phy", device2, frequencyBand) setup = dotdict() setup.frequencyBand = frequencyBand setup.device1 = device1 setup.device2 = device2 setup.device1Phy = device1Phy setup.device2Phy = device2Phy return setup
def transmit(self, sender: Device, power: float, packet: Packet, mcsHeader: Mcs, mcsPayload: Mcs) -> Transmission: """ Simulates the transmission of `packet` with the given properties. This is achieved by creating a :class:`Transmission` object with the values passed and triggering the :attr:`transmissionStarted` event of the :class:`FrequencyBand`. Args: sender: The device that transmits mcs: The modulation and coding scheme to be used (represented by an instance of an Mcs subclass) power: Transmission power in dBm brHeader: Header bitrate brPayload: Payload bitrate packet: :class:`~gymwipe.networking.messages.Packet` object representing the packet being transmitted Returns: The :class:`Transmission` object representing the transmission """ self._removeFirstPastTransmission() # regular cleanup t = Transmission(sender, power, packet, mcsHeader, mcsPayload, SimMan.now) self._transmissions.append(t) logger.info("%s added", t, sender=self) # trigger notifiers after returning the transmission def callAfterReturn(value: Any): self.nNewTransmission.trigger(t) # check which transmissionInReachNotifiers have to be triggered for (receiver, radius ), notifier in self._transmissionInReachNotifiers.items(): if receiver.position.distanceTo(sender.position) <= radius: notifier.trigger(t) SimMan.timeout(0).callbacks.append(callAfterReturn) return t
def control(self): correction = 0 kp = 1.0 # 57.0 ki = 0.0 # 26.0 kd = 0.0 # 12.0 last_error = 0 sp = 0 def calcVelocity(error): nonlocal last_error PID = kp * error + ki * (error + last_error) + kd * (error - last_error) last_error = error return PID yield SimMan.timeout(1) while True: errorcw = abs(sp - self._angle) correction = calcVelocity(errorcw) if self._angle < sp: self._sendVelocity(correction) if self._angle > sp: self._sendVelocity(-correction) yield SimMan.timeout(0.01)
def networkInHandler(self, cmd): if isinstance(cmd, Message): if cmd.type is StackMessageTypes.RECEIVE: logger.debug("%s: Entering receive mode.", self) # start receiving self._receiveCmd = cmd # set _receiving and a timeout event self._receiving = True self._receiveTimeout = SimMan.timeout(cmd.args["duration"]) self._receiveTimeout.callbacks.append( self._receiveTimeoutCallback) elif isinstance(cmd, Packet): payload = cmd packet = Packet( SimpleMacHeader(self.addr, payload.header.destMAC, flag=0), payload) self._packetQueue.append(packet) self._packetAddedEvent.succeed() self._packetAddedEvent = Event(SimMan.env)
def macInHandler(self, cmd): p = cmd.args if cmd.type is StackMessageTypes.SEND: logger.info("Received SEND command", sender=self) # If the receiver is active, wait until it is inactive again if self._receiving: yield self._nReceivingFinished.event self._transmitting = True # Wait for the beginning of the next time slot yield SimMan.nextTimeSlot(TIME_SLOT_LENGTH) # Simulate transmitting t = self.frequencyBand.transmit(self.device, p["power"], p["packet"], p["mcs"], p["mcs"]) self._currentTransmission = t # Wait for the transmission to finish yield t.eCompletes self._transmitting = False # Indicate that the send command was processed cmd.setProcessed()
def test_gate_listener_generator(caplog): caplog.set_level(logging.DEBUG, logger='gymwipe.networking.construction') SimMan.init() # Checking side effects by using two identical modules again modules = MyModule("Test1"), MyModule("Test2") def main(): for i in range(3): for module in modules: module.gates["bIn"].send("msg" + str(i)) yield SimMan.timeout(1) SimMan.process(main()) SimMan.runSimulation(40) for module in modules: # Non-queued PortListener should only have received the first message, # since receiving takes 10 time units and the send interval is 1 time unit. assert module.logs[2] == ["msg0"] # Queued PortListener should have received all messages. assert module.logs[3] == ["msg" + str(n) for n in range(3)]
def main(): for i in range(1, 3): n.trigger("msg" + str(i)) yield SimMan.timeout(1)