无法将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...)。
错误原因分析
- 空帧处理缺失:Tello视频流初始化或传输不稳定时,
frame_read.frame可能为空,直接处理会导致后续检测逻辑异常。 - 检测结果判断逻辑漏洞:原代码中
if results[0] is not None and len(results[0].boxes) > 0的判断不足以覆盖无检测结果的场景,当无目标时results[0].boxes为空张量,执行[:,4]切片会触发断言错误。 - 变量命名冲突:PID计算时
enumerate([error_x, integral_x, derivative_x])的循环变量与外部error_x重名,导致计算逻辑错误。
修复步骤
- 添加帧有效性检查:在处理帧前判断
frame_read.frame是否为空,跳过无效帧。 - 优化检测结果判断:改用
len(results[0].boxes) > 0作为唯一判断条件(results[0]永远不为空,无需额外判断)。 - 修正PID计算变量名:避免循环变量与外部变量重名,改用直接计算的方式简化逻辑。
- 增加异常捕获:用
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
相关产品推荐
相关产品推荐

