You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法将YOLOv8与DJI Tello集成实现目标跟随的问题求助

解决DJI Tello + YOLOv8目标跟随程序的AssertionError问题

问题概述

使用Python结合DJI Tello无人机与YOLOv8模型编写目标跟随程序时,运行出现AssertionError: expected n in [6, 7], but got 0错误,同时伴随视频流解码报错(no frame!、error while decoding MB...)。

错误原因分析

  1. 空帧处理缺失:Tello视频流初始化或传输不稳定时,frame_read.frame可能为空,直接处理会导致后续检测逻辑异常。
  2. 检测结果判断逻辑漏洞:原代码中if results[0] is not None and len(results[0].boxes) > 0的判断不足以覆盖无检测结果的场景,当无目标时results[0].boxes为空张量,执行[:,4]切片会触发断言错误。
  3. 变量命名冲突:PID计算时enumerate([error_x, integral_x, derivative_x])的循环变量与外部error_x重名,导致计算逻辑错误。

修复步骤

  1. 添加帧有效性检查:在处理帧前判断frame_read.frame是否为空,跳过无效帧。
  2. 优化检测结果判断:改用len(results[0].boxes) > 0作为唯一判断条件(results[0]永远不为空,无需额外判断)。
  3. 修正PID计算变量名:避免循环变量与外部变量重名,改用直接计算的方式简化逻辑。
  4. 增加异常捕获:用try-finally确保无人机在程序中断时能安全降落,释放资源。

完整修正代码

import cv2
import numpy as np
from djitellopy import Tello
from ultralytics import YOLO
import sys
sys.path.insert(0, r"C:\Users\abeer\OneDrive\Desktop\ultralytics")

# Load the YOLOv8 model
model = YOLO(r"C:\\FYP\\Tello Programs\\My TELLO Journey\\TELLO Ball Tracker(TBT)\\Tello Ball Tracker - TBT.v3i.yolov8\\runs\detect\\train\\weights\\best.pt")

# Initialize DJI Tello
tello = Tello()
tello.connect()
tello.streamon()

# Initial speed
S = 60

# PID coefficients for the bounding box's x, y, and area coordinates
pid_x = [0.5, 0.5, 0]
pid_y = [0.5, 0.5, 0]
pid_area = [0.5, 0.5, 0]

# Initialize the error and integral terms
error_x, integral_x = 0, 0
error_y, integral_y = 0, 0
error_area, integral_area = 0, 0

# The target area of the bounding box (area of the frame to be covered by the bounding box)
target_area = 720*960/5

# The target position of the bounding box's center (center of the frame)
target_x = 960 // 2
target_y = 720 // 2

try:
    # Take off
    tello.takeoff()
    # Fly to human height
    tello.move_up(160)

    while True:
        # Get the current frame
        frame_read = tello.get_frame_read()
        # Skip invalid frames
        if frame_read is None or frame_read.frame is None:
            continue
        
        frame = cv2.cvtColor(frame_read.frame, cv2.COLOR_BGR2RGB)
        frame = cv2.resize(frame, (960, 720))

        # Perform object detection
        results = model.predict(frame, show=False, conf=0.9)

        # If an object was detected
        if len(results[0].boxes) > 0:
            # Get the bounding box with the highest objectness score
            max_score_idx = results[0].boxes.conf.argmax()
            box = results[0].boxes[max_score_idx]
            x1, y1, x2, y2 = box.xyxy[0].tolist()

            # Calculate the bounding box's area and center
            area = (x2 - x1) * (y2 - y1)
            center_x = (x1 + x2) / 2
            center_y = (y1 + y2) / 2

            # Calculate the error terms
            error_x_prev = error_x
            error_y_prev = error_y
            error_area_prev = error_area

            error_x = target_x - center_x
            error_y = target_y - center_y
            error_area = target_area - area

            # Calculate the integral terms
            integral_x += error_x
            integral_y += error_y
            integral_area += error_area

            # Calculate the derivative terms
            derivative_x = error_x - error_x_prev
            derivative_y = error_y - error_y_prev
            derivative_area = error_area - error_area_prev

            # Calculate the adjustment values for the drone's position
            adjustment_x = pid_x[0]*error_x + pid_x[1]*integral_x + pid_x[2]*derivative_x
            adjustment_y = pid_y[0]*error_y + pid_y[1]*integral_y + pid_y[2]*derivative_y
            adjustment_area = pid_area[0]*error_area + pid_area[1]*integral_area + pid_area[2]*derivative_area

            # Adjust the drone's position using RC control (smoother than move commands)
            tello.send_rc_control(
                int(np.clip(adjustment_x, -S, S)),
                int(np.clip(adjustment_area, -S, S)),
                int(np.clip(adjustment_y, -S, S)),
                0
            )
        # If no object was detected
        else:
            # Hover in place
            tello.send_rc_control(0, 0, 0, 0)

        # Display the frame
        cv2.imshow('Tello Tracking...', frame)

        # Break the loop if 'q' is pressed
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
finally:
    # Ensure the drone lands and resources are released
    tello.land()
    tello.streamoff()
    cv2.destroyAllWindows()

额外建议

  • 降低置信度阈值:如果目标检测不灵敏,可将conf=0.9调整为conf=0.5或更低,测试检测效果。
  • 优化PID参数:当前PID系数为初始值,需根据实际飞行场景调整,避免无人机动作幅度过大。
  • 检查网络连接:确保Tello与电脑连接同一WiFi,避免视频流传输中断。
  • 验证模型有效性:先用本地图片测试YOLOv8模型是否能正常检测目标,排除模型本身问题。

内容的提问来源于stack exchange,提问作者Abeer Ilyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 09:57:01