bitcraze / crazyflie-lib-python

Python library to communicate with Crazyflie
Other
259 stars 892 forks source link

qualisys hl commander error #395

Closed gaurav713914 closed 1 year ago

gaurav713914 commented 1 year ago

I am getting the following error upon running this qualisys_hl_commander.py script on my pc which is connected to a qualisys mocap system and my crazyflie is having 12/2022 firmware, I also tried it with 02/2023 firmware but it is not running. Please help.

2023-04-27 17:55:21,565 - cflib.crazyflie - INFO - Callback->Connection initialized[radio://0/80/2M/E7E7E7E704]
Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 536, in _loop_writing
    self._write_fut = self._loop._proactor.sendto(self._sock,
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\windows_events.py", line 543, in sendto        
    ov.WSASendTo(conn.fileno(), buf, flags, addr)
OSError: [WinError 10022] An invalid argument was supplied

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 97, in run
    asyncio.run(self._life_cycle())
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 100, in _life_cycle
    await self._connect()
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 106, in _connect
2023-04-27 17:55:21,576 - cflib.crazyflie - INFO - We are connected[radio://0/80/2M/E7E7E7E704], request connection setup
2023-04-27 17:55:21,576 - cflib.crazyflie.platformservice - INFO - Request _request_protocol_version()
    qtm_instance = await self._discover()
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 120, in _discover
    async for qtm_instance in qtm.Discover('0.0.0.0'):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 85, in __anext__
    protocol.send_discovery_packet()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 50, in send_discovery_packet
    self.transport.sendto(
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 508, in sendto
    self._loop_writing()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 540, in _loop_writing
    self._protocol.error_received(exc)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'QRTDiscoveryProtocol' object has no attribute 'error_received'
2023-04-27 17:55:21,589 - cflib.crazyflie - INFO - Callback->Connected to [radio://0/80/2M/E7E7E7E704]
2023-04-27 17:55:21,647 - cflib.crazyflie.platformservice - INFO - _crt_service_callback
2023-04-27 17:55:21,647 - cflib.crazyflie.platformservice - INFO - Request protocol version
2023-04-27 17:55:21,651 - cflib.crazyflie.platformservice - INFO - _platform_callback
2023-04-27 17:55:21,651 - cflib.crazyflie.platformservice - INFO - Protocol version (platform): 5
2023-04-27 17:55:24,003 - cflib.crazyflie.toccache - INFO - Saved cache to [./cache/06E08EEC.json]
2023-04-27 17:55:24,003 - cflib.crazyflie - INFO - Log TOC finished updating
2023-04-27 17:55:24,006 - cflib.crazyflie.mem - INFO - 5 memories found
2023-04-27 17:55:24,087 - cflib.crazyflie - INFO - Memories finished updating
2023-04-27 17:55:25,405 - cflib.crazyflie.toccache - INFO - Saved cache to [./cache/E60D1F34.json]
2023-04-27 17:55:25,820 - cflib.crazyflie - INFO - Param TOC finished updating
2023-04-27 17:55:25,820 - cflib.crazyflie - INFO - Callback->Connection setup finished [radio://0/80/2M/E7E7E7E704]
2023-04-27 17:55:26,837 - cflib.crazyflie - INFO - All parameters updated
2023-04-27 17:55:26,838 - cflib.crazyflie - INFO - Callback->Connection completed [radio://0/80/2M/E7E7E7E704]
The sequence is 7.3 seconds long
Waiting for estimator to find position...
2023-04-27 17:55:27,175 - cflib.crazyflie.log - INFO - Have successfully started logging for id=1
knmcguire commented 1 year ago

which QTM version are you using on the mocap computer and which version do you have installed on pip?

This all is not related to the firmware of the crazyflie as you have no problem connecting it. It is just going wrong at the qualisys api

gaurav713914 commented 1 year ago

My qtm version is 2022.2 (build 7710)

and pip version is pip 23.1 from C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\pip (python 3.11)

the qtm version installed on pip is Name: qtm Version: 2.1.1 Summary: QTM Python SDK Home-page: https://github.com/qualisys/qualisys_python_sdk Author: Martin Gejke Author-email: support@qualisys.com License: MIT Location: C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages Requires: Required-by: qfly

and qfly version is

Name: qfly Version: 0.2 Summary: Qualisys Drone SDK Home-page: https://github.com/qualisys/qualisys_drone_sdk Author: Mehmet Aydin Baytas c/o Qualisys AB Author-email: support@qualisys.com License: MIT Location: C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages Requires: cflib, pynput, qtm Required-by:

krichardsson commented 1 year ago

I can not reproduce this in our system. We are running QTM 2023.02, but I also tested on 2021.02 and that also worked fine. I'm also using V2.1.1 of the python qtm module. qfly is not used by the qualisys_hl_commander.py script.

I'm not sure why you get this problem, but maybe you can check with Qualisys?

gaurav713914 commented 1 year ago

I can not reproduce this in our system. We are running QTM 2023.02, but I also tested on 2021.02 and that also worked fine. I'm also using V2.1.1 of the python qtm module. qfly is not used by the qualisys_hl_commander.py script.

I'm not sure why you get this problem, but maybe you can check with Qualisys?

We first raised the issue with Qualisys and they said that the issue is with crazyflie. Also the Sr. Tech. Engineer from Qualisys asked us not to upgrade the Qualisys software. Can you please reproduce and check the issue on QTM 2022.2 (Build 7710)?

Also, why does it matter what version of QTM Version we are using?

From what I know, QTM just gives the data related to position and orientation of crazyflie. The crazyflie is identified in the GUI of the QTM software, so there should be no problem in receiving the data from QTM.

krichardsson commented 1 year ago

Also, why does it matter what version of QTM Version we are using?

The qualisys_hl_commander.py script connects to QTM to get the position of the Crazyflie, which is then forwarded to the Crazyflie itself. The python lib qualisys_python_sdk from Qualisys is used to handle the connection and the qualisys_hl_commander.py script. Back in 2020 there was a change in the QTM protocol that was not handled by the qualisys lib, see issue #13, but that was fixed in version 2.1.0

To me it looks like the error you get happens when the qualisys_python_sdk lib tries to find out if there are any QTM systems on the network (discovery)

    qtm_instance = await self._discover()
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 120, in _discover
    async for qtm_instance in qtm.Discover('0.0.0.0'):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 85, in __anext__
    protocol.send_discovery_packet()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 50, in send_discovery_packet
    self.transport.sendto(
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 508, in sendto
    self._loop_writing()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 540, in _loop_writing
    self._protocol.error_received(exc)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'QRTDiscoveryProtocol' object has no attribute 'error_received'

The script pretty much just calls discover, connect and gets the data back in a callback, see https://github.com/bitcraze/crazyflie-lib-python/blob/ab0898a074e81f0dc1c2e69049809a347bd5c5f5/examples/qualisys/qualisys_hl_commander.py#L106-L117

I'm not sure what else we could do?

I think the problem is some sort of incompatibility between your QTM and qualisys_python_sdk.

push2312 commented 1 year ago

Also, why does it matter what version of QTM Version we are using?

The qualisys_hl_commander.py script connects to QTM to get the position of the Crazyflie, which is then forwarded to the Crazyflie itself. The python lib qualisys_python_sdk from Qualisys is used to handle the connection and the qualisys_hl_commander.py script. Back in 2020 there was a change in the QTM protocol that was not handled by the qualisys lib, see issue #13, but that was fixed in version 2.1.0

To me it looks like the error you get happens when the qualisys_python_sdk lib tries to find out if there are any QTM systems on the network (discovery)

    qtm_instance = await self._discover()
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "d:\Gaurav Singh Bhati\MoCap\qualisys_hl_commander.py", line 120, in _discover
    async for qtm_instance in qtm.Discover('0.0.0.0'):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 85, in __anext__
    protocol.send_discovery_packet()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 50, in send_discovery_packet
    self.transport.sendto(
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 508, in sendto
    self._loop_writing()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 540, in _loop_writing
    self._protocol.error_received(exc)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'QRTDiscoveryProtocol' object has no attribute 'error_received'

The script pretty much just calls discover, connect and gets the data back in a callback, see

https://github.com/bitcraze/crazyflie-lib-python/blob/ab0898a074e81f0dc1c2e69049809a347bd5c5f5/examples/qualisys/qualisys_hl_commander.py#L106-L117

I'm not sure what else we could do?

I think the problem is some sort of incompatibility between your QTM and qualisys_python_sdk.

Can you provide the versions of every software/package/tools on which the high level commander is working in your system. We will try to see if it works for us with same version. Specifically, we need versions of QTM, python, qfly, QTM python SDK and any other dependencies, if any.

I'm referring this issue to Qualisys as well.

krichardsson commented 1 year ago

As far as I know this has been working since the issue above was fixed, but we do not test with all QTM releases.

I have written a script for you to try. It connects to QTM, waits a bit and disconnects. If you have a rigid body defined in QTM with the name "cf" it will also print the position of this body. There is no connection or code related to the Crazyflie in this script. If you also have problems with this script, it is not related to the Crazyflie.

Have you checked that you are actually running the python version with the correct qtm lib? Is is possible that you have an older version of the lib installed in some other python version that you run accidentally?


import asyncio
import math
import time
import xml.etree.cElementTree as ET
from threading import Thread

import qtm

# The name of the rigid body in QTM that represents the Crazyflie
rigid_body_name = 'cf'

class QtmWrapper(Thread):
    def __init__(self, body_name):
        Thread.__init__(self)

        self.body_name = body_name
        self.on_pose = None
        self.connection = None
        self.qtm_6DoF_labels = []
        self._stay_open = True

        self.start()

    def close(self):
        self._stay_open = False
        self.join()

    def run(self):
        asyncio.run(self._life_cycle())

    async def _life_cycle(self):
        await self._connect()
        while (self._stay_open):
            await asyncio.sleep(1)
        await self._close()

    async def _connect(self):
        qtm_instance = await self._discover()
        host = qtm_instance.host
        print('Connecting to QTM on ' + host)
        self.connection = await qtm.connect(host)

        params = await self.connection.get_parameters(parameters=['6d'])
        xml = ET.fromstring(params)
        self.qtm_6DoF_labels = [label.text.strip() for index, label in enumerate(xml.findall('*/Body/Name'))]

        await self.connection.stream_frames(
            components=['6D'],
            on_packet=self._on_packet)

    async def _discover(self):
        async for qtm_instance in qtm.Discover('0.0.0.0'):
            return qtm_instance

    def _on_packet(self, packet):
        header, bodies = packet.get_6d()

        if bodies is None:
            return

        if self.body_name not in self.qtm_6DoF_labels:
            print('Body ' + self.body_name + ' not found.')
        else:
            index = self.qtm_6DoF_labels.index(self.body_name)
            temp_cf_pos = bodies[index]
            x = temp_cf_pos[0][0] / 1000
            y = temp_cf_pos[0][1] / 1000
            z = temp_cf_pos[0][2] / 1000

            r = temp_cf_pos[1].matrix
            rot = [
                [r[0], r[3], r[6]],
                [r[1], r[4], r[7]],
                [r[2], r[5], r[8]],
            ]

            if self.on_pose:
                # Make sure we got a position
                if math.isnan(x):
                    return

                self.on_pose([x, y, z, rot])

    async def _close(self):
        await self.connection.stream_frames_stop()
        self.connection.disconnect()

if __name__ == '__main__':
    # Connect to QTM
    qtm_wrapper = QtmWrapper(rigid_body_name)
    qtm_wrapper.on_pose = lambda pose: print(pose[0], pose[1], pose[2])
    time.sleep(5)
    qtm_wrapper.close()
gaurav713914 commented 1 year ago

Apologies for the late response. We only have one installation of python and QTM which is mentioned above. We have a new PC so there is no chance of any previously installed versions creating problem. Do you have any suggestion to which we should change versions of python or QTM.

We are getting the same error for your code (see below).

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 536, in _loop_writing
    self._write_fut = self._loop._proactor.sendto(self._sock,
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\windows_events.py", line 543, in sendto        
    ov.WSASendTo(conn.fileno(), buf, flags, addr)
OSError: [WinError 10022] An invalid argument was supplied

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "d:\qtest.py", line 30, in run
    asyncio.run(self._life_cycle())
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "d:\qtest.py", line 33, in _life_cycle
    await self._connect()
  File "d:\qtest.py", line 39, in _connect
    qtm_instance = await self._discover()
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "d:\qtest.py", line 53, in _discover
    async for qtm_instance in qtm.Discover('0.0.0.0'):
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 85, in __anext__
    protocol.send_discovery_packet()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\qtm\discovery.py", line 50, in send_discovery_packet
    self.transport.sendto(
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 508, in sendto
    self._loop_writing()
  File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\proactor_events.py", line 540, in _loop_writing
    self._protocol.error_received(exc)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'QRTDiscoveryProtocol' object has no attribute 'error_received'

However we are able to run this code with QTM and Crazyflie. However, we need to use High Level Commander for our experiments. Please suggest what we can do.

krichardsson commented 1 year ago

I'm not sure what to do, we mainly provide the example to show how to use QTM data with the Crazyflie. As you can see in the last code snippet I sent you, there is nothing related to the Crazyflie, it is only trying to connect to QTM. I'm afraid that debugging this problem is beyond what we can do.

gaurav713914 commented 1 year ago

We have received a response from Qualisys team on their GitHub repository for the same issue and they have given a solution that worked for us. The solution is given here.

krichardsson commented 1 year ago

Thanks for sharing!