Closed huytd-pi closed 2 years ago
You could manually set up a mission that lands at the previous home position. Not sure how else this could be done.
I do download mission which was uploaded from QGC, purpose to do mission edit so drone can return to original position, but i have problem with download_mission()
. i don't understand how it works so i can edit the downloaded quest here is my test code:
import asyncio
from mavsdk import System
from mavsdk.mission import (MissionItem, MissionPlan)
async def run():
# Init the drone
drone = System()
await drone.connect(system_address="udp://:14540")
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"Drone discovered!")
break
await drone.mission.download_mission()
print("-- Arming")
await drone.action.arm()
print("-- Starting mission")
await drone.mission.start_mission()
if __name__ == "__main__":
# Start the main function
asyncio.ensure_future(run())
# Runs the event loop until the program is canceled with e.g. CTRL-C
asyncio.get_event_loop().run_forever()
and when run, an error occurs
huytd@huytd-HP:~/Project/Drone/MAVSDK/MAVSDK-Python/examples$ python3 test_mission.py
Waiting for drone to connect...
Drone discovered!
test_mission.py:17: RuntimeWarning: coroutine 'Mission.download_mission' was never awaited
drone.mission.download_mission()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
^CTraceback (most recent call last):
File "test_mission.py", line 30, in <module>
asyncio.get_event_loop().run_forever()
File "/usr/lib/python3.7/asyncio/base_events.py", line 541, in run_forever
self._run_once()
File "/usr/lib/python3.7/asyncio/base_events.py", line 1750, in _run_once
event_list = self._selector.select(timeout)
File "/usr/lib/python3.7/selectors.py", line 468, in select
fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
I wonder if you need to actually to get the result, so the downloaded mission using:
result = await drone.mission.download_mission()
I wonder if you need to actually to get the result, so the downloaded mission using:
You don't. It's weird because await
is there. Usually that message comes when you forget it and just call drone.mission.download_mission()
instead of await drone.mission.download_mission()
:thinking:.
Which version of MAVSDK is that? I just tried with latest develop (in the python REPL) and it works for me...
@JonasVautherin huh? But where is the result stored/returned?
Well it's lost if you don't save it :slightly_smiling_face:. Just like a normal function. Say in C++:
action->get_takeoff_altitude();
vs
auto takeoff_altitude = action->get_takeoff_altitude();
It's just that in python, drone.mission.download_mission()
returns a coroutine, but does not run it. In order to run that coroutine, you need to await
it. So you could do something like this if you wanted to:
my_coroutine = drone.mission.download_mission()
downloaded_mission = await my_coroutine
Look at this, in the apython
REPL (from package aioconsole
):
>>> async def foo():
... print("hello")
...
>>> foo()
<coroutine object __corofn.<locals>.foo at 0x7fa61d7fc240>
>>> await foo()
hello
foo()
returns a coroutine, await foo()
executes it.
Finally, if the coroutine returns something:
>>> async def get_foo():
... return 2
...
>>> await get_foo()
2
>>> result = await get_foo()
>>> print(result)
2
Back to the error that says "test_mission.py:17: RuntimeWarning: coroutine 'Mission.download_mission' was never awaited
drone.mission.download_mission()", it means that it tries to garbage collect a coroutine object that was never awaited. It's a bit like a "warning: unused". But that's really weird here because line 17 has the await
...
Here are two examples to illustrate it.
This one works and waits for 2 seconds before terminating:
#!/usr/bin/env python3
import asyncio
from mavsdk import System
async def foo():
await asyncio.sleep(2)
async def run():
await foo()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
This one says: "example.py:11: RuntimeWarning: coroutine 'foo' was never awaited"
#!/usr/bin/env python3
import asyncio
from mavsdk import System
async def foo():
await asyncio.sleep(2)
async def run():
foo()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
Ok, I was confused because you seemed to say that my "solution":
from:
await drone.mission.download_mission()
to:
result = await drone.mission.download_mission()
was not correct but it seems to actually fix the problem here, doesn't it?
So await doesn't run the coroutine unless you also get the result? It's a bit odd, right?
it seems to actually fix the problem here, doesn't it?
Does it? I would not understand why, it would be very weird to me :sweat_smile:. Is that fixing the problem?
await
executes the coroutine, the result is completely independent. Just like in C++ you can call mission->download_mission();
and not take the result if you are not interested in it, in python you can run await drone.mission.download_mission()
. It could be that you only want the side effects of the function.
But calling drone.mission.download_mission()
(without awaiting it) never, ever makes sense in a program. So the interpreter warns you about it.
Or did I miss something? :smile:
That would make sense yes.
I'll try it out tomorrow.
I am testing my flight according to the scenario when i land on the ground, after a few seconds the drone makes a return to the launch position. but I encountered that when I landed on the ground, the launch position is now the landing position, so how can the launch position not change? Thank you for your answers.