Esempio n. 1
0
    def _create_packet(self):
        packet_size = 0
        packet_bytes = ""

        sent_messages = []

        self._log.debug('%d packets pending' % len(self._outgoing))

        for message in self._outgoing:

            if message.require_ack:

                # a minimum resend delay is required for two reasons:
                # 1. deadlock with a 0ms latency connection causes _do_write
                #    to never exit as _create_packet always returns data.
                # 2. resending every 0ms is just plain stupid.

                t = time.time()
                resend_delay = max(self.MINIMUM_RESEND_DELAY_MS,
                                   self._transport_latency)

                self._log.debug('LSAT: %s' %
                                str(message.last_send_attempt_timestamp))
                self._log.debug('l8nc: %s' % str(self._transport_latency))
                self._log.debug('time: %s' % t)
                self._log.debug('rsnd: %s' % resend_delay)

                if message.last_send_attempt_timestamp is not None:
                    if ((message.last_send_attempt_timestamp + resend_delay) >=
                            t):
                        self._log.debug('Waiting for ack.')
                        continue

            if packet_size + message.length <= self.MTU:
                self._log.debug('Added data message into UDP packet')
                packet_size += message.length
                packet_bytes += message.message_bytes
                message.last_send_attempt_timestamp = time.time()
                sent_messages.append(message)
            else:
                self._log.debug('packet at MTU limit.')

        for sent_message in sent_messages:
            # Packets that require an ack are only removed
            # from the outgoing list if an ack is received.
            if not sent_message.require_ack:
                self._log.info('Message %d doesnt require ack - removing' %
                               sent_message.message_id)
                self._outgoing.remove(sent_message)
            else:
                self._log.info(
                    'Message %d requires ack - waiting for response' %
                    sent_message.message_id)

        return packet_bytes
Esempio n. 2
0
    def __init__(self, parent=None, message_factory=None):
        if message_factory is None:
            self.message_factory = parent.message_factory
        else:
            self.message_factory = message_factory

        self.parent = parent
        self._last_receive_timestamp = time.time()
        self._last_send_timestamp = time.time()
        self._keep_alive_send_timestamp = time.time()
        self._keep_alive_message_id = 0

        # server: number of keepalives sent
        # client: number of keepalives received
        self._keepalive_count = 0

        self._ping_id = 0
        self._ping_send_timestamp = time.time()
        self._ping_meter = PingSampler()

        self.OnConnectRequestAccepted = Event()
        self.OnConnectRequestRejected = Event()
        self.OnConnectRequest = Event()
        self.OnError = Event()
        self.OnMessage = Event()
        self.OnDisconnect = Event()

        # Packet instances to be processed go in here
        self._incoming_messages = []

        # List of OutgoingMessages
        self._outgoing = []

        # In-order packet instances that have arrived early
        self._incoming_out_of_sequence_messages = []

        self._incoming_ordered_sequence_number = 0
        self._outgoing_ordered_sequence_number = 1
        self._outgoing_message_id = 0
        self._recent_message_ids = []

        # Metrics
        self._in_bytes = 0
        self._out_bytes = 0
        self._in_packets = 0
        self._out_packets = 0
        self._in_messages = 0
        self._out_messages = 0
        '''
        Default transport latency is high - This prevents spamming
        of the network prior to obtaining a calculated latency.
        '''
        self._transport_latency = 0.3  # 0.1 = 100ms
Esempio n. 3
0
    def _send_ping(self):
        self._ping_id += 1
        if (self._ping_id > netshared.USHRT_MAX):
            self._ping_id = 0

        ping = self.message_factory.get_by_name('Ping')()
        ping.id.value = self._ping_id
        self.send_message(ping)
        self._ping_send_timestamp = time.time()
Esempio n. 4
0
    def _send_keep_alive(self):
        self._keep_alive_message_id += 1
        if (self._keep_alive_message_id > netshared.USHRT_MAX):
            self._keep_alive_message_id = 0

        message = self.message_factory.get_by_name('KeepAliveRequest')()
        message.id.value = self._keep_alive_message_id

        self.send_message(message)
        self._keep_alive_send_timestamp = time.time()
        self._keepalive_count += 1
Esempio n. 5
0
    def __init__(self, parent=None, address=None):
        self._connected = False
        self.parent = parent
        self._socket = parent.socket
        self._address = address
        self._last_receive_timestamp = time.time()
        self._pending_disconnect = False

        self.OnConnectRequest = Event()
        self.OnDisconnect = Event()
        self.OnError = Event()
        self.OnMessage = Event()

        self._connection = Service('Connection', {'parent': self})

        self._connection.OnMessage += self._Connection_OnMessage
        self._connection.OnDisconnect += self._Connection_OnDisconnect
        self._connection.OnError += self._Connection_OnError
        self._connection.OnConnectRequest += self._Connection_OnConnectRequest
Esempio n. 6
0
    def send_message(self, message, ordered=False, reliable=False):
        '''
        Send a message and specify any options for the send method used.
        A message sent inOrder is implicitly sent as reliable.
        message is an instance of a subclass of packets.BasePacket.
        Returns the number of bytes added to the output queue for this
        message (header + message).
        '''
        self._last_send_timestamp = time.time()

        self._outgoing_message_id += 1
        message_id = self._outgoing_message_id
        if ordered:
            self._outgoing_ordered_sequence_number += 1
            inorder_sequence_number = self._outgoing_ordered_sequence_number
        else:
            inorder_sequence_number = 0

        packet_flags = bitfield()
        packet_flags[0] = int(ordered)
        packet_flags[1] = int(reliable)

        message_transport_header = struct.pack(
            '!' + self.MESSAGE_TRANSPORT_HEADER, message_id,
            inorder_sequence_number, int(packet_flags))

        message_bytes = message.get_packet_bytes()
        total_length = len(message_bytes) + len(message_transport_header)
        self._out_bytes += total_length

        self._add_message_bytes_to_output_list(
            message_id, message_transport_header + message_bytes, ordered
            or reliable)

        self._log.debug('Packet data length = %s' % len(message_bytes))
        self._log.debug('Header length = %s' % len(message_transport_header))
        self._log.debug('Added %d byte %s packet in outgoing buffer' %
                        (total_length, message.__class__.__name__))

        return total_length
Esempio n. 7
0
class Connection(object):

    MTU = 1400
    MESSAGE_TRANSPORT_HEADER = 'HHB'
    RECENT_MESSAGE_LIST_SIZE = 1000
    MINIMUM_RESEND_DELAY_MS = 10 / 1000.0

    _log = logging.getLogger('legume.Connection')

    def __init__(self, parent=None, message_factory=None):
        if message_factory is None:
            self.message_factory = parent.message_factory
        else:
            self.message_factory = message_factory

        self.parent = parent
        self._last_receive_timestamp = time.time()
        self._last_send_timestamp = time.time()
        self._keep_alive_send_timestamp = time.time()
        self._keep_alive_message_id = 0

        # server: number of keepalives sent
        # client: number of keepalives received
        self._keepalive_count = 0

        self._ping_id = 0
        self._ping_send_timestamp = time.time()
        self._ping_meter = PingSampler()

        self.OnConnectRequestAccepted = Event()
        self.OnConnectRequestRejected = Event()
        self.OnConnectRequest = Event()
        self.OnError = Event()
        self.OnMessage = Event()
        self.OnDisconnect = Event()

        # Packet instances to be processed go in here
        self._incoming_messages = []

        # List of OutgoingMessages
        self._outgoing = []

        # In-order packet instances that have arrived early
        self._incoming_out_of_sequence_messages = []

        self._incoming_ordered_sequence_number = 0
        self._outgoing_ordered_sequence_number = 1
        self._outgoing_message_id = 0
        self._recent_message_ids = []

        # Metrics
        self._in_bytes = 0
        self._out_bytes = 0
        self._in_packets = 0
        self._out_packets = 0
        self._in_messages = 0
        self._out_messages = 0
        '''
        Default transport latency is high - This prevents spamming
        of the network prior to obtaining a calculated latency.
        '''
        self._transport_latency = 0.3  # 0.1 = 100ms

    @property
    def out_buffer_bytes(self):
        return sum([len(o.message_bytes) for o in self._outgoing])

    @property
    def latency(self):
        return self._ping_meter.get_ping()

    @property
    def in_bytes(self):
        return self._in_bytes

    @property
    def out_bytes(self):
        return self._out_bytes

    @property
    def reorder_queue(self):
        return len(self._incoming_out_of_sequence_messages)

    @property
    def keepalive_count(self):
        return self._keepalive_count

    # ------------- Public Methods -------------

    def process_inbound_packet(self, data):
        self._in_packets += 1
        self._process_inbound_packet(data)

    def update(self):
        '''
        Send any packets that are in the output buffer and read
        any packets that have been received.
        '''
        try:
            self.parent.do_read(self._on_socket_data)
        except netshared.NetworkEndpointError, e:
            self.raiseOnError('Connection reset by peer')
            return

        if self._ping_meter.has_estimate():
            self._transport_latency = self._ping_meter.get_ping()

        read_messages = self._update(self.parent._socket, self.parent._address)

        if len(read_messages) != 0:
            self._last_receive_timestamp = time.time()

        for message in read_messages:

            if self.message_factory.is_a(message, 'ConnectRequestAccepted'):
                self.OnConnectRequestAccepted(self, None)

            elif self.message_factory.is_a(message, 'ConnectRequestRejected'):
                self.OnConnectRequestRejected(self, None)

            elif self.message_factory.is_a(message, 'KeepAliveResponse'):

                if (message.id.value == self._keep_alive_message_id):
                    self._ping_meter.add_sample(
                        (time.time() - self._keep_alive_send_timestamp) * 1000)
                else:
                    self._log.warning('Received old keep-alive, discarding')

            elif self.message_factory.is_a(message, 'KeepAliveRequest'):
                self._keepalive_count += 1
                response = self.message_factory.get_by_name(
                    'KeepAliveResponse')()
                response.id.value = message.id.value
                self.send_message(response)

            elif self.message_factory.is_a(message, 'Pong'):
                if (message.id.value == self._ping_id):
                    self._ping_meter.add_sample(
                        (time.time() - self._ping_send_timestamp) * 1000)
                else:
                    self._log.warning('Received old Pong, discarding')

            elif self.message_factory.is_a(message, 'Ping'):
                self._send_pong(message.id.value)

            elif self.message_factory.is_a(message, 'Disconnected'):
                self._log.debug('Received `Disconnected` message')
                self.OnDisconnect(self, None)

            elif self.message_factory.is_a(message, 'MessageAck'):
                self._process_message_ack(message.message_to_ack.value)

            elif self.message_factory.is_a(message, 'ConnectRequest'):
                # Unless the connection request is explicitly denied then
                # a connection is made - OnConnectRequest may return None
                # if no event handlers are bound.
                accept = True

                if (message.protocol.value != netshared.PROTOCOL_VERSION):
                    self._log.error('Invalid protocol version for client')
                    accept = False
                if self.OnConnectRequest(self.parent, message) is False:
                    accept = False

                if accept:
                    response = self.message_factory.get_by_name(
                        'ConnectRequestAccepted')
                    self.send_reliable_message(response())
                else:
                    response = self.message_factory.get_by_name(
                        'ConnectRequestRejected')
                    self.send_reliable_message(response())
                    self.pendingDisconnect = True
            else:
                self.OnMessage(self, message)

        if (time.time() > self._ping_send_timestamp + PING_REQUEST_FREQUENCY):
            if self.parent.is_server:
                self._keep_alive_send_timestamp = time.time()
            self._send_ping()

        if self.parent.is_server:
            # Server sends keep alive requests...
            if ((time.time() - self._keep_alive_send_timestamp) >
                (self.parent.timeout / 2)):
                self._send_keep_alive()
            # though it will eventually give up...
            if (time.time() -
                    self._last_receive_timestamp) > (self.parent.timeout):
                self.OnError(self, 'Connection timed out')
        else:
            # ...Client waits for the connection to timeout
            if (time.time() -
                    self._last_receive_timestamp) > (self.parent.timeout):
                self._log.info('Connection has timed out')
                self.OnError(self, 'Connection timed out')
 from timeit import gc
 total = list()
 iterations = 10
 # for i in range(iterations):
 #     start = timer()
 #     gc.enable()
 #     connect_graph2(G)
 #     end = timer()
 #     total.append((end - start))
 # print('connect graph: ',np.mean(total), np.std(total))
 # total = list()
 for i in range(iterations):
 #     start = timer()
 #     gc.enable()
     timing.log('Connect graph started')
     time = timing.time()
     connect_graph3(G)
     timing.log('Connect graph ended', timing.time()-time)
 # plt.plot(times0)
 # plt.plot(times1)
 # plt.plot(times11)
 # plt.plot(times2)
 # plt.plot(times3)
 # plt.plot(times4)
 # plt.plot(times5)
 print('complete while loop ocurred ', len(times0), ' with mean ',  np.mean(times0),   ' total cost ', len(times0)*np.mean(times0))
 print('get_oposition_points_by_distance ocurred ', len(times1), ' with mean ',  np.mean(times1),   ' total cost ', len(times1)*np.mean(times1))
 print('get_triangles_to_look ocurred ', len(times11), ' with mean ', np.mean(times11), ' total cost ', len(times11)*np.mean(times11))
 print('for candidate loop ocurred ', len(times2), ' with mean ',  np.mean(times2),   ' total cost ', len(times2)*np.mean(times2))
 print('create new_triangle ocurred ', len(times3), ' with mean ',  np.mean(times3),   ' total cost ', len(times3)*np.mean(times3))
 print('check_triangle_intersection ocurred ', len(times4), ' with mean ',  np.mean(times4),   ' total cost ', len(times4)*np.mean(times4))
Esempio n. 9
0
    gyro_slipping = qt.quaternion_rotate(q_pitch1, gyro[:, i])
    slipping_one[i] = one_wheel_slip_detection(
        encoder.r, encoder.d, np.array([enc_meas[-1, i], enc_meas[-2, i]]),
        gyro_slipping)

    # Data for Sensor data plots
    theta = x2[2, i]
    q_pitch = qt.quaternion(theta, [0, 1, 0])
    psi = x2[4, i]
    q_yaw = qt.quaternion(psi, [0, 0, 1])
    q_s = qt.multiply(q_yaw, q_pitch)
    gyro_s[:, i] = qt.quaternion_rotate(q_pitch, gyro[:, i])
    acc_s[:, i] = qt.quaternion_rotate(q_pitch, acceleration[:, i])

    # Orientation Estimation
    t_ori = timing.time()
    R_IMU_b = np.identity(3)
    acc = R_IMU_b @ acceleration[:, i]
    gyr = R_IMU_b @ gyro[:, i]

    V = np.identity(4) * 0.1
    W = np.identity(3) * 1000000

    xh[:, i], Ph = quaternionestimation.ekf(xh[:, i - 1], gyr, acc, head_enc,
                                            V, W, Ph, 9.81, robot.Ts)
    heading[:, i] = qt.get_heading(xh[:, i])
    euler[:, i] = qt.euler_from_q(xh[:, i], 'zyx', True)
    time_orientation[i] = timing.time() - t_ori

    # Position Estimation
    t_pos = timing.time()