# Path: imusim/behaviours/mac.py
# class MAC(object):
#     """
#     Base class for MAC implementations.
# 
#     @ivar radio: The L{Radio} used by the MAC.
#     @ivar timerMux: L{TimerMultiplexer} used by the MAC.
#     """
# 
#     __metaclass__ = ABCMeta
# 
#     def __init__(self, radio, timerMux):
#         """
#         Initialise MAC.
# 
#         @param radio: The L{Radio} to be used by the MAC.
#         @param timerMux: L{TimerMultiplexer} to be used by the MAC.
#         """
#         self.radio = radio
#         self.timerMux = timerMux
# 
#         self.radio.setReceiveHandler(self.handleIncomingPacket)
# 
#     @abstractmethod
#     def queuePacket(self, packet):
#         """
#         Queue a packet for transmission
# 
#         @param packet: The L{RadioPacket} to transmit.
#         """
#         pass
# 
#     @abstractmethod
#     def handleIncomingPacket(self, packet):
#         """
#         Handle a received packet from the radio.
# 
#         @param packet: the received L{RadioPacket}.
#         """
#         pass
# 
# Path: imusim/behaviours/timing.py
# class VirtualTimer(object):
#     """
#     A virtual timer multiplexed to a hardware timer.
# 
#     Implements the same interface as L{Timer}.
# 
#     @ivar callback: Function to be called when timer fires.
#     """
#     def __init__(self, mux, callback=None):
#         """
#         Create virtual timer.
# 
#         @param mux: The L{TimerMultiplexer} implementing this timer.
#         """
#         self._period = None
#         self._mux = mux
#         self.callback = callback
#         self._mux._vtimers.append(self)
# 
#     @prepend_method_doc(Timer)
#     def start(self, period, repeat=False):
#         self._period = period
#         self._repeat = repeat
# 
#         if self._mux._inHandler:
#             # In timer event, handler is iterating through virtual timer list.
#             self._done = True
#             self._remaining = self._period
#         else:
#             self._done = False
#             if self._mux._period is None:
#                 # Timer off, this will become the only active virtual timer.
#                 self._remaining = self._period
#                 self._mux._period = self._period
#                 self._mux._timer.start(self._period, self._mux._timerHandler)
#             elif self._period < self._mux._period:
#                 # This timer will fire before any others.
#                 self._remaining = self._period
#                 elapsed = self._mux._timer.timeElapsed()
#                 for vtimer in self._mux._vtimers:
#                     if vtimer is not self and vtimer._period is not None:
#                         vtimer._remaining -= elapsed
#                 self._mux._period = self._period
#                 self._mux._timer.start(self._mux._period,
#                         self._mux._timerHandler)
#             elif self._period == self._mux._period:
#                 # This timer will fire at the same time as others.
#                 self._remaining = self._period
#             else:
#                 # Other timers will fire before this one.
#                 self._remaining = self._period + self._mux._timer.timeElapsed()
# 
#     @prepend_method_doc(Timer)
#     def clear(self):
#         self._period = None
# 
#     @prepend_method_doc(Timer)
#     def timeElapsed(self):
#         return (self._period - self._remaining) + self.mux._timer.timeElapsed()
# 
# Path: imusim/platforms/radios.py
# class RadioPacket(dict):
#     """
#     Class to represent a radio packet.
# 
#     Payload fields should be added as dictionary items.
# 
#     Metadata relevant to radio simulation should be added as attributes.
#     """
# 
#     __metaclass__ = ABCMeta
# 
#     def __init__(self, *args, **kwargs):
#         dict.__init__(self, *args, **kwargs)
#         """
#         Construct a radio packet.
#         """
#         pass
# 
#     @abstractproperty
#     def bytes(self):
#         pass


from imusim.behaviours.mac import MAC
from imusim.behaviours.timing import VirtualTimer
from imusim.platforms.radios import RadioPacket
from imusim.maths.quaternions import Quaternion
from imusim.utilities.documentation import prepend_method_doc
import numpy as np

    def __init__(self, dataSlotTime, syncSlotTime, dataSlots):
        """
        Initialise schedule.

        @param dataSlotTime: Data slot duration (float, s).
        @param syncSlotTime: Synchronisation slot duration (float, s).
        @param dataSlots: List of device IDs indexed by allocated slot.
        """
        self.dataSlotTime = dataSlotTime
        self.syncSlotTime = syncSlotTime
        self.dataSlots = dataSlots

    @property
    def framePeriod(self):
        """ Duration of one complete frame. """
        return len(self.dataSlots) * self.dataSlotTime + self.syncSlotTime

    def dataTxSlot(self, id):
        """ Transmission slot number for given device ID. """
        return self.dataSlots.index(id)

class SyncPacket(RadioPacket):
    """
    Synchronisation packet from master.
    """
    @property
    def bytes(self):
        return 1


# Path: imusim/behaviours/mac.py
# class MAC(object):
#     """
#     Base class for MAC implementations.
# 
#     @ivar radio: The L{Radio} used by the MAC.
#     @ivar timerMux: L{TimerMultiplexer} used by the MAC.
#     """
# 
#     __metaclass__ = ABCMeta
# 
#     def __init__(self, radio, timerMux):
#         """
#         Initialise MAC.
# 
#         @param radio: The L{Radio} to be used by the MAC.
#         @param timerMux: L{TimerMultiplexer} to be used by the MAC.
#         """
#         self.radio = radio
#         self.timerMux = timerMux
# 
#         self.radio.setReceiveHandler(self.handleIncomingPacket)
# 
#     @abstractmethod
#     def queuePacket(self, packet):
#         """
#         Queue a packet for transmission
# 
#         @param packet: The L{RadioPacket} to transmit.
#         """
#         pass
# 
#     @abstractmethod
#     def handleIncomingPacket(self, packet):
#         """
#         Handle a received packet from the radio.
# 
#         @param packet: the received L{RadioPacket}.
#         """
#         pass
# 
# Path: imusim/behaviours/timing.py
# class VirtualTimer(object):
#     """
#     A virtual timer multiplexed to a hardware timer.
# 
#     Implements the same interface as L{Timer}.
# 
#     @ivar callback: Function to be called when timer fires.
#     """
#     def __init__(self, mux, callback=None):
#         """
#         Create virtual timer.
# 
#         @param mux: The L{TimerMultiplexer} implementing this timer.
#         """
#         self._period = None
#         self._mux = mux
#         self.callback = callback
#         self._mux._vtimers.append(self)
# 
#     @prepend_method_doc(Timer)
#     def start(self, period, repeat=False):
#         self._period = period
#         self._repeat = repeat
# 
#         if self._mux._inHandler:
#             # In timer event, handler is iterating through virtual timer list.
#             self._done = True
#             self._remaining = self._period
#         else:
#             self._done = False
#             if self._mux._period is None:
#                 # Timer off, this will become the only active virtual timer.
#                 self._remaining = self._period
#                 self._mux._period = self._period
#                 self._mux._timer.start(self._period, self._mux._timerHandler)
#             elif self._period < self._mux._period:
#                 # This timer will fire before any others.
#                 self._remaining = self._period
#                 elapsed = self._mux._timer.timeElapsed()
#                 for vtimer in self._mux._vtimers:
#                     if vtimer is not self and vtimer._period is not None:
#                         vtimer._remaining -= elapsed
#                 self._mux._period = self._period
#                 self._mux._timer.start(self._mux._period,
#                         self._mux._timerHandler)
#             elif self._period == self._mux._period:
#                 # This timer will fire at the same time as others.
#                 self._remaining = self._period
#             else:
#                 # Other timers will fire before this one.
#                 self._remaining = self._period + self._mux._timer.timeElapsed()
# 
#     @prepend_method_doc(Timer)
#     def clear(self):
#         self._period = None
# 
#     @prepend_method_doc(Timer)
#     def timeElapsed(self):
#         return (self._period - self._remaining) + self.mux._timer.timeElapsed()
# 
# Path: imusim/platforms/radios.py
# class RadioPacket(dict):
#     """
#     Class to represent a radio packet.
# 
#     Payload fields should be added as dictionary items.
# 
#     Metadata relevant to radio simulation should be added as attributes.
#     """
# 
#     __metaclass__ = ABCMeta
# 
#     def __init__(self, *args, **kwargs):
#         dict.__init__(self, *args, **kwargs)
#         """
#         Construct a radio packet.
#         """
#         pass
# 
#     @abstractproperty
#     def bytes(self):
#         pass


# Path: imusim/behaviours/orient_tdma.py
from imusim.behaviours.mac import MAC
from imusim.behaviours.timing import VirtualTimer
from imusim.platforms.radios import RadioPacket
from imusim.maths.quaternions import Quaternion
from imusim.utilities.documentation import prepend_method_doc
import numpy as np


    def __init__(self, dataSlotTime, syncSlotTime, dataSlots):
        """
        Initialise schedule.

        @param dataSlotTime: Data slot duration (float, s).
        @param syncSlotTime: Synchronisation slot duration (float, s).
        @param dataSlots: List of device IDs indexed by allocated slot.
        """
        self.dataSlotTime = dataSlotTime
        self.syncSlotTime = syncSlotTime
        self.dataSlots = dataSlots

    @property
    def framePeriod(self):
        """ Duration of one complete frame. """
        return len(self.dataSlots) * self.dataSlotTime + self.syncSlotTime

    def dataTxSlot(self, id):
        """ Transmission slot number for given device ID. """
        return self.dataSlots.index(id)

class SyncPacket(RadioPacket):
    """
    Synchronisation packet from master.
    """
    @property
    def bytes(self):
        return 1


class DataPacket(RadioPacket):