How to Build an Object Tracking Drone Using Litewing

Published  July 19, 2026   0
V Vishnu S
Author
Litewing Drone with Object Tracking

Most people assume object tracking for autonomous flight is very complex, but it doesn’t have to be that way. All you need is a different way of looking at the problem. We built this project to see if we could make a simple LiteWing drone behave intelligently using just a laptop and a basic camera.
By placing the camera above the room ceiling, the floor becomes a large coordinate map. The code is very simple; it detects a red marker on the drone and a green target, then makes the drone move toward the target, like matching two points. If the target moves, the drone follows it. No complex algorithms or costly hardware, but with smart Python logic and a Wi-Fi connection.
If you're interested in building more drone-based projects like this, be sure to check out our dedicated Drone Projects section on Circuit Digest. 

Key Takeaways

  • Tracks a target using only a ceiling webcam and colour detection, no GPS or expensive sensors needed.
  • Runs on a simple three-zone distance model: Follow, Maintain, and Retreat.
  • Built entirely in Python using OpenCV and NumPy, with the LiteWing library handling Wi-Fi flight commands.
  • The LiteWing Position Module keeps height and position stable so the tracking script only has to worry about direction.

Prerequisites & Components for the Object Tracking Drone Project

Before building the system, a few basic hardware and software components are required. The goal of this setup is to keep everything simple and accessible while still achieving reliable tracking.

Hardware side

The hardware setup for this system is simple. It mainly consists of a LiteWing drone equipped with the LiteWing Position Module, a laptop or PC that runs the object tracking program, and a ceiling-mounted USB webcam. The Position Module enables features such as height hold and position hold, allowing the drone to maintain a stable flight while the tracking algorithm focuses on following the target. Meanwhile, the ceiling-mounted webcam continuously monitors the entire area from above, providing a consistent top-down view for accurate object tracking. 

The laptop connects to the drone using its built-in Wi-Fi access point (AP), allowing real-time communication and control. The LiteWing positioning module also plays a key role by helping the drone stay stable and maintain its height, resulting in smoother and more reliable movement while following the target.

Software side

Component                                                                 Description
Python 3.11Main programming language used to develop the object tracking application.
OpenCVPerforms colour detection, image processing, and object position tracking.
NumPyHandles mathematical calculations such as distance and coordinate computations.
LiteWing LibraryEstablishes communication with the LiteWing drone and sends real-time flight commands over Wi-Fi. 

This minimal setup makes the project easy to replicate without needing specialised hardware or complex dependencies.

*NOTE 

  • Before running the project, make sure that the LiteWing drone is updated with the latest firmware, as outdated firmware may cause connection issues or unexpected behaviour during flight.
  • It is also important to use the latest version of the LiteWing Python library, since newer updates often include bug fixes, performance improvements, and better compatibility with the drone.

Keeping both the firmware and library up to date ensures smooth operation and reliable performance of the system.

How the Drone Object Tracking System Works

The system follows a simple but efficient workflow that runs continuously in real time. First, the ceiling-mounted camera captures live video frames from a top-down view. Each frame is then converted into the HSV colour space using OpenCV, which makes it easier to detect specific colours under different lighting conditions.
Next, the system applies colour thresholds to identify the green target and the red marker on the drone. From the detected regions, the system extracts the largest contour and calculates its centre position, which represents the coordinates of the drone and the target.

Once both positions are known, the system computes the coordinate difference (dx, dy) and calculates the distance between them. Based on predefined thresholds, the control logic decides whether the drone should move toward the target, maintain its position, or move away if it is too close.
These decisions are converted into simple movement commands like xforward, backward, left, right and sent to the drone over Wi-Fi using the LiteWing library. The drone then responds in real time, adjusting its position accordingly.
This entire loop captures, processes, calculates, and controls, running multiple times per second to enable smooth, responsive tracking without the need for complex algorithms.

Core Logic: Three-Zone Object Tracking Model

The tracking system is based on a simple three-zone control model that uses the distance between the drone and the target to decide how the drone should move. Instead of using complex navigation algorithms, the system relies on basic distance thresholds, making it both efficient and easy to implement.
Follow Zone:
When the target is far from the drone (beyond a predefined distance), the system enters the following mode. Here, the drone moves toward the target by comparing its positions (dx, dy). It decides the dominant direction (horizontal or vertical) and sends the appropriate movement command to reduce the distance.
Maintain Zone:
When the drone reaches an optimal distance from the target, it enters the maintenance zone. In this state, no movement commands are sent, allowing the drone to hover steadily. This prevents unnecessary oscillations and ensures smoother tracking behaviour.
Retreat Zone:
If the drone gets too close to the target (below a minimum safe distance), it enters the retreat zone. In this case, the drone moves in the opposite direction to increase the distance, avoiding collisions and maintaining safe operation.

This zone-based logic works continuously in real time. By switching between these three states to follow, maintain, and retreat, the drone can track the target smoothly without requiring complex path planning or heavy computations.

Working Demo

To begin the demonstration, first power on the LiteWing drone along with the LiteWing Position Module. Make sure the drone is running the latest firmware, then connect your laptop to the LiteWing Wi-Fi access point (AP). Next, open the project in your preferred Python environment and run the Python script. Once the program starts, a live camera window will appear, and the system will begin detecting both the drone and the target using the configured colour settings. After confirming that both objects are being detected correctly, press T in the terminal. The drone will take off, reach the configured target height, and automatically begin tracking the target using the three-zone control logic.

Now, simply move the target around within the camera's field of view. As the target moves, the drone continuously adjusts its position and follows it while maintaining the desired distance. If you want to end the demonstration, press L to land the drone safely, or press the Spacebar at any time to perform an emergency stop.

Code Explanation: Building the Drone Object Tracking Program

The first part of the program is responsible for detecting both the drone and the target object using colour detection. Every frame captured by the ceiling-mounted camera is converted into the HSV colour space, which provides more reliable colour segmentation under varying lighting conditions.

import threading, msvcrt, time
import cv2
import numpy as np
from litewing import LiteWing
from litewing.manual_control import run_manual_control
# ── Configuration ─────────────────────────────────────────────
DEBUG_MODE       = 0                 # Enable debug mode (displays debug info/badge on the HUD)
CAMERA_INDEX     = 1                 # Index of the camera device to use (e.g., 0 for built-in, 1 for external ceiling camera)
DRONE_IP         = "192.168.43.42"   # IP address of the LiteWing drone for network connection
SENSITIVITY      = 0.2               # Movement sensitivity modifier for the drone controller
TARGET_HEIGHT    = 0.4               # Target altitude in meters for the drone to maintain when airborne
RESIZE_WIDTH     = None
RESIZE_HEIGHT    = None
# HSV ranges -- light green target (tuned for bright green ball)
GREEN_LO = (35, 60, 50)
GREEN_HI = (90, 255, 255)
# HSV ranges -- blue drone marker (Light/Sky Blue)
BLUE_LO = (90, 80, 100)
BLUE_HI = (135, 255, 255)
# Tracking -- 3-zone distance model
RETREAT_DIST    = 85   # px -- retreat if closer than this
FOLLOW_DIST     = 125   # px -- follow only if farther than this
DEADZONE        = 20    # px -- ignore smaller offsets
MIN_AREA        = 500   # px² -- noise filter
BOUNDARY        = 40    # px -- safety margin from frame edge
# Direction keys (adjust to match camera orientation)
DIRS = {"up": "w", "down": "s", "left": "a", "right": "d"}
# States that allow autonomous movement
AIRBORNE = {"HOVERING", "TRACKING", "TOO CLOSE", "MAINTAINING",
           "ALIGNED", "TARGET LOST", "TAKING_OFF"}
# ── Helpers ───────────────────────────────────────────────────
def clear_keys(drone):
   """Reset all movement keys to False."""
   for k in "wasd":
       drone._manual_keys[k] = False
def detect(hsv, color):
   """Return (cx, cy, radius) of the largest blob, or None."""
   if color == "target":
       mask = cv2.inRange(hsv, BLUE_LO, BLUE_HI)
   else:
       mask = cv2.inRange(hsv, GREEN_LO, GREEN_HI)
   kern = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
   mask = cv2.dilate(cv2.erode(mask, kern, iterations=1), kern, iterations=2)
   contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
   if not contours:
       return None
   best = max(contours, key=cv2.contourArea)
   if cv2.contourArea(best) < MIN_AREA:
       return None
   (cx, cy), r = cv2.minEnclosingCircle(best)
   return int(cx), int(cy), int(r)

The detect() function applies predefined HSV thresholds to isolate the colored markers placed on the drone and the target. To remove unwanted noise, the detected mask is processed using erosion and dilation operations. The function then finds the largest contour, calculates its centre position, and returns the coordinates of the detected object.
These coordinates serve as the input for the tracking algorithm, allowing the system to continuously monitor the positions of both the drone and the target in real time.

   def track(target, drone_pos, drone):
   """3-zone autonomous tracking. Returns (status, direction)."""
   clear_keys(drone)
   if target is None or drone_pos is None:
       return "TARGET LOST", "HOLD"
   dx = target[0] - drone_pos[0]
   dy = target[1] - drone_pos[1]
   dist = (dx**2 + dy**2) ** 0.5
   vert_dom = abs(dy) >= abs(dx)
   # ── ZONE 1: RETREAT (too close) ───────────────────────
   if dist < RETREAT_DIST:
       if vert_dom:
           key = DIRS["down"] if dy < 0 else DIRS["up"]
           label = "RETREAT " + ("BACK" if dy < 0 else "FWD")
       else:
           key = DIRS["right"] if dx < 0 else DIRS["left"]
           label = "RETREAT " + ("RIGHT" if dx < 0 else "LEFT")
       drone._manual_keys[key] = True
       return "TOO CLOSE", label
   # ── ZONE 2: MAINTAIN (buffer -- hold position) ────────
   if dist < FOLLOW_DIST:
       return "MAINTAINING", "HOLD"
   # ── ZONE 3: FOLLOW (far away -- move toward target) ───
   if vert_dom and abs(dy) > DEADZONE:
       key = DIRS["up"] if dy < 0 else DIRS["down"]
       label = "FWD" if dy < 0 else "BACK"
   elif abs(dx) > DEADZONE:
       key = DIRS["left"] if dx < 0 else DIRS["right"]
       label = "LEFT" if dx < 0 else "RIGHT"
   else:
       return "ALIGNED", "ALIGNED"
   drone._manual_keys[key] = True
   return "TRACKING", label

Once the positions of the drone and the target are known, the track() function calculates the horizontal and vertical offsets (dx and dy) along with the distance between them. Based on this distance, the system switches between three predefined control zones.

  • Follow Zone: If the target is farther than the follow threshold, the drone moves toward the target by determining the dominant direction and sending the corresponding movement command.
  • Maintain Zone: When the drone reaches the desired distance from the target, it simply hovers without sending any movement commands, resulting in smooth and stable tracking.
  • Retreat Zone: If the drone gets too close to the target, it moves in the opposite direction until a safe distance is restored.
    This simple zone-based control strategy eliminates the need for complex path-planning algorithms while still providing reliable object-following behaviour.

Troubleshooting Common Object Tracking Issues

While the system is simple, you may face a few common issues during setup and testing. Here are some typical problems and how to fix them:

Issue              Likely Cause                                             Fix
Object not detected properlyPoor lighting or low colour contrastImprove lighting and adjust the HSV range values in the code for the drone marker colour
Noisy or unstable detectionImage noise or inconsistent lightingIncrease the minimum contour area and fine-tune erosion/dilation settings
The wrong object is getting detectedSimilar-coloured objects in the backgroundRemove similar colours from the environment or narrow the HSV range
Drone drifting outside the boundaryTarget near the frame edge or overly aggressive correctionSet proper boundary limits in the code, reduce sensitivity, or add stricter boundary checks

Drone Object Tracking GitHub

Access the complete GitHub repository containing the source code, project files, and setup instructions to build your own AI-powered drone object tracking system.

Drone Object Tracking GitHubDrone Object Tracking Zip File

Frequently Asked Questions About Object Tracking Drone Project 

⇥ Why is color detection used instead of an object detection model?
The project uses color detection because it is lightweight, fast, and easy to implement. Since the drone and the target are marked with different colors, OpenCV can reliably detect and track them in real time without requiring machine learning models.

⇥ Can I use different colors for the drone and the target? 
Yes. You can use any pair of distinct colors as long as you update the corresponding HSV ranges in the code. Make sure the chosen colors are different from the background for reliable detection.

⇥ Does this project require an internet connection?  
No. The laptop communicates directly with the LiteWing drone over its built-in Wi-Fi access point. An internet connection is not required during operation.

⇥ Can this project track multiple objects?
The current implementation is designed to track a single target. However, the code can be extended to detect and track multiple objects by modifying the detection and control logic.

⇥ Can I replace colour detection with AI-based object detection?
Yes. Instead of colour detection, you can integrate object detection models such as YOLO or TensorFlow-based detectors. However, this requires more computational power and may reduce the overall processing speed compared to simple color detection.

Discover more hands-on LiteWing drone projects and tutorials to expand your skills in autonomous flight, computer vision, ESP32 programming, and drone control. From voice-controlled and gesture-controlled drones to Betaflight setup and configuration, these step-by-step guides will help you build smarter, AI-powered drone applications.

Build an ESP32 Voice Controlled Drone with LiteWing using Python

Build an ESP32 Voice-Controlled Drone with LiteWing using Python

We built a voice-controlled drone using ESP32 for the LiteWing drone using Python and speech recognition tools.The system listens to voice input through a microphone, converts the spoken words into text, and then translates those commands into actions for the drone

DIY Gesture Control Drone using Python with LiteWing and ESP32

DIY Gesture Control Drone using Python with LiteWing and ESP32

In this article, we are going to show you how you can build a gesture-controlled drone. To do this, we will obviously need a drone, which in our case is a LiteWing Drone, and to control this drone, we will use an ESP32 dev module along with an mpu6050, both of which are strapped to our hand.

How to Connect the LiteWing ESP32 Drone to Betaflight

How to Connect the LiteWing ESP32 Drone to Betaflight

LiteWing can also be configured using Betaflight, a powerful and widely adopted flight control software used in FPV and racing drones. In this ESP32 Betaflight tutorial, we will go through the process of configuring the LiteWing drone Betaflight and turning it into a fully tunable drone.

Complete Project Code

# LiteWing Object Tracker — Lite Edition
# Autonomous BLUE-ball follower using a ceiling camera.
# Drone is identified by GREEN paper on top.
#
# Keys: T=Takeoff | L=Land | SPACE=E-Stop | Q=Quit
import threading, msvcrt, time
import cv2
import numpy as np
from litewing import LiteWing
from litewing.manual_control import run_manual_control
# ── Configuration ─────────────────────────────────────────────
DEBUG_MODE       = 0                 # Enable debug mode (displays debug info/badge on the HUD)
CAMERA_INDEX     = 1                 # Index of the camera device to use (e.g., 0 for built-in, 1 for external ceiling camera)
DRONE_IP         = "192.168.43.42"   # IP address of the LiteWing drone for network connection
SENSITIVITY      = 0.2               # Movement sensitivity modifier for the drone controller
TARGET_HEIGHT    = 0.4               # Target altitude in meters for the drone to maintain when airborne
# Camera Feed Resizing Options
# Set to integers (e.g., 640 and 480) to scale the processed camera frame.
# Set both to None to use the camera's original default resolution.
RESIZE_WIDTH     = None
RESIZE_HEIGHT    = None
# HSV ranges — light green target (tuned for bright green ball)
GREEN_LO = (35, 60, 50)
GREEN_HI = (90, 255, 255)
# HSV ranges — blue drone marker (Light/Sky Blue)
BLUE_LO = (90, 80, 100)
BLUE_HI = (135, 255, 255)

# Tracking — 3-zone distance model
RETREAT_DIST    = 85   # px — retreat if closer than this
FOLLOW_DIST     = 125   # px — follow only if farther than this
DEADZONE        = 20    # px — ignore smaller offsets
MIN_AREA        = 500   # px² — noise filter
BOUNDARY        = 40    # px — safety margin from frame edge
# Direction keys (adjust to match camera orientation)
DIRS = {"up": "w", "down": "s", "left": "a", "right": "d"}
# States that allow autonomous movement
AIRBORNE = {"HOVERING", "TRACKING", "TOO CLOSE", "MAINTAINING",
           "ALIGNED", "TARGET LOST", "TAKING_OFF"}
# ── Helpers ───────────────────────────────────────────────────
def clear_keys(drone):
   """Reset all movement keys to False."""
   for k in "wasd":
       drone._manual_keys[k] = False

def detect(hsv, color):
   """Return (cx, cy, radius) of the largest blob, or None."""
   if color == "target":
       mask = cv2.inRange(hsv, BLUE_LO, BLUE_HI)
   else:
       mask = cv2.inRange(hsv, GREEN_LO, GREEN_HI)
   kern = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
   mask = cv2.dilate(cv2.erode(mask, kern, iterations=1), kern, iterations=2)
   contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
   if not contours:
       return None
   best = max(contours, key=cv2.contourArea)
   if cv2.contourArea(best) < MIN_AREA:
       return None
   (cx, cy), r = cv2.minEnclosingCircle(best)
   return int(cx), int(cy), int(r)

def out_of_bounds(pos, shape):
   """True if pos is outside the boundary margin."""
   if pos is None:
       return False
   h, w = shape[:2]
   x, y = pos[0], pos[1]
   return x < BOUNDARY or x > w - BOUNDARY or y < BOUNDARY or y > h - BOUNDARY

# ── Tracking Logic ────────────────────────────────────────────
def track(target, drone_pos, drone):
   """3-zone autonomous tracking. Returns (status, direction)."""
   clear_keys(drone)
   if target is None or drone_pos is None:
       return "TARGET LOST", "HOLD"
   dx = target[0] - drone_pos[0]
   dy = target[1] - drone_pos[1]
   dist = (dx**2 + dy**2) ** 0.5
   vert_dom = abs(dy) >= abs(dx)
   # ── ZONE 1: RETREAT (too close) ───────────────────────
   if dist < RETREAT_DIST:
       if vert_dom:
           key = DIRS["down"] if dy < 0 else DIRS["up"]
           label = "RETREAT " + ("BACK" if dy < 0 else "FWD")
       else:
           key = DIRS["right"] if dx < 0 else DIRS["left"]
           label = "RETREAT " + ("RIGHT" if dx < 0 else "LEFT")
       drone._manual_keys[key] = True
       return "TOO CLOSE", label
   # ── ZONE 2: MAINTAIN (buffer — hold position) ────────
   if dist < FOLLOW_DIST:
       return "MAINTAINING", "HOLD"
   # ── ZONE 3: FOLLOW (far away — move toward target) ───
   if vert_dom and abs(dy) > DEADZONE:
       key = DIRS["up"] if dy < 0 else DIRS["down"]
       label = "FWD" if dy < 0 else "BACK"
   elif abs(dx) > DEADZONE:
       key = DIRS["left"] if dx < 0 else DIRS["right"]
       label = "LEFT" if dx < 0 else "RIGHT"
   else:
       return "ALIGNED", "ALIGNED"
   drone._manual_keys[key] = True
   return "TRACKING", label

# ── HUD ───────────────────────────────────────────────────────
STATUS_COLORS = {
   "TRACKING":    (0, 200, 0),
   "ALIGNED":     (0, 255, 200),
   "MAINTAINING": (200, 180, 0),
   "TOO CLOSE":   (0, 100, 255),
   "TARGET LOST": (0, 140, 255),
}
def draw_hud(frame, target, drone_pos, status, drone, oob, direction):
   """Minimal heads-up display."""
   h, w = frame.shape[:2]
   # Boundary box
   color = (0, 0, 255) if oob else (80, 80, 80)
   cv2.rectangle(frame, (BOUNDARY, BOUNDARY), (w - BOUNDARY, h - BOUNDARY), color, 2)
   # Target marker
   if target:
       tx, ty, tr = target
       cv2.circle(frame, (tx, ty), tr, (255, 0, 0), 3)
       cv2.circle(frame, (tx, ty), 4, (255, 0, 0), -1)
       cv2.putText(frame, "TARGET", (tx - 28, ty - tr - 8),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.45, (255, 0, 0), 1, cv2.LINE_AA)
   # Drone marker
   if drone_pos:
       dx, dy, dr = drone_pos
       cv2.circle(frame, (dx, dy), dr, (0, 255, 0), 3)
       cv2.circle(frame, (dx, dy), 4, (0, 255, 0), -1)
       cv2.putText(frame, "DRONE", (dx - 24, dy - dr - 8),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 1, cv2.LINE_AA)
   else:
       cv2.putText(frame, "DRONE: NOT FOUND", (15, h - 40),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
   # Arrow from drone → target + zone rings
   if target and drone_pos:
       cv2.arrowedLine(frame, (drone_pos[0], drone_pos[1]),
                       (target[0], target[1]), (0, 255, 255), 2, tipLength=0.15)
       cv2.circle(frame, (drone_pos[0], drone_pos[1]), RETREAT_DIST, (0, 80, 200), 1)
       cv2.circle(frame, (drone_pos[0], drone_pos[1]), FOLLOW_DIST, (0, 160, 0), 1)
   # Status + direction (top-left)
   s_col = STATUS_COLORS.get(status, (200, 200, 200))
   cv2.putText(frame, status, (15, 30),
               cv2.FONT_HERSHEY_SIMPLEX, 0.65, s_col, 2, cv2.LINE_AA)
   if direction:
       cv2.putText(frame, direction, (15, 58),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1, cv2.LINE_AA)
   # Telemetry (bottom-left)
   info = f"Bat {drone.battery:.1f}V | Alt {drone.height:.2f}m"
   cv2.putText(frame, info, (15, h - 15),
               cv2.FONT_HERSHEY_SIMPLEX, 0.42, (200, 200, 200), 1, cv2.LINE_AA)
   # Debug badge
   if drone.debug_mode:
       cv2.putText(frame, "[DEBUG]", (w - 100, 28),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 165, 255), 2, cv2.LINE_AA)

# ── Main ──────────────────────────────────────────────────────
def main():
   drone = LiteWing(DRONE_IP)
   drone.debug_mode    = bool(DEBUG_MODE)
   drone.sensitivity   = SENSITIVITY
   drone.target_height = TARGET_HEIGHT
   drone.default_landing_duration = 0.1
   try:
       drone.connect()
       drone.land()
       time.sleep(1)
   except Exception as e:
       print(f"[CONN] {e}")
   cap = cv2.VideoCapture(CAMERA_INDEX, cv2.CAP_DSHOW)
   if not cap.isOpened():
       cap = cv2.VideoCapture(CAMERA_INDEX)
   if not cap.isOpened():
       print(f"[ERR] Cannot open camera {CAMERA_INDEX}")
       return
   print("LiteWing Tracker Lite  |  T=Takeoff  L=Land  SPACE=Stop  Q=Quit")
   status = "LANDED"
   flight_thread = None
   def _flight_loop():
       nonlocal status
       drone._manual_active = True
       try:
           run_manual_control(drone)
       except Exception:
           pass
       finally:
           drone._manual_active = False
           status = "LANDED"
   # Initialize resizable display window
   cv2.namedWindow("LiteWing Tracker", cv2.WINDOW_NORMAL)
   while True:
       ret, frame = cap.read()
       if not ret:
           break
       if RESIZE_WIDTH is not None and RESIZE_HEIGHT is not None:
           frame = cv2.resize(frame, (RESIZE_WIDTH, RESIZE_HEIGHT))
       hsv    = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
       target = detect(hsv, "target")
       dpos   = detect(hsv, "drone")
       # ── Key handling ──
       if msvcrt.kbhit():
           key = msvcrt.getch()
           if key in (b'q', b'Q'):
               break
           elif key == b' ':
               drone._manual_active = False
               clear_keys(drone)
               try:
                   drone.emergency_stop()
               except Exception:
                   pass
               break
           elif key in (b't', b'T') and status == "LANDED":
               if flight_thread is None or not flight_thread.is_alive():
                   status = "TAKING_OFF"
                   flight_thread = threading.Thread(target=_flight_loop, daemon=True)
                   flight_thread.start()
           elif key in (b'l', b'L') and status not in ("LANDED", "LANDING"):
               status = "LANDING"
               clear_keys(drone)
               drone._manual_active = False
       # Transition: taking off → hovering
       if status == "TAKING_OFF" and drone.height >= TARGET_HEIGHT * 0.85:
           status = "HOVERING"
       oob = out_of_bounds(target, frame.shape) or out_of_bounds(dpos, frame.shape)
       # ── Autonomous tracking ──
       direction = ""
       if status in AIRBORNE:
           status, direction = track(target, dpos, drone)
       else:
           clear_keys(drone)
           if status == "LANDED":
               direction = "Press T"
       label = f"[DBG] {status}" if drone.debug_mode else status
       draw_hud(frame, target, dpos, label, drone, oob, direction)
       cv2.imshow("LiteWing Tracker", frame)
       if cv2.waitKey(1) & 0xFF in (ord('q'), ord(' ')):
           break
   # Cleanup
   drone._manual_active = False
   clear_keys(drone)
   cap.release()
   cv2.destroyAllWindows()

if __name__ == "__main__":
   main()
Have any question related to this Article?

Add New Comment

Login to Comment Sign in with Google Log in with Facebook Sign in with GitHub