Files
RflySimhighschool/基础智能/e11.无人机跟随圆形案板移动实验/circle_follow.py

200 lines
5.1 KiB
Python
Raw Normal View History

2025-07-25 17:54:28 +08:00
"""
视觉跟随圆移动控制飞机飞行
圆形案板移动有前后左右上下移动
"""
import cv2
import threading
import time
import VisionCaptureApi
import PX4MavCtrlV4 as PX4MavCtrl
import sys
import numpy as np
import keyboard
import UE4CtrlAPI
ue = UE4CtrlAPI.UE4CtrlAPI()
"""
初始化飞机起飞,创建圆形目标
"""
vis = VisionCaptureApi.VisionCaptureApi()
# ue.sendUE4Cmd(b"r.setres 720x405w", 0)
ue.sendUE4Cmd(b"t.MaxFPS 30", 0)
ue.sendUE4PosNew(3, vehicleType=809, PosE=[2, 0, -2])
vis.jsonLoad()
time.sleep(1)
ue.sendUE4ExtAct(3, ActExt=[1, 0.8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0])
isSuss = vis.sendReqToUE4() # 向RflySim3D发送取图请求并验证
if not isSuss: # 如果请求取图失败,则退出
sys.exit(0)
vis.startImgCap() # 开启取图,并启用共享内存图像转发,转发到填写的目录
time.sleep(2)
mav = PX4MavCtrl.PX4MavCtrler()
mav.InitMavLoop()
time.sleep(2)
mav.initOffboard()
time.sleep(2)
mav.SendMavArm(True)
mav.SendPosNED(0, 0, -2, 0)
time.sleep(10)
detect_flag = False
"""
开辟线线程,控制圆形目标移动
"""
Circle_pose = [2, 0, -2, 0]
def MoveCircle(val):
"""
圆板目标移动没有旋转只有平移且始终朝向飞机
"""
global vis
global detect_flag
global CalCirle_pose
offset = 0.01 # 每次移动的距离
yaw_offset = np.deg2rad(1)
drone_pose = ue.getUE4Pos()
# if not detect_flag:
# time.sleep(0.001)
# continue
if val == "right": # 如果按键按下这个值为1
# 向右移动
Circle_pose[1] += offset
if val == "left":
# 向左移动
Circle_pose[1] -= offset
if val == "up":
# 向上移动
Circle_pose[2] -= offset
if val == "down":
# 向下移动
Circle_pose[2] += offset
if val == "front":
# 向前移动
Circle_pose[0] += offset
if val == "back":
# 向后移动
Circle_pose[0] -= offset
ue.sendUE4PosNew(
3,
vehicleType=809,
PosE=[Circle_pose[0], Circle_pose[1], Circle_pose[2]],
AngEuler=[0, 0, Circle_pose[3]],
)
# move_circle_th = threading.Thread(target=MoveCircle)
# move_circle_th.start()
"""
开辟线程,获取图像,并控制飞机移动
"""
def CalCirle(img: np.array) -> tuple():
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
low_hsv = np.array([0, 43, 46])
high_hsv = np.array([10, 255, 255])
mask1 = cv2.inRange(hsv, lowerb=low_hsv, upperb=high_hsv)
lower2 = np.array([156, 43, 46])
upper2 = np.array([180, 255, 255])
mask2 = cv2.inRange(hsv, lower2, upper2)
mask = mask1 + mask2
nonzero = np.nonzero(mask)
if np.size(nonzero) == 0:
return [-1, -1], [-1, -1], [-1, -1]
row_min = np.min(nonzero[0])
row_max = np.max(nonzero[0])
col_min = np.min(nonzero[1])
col_max = np.max(nonzero[1])
mid_row = int((row_max + row_min) / 2)
mid_col = int((col_max + col_min) / 2)
cv2.line(
img,
(col_min, mid_row),
(col_max, mid_row),
(255, 255, 255),
1,
)
cv2.line(
img,
(mid_col, row_min),
(mid_col, row_max),
(255, 255, 255),
1,
)
cv2.imshow("img ", img)
cv2.waitKey(1)
# cv2.imshow("test", mask1 + mask2)
# cv2.waitKey(1)
return [col_min, col_max], [row_min, row_max], [mid_col, mid_row]
def CtrlDrone():
global vis
global mav
global detect_flag
img = None
init_dist_x = 0
init_dist_y = 0
img_cnt_x = 320
img_cnt_y = 240
tolerance_cnt = 15
tolerance_y = 15
tolerance_x = 20
kx = 0.015
ky = 0.009
kz = 0.005
while True:
if vis.hasData[0]:
img = vis.Img[0]
vis.hasData[0] = False
# cv2.imshow("img", vis.Img[0])
cv2.waitKey(1)
[x_min, x_max], [y_min, y_max], [cnt_x, cnt_y] = CalCirle(img)
if x_min == -1:
time.sleep(0.001)
continue
if not detect_flag:
detect_flag = True
dist_x = x_max - x_min
dist_y = y_max - y_min
if init_dist_x == 0:
init_dist_x = dist_x
if init_dist_y == 0:
init_dist_y = dist_y
vx = 0
vy = 0
vz = 0
yaw_rate = 0
if abs(cnt_x - img_cnt_x) > tolerance_cnt:
vy = ky * (cnt_x - img_cnt_x)
if abs(cnt_y - img_cnt_y) > tolerance_cnt:
vz = kz * (cnt_y - img_cnt_y)
if abs(dist_y - init_dist_y) > tolerance_y:
vx = kx * (init_dist_y - dist_y)
mav.SendVelFRD(vx, vy, vz, 0)
time.sleep(0.001)
ctrl_drone_th = threading.Thread(target=CtrlDrone)
ctrl_drone_th.start()
keyboard.add_hotkey("ctrl+up", MoveCircle, args=("front",))
keyboard.add_hotkey("ctrl+down", MoveCircle, args=("back",))
keyboard.add_hotkey("up", MoveCircle, args=("up",))
keyboard.add_hotkey("down", MoveCircle, args=("down",))
keyboard.add_hotkey("right", MoveCircle, args=("right",))
keyboard.add_hotkey("left", MoveCircle, args=("left",))
keyboard.wait()