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,我将原来代码的单位从厘米调成了毫米2017电赛国赛滚球控制系统(控制部分代码、PID的调试)_第1张图片

这里拟合就不用笔算了,直接用matlab进行拟合
2017电赛国赛滚球控制系统(控制部分代码、PID的调试)_第2张图片
得出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

你可能感兴趣的:(Opencv,树莓派,python)