DroneAPI Reference¶
DroneAPI is the main high-level SDK class.
Import:
Related config types:
Construction¶
DroneAPI(
config: DroneConfig | None = None,
enable_logging: bool = True,
flight_logger: FlightLogger | None = None,
battery_threshold: int | None = None,
media_dir: Path | str | None = None,
enable_file_logging: bool = True,
file_log_dir: str = "logs",
enable_command_logging: bool = True,
command_log_dir: str = "logs",
)
Important properties:
is_connectedconfigdefault_ip
Context manager support:
Connection and Lifecycle¶
connect(ip: str | None = None, timeout: float = 5.0) -> Nonerobust_connect(ip: str | None = None, timeout: float = 5.0, verbose: bool = True) -> booldisconnect() -> None
Typical usage:
Connection flow adapted from the calibration and challenge scripts:
from droneapi import DroneAPI, DroneConfig, NetworkConfig
config = DroneConfig(
network=NetworkConfig(drone_ip="192.168.100.1")
)
with DroneAPI(config=config) as drone:
if not drone.robust_connect(verbose=True):
raise SystemExit("Failed to connect to drone")
battery = drone.get_battery()
print(f"Connected. Battery: {battery}%")
Flight and Movement¶
Basic movement:
move(direction, distance_cm, led=None, blocking=True, speed=VelocityLevel.ZOOM)rotate(angle_degrees, led=None, blocking=True)move_to(x, y, z, led=None, blocking=True, speed=VelocityLevel.ZOOM)curve_to(x, y, z, velocity, radius_cm=None, led=None, blocking=True)circle(radius_cm, velocity, clockwise=True, led=None, blocking=True)
Core flight lifecycle:
takeoff(height_cm=None, led=None, reset_yaw=False, with_load=False, blocking=True)land(led=None, blocking=True)hover(led=None, blocking=True)arm()disarm()
Typical flight block:
from pypack.core import Direction, VelocityLevel
with DroneAPI() as drone:
drone.connect()
drone.set_barrier_mode(enabled=True)
drone.set_qr_localization(enabled=True)
try:
drone.takeoff(height_cm=100)
drone.move(Direction.FORWARD, 100, speed=VelocityLevel.ZOOM)
drone.rotate(90)
drone.move_to(50, 100, 100)
drone.hover()
finally:
drone.land()
Acrobatic and motion helpers:
flip(direction, led=None, blocking=True)bounce(height_cm=50, cycles=3, led=None, blocking=True)spin(rotations=1, led=None, blocking=True)vertical_circle(radius_cm, blocking=True)
State and Telemetry¶
get_state() -> DroneStateget_position() -> Vector3get_orientation() -> Orientationget_battery() -> intget_altitude() -> floatget_velocity() -> Vector3get_acceleration() -> Vector3get_obstacles() -> Obstaclesget_flight_data() -> FlightDataget_drone_id() -> int | None
Telemetry snapshot pattern:
flight = drone.get_flight_data()
state = drone.get_state()
print(flight.position)
print(flight.orientation.yaw)
print(state.obstacles)
print(drone.get_drone_id())
Vision, Color, and QR¶
recognize_target(target) -> AIResultrecognize_qr(mode=..., timeout=...) -> AIResulttrack_qr(timeout=...) -> AIResultdetect_qr(timeout=...) -> AIResultget_color(mode=1) -> ColorResult
LED, Sensors, and Payload¶
set_led(led, blocking=True)enable_led(blocking=True)disable_led(blocking=True)cancel_rgb_animation(blocking=True)set_rgb_brightness(brightness, blocking=True)set_avoidance_direction(mode, blocking=True)set_electromagnet(on)set_clamp(is_open=None, angle=None)set_barrier_mode(enabled)fire_laser(count=1, interval=0.2, blocking=True)is_laser_hit() -> bool
Camera, Video, and Imaging¶
take_photo(download=True, timeout=5.0) -> Path | Nonetake_photo(download=True, timeout=5.0, save_path=None) -> Path | Noneset_video(recording: bool)set_video_stream(enabled: bool)flip_video()set_camera_angle(mode)set_video_resolution(resolution, blocking=True)start_video_stream(display=True, web_server=False, web_port=None) -> VideoStreamcreate_video_stream() -> VideoStream
Localization and Autonomy¶
set_qr_localization(enabled: bool)follow_line(color=..., speed=..., blocking=True) -> LineFollowResult
System and Firmware¶
get_product_id()get_firmware_version()get_mcu_version()shutdown()reboot()get_storage_capacity()sync_time()
Wi-Fi and Radio¶
set_wifi_mode(mode, channel_id=0)set_wifi_band(band_5ghz=False)set_wifi_power(high=True)set_wifi_broadcast(enabled=True)set_wifi_channel(manual=False, channel_id=0)set_wifi_ap_mode()set_velocity_level(level, blocking=True)set_yaw_rate_level(level, blocking=True)set_anti_flicker(hz_50=True)
Safety and Parameters¶
enable_battery_failsafe()disable_battery_failsafe()set_parameters(fly_mode=None, opt_mode=None, vision_intensity=None, blocking=True)set_operate_status(status)set_land_speed(fast=False)
Media Management¶
Listing:
list_photos(page=0) -> list[MediaFile]list_videos(page=0) -> list[MediaFile]list_logs(page=0) -> list[MediaFile]
Download:
download_photo(photo, save_dir=None) -> Path | Nonedownload_video(video, save_dir=None) -> Path | Nonedownload_log(log, save_dir=None) -> Path | Nonedownload_all_photos(save_dir=None) -> list[Path]download_all_videos(save_dir=None) -> list[Path]download_all_logs(save_dir=None) -> list[Path]
Delete:
delete_photo(photo) -> booldelete_video(video) -> booldelete_log(log) -> booldelete_all_photos() -> tuple[int, int]delete_all_videos() -> tuple[int, int]delete_all_logs() -> tuple[int, int]delete_all_media() -> dict[str, tuple[int, int]]
URL helpers:
Photo capture respects DroneConfig.media for default storage, and
take_photo(save_path=...) can override the destination per call. If
save_path points to a directory, the drone filename is preserved. If it
points to a file path such as captures/latest.jpg, the download is renamed to
that exact path.
Typical photo and stream usage:
from pypack.core import VideoResolution
with DroneAPI() as drone:
drone.connect()
drone.set_video_resolution(VideoResolution.LOW)
stream = drone.start_video_stream(display=False, web_server=True)
try:
print(drone.take_photo(save_path="captures/latest.jpg"))
stream.wait()
finally:
stream.stop()
Manual Control¶
send_manual_control(forward=0.0, right=0.0, up=0.0, rotate=0.0, buttons=0) -> boolmanual_fly(duration_sec, forward=0.0, right=0.0, up=0.0, rotate=0.0, heartbeat_interval=1.0)send_app_heartbeat(user_mode=1) -> boolset_app_mode(mode: int) -> Noneget_app_mode() -> intstop_manual_control() -> bool
Use set_app_mode(1) before takeoff if you intend to drive the drone with MANUAL_CONTROL.
Manual-control startup pattern:
drone.set_app_mode(1)
drone.set_velocity_level(200)
drone.set_qr_localization(enabled=True)
drone.set_barrier_mode(enabled=True)
Closed-Loop Flight Controller¶
This returns the PD controller from pypack.control.
Example:
ctrl = drone.create_flight_controller()
result = ctrl.fly_to(x=100, y=150, z=120, yaw=90)
print(result.success, result.reason)
This is the same control pattern used by the solver scripts, just without the maze layer:
from pypack.control import ControllerConfig
controller = drone.create_flight_controller(
ControllerConfig(kp_xy=2.5, kp_z=3.5)
)
try:
drone.takeoff(height_cm=100)
result = controller.fly_to(x=120, y=0, z=100, yaw=0)
print(result.success, result.error_position_cm)
finally:
controller.stop()
drone.land()
Return Types and Errors¶
Most command-style methods return CommandResult.
Telemetry and state methods return typed models from pypack.core.models.
Common exceptions:
Notes¶
connect()androbust_connect()useconfig.network.drone_ipif no IP is supplied.- Maze-oriented helpers are intentionally not part of
DroneAPI. - Optional video and web features live in
pypack.videoand require extras.