2017電賽國賽滾球控制系統(控制部分代碼、PID的調試)

  1. 題目要求和機械設計參考本人博客 https://blog.csdn.net/DerrickRose25/article/details/90181677

    經過幾番測試之後我才用的硬件設計是 樹莓派 + 攝像頭 + STM32
    軟件方面採用 OpenCV + Python + PID算法

  2. 攝像頭部分參考本人博客:https://blog.csdn.net/DerrickRose25/article/details/90733386
    先通過如下代碼得到板和球在攝像頭中的位置:

圖像處理代碼

import cv2
import numpy as np

class ball():
    def __init__(self):
        self.point_flag = False
        self.ban_flag = False
    
def detect(self, frame ,contours):
    # 板的長度和麪積的最大值和最小值
    BanarclengthMin = 1000
    BanarclengthMax = 2000
    BansquareMin = 60000
    BansquareMax = 100000

    # 球的長度和麪積的最大值和最小值
    BallarclengthMin = 50
    BallarclengthMax = 100
    BallsquareMin = 350
    BallsquareMax = 600

    # print(len(contours))
    for cnt in range(len(contours)):
        # cv2.drawContours(frame, contours, cnt, (0, 255, 0), 2)
        square = cv2.contourArea(contours[cnt])                                 # 面積
        arcLength = cv2.arcLength(contours[cnt], True)                          # 長度
        # print(square, arcLength)
        # 板定位
        if BanarclengthMin < arcLength < BanarclengthMax and BansquareMin < square < BansquareMax:
            approx = cv2.approxPolyDP(contours[cnt], arcLength * 0.02, 1)
            cv2.polylines(frame, [approx], True, (0, 0, 255), 2)                # 擬合
            mm = cv2.moments(approx)                                            # 中心求解
            cx = int(mm['m10'] / mm['m00'])
            cy = int(mm['m01'] / mm['m00'])
            cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
            print("板的中心座標是 (%d,%d)" % (np.int(cx), np.int(cy)))
            # cv2.drawContours(image, contours, cnt, (0, 255, 0), 2)
            self.ban_flag = True

        # 球定位
        elif BallarclengthMin < arcLength < BallarclengthMax and BallsquareMin < square < BallsquareMax:
            # cv2.drawContours(frame, contours, cnt, (0, 255, 0), 2)
            epsilon = 0.01 * arcLength                                          # 輪廓逼近,主要是對閉合輪廓進行檢測,即水管的漏油點
            approx = cv2.approxPolyDP(contours[cnt], epsilon, True)             # 進行圖像擬合
            rrt = cv2.fitEllipse(contours[cnt])                                 # 橢圓擬合
            cv2.ellipse(frame, rrt, (255, 0, 0), 2, cv2.LINE_AA)                # 畫出擬合橢圓
            x, y = rrt[0]                                                       # 求出橢圓中心
            print("球的座標是 (%d,%d)" % (np.int(x), np.int(y)))
            cv2.circle(frame, (np.int(x), np.int(y)), 4, (255, 0, 0), -1, 8, 0)  # 畫出橢圓中心
            self.point_flag = True
    
def cameraAnalysis(self, frame):
    frame = cv2.resize(frame, (640, 360), interpolation = cv2.INTER_CUBIC)      # 因爲攝像頭問題,對圖像進行了大小修改
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)                              # 轉爲灰度圖
    # cv2.imshow("gray", gray)
    ret, binary = cv2.threshold(gray, 140, 255, cv2.THRESH_BINARY)              # 二值化
    # cv2.imshow("binary", binary)
    blurred = cv2.GaussianBlur(binary, (3, 3), 0)  # 高斯濾波處理
    cv2.imshow("blur", blurred)                                               # 顯示濾波圖像
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 建立7 * 7的卷積核
    closed = cv2.morphologyEx(blurred, cv2.MORPH_RECT, kernel)  # 去除噪點
    cv2.imshow("closed", closed)
    ret, binary = cv2.threshold(closed, 30, 255, cv2.THRESH_BINARY)  # 再次二值化
    cv2.imshow("binary", binary)
    contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)  # 尋找輪廓
    self.detect(frame, contours)
    cv2.imshow("frame", frame)
    if gunqiu.point_flag == True and gunqiu.ban_flag == True :
        print("------------------  Successful positioning!  ------------------")


if __name__ == "__main__":
    frame = cv2.imread("./image/qiu6.jpg")
    gunqiu = ball()
    gunqiu.cameraAnalysis(frame)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

在這裏插入圖片描述

之後進行線性擬合得到球在板上的真實座標,先把板球放在指定的9個位置並記錄在攝像頭中的位置,爲了提高精度來調節PID,我將原來代碼的單位從釐米調成了毫米在這裏插入圖片描述

這裏擬合就不用筆算了,直接用matlab進行擬合
在這裏插入圖片描述
得出x方向方程爲y = -2.381 * x + 1013
同理y方向方程y = -2.15 * x + 744.2
代入原代碼中
在這裏插入圖片描述

3.PID的調節

PID stm32部分代碼上傳github上,因爲時間問題PID沒有調好,但是程序基本結構已經出來,只需要修改調試PID參數即可
https://github.com/DerrickRose25/Ball_rolling_control

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章