나갔던 대회 자료 정리하기
설명 | 기능 | 명령어 |
---|---|---|
드론 객체 선언 | 생성 | Drone() |
이착륙 제어 | 이륙 | sendTakeOff() |
착륙 | sendLanding() | |
방향 및 이동 제어 | 이동 | sendControlPosition16() |
이동 | sendControlWhile() |
방향 및 이동제어에서는 좀 더 정밀한 제어가 가능한 sendControlPosition16()
함수를 중점적으로 사용
def sendControlPosition(self, positionX, positionY, positionZ, velocity, heading, rotationalVelocity):
변수 이름 | 형식 | 범위 | 단위 | 설명 |
---|---|---|---|---|
position X | Int16 | -100 ~ 100(-10.0 ~ 10.0) | meter x 10 | 앞(+), 뒤(-) |
position Y | Int16 | -100 ~ 100(-10.0 ~ 10.0) | meter x 10 | 좌(+), 우(-) |
position Z | Int16 | -100 ~ 100(-10.0 ~ 10.0) | meter x 10 | 위(+), 아래(-) |
velocity | Int16 | 5~200(0.5 ~ 2.0) | m/s x 10 | 위치 이동 속도 |
heading | Int16 | -360 ~ 360 | degree | 좌회전(+), 우회전(-) |
rotationalVelocity | Int16 | 10 ~ 360 | degree/s | 좌우 회전속도 |
e-drone==21.1.6
numpy==1.16.2
Pillow==5.4.1
opencv==3.2.0
Toolbar code를 이용하여 적정 Threshold 값 탐색
변수 안에 값 설정
lower_blue = (95, 0, 50)
upper_blue = (110, 255, 250)
lower_red = (0, 0, 5)
upper_red = (17, 255, 240)
lower_purple = (110, 0, 5)
upper_purple = (140, 255, 50)
img = frame.array
img = cv2.flip(img, 0)
img = cv2.flip(img, 1)
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
imgH_B = cv2.inRange(imghsv, lower_blue, upper_blue)
imgH_R = cv2.inRange(imghsv, lower_red, upper_red)
imgH_P = cv2.inRange(imghsv, lower_purple, upper_purple)
tmpB = cv2.medianBlur(imgH_B, 21)
tmpR = cv2.medianBlur(imgH_R, 7)
tmpP = cv2.medianBlur(imgH_P, 7)
mode = {1:[range(100, 30000), range(30000, 100000), range(100000, 150000), 150000],
2:[range(100, 50000), range(50000, 120000), range(120000, 170000), 170000],
3:[range(100, 70000), range(70000, 140000), range(140000, 200000), 200000]}
def moveLarge(drone, BlueSum):
#이동 11
print(f"move Large / BlueSum : {BlueSum}")
drone.sendControlPosition16(11, 0, 0, 6, 0, 0)
sleep(4)
def moveSoso(drone, BlueSum):
#이동 8
print(f"move soso / BlueSum : {BlueSum}")
drone.sendControlPosition16(8, 0, 0, 5, 0, 0)
sleep(4)
def moveSmall(drone, BlueSum, dist_x, dist_y):
#이동 6
print(f"move small / BlueSum : {BlueSum}")
if (dist_x == 0 and dist_y == 0):
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y == 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x == 0 and dist_y != 0):
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y != 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
def move2Small(drone, BlueSum, dist_x, dist_y):
#속도 4
print(f"move 2 Small / BlueSum : {BlueSum}")
if (dist_x == 0 and dist_y == 0):
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y == 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x == 0 and dist_y != 0):
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y != 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
def detectDist(tmpB):
tmpB_div_1 = tmpB[:240, :320]
tmpB_div_2 = tmpB[240:, :320]
tmpB_div_3 = tmpB[:240, 320:]
tmpB_div_4 = tmpB[240:, 320:]
tmpB_div_1 = np.sum(tmpB_div_1 == 255, axis = None)
tmpB_div_2 = np.sum(tmpB_div_2 == 255, axis = None)
tmpB_div_3 = np.sum(tmpB_div_3 == 255, axis = None)
tmpB_div_4 = np.sum(tmpB_div_4 == 255, axis = None)
dist_x = (tmpB_div_3 + tmpB_div_4) - (tmpB_div_1 +tmpB_div_2)
dist_y = (tmpB_div_4 + tmpB_div_2) - (tmpB_div_3 +tmpB_div_1)
return (dist_x, dist_y)
if (BlueSum < Dmode[0][0]):
#링 내부로 들어왔다는 뜻
print(f"inside ring / BlueSum : {BlueSum}")
imgH_R = cv2.inRange(imghsv, lower_red, upper_red)
imgH_P = cv2.inRange(imghsv, lower_purple, upper_purple)
tmpR = cv2.medianBlur(imgH_R, 7) # 좌회전을 판단할 점 요소
tmpP = cv2.medianBlur(imgH_P, 7)
RedSum = np.sum(tmpR == 255, axis = None)
PurpleSum = np.sum(tmpP == 255, axis = None)
if (RedSum != 0 and level_cnt != 3):
if (RedSum < 200):
print(f"detect red / BlueSum : {BlueSum}")
drone.sendControlPosition16(4, 0, 0, 4, 0, 0)
sleep(4)
drone.sendControlPosition16(0, 0, 0, 0, 90, 20)
sleep(6)
level_cnt += 1
print("red, rotate complete, now level_cnt:", level_cnt)
Dmode = mode[level_cnt]
no_trap = True
drone.sendControlPosition16(10,0,0,5,0,0)
sleep(5)
continue
else:
print(f"detect red / BlueSum : {BlueSum}")
drone.sendControlPosition16(3, 0, 0, 3, 0, 0)
sleep(4)
drone.sendControlPosition16(0, 0, 0, 0, 90, 20)
sleep(6)
level_cnt += 1
print("red, rotate complete, now level_cnt:", level_cnt)
Dmode = mode[level_cnt]
no_trap = True
drone.sendControlPosition16(10,0,0,5,0,0)
sleep(5)
continue
elif (RedSum == 0 and PurpleSum != 0 or level_cnt == 3):
print("purple")
drone.sendLanding()
drone.close()
break
else:
#둘다 노이즈로 판명난 경우엔 다시 검출을 합니다
continue
if (BlueSum < Dmode[0][0]):...
else:
# 링 외부에 있다는 뜻
print(f"out of ring / BlueSum : {BlueSum}")
(dist_x, dist_y) = detectDist(tmpB)
if (BlueSum in Dmode[0]):
#링 경계
if (BlueSum - lastBluesum >= 0 and no_trap):
#현재 - 과거 픽셀이며, 양수면 매우 멀리있는 경우이므로 moveLarge 모드로 더 다가가야 함
moveLarge(drone, BlueSum)
else:
#음수면 링과 매우 근접한 경우이므로, 조금만 움직여야 함.
move2Small(drone, BlueSum, dist_x, dist_y)
lastBluesum = BlueSum
continue
elif (BlueSum in Dmode[1]):
if (BlueSum - lastBluesum >= 0):
moveSoso(drone, BlueSum)
no_trap = False
else:
moveSoso(drone, BlueSum)
no_trap = False
lastBluesum = BlueSum
continue
elif (BlueSum in Dmode[2]):
if (BlueSum - lastBluesum >= 0):
moveSmall(drone, BlueSum, dist_x, dist_y)
no_trap = False
else:
move2Small(drone, BlueSum, dist_x, dist_y)
no_trap = False
lastBluesum = BlueSum
continue
elif (BlueSum >= Dmode[3]):
moveSmall(drone, BlueSum, dist_x, dist_y)
lastBluesum = BlueSum
continue
else:
continue
main.py
를 Raspberry Pi에서 실행from e_drone.drone import *
from picamera.array import PiRGBArray
from picamera import PiCamera
from time import sleep
import numpy as np
import cv2
lower_blue = (95, 0, 50)
upper_blue = (110, 255, 250)
lower_red = (0, 0, 5)
upper_red = (17, 255, 240)
lower_purple = (110, 0, 5)
upper_purple = (140, 255, 50)
level_cnt = 1
no_trap = True
mode = {1:[range(100, 30000), range(30000, 100000), range(100000, 150000), 150000],
2:[range(100, 50000), range(50000, 120000), range(120000, 170000), 170000],
3:[range(100, 70000), range(70000, 140000), range(140000, 200000), 200000]} # [min,max]
lastBluesum = 0
def moveLarge(drone, BlueSum):
#이동 11
print(f"move Large / BlueSum : {BlueSum}")
drone.sendControlPosition16(11, 0, 0, 6, 0, 0)
sleep(4)
def moveSoso(drone, BlueSum):
#이동 8
print(f"move soso / BlueSum : {BlueSum}")
drone.sendControlPosition16(8, 0, 0, 5, 0, 0)
sleep(4)
def moveSmall(drone, BlueSum, dist_x, dist_y):
#이동 6
print(f"move small / BlueSum : {BlueSum}")
if (dist_x == 0 and dist_y == 0):
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y == 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x == 0 and dist_y != 0):
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y != 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(6, 0, 0, 4, 0, 0)
sleep(3)
def move2Small(drone, BlueSum, dist_x, dist_y):
#속도 4
print(f"move 2 Small / BlueSum : {BlueSum}")
if (dist_x == 0 and dist_y == 0):
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y == 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x == 0 and dist_y != 0):
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
elif (dist_x != 0 and dist_y != 0):
drone.sendControlPosition16(0, dist_x//abs(dist_x), 0, 1, 0, 0)
sleep(3)
drone.sendControlPosition16(0, 0, 2*(dist_y//abs(dist_y)), 2, 0, 0)
sleep(3)
drone.sendControlPosition16(4, 0, 0, 3, 0, 0)
sleep(3)
def detectDist(tmpB):
tmpB_div_1 = tmpB[:240, :320]
tmpB_div_2 = tmpB[240:, :320]
tmpB_div_3 = tmpB[:240, 320:]
tmpB_div_4 = tmpB[240:, 320:]
tmpB_div_1 = np.sum(tmpB_div_1 == 255, axis = None)
tmpB_div_2 = np.sum(tmpB_div_2 == 255, axis = None)
tmpB_div_3 = np.sum(tmpB_div_3 == 255, axis = None)
tmpB_div_4 = np.sum(tmpB_div_4 == 255, axis = None)
dist_x = (tmpB_div_3 + tmpB_div_4) - (tmpB_div_1 +tmpB_div_2)
dist_y = (tmpB_div_4 + tmpB_div_2) - (tmpB_div_3 +tmpB_div_1)
return (dist_x, dist_y)
drone = Drone()
drone.open()
try:
drone.sendTakeOff()
sleep(5)
drone.sendControlPosition16(11,0,0,5,0,0)
sleep(5)
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))
Dmode = mode[level_cnt]
for frame in camera.capture_continuous(rawCapture, format='bgr', use_video_port=True):
img = frame.array
img = cv2.flip(img, 0)
img = cv2.flip(img, 1)
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
imgH_B = cv2.inRange(imghsv, lower_blue, upper_blue)
rawCapture.truncate(0)
tmpB = cv2.medianBlur(imgH_B, 21) # 파란색 링에 medianBlur 적용한 이미지
BlueSum = np.sum(tmpB == 255, axis = None) # 파란색링의 이미지
print(f"first BlueSum : {BlueSum}")
if (BlueSum < Dmode[0][0]):
#링 내부로 들어왔다는 뜻
print(f"inside ring / BlueSum : {BlueSum}")
imgH_R = cv2.inRange(imghsv, lower_red, upper_red)
imgH_P = cv2.inRange(imghsv, lower_purple, upper_purple)
tmpR = cv2.medianBlur(imgH_R, 7) # 좌회전을 판단할 점 요소
tmpP = cv2.medianBlur(imgH_P, 7)
RedSum = np.sum(tmpR == 255, axis = None)
PurpleSum = np.sum(tmpP == 255, axis = None)
if (RedSum != 0 and level_cnt != 3):
#일단 노이즈 없이 검출 되는 경우
if (RedSum < 200):
print(f"detect red / BlueSum : {BlueSum}")
drone.sendControlPosition16(4, 0, 0, 4, 0, 0)
sleep(4)
drone.sendControlPosition16(0, 0, 0, 0, 90, 20)
sleep(6)
level_cnt += 1
print("red, rotate complete, now level_cnt:", level_cnt)
Dmode = mode[level_cnt]
no_trap = True
drone.sendControlPosition16(10,0,0,5,0,0)
sleep(5)
continue
else:
print(f"detect red / BlueSum : {BlueSum}")
drone.sendControlPosition16(3, 0, 0, 3, 0, 0)
sleep(4)
drone.sendControlPosition16(0, 0, 0, 0, 90, 20)
sleep(6)
level_cnt += 1
print("red, rotate complete, now level_cnt:", level_cnt)
Dmode = mode[level_cnt]
no_trap = True
drone.sendControlPosition16(10,0,0,5,0,0)
sleep(5)
continue
elif (RedSum == 0 and PurpleSum != 0 or level_cnt == 3):
print("purple")
drone.sendLanding()
drone.close()
break
else:
#둘다 노이즈로 판명난 경우엔 다시 검출을 합니다
continue
else:
# 링 외부에 있다는 뜻
print(f"out of ring / BlueSum : {BlueSum}")
(dist_x, dist_y) = detectDist(tmpB)
if (BlueSum in Dmode[0]):
#링 경계
if (BlueSum - lastBluesum >= 0 and no_trap):
#현재 - 과거 픽셀이며, 양수면 매우 멀리있는 경우이므로 moveLarge 모드로 더 다가가야 함
moveLarge(drone, BlueSum)
else:
#음수면 링과 매우 근접한 경우이므로, 조금만 움직여야 함.
move2Small(drone, BlueSum, dist_x, dist_y)
lastBluesum = BlueSum
continue
elif (BlueSum in Dmode[1]):
if (BlueSum - lastBluesum >= 0):
moveSoso(drone, BlueSum)
no_trap = False
else:
moveSoso(drone, BlueSum)
no_trap = False
lastBluesum = BlueSum
continue
elif (BlueSum in Dmode[2]):
if (BlueSum - lastBluesum >= 0):
moveSmall(drone, BlueSum, dist_x, dist_y)
no_trap = False
else:
move2Small(drone, BlueSum, dist_x, dist_y)
no_trap = False
lastBluesum = BlueSum
continue
elif (BlueSum >= Dmode[3]):
moveSmall(drone, BlueSum, dist_x, dist_y)
lastBluesum = BlueSum
continue
else:
continue
except Exception as e:
print("exception")
drone.sendLanding()
drone.close()