Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ jobs:
fetch-depth: 0

- name: Install pip
run: sudo apt-get install -y python3-pip
run: sudo apt-get install -y python3-pip pipx

- name: Check style
run: |
python3 -m pip install pycodestyle
export PATH=$PATH:$HOME/.local/bin
pycodestyle --max-line-length=100 examples/*
pipx run ruff format --check --line-length=100 examples
pipx run ruff check --select=ASYNC,RUF006,E,F --line-length=100 examples
pipx run codespell .

- name: Install prerequisites
run: |
Expand Down
2 changes: 1 addition & 1 deletion examples/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print_mode_task = asyncio.ensure_future(print_mode(drone))
Expand Down
36 changes: 17 additions & 19 deletions examples/camera_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,22 @@ async def run():
drone = System()
await drone.connect(system_address="udpin://0.0.0.0:14540")

asyncio.ensure_future(observe_current_settings(drone))
asyncio.ensure_future(observe_camera_mode(drone))
asyncio.ensure_future(observe_possible_setting_options(drone))
_tasks = [
Copy link
Contributor

@cclauss cclauss Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unusual to assemble these tasks but not await them. Are we certain that they will be run at some point?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, so this code was working fine but ruff complained that the tasks were dangling: https://docs.astral.sh/ruff/rules/asyncio-dangling-task/.

So, the advice was to create a strong reference to the tasks. However, now ruff complains that tasks are assigned but never used. It feels like you can't win.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cclauss you need to actually do a read&write conversation, not just write only please.

Copy link
Contributor

@cclauss cclauss Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wrong... This usage is correct.

>>> import asyncio
>>> async def print_char(char: str) -> None:
...     print(char)
...
>>> async def run(chars: str) -> None:
...     _tasks = [asyncio.create_task(print_char(char)) for char in chars]
...
>>> asyncio.run(run("abcdefg"))
a
b
c
d
e
f
g

asyncio.create_task(observe_current_settings(drone)),
asyncio.create_task(observe_camera_mode(drone)),
asyncio.create_task(observe_possible_setting_options(drone)),
]
Comment on lines +27 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax would delete tasks as they are completed, as discussed in ruff rule RUF006.

Suggested change
_tasks = [
asyncio.create_task(observe_current_settings(drone)),
asyncio.create_task(observe_camera_mode(drone)),
asyncio.create_task(observe_possible_setting_options(drone)),
]
tasks = {
asyncio.create_task(observe_current_settings(drone)),
asyncio.create_task(observe_camera_mode(drone)),
asyncio.create_task(observe_possible_setting_options(drone)),
}
for task in tasks:
task.add_done_callback(tasks.discard)


while True:
entered_input = await ainput(usage_str)

if entered_input == "p":
print(f"\n=== Current settings ===\n")
print("\n=== Current settings ===\n")
print_current_settings()
elif entered_input == "m":
print(f"\n=== Possible modes ===\n")
print(f"1. PHOTO")
print(f"2. VIDEO")
print("\n=== Possible modes ===\n")
print("1. PHOTO")
print("2. VIDEO")

try:
index_mode = await make_user_choose_camera_mode()
Expand All @@ -54,11 +56,11 @@ async def run():

try:
await drone.camera.set_mode(chosen_mode)
print(f" --> Succeeded")
print(" --> Succeeded")
except CameraError as error:
print(f" --> Failed with code: {error._result.result_str}")
elif entered_input == "s":
print(f"\n=== Possible settings ===\n")
print("\n=== Possible settings ===\n")
print_possible_settings(possible_setting_options)

try:
Expand All @@ -70,10 +72,10 @@ async def run():
selected_setting = possible_setting_options[index_setting - 1]
possible_options = selected_setting.options

print(f"\n=== Available options ===")
print("\n=== Available options ===")
print(f"Setting: {selected_setting.setting_id}")
if not selected_setting.is_range:
print(f"Options:")
print("Options:")
try:
print_possible_options(possible_options)
index_option = await make_user_choose_option(possible_options)
Expand All @@ -94,9 +96,7 @@ async def run():
continue
else:
try:
selected_value = await make_user_choose_option_range(
possible_options
)
selected_value = await make_user_choose_option_range(possible_options)

print(f"Setting {selected_setting.setting_id} to {selected_value}!")
setting = Setting(
Expand All @@ -111,7 +111,7 @@ async def run():

try:
await drone.camera.set_setting(setting)
print(f" --> Succeeded")
print(" --> Succeeded")
except CameraError as error:
print(f" --> Failed with code: {error._result.result_str}")
else:
Expand Down Expand Up @@ -148,7 +148,7 @@ def print_current_settings():


async def make_user_choose_camera_mode():
index_mode_str = await ainput(f"\nWhich mode do you want? [1..2] >>> ")
index_mode_str = await ainput("\nWhich mode do you want? [1..2] >>> ")
index_mode = int(index_mode_str)
if index_mode < 1 or index_mode > 2:
raise ValueError()
Expand Down Expand Up @@ -185,9 +185,7 @@ def print_possible_options(possible_options):

async def make_user_choose_option(possible_options):
n_options = len(possible_options)
index_option_str = await ainput(
f"\nWhich option do you want? [1..{n_options}] >>> "
)
index_option_str = await ainput(f"\nWhich option do you want? [1..{n_options}] >>> ")

index_option = int(index_option_str)
if index_option < 1 or index_option > n_options:
Expand Down
2 changes: 1 addition & 1 deletion examples/failure_injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print("Waiting for drone to have a global position estimate...")
Expand Down
2 changes: 1 addition & 1 deletion examples/firmware_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

info = await drone.info.get_version()
Expand Down
4 changes: 2 additions & 2 deletions examples/follow_me_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import asyncio
from mavsdk import System
from mavsdk.follow_me import Config, FollowMeError, TargetLocation
from mavsdk.follow_me import Config, TargetLocation


follow_height = 8.0 # in meters
Expand Down Expand Up @@ -32,7 +32,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print("Waiting for drone to have a global position estimate...")
Expand Down
2 changes: 1 addition & 1 deletion examples/ftp_download_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

async for update in drone.ftp.download(
Expand Down
2 changes: 1 addition & 1 deletion examples/ftp_list_dir.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print("directory list", await drone.ftp.list_directory("/"))
Expand Down
2 changes: 1 addition & 1 deletion examples/geofence.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

# Fetch the home location coordinates, in order to set a boundary around
Expand Down
4 changes: 1 addition & 3 deletions examples/gimbal.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ async def run():
# Set the gimbal to track a region of interest (lat, lon, altitude)
# Units are degrees and meters MSL respectively
print("Look at a ROI (region of interest) with gimbal ID", gimbal.gimbal_id)
await drone.gimbal.set_roi_location(
gimbal.gimbal_id, 47.39743832, 8.5463316, 488
)
await drone.gimbal.set_roi_location(gimbal.gimbal_id, 47.39743832, 8.5463316, 488)
await asyncio.sleep(4)

print("Back to forward again with gimbal ID", gimbal.gimbal_id)
Expand Down
2 changes: 1 addition & 1 deletion examples/goto.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print("Waiting for drone to have a global position estimate...")
Expand Down
6 changes: 3 additions & 3 deletions examples/gripper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print(f"-- Gripper Grab")
print("-- Gripper Grab")
await drone.gripper.grab(instance=1)

await asyncio.sleep(1)

print(f"-- Gripper Release")
print("-- Gripper Release")
await drone.gripper.release(instance=1)

while True:
Expand Down
2 changes: 1 addition & 1 deletion examples/highres_imu.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async def get_imu_data():
print("Fetching IMU data...")
async for imu in telemetry.imu():
# Print data in HIGHRES_IMU format
print(f"HIGHRES_IMU (105)")
print("HIGHRES_IMU (105)")
print(f"Time (us): {imu.timestamp_us}")
print(f"X Acceleration (m/s^2): {imu.acceleration_frd.forward_m_s2}")
print(f"Y Acceleration (m/s^2): {imu.acceleration_frd.right_m_s2}")
Expand Down
2 changes: 1 addition & 1 deletion examples/logfile_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

entries = await get_entries(drone)
Expand Down
10 changes: 3 additions & 7 deletions examples/manual_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def manual_controls():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

# Checking if Global Position Estimate is ok
Expand All @@ -50,9 +50,7 @@ async def manual_controls():
break

# set the manual control input after arming
await drone.manual_control.set_manual_control_input(
float(0), float(0), float(0.5), float(0)
)
await drone.manual_control.set_manual_control_input(float(0), float(0), float(0.5), float(0))

# Arming the drone
print("-- Arming")
Expand All @@ -64,9 +62,7 @@ async def manual_controls():
await asyncio.sleep(5)

# set the manual control input after arming
await drone.manual_control.set_manual_control_input(
float(0), float(0), float(0.5), float(0)
)
await drone.manual_control.set_manual_control_input(float(0), float(0), float(0.5), float(0))

# start manual control
print("-- Starting manual control")
Expand Down
2 changes: 1 addition & 1 deletion examples/mission.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print_mission_progress_task = asyncio.ensure_future(print_mission_progress(drone))
Expand Down
8 changes: 2 additions & 6 deletions examples/mission_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import asyncio

from mavsdk import System
import mavsdk.mission_raw


async def run():
Expand All @@ -13,15 +12,12 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

out = await drone.mission_raw.import_qgroundcontrol_mission("example-mission.plan")

print(
f"{len(out.mission_items)} mission items and"
f"{len(out.rally_items)} rally items imported."
)
print(f"{len(out.mission_items)} mission items and{len(out.rally_items)} rally items imported.")

await drone.mission_raw.upload_mission(out.mission_items)
await drone.mission_raw.upload_rally_points(out.rally_items)
Expand Down
2 changes: 1 addition & 1 deletion examples/offboard_attitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async def run():
print("Waiting for drone to connect...")
async for state in drone.core.connection_state():
if state.is_connected:
print(f"-- Connected to drone!")
print("-- Connected to drone!")
break

print("Waiting for drone to have a global position estimate...")
Expand Down
49 changes: 23 additions & 26 deletions examples/offboard_from_csv/offboard_from_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@

import asyncio
import csv
import io
import anyio
from mavsdk import System
from mavsdk.offboard import PositionNedYaw, VelocityNedYaw
from mavsdk.offboard import AccelerationNed, OffboardError
from mavsdk.offboard import OffboardError
from mavsdk.telemetry import LandedState


Expand Down Expand Up @@ -143,27 +145,25 @@ async def run():
await drone.action.disarm()
return

waypoints = []

# Read data from the CSV file
with open("active.csv", newline="") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
waypoints.append(
(
float(row["t"]),
float(row["px"]),
float(row["py"]),
float(row["pz"]),
float(row["vx"]),
float(row["vy"]),
float(row["vz"]),
float(row["ax"]),
float(row["ay"]),
float(row["az"]),
int(row["mode"]),
)
)
async with await anyio.open_file("active.csv", "r", newline="") as csvfile:
content = await csvfile.read()
waypoints = [
(
float(row["t"]),
float(row["px"]),
float(row["py"]),
float(row["pz"]),
float(row["vx"]),
float(row["vy"]),
float(row["vz"]),
float(row["ax"]),
float(row["ay"]),
float(row["az"]),
int(row["mode"]),
)
for row in csv.DictReader(io.StringIO(content))
]

print("-- Performing trajectory")
total_duration = waypoints[-1][0]
Expand All @@ -178,14 +178,11 @@ async def run():

position = current_waypoint[1:4]
velocity = current_waypoint[4:7]
acceleration = current_waypoint[7:10]
_acceleration = current_waypoint[7:10] # unused
mode_code = current_waypoint[-1]
if last_mode != mode_code:
# Print the mode number and its description
print(
" Mode number: " + f"{mode_code}, "
f"Description: {mode_descriptions[mode_code]}"
)
print(" Mode number: " + f"{mode_code}, Description: {mode_descriptions[mode_code]}")
last_mode = mode_code
# set_position_velocity_acceleration_ned is not yet available
# in the default build for MAVSDK-Python Installation with pip3
Expand Down
Loading
Loading