robagar / tello-asyncio

A library for controlling and interacting with the Tello EDU drone using modern asynchronous Python.
GNU Lesser General Public License v2.1
25 stars 5 forks source link

Opencv example does not work for linux or Mac OS: address already in use #8

Closed jsolderitsch closed 3 years ago

jsolderitsch commented 3 years ago

Maybe I am doing something wrong but I am following the docs for the asyncio package. I see:

pi@raspberry:~/tello/tello-asyncio/examples $ python3 video_opencv.py 
waiting for WiFi (TELLO)...
...wait for WiFi failed, error: Cannot add child handler, the child watcher does not have a loop attached
assuming WiFi network is connected and continuing
CONNECT 192.168.10.1
SEND command
RECEIVED ok
SEND battery?
RECEIVED 83

battery: 83%
SEND streamoff
RECEIVED ok
DISCONNECT 192.168.10.1
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "video_opencv.py", line 27, in fly
    asyncio.run(main())
  File "/usr/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
    return future.result()
  File "video_opencv.py", line 19, in main
    await drone.start_video()
  File "/home/pi/.local/lib/python3.7/site-packages/tello_asyncio/tello.py", line 611, in start_video
    await self.connect_video(on_frame)
  File "/home/pi/.local/lib/python3.7/site-packages/tello_asyncio/tello.py", line 634, in connect_video
    await self._video.connect(self._loop, self._on_video_frame_chunk, self._on_video_frame)
  File "/home/pi/.local/lib/python3.7/site-packages/tello_asyncio/video.py", line 38, in connect
    local_addr=("0.0.0.0", VIDEO_UDP_PORT)
  File "/usr/lib/python3.7/asyncio/base_events.py", line 1245, in create_datagram_endpoint
    raise exceptions[0]
  File "/usr/lib/python3.7/asyncio/base_events.py", line 1230, in create_datagram_endpoint
    sock.bind(local_address)
OSError: [Errno 98] Address already in use

This is in a VM emulating a Raspberry Pi. Looks like the wifi check fails because of the separate threads? I don't know what address is already in use. The video UDP connection should not have been established before since this is the first time I am running the example.

On the Mac it's a very similar result:

jjsretina:examples jjs$ python video_opencv.py 
waiting for WiFi (RMTT)...
...wait for WiFi failed, error: Cannot add child handler, the child watcher does not have a loop attached
assuming WiFi network is connected and continuing
CONNECT 192.168.10.1
SEND command
RECEIVED ok
SEND battery?
RECEIVED 93

battery: 93%
SEND streamoff
RECEIVED ok
DISCONNECT 192.168.10.1
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "video_opencv.py", line 27, in fly
    asyncio.run(main())
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
    return future.result()
  File "video_opencv.py", line 19, in main
    await drone.start_video()
  File "/usr/local/lib/python3.7/site-packages/tello_asyncio/tello.py", line 611, in start_video
    await self.connect_video(on_frame)
  File "/usr/local/lib/python3.7/site-packages/tello_asyncio/tello.py", line 634, in connect_video
    await self._video.connect(self._loop, self._on_video_frame_chunk, self._on_video_frame)
  File "/usr/local/lib/python3.7/site-packages/tello_asyncio/video.py", line 38, in connect
    local_addr=("0.0.0.0", VIDEO_UDP_PORT)
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1256, in create_datagram_endpoint
    raise exceptions[0]
  File "/usr/local/Cellar/python@3.7/3.7.10_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1240, in create_datagram_endpoint
    sock.bind(local_address)
OSError: [Errno 48] Address already in use

Could I need to update the version of Python? -- in both cases, a version of Python 3.7 is in use.

robagar commented 3 years ago

yeah, in python<3.8 apparently you need to call asyncio.get_child_watcher() before starting an event loop in a worker thread

The address already in use error is my fault - I changed the drone.start_video() method to automatically connect by default