200 lines
5.1 KiB
Python
200 lines
5.1 KiB
Python
"""
|
||
视觉跟随圆移动控制飞机飞行。
|
||
圆形案板移动有前后,左右,上下移动
|
||
|
||
"""
|
||
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()
|