Timing errors with Pymavlink

Hello, I am working on a project that uses pymavlink to programmatically issue commands to a simulated plane. I have a problem where pymavlink crashes whenever I send a message using pymavlink’s wrapper functions or when I use recv_match to wait for a message due to one of three errors:

bytearray / array index out of bounds:

Traceback (most recent call last):
  File "/mavsim/mavproxy_utils/ardupilot.py", line 55, in mavMsgHandler
    msg = m.recv_msg()
  File "/usr/lib/python2.7/site-packages/pymavlink/mavutil.py", line 926, in recv_msg
    m = self.mav.parse_char(s)
  File "/usr/lib/python2.7/site-packages/pymavlink/dialects/v10/ardupilotmega.py", line 9587, in parse_char
    m = self.__parse_char_legacy()
  File "/usr/lib/python2.7/site-packages/pymavlink/dialects/v10/ardupilotmega.py", line 9604, in __parse_char_legacy
    if self.buf_len() >= 1 and self.buf[self.buf_index] == PROTOCOL_MARKER_V2:

and a “local variable “magic” has been referenced before assignment” error. I don’t have a stack trace for this one, but I do know that the line where it occurs is in a generated python file. The line that generates it can be found in pymavlink/generator/mavgen_python.py on line 559.

An example of one of my functions that sends commands, where self.craft.mav is the reference to pymavlink’s mavutil.py:

def set_wp(self, wp_list):
        '''
        @description:
            Set the craft's mission in terms of waypoints according to the stored waypoints
        @params:
            wp_list: list of tuples that represent waypoints
        '''
        # Send number of waypoints to expect
        self.craft.mav.waypoint_count_send(len(wp_list))
        count = 0

        for wp in wp_list:
            if self.craft.mav.recv_match(type='MISSION_REQUEST', blocking=True, timeout=5) is None:
                settings.logger.error('Waypoint ' + str(wp[0]) + 'was not set due to timeout')
            else:
                self.craft.mav.setMissionItem(int(wp[0]), int(wp[1]), int(wp[2]),
                                              int(wp[3]), float(wp[4]), float(wp[5]),
                                              float(wp[6]), float(wp[7]), float(wp[8]),
                                              float(wp[9]), float(wp[10]), int(wp[11]))
                settings.logger.debug('Waypoint ' + wp)
                count += 1

            settings.logger.info('Set ' + count + '/' + len(wp_list) + 'waypoints')

From what I can tell, I am probably overloading mavlink with too many messages. I have tried to space out message sending by 5 seconds, but I still receive these errors intermittently. I have attempted this using code similar to mavparm.py example and still got one of the three errors. Any suggestions?

Hello, I am working on a project that uses pymavlink to programmatically
issue commands to a simulated plane. I have a problem where pymavlink

Can you put up a minimal example which shows the problem?

Are you using threading in your script?

I thread this function for retrieving waypoints:

wp = []
        count = None
        stored = None
        self.craft.mav.waypoint_request_list_send()
        settings.logger.info('Sending waypoint list request')

        while True:
            if count is None:
                try:
                    count = self.craft.mav.recv_match(type='MISSION_COUNT', blocking=True,
                                                 timeout=15).count
                except:
                    count = None
                    continue
                settings.logger.debug('Waypoint list request recieved: %d waypoints', count)
                if count == 0:
                    settings.logger.info('Waypoint request transaction complete, 0 waypoints found')
                    break
                self.craft.mav.waypoint_request_send(0)
            next_wp = self.craft.mav.recv_match(type='MISSION_ITEM')
            if next_wp:
                if stored is None or (next_wp and stored.seq != next_wp.seq):
                    stored = next_wp
                    wp.append(next_wp)
                    count -= 1
                    if count == 0:
                        settings.logger.info('Waypoint request transaction complete')
                        break
                    settings.logger.debug('getting next waypoint: %d', next_wp.seq + 1)
                    self.craft.mav.waypoint_request_send(next_wp.seq + 1)

As for a minimal example, where flyTo and setSpeed use mavlink’s mission_item_send:

        self.s_sim.craft.flyTo(lat, lon, alt)
        time.sleep(1)
        self.s_sim.craft.setSpeed(vel)
        time.sleep(1)
        settings.logger.info('Flying to lat: %f lon: %f alt: %u at %u m/s', lat, lon, alt, vel)

        # Wait until point reached
        if self.s_sim.craft.mav.recv_match('MISSION_ITEM_REACHED', blocking=True, timeout=100.0):

The errors occur fairly consistently whenever recv_match is called.

Thank you for the reply!

1 Like

I thread this function for retrieving waypoints:

Ah. You have multiple threads calling recv_match? If so, that’s not
going to work. They’ll both be trying to read from the (e.g.) serial port
and feeding the state machine.

You might look at what both MAVProxy and dronekit-python do; they despatch
parsed messages from a central point.

1 Like

Thanks, I will try that!