mavlink / MAVSDK-Python

MAVSDK client for Python.
https://mavsdk.mavlink.io
BSD 3-Clause "New" or "Revised" License
312 stars 218 forks source link

Altitude error while doing swarming using mavsdk-python ? #719

Open smith0022 opened 1 month ago

smith0022 commented 1 month ago

when I tried flying two drones at the same altitude using the same function (i.e takeoff) both the drones react in different way (error in altitude ) .Why does this error exist in the simulation ? apart from these when i tried to fly both the drones using the manual control when when both the drones received the same input both reacted differently.there is no significant difference in roll.yaw or pitch but the error in height is persistent even with manual control or offboard mode. here is the code for takeoff :


#!/usr/bin/env python3

import asyncio#!/usr/bin/env python3

import asyncio
from mavsdk import System

async def run():
    drone = System(mavsdk_server_address="localhost", port=50040)
    await drone.connect(system_address="udp://:14541")
    drone2 = System(mavsdk_server_address="localhost", port=50041)
    await drone2.connect(system_address="udp://:14542")
    async def print_position(drone):
        async for position in drone.telemetry.position():
            return [position.latitude_deg,position.longitude_deg,position.relative_altitude_m]
    print("Waiting for drone to connect...")
    async for state in drone.core.connection_state():
        if state.is_connected:
            print(f"-- Connected to drone!")
            break

    print("Waiting for drone to have a global position estimate...")
    async for health in drone.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print("-- Global position state is good enough for flying.")
            break

    print("Fetching amsl altitude at home location....")
    async for terrain_info in drone.telemetry.home():
        absolute_altitude = terrain_info.absolute_altitude_m
        break
        print("Waiting for drone to connect...")
    async for state in drone2.core.connection_state():
        if state.is_connected:
            print(f"-- Connected to drone!")
            break

    print("Waiting for drone to have a global position estimate...")
    async for health in drone2.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print("-- Global position state is good enough for flying.")
            break

    print("Fetching amsl altitude at home location....")
    async for terrain_info in drone2.telemetry.home():
        absolute_altitude = terrain_info.absolute_altitude_m
        break
    await asyncio.sleep(10)
    print("-- Arming")
    await drone.action.arm()
    await drone2.action.arm()
    print("-- Taking off")
    await drone.action.set_takeoff_altitude(10)
    await drone2.action.set_takeoff_altitude(10)
    await drone.action.takeoff()
    await drone2.action.takeoff()
    await asyncio.sleep(10)
    height_b =  await print_position(drone)
    height_C =  await print_position(drone2)
    i=0
    while i < 10:
            height_b =  await print_position(drone)
            height_C =  await print_position(drone2)
            print("height of A")
            print("expected :" + "10")
            print(height_b[2])
            print("height of B")
            print("expected :" + "10")
            print(height_C[2])
            await asyncio.sleep(1)
            i+=1
    await drone.action.land()
    await drone2.action.land()
    await asyncio.sleep(5)
    await drone.action.kill()
    await drone2.action.kill()

from mavsdk import System

async def run():
    drone = System(mavsdk_server_address="localhost", port=50040)
    await drone.connect(system_address="udp://:14541")
    drone2 = System(mavsdk_server_address="localhost", port=50041)
    await drone2.connect(system_address="udp://:14542")
    async def print_position(drone):
        async for position in drone.telemetry.position():
            return [position.latitude_deg,position.longitude_deg,position.relative_altitude_m]
    print("Waiting for drone to connect...")
    async for state in drone.core.connection_state():
        if state.is_connected:
            print(f"-- Connected to drone!")
            break

    print("Waiting for drone to have a global position estimate...")
    async for health in drone.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print("-- Global position state is good enough for flying.")
            break

    print("Fetching amsl altitude at home location....")
    async for terrain_info in drone.telemetry.home():
        absolute_altitude = terrain_info.absolute_altitude_m
        break
        print("Waiting for drone to connect...")
    async for state in drone2.core.connection_state():
        if state.is_connected:
            print(f"-- Connected to drone!")
            break

    print("Waiting for drone to have a global position estimate...")
    async for health in drone2.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print("-- Global position state is good enough for flying.")
            break

    print("Fetching amsl altitude at home location....")
    async for terrain_info in drone2.telemetry.home():
        absolute_altitude = terrain_info.absolute_altitude_m
        break
    await asyncio.sleep(10)
    print("-- Arming")
    await drone.action.arm()
    await drone2.action.arm()
    print("-- Taking off")
    await drone.action.set_takeoff_altitude(10)
    await drone2.action.set_takeoff_altitude(10)
    await drone.action.takeoff()
    await drone2.action.takeoff()
    await asyncio.sleep(10)
    height_b =  await print_position(drone)
    height_C =  await print_position(drone2)
    i=0
    while i < 10:
            height_b =  await print_position(drone)
            height_C =  await print_position(drone2)
            print("height of A")
            print("expected :" + "10")
            print(height_b[2])
            print("height of B")
            print("expected :" + "10")
            print(height_C[2])
            await asyncio.sleep(1)
            i+=1
    await drone.action.land()
    await drone2.action.land()
    await asyncio.sleep(5)
    await drone.action.kill()
    await drone2.action.kill()

if __name__ == "__main__":
    # Run the asyncio loop
    asyncio.run(run())

**```the error : 
Waiting for drone to connect...
-- Connected to drone!
Waiting for drone to have a global position estimate...
-- Global position state is good enough for flying.
Fetching amsl altitude at home location....
-- Connected to drone!
Waiting for drone to have a global position estimate...
-- Global position state is good enough for flying.
Fetching amsl altitude at home location....
-- Arming
-- Taking off
height of A
expected :10
5.838000297546387
height of B
expected :10
9.23900032043457
height of A
expected :10
7.3560004234313965
height of B
expected :10
9.908000946044922
height of A
expected :10
8.594000816345215
height of B
expected :10
10.116000175476074
height of A
expected :10
9.374000549316406
height of B
expected :10
10.28600025177002
height of A
expected :10
9.53600025177002
height of B
expected :10
10.326000213623047
height of A
expected :10
9.672000885009766
height of B
expected :10
10.3410005569458
height of A
expected :10
9.738000869750977
height of B
expected :10
10.292000770568848
height of A
expected :10
9.835000038146973
height of B
expected :10
10.327000617980957
height of A
expected :10
9.795000076293945
height of B
expected :10
10.268000602722168
height of A
expected :10
9.756000518798828
height of B
expected :10
10.235000610351562**

![image](https://github.com/user-attachments/assets/d11c8e31-50c5-4368-9e16-a2b85415dc4f)
julianoes commented 1 month ago

Not quite sure but my guess is that both drones will take off 10 meters above the current home altitude as measured at the time. My guess is that GPS altitude can drift for the drones, and so the number shown later is off, as the estimate is corrected.

Or to put it differently, the drone takes off in local coordinates 10 meters above the home altitude but the global estimate drifts or changes slightly. The take off command is a local/relative command, but the altitude you're printing is "global". If you want to get to a "global" same altitude, you could use goto_location which will give you an absolute altitude to aim for.

smith0022 commented 4 weeks ago

i actually did try mavsdk with real drones and in simulation where both the drones were same . I tried off board and manual control and yet there was some reason a difference in altitude for mavsdk .I don't understand the reason for this but the drones in simulation and real life show the altitude error without any reason.