/drone_contest_project

About drone contest in 2020

Primary LanguagePythonMIT LicenseMIT

KIEE

2020 Mini drone autonomous flight competition

Kyunghee University


License License License License

Context

1. Progress strategy
2. Algorithm
3. Source code
4. Data sheet of Humming bird
5. Author
6. License


1. Progress strategy

1-a. Understanding of python

1-b. Understanding of Raspberry pi communication

  • Control a drone by pc through Raspberry pi communication

1-c. Practicing of using programs for contest

Using program

PyCharm Community Edition 2020

  • Using for editting python
  • Guide

WinSCP

  • Using for data file trasfer
  • Guide

VNC viewer

  • Using for connect PC and Raspberry pi
  • Guide

Sourcetree

  • Using for github update
  • Guide

1-d. Theorical understanding for flight of drone

  • Changing of Throttle, Roll, Pitch and Yaw for position control

1-e. Position codes of drone and application codes

def sendControlPosition(self, positionX, positionY, positionZ, velocity, heading, rotationalVelocity):
Variable name form range unit explain
position X float -10.0 ~ 10.0 meter forward(+), behind(-)
position Y float -10.0 ~ 10.0 meter left(+), right(-)
position Z float -10.0 ~ 10.0 meter up(+), down(-)
velocity float 0.5 ~ 2.0 meter moving velocity
heading Int16 -360 ~ 360 degree left turn(+), right turn(-)
rotationalVelocity Int16 10 ~ 360 degree/s rotational velocity

1-f. Map

  • Fix rings below the ceiling and we can change heights of ring
  • About the third ring, it can change right or left
  • Have some patterns on the floor for stable hovering

1-g. Error handling

Hardware problem

Use sensor reset in controller for H.W problem
Setting trim for stable hovering
Check the whole manual 

Go to "manual "

Software problem

Used the try catch grammer for landing that you have any errors in flight

2. Algorithm

In mode3, if the circle color is red go back to mode 1
After in mode3, if the circle color is blue just Landing

real_last_algorithm

3. Source code

Setting the mask of ring

  • Pictures from contest map
lower_green = (60, 150, 55)
upper_green = (80, 255, 255)
lower_red1 = (150, 30, 30)  
upper_red1 = (190, 255, 255)  
lower_red2 = (-10, 100, 55)  
upper_red2 = (10, 255, 255)  
lower_blue = (90, 190, 75)  
upper_blue = (110, 255, 255) 

drone = Drone()
drone.open()

Function

  • The function of find the ring
  • Return value is center of the ring
def detect_rect(img_hsv):
    try:
        img_mask_green = cv2.inRange(img_hsv, lower_green, upper_green)
        dst3 = cv2.medianBlur(img_mask_green, 15)

        _, contours, hierarchy = cv2.findContours(dst3, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

        area_temp = 640 * 480
        area_temp2 = 0

        for cnt in contours:
            epsilon = 0.01 * cv2.arcLength(cnt, True)  
            approx = cv2.approxPolyDP(cnt, epsilon, True)
            area = cv2.contourArea(approx)
            mmt = cv2.moments(approx)
            cx = int(mmt['m10'] / mmt['m00'])
            cy = int(mmt['m01'] / mmt['m00'])

            if (8000 < area) and (area < area_temp):
                area_temp = area
                pt_temp = (cx, cy)

            if (8000 < area) and (area > area_temp2):
                area_temp2 = area
                approx_temp = approx

        if len(approx_temp) == 4:
            approx_list = [tuple(approx_temp[0, 0]), tuple(approx_temp[1, 0]), tuple(approx_temp[2, 0]),
                           tuple(approx_temp[3, 0])]
            approx_list.sort()
            left_length = abs(approx_list[0][1] - approx_list[1][1])
            right_length = abs(approx_list[2][1] - approx_list[3][1])
        else:
            left_length = 0
            right_length = 0

        return pt_temp, left_length, right_length

    except Exception as e:
        return 'fail'

original HSV
mask_green morphology
median result

  • The function of find the color of circle
  • Return value is color of circle
def detect_color(img_hsv):
 img_mask_red1 = cv2.inRange(img_hsv, lower_red1, upper_red1)
 img_mask_red2 = cv2.inRange(img_hsv, lower_red2, upper_red2)
 img_mask_red = cv2.add(img_mask_red1, img_mask_red2)
 img_mask_blue = cv2.inRange(img_hsv, lower_blue, upper_blue)

 R = np.sum(img_mask_red == 255, axis=None)
 B = np.sum(img_mask_blue == 255, axis=None)

 if R > B:  # red
     circle_color = 'red'
 else:  # blue
     circle_color = 'blue'
 return circle_color

  • The function of find the circle
  • Return value is center of circle
def detect_circle(img_hsv, circle_color):
 if circle_color == 'red':
     img_mask_red1 = cv2.inRange(img_hsv, lower_red1, upper_red1)
     img_mask_red2 = cv2.inRange(img_hsv, lower_red2, upper_red2)
     img_mask_red = cv2.add(img_mask_red1, img_mask_red2)
     dilation_red = cv2.morphologyEx(img_mask_red, cv2.MORPH_CLOSE, np.ones((15, 15), np.uint8))
     dilation_red = cv2.dilate(dilation_red, np.ones((7, 7), np.uint8), iterations=1)
     dst_red = cv2.medianBlur(dilation_red, 7)
     circles = cv2.HoughCircles(dst_red, cv2.HOUGH_GRADIENT, 1, 50, param1=50, param2=10, minRadius=3, maxRadius=70)
 elif circle_color == 'blue':
     img_mask_blue = cv2.inRange(img_hsv, lower_blue, upper_blue)
     dilation_blue = cv2.morphologyEx(img_mask_blue, cv2.MORPH_CLOSE, np.ones((15, 15), np.uint8))
     dilation_blue = cv2.dilate(dilation_blue, np.ones((7, 7), np.uint8), iterations=1)
     dst_blue = cv2.medianBlur(dilation_blue, 7)
     circles = cv2.HoughCircles(dst_blue, cv2.HOUGH_GRADIENT, 1, 50, param1=50, param2=10, minRadius=3, maxRadius=70)

 if circles is not None:
     max_circle = max(circles[0, :, 2])
     for j in circles[0]:
         if int(max_circle) == int(j[2]):
             return j[0], j[1]
 else:
     return 0, 0

img_mask_blue morphology
dilate medianBlur
result

Inside of try

  • After take off, go forward for 0.7m & begin mode 2
try:
  drone.sendTakeOff()
  sleep(5)
  camera = PiCamera()
  camera.resolution = (640, 480)  # (2592,1944)
  camera.framerate = 32
  rawCapture = PiRGBArray(camera, size=(640, 480))

  circle_color = 'red'
  mode1 = False
  mode2 = True
  mode3 = False

  ring_range = 40
  
  i = 0
  no_ring_cnt = 0
  drone.sendControlPosition16(7, 0, 0, 5, 0, 0)
  sleep(3)
  
  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)  
      img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
      cv2.imwrite("total_capture/{}.jpg".format(i), img)
      i = i + 1

      rawCapture.truncate(0)  
  • mode 1 : go forward for 1.3m & change to mode 2
    if mode1:  # 1.3m
         drone.sendControlPosition16(13, 0, 0, 5, 0, 0)
         sleep(5)
         mode1 = False
         mode2 = True
         
  • mode 2 : Control left right and degree adjustment (watch the camera straight forward) & change to mode 3
     
     elif mode2:
         if 'fail' == detect_rect(img_hsv):
             continue
         else:
             pt_temp, left_length, right_length = detect_rect(img_hsv)
             if pt_temp[1] > 480 - 90+20:
                 drone.sendControlPosition16(0, 0, -7, 5, 0, 0)
                 sleep(3)
             elif pt_temp[1] < 90+20:
                 drone.sendControlPosition16(0, 0, 7, 5, 0, 0)
                 sleep(3)
             else:
                 if pt_temp[1] > 480 - 130+20:
                     drone.sendControlPosition16(0, 0, -3, 5, 0, 0)
                     sleep(1)
                 elif pt_temp[1] < 130+20:
                     drone.sendControlPosition16(0, 0, 3, 5, 0, 0)
                     sleep(1)
                 elif pt_temp[0] < 100:
                     drone.sendControlPosition16(0, 11, 0, 5, 0, 0)
                     sleep(5)
                 elif pt_temp[0] > 640 - 100:
                     drone.sendControlPosition16(0, -11, 0, 5, 0, 0)
                     sleep(5)
                 else:
                     if pt_temp[1] > 240 + ring_range + 30:
                         drone.sendControlPosition16(0, 0, -1, 5, 0, 0)
                         sleep(0.5)
                     elif pt_temp[1] < 240 - ring_range + 30:
                         drone.sendControlPosition16(0, 0, 1, 5, 0, 0)
                         sleep(0.5)
                     elif pt_temp[0] > 320 + ring_range:
                         drone.sendControlPosition16(0, -1, 0, 5, 0, 0)
                         sleep(0.5)
                     elif pt_temp[0] < 320 - ring_range:
                         drone.sendControlPosition16(0, 1, 0, 5, 0, 0)
                         sleep(0.5)
                     else: #각도 미세조정
                         if left_length - right_length > 25:
                             drone.sendControlPosition16(0, 0, 0, 0, 10, 20)
                             sleep(3)
                         elif right_length - left_length > 25:
                             drone.sendControlPosition16(0, 0, 0, 0, -10, 20)
                             sleep(3)
                         else:
                             drone.sendControlPosition16(8, 0, 0, 5, 0, 0)
                             sleep(3)
                             mode2 = False
                             mode3 = True
  • mode 3 : go forward after find a color of the circle and find cirle (Blue color is Landing, Red color is rotate for 90 degrees to counter clockwise)
     elif mode3:
         circle_color = detect_color(img_hsv)
         circle_x, circle_y = detect_circle(img_hsv, circle_color)
         if circle_x == 0:
             continue
         else:   
                 drone.sendControlPosition16(0, -1, 0, 5, 0, 0)
                 sleep(0.5)
             elif circle_x < 320 - 40:
                 drone.sendControlPosition16(0, 1, 0, 5, 0, 0)
                 sleep(0.5)
             else:
                 sleep(1)
                 drone.sendControlPosition16(10, 0, 0, 5, 0, 0)
                 sleep(6)
                 if circle_color == 'blue':
                     sleep(1)
                     drone.sendLanding()
                     drone.close()
                     break
                 elif circle_color == 'red':
                     drone.sendControlPosition16(0, 0, 0, 0, 90, 20)
                     sleep(6)
                     mode3 = False
                     mode1 = True
  • If there is errors just landing (prevention of collision)
except Exception as e:
 drone.sendLanding()
 drone.close()

4. Data sheet of humming bird

Hummingbird

5. Author

Team leader: Seungjik Kim

Team members: Yeongin Kim, Soyoung Jung

6. License

This project is licensed under the MIT License - see the LICENSE file for details