实验环境

(1)硬件环境

机械臂一台:具备视觉引导和运动控制功能的机械臂设备
摄像头:用于采集图像并进行颜色追踪的视觉设备
彩色物体:红、绿、蓝、黄等不同颜色的待追踪物体

(2)软件环境

Vmware虚拟环境:运行Ubuntu系统的虚拟化平台
Python 3.x 环境:支持OpenCV和机械臂控制库运行
OpenCV库:用于图像处理和颜色追踪的计算机视觉库
Jupyter Notebook:用于运行和调试颜色追踪代码的交互式环境
机械臂控制库:Arm_Lib(用于控制机械臂运动)

实验步骤

注意:请确保摄像头视觉范围内出现待追踪的颜色物体。
  1. 启动虚拟机,在Windows电脑中,使用Vmware运行Ubuntu系统。
  2. 找到路径 /Home/dofbot_ws/src/dofbot_color_follow/颜色追踪color_follow.ipynb,右击选择用Jupyter Notebook启动,输入密码 shujia
  3. 按照代码单元顺序执行程序,初始化机械臂位置并启动交互界面。
  4. 点击【learning_color】按钮,画面中心出现一个方框,在方框内放置待追踪物体,实时观察HSV的高低阈值,当方框下面出现【OK !!!】字样时,说明识别成功。
  5. 点击【learning_follow】按钮,机械臂将对学习到的颜色进行实时跟踪。
  6. 点击【follow_cancel】按钮可取消跟踪(不退出程序);点击【Exit】按钮可退出程序。
  7. 也可直接点击【color_follow】按钮,通过【choose_color】选择预设的红、绿、蓝、黄四种颜色进行追踪。

实验结果

取色追踪结果显示

实验原理

概述:目标追踪包含两种玩法:颜色追踪、取色追踪(学习追踪)。其原理是,通过相机对图像做一定的处理,通过特定的方式识别目标,获取到目标在相机下的坐标位置,计算目标中心点距离图像中心点的偏差值,通过PID算法调试,驱动机械臂移动,使得目标中心点与图像中心点重合。
PID算法基础

PID,就是对输入偏差进行比例积分微分运算,运算的叠加结果去控制执行机构。公式如下:

它由三部分组成:

  • P(比例):输入偏差乘以一个系数
  • I(积分):对输入偏差进行积分运算
  • D(微分):对输入偏差进行微分运算

如下图所示就是一个基本的PID控制器:

(1)比例部分

比例部分的数学式表示是:

在模拟PID控制器中,比例环节的作用是对偏差瞬间作出反应。偏差一旦产生,控制器立即产生控制作用使控制量向减少偏差的方向变化。控制作用的强弱取决于比例系数,比例系数越大,控制作用越强,则过渡过程越快,控制过程的静态偏差也就越小;但是比例系数过大,也越容易产生振荡,破坏系统的稳定性。

优点:调整系统的开环比例系数,提高系统的稳态精度,减低系统的惰性,加快响应速度。

缺点:过大的开环比例系数不仅会使系统的超调量增大,而且会使系统稳定裕度变小,甚至不稳定。

(2)积分部分

积分部分的数学式表示是:∫e(t)dt * Ki

积分常数越大,积分的积累作用越弱,这时系统在过渡时不会产生振荡;但是增大积分常数会减慢静态误差的消除过程,消除偏差所需的时间也较长,但可以减少超调量,提高系统的稳定性。当积分常数较小时,则积分的作用较强,这时系统过渡时间中有可能产生振荡,不过消除偏差所需的时间较短。

优点:消除稳态误差。

缺点:会影响系统的稳定性,使系统的稳定裕度减小。

(3)微分部分

微分部分的数学式表示是:de(t)/dt * Kd

微分环节的作用是阻止偏差的变化。它是根据偏差的变化趋势(变化速度)进行控制。偏差变化的越快,微分控制器的输出就越大,并能在偏差值变大之前进行修正。微分作用的引入,将有助于减小超调量,克服振荡,使系统趋于稳定,特别对高阶系统非常有利,它加快了系统的跟踪速度。

优点:使系统的响应速度变快,超调减小,振荡减轻,对动态过程有"预测"作用。

缺点:对输入信号的噪声很敏感,对那些噪声较大的系统一般不用微分。

主要代码

代码路径:/Home/dofbot_ws/src/dofbot_color_follow/颜色追踪color_follow.ipynb

1. 导入头文件与初始化:

# 导入头文件
import cv2 as cv 
import threading 
import random
from time import sleep
import ipywidgets as widgets
from IPython.display import display
from color_follow import color_follow

# 初始化机械臂位置
import Arm_Lib
Arm = Arm_Lib.Arm_Device()
joints_0 = [90, 135, 20, 25, 90, 30]
Arm.Arm_serial_servo_write6_array(joints_0, 1000)

# 创建实例,初始化参数
follow = color_follow()
# 初始化模式
model = 'General'
# 初始化HSV_learning值
HSV_learning = ()
# 初始化HSV值
color_hsv = {"red" : ((0, 43, 46), (10, 255, 255)), 
             "green" : ((35, 43, 46), (77, 255, 255)),
             "blue" : ((100, 43, 46), (124, 255, 255)), 
             "yellow": ((26, 43, 46), (34, 255, 255))}
# 设置随机颜色
color = [[random.randint(0, 255) for _ in range(3)] for _ in range(255)]

2. 创建交互控件:

button_layout = widgets.Layout(width='200px', height='100px',align_self='center')
# 输出控件
output = widgets.Output()
# 颜色追踪
color_follow = widgets.Button(description='color_follow', button_style='success', layout=button_layout)
# 选择颜色
choose_color = widgets.ToggleButtons(options=['red', 'green', 'blue', 'yellow'],  
                                     button_style='success',
                                     tooltips=['Description of slow', 'Description of regular', 'Description of fast'])
# 取消追踪
follow_cancel = widgets.Button(description='follow_cancel', button_style='danger', layout=button_layout)
# 学习颜色
learning_color = widgets.Button(description='learning_color', button_style='primary', layout=button_layout)
# 学习颜色追踪
learning_follow = widgets.Button(description='learning_follow', button_style='success', layout=button_layout)
# 退出
exit_button = widgets.Button(description='Exit', button_style='danger', layout=button_layout)
# 图像控件
imgbox = widgets.Image(format='jpg', height=480, width=640, layout=widgets.Layout(align_self='auto'))
# 垂直布局
img_box = widgets.VBox([imgbox, choose_color], layout=widgets.Layout(align_self='auto'))
# 垂直布局
Slider_box = widgets.VBox([color_follow, learning_color,
                          learning_follow,follow_cancel,exit_button],
                          layout=widgets.Layout(align_self='auto'))
# 水平布局
controls_box = widgets.HBox([img_box, Slider_box],layout=widgets.Layout(align_self='auto'))

3. 模式切换函数:

def color_follow_Callback(value): 
    global model
    model = 'color_follow'

def learning_color_Callback(value): 
    global model
    model = 'learning_color'

def learning_follow_Callback(value): 
    global model
    model = 'learning_follow'

def follow_cancel_Callback(value): 
    global model
    model = 'General'

def exit_button_Callback(value): 
    global model
    model = 'Exit'

# 绑定按钮事件
color_follow.on_click(color_follow_Callback)
learning_color.on_click(learning_color_Callback)
learning_follow.on_click(learning_follow_Callback)
follow_cancel.on_click(follow_cancel_Callback) 
exit_button.on_click(exit_button_Callback)

4. 主程序:

def camera():
    global HSV_learning,model
    # 打开摄像头
    capture = cv.VideoCapture(0) 
    capture.set(3, 640)
    capture.set(4, 480)
    capture.set(5, 30)  # 设置帧率
    
    # 当摄像头正常打开的情况下循环执行
    while capture.isOpened(): 
        try:
            # 读取相机的每一帧
            _, img = capture.read()
            # 统一图像大小
            img = cv.resize(img, (640, 480)) 
            
            if model == 'color_follow':
                img = follow.follow_function(img,color_hsv[choose_color.value])
                # 添加文字
                cv.putText(img, choose_color.value, (int(img.shape[0] / 2), 50), 
                          cv.FONT_HERSHEY_SIMPLEX, 2, color[random.randint(0, 254)], 2)
            
            if model == 'learning_color':
                img,HSV_learning = follow.get_hsv(img)
            
            if model == 'learning_follow':
                img = follow.learning_follow(img, HSV_learning)
                # 添加文字
                cv.putText(img,'LeColor', (200, 50), 
                          cv.FONT_HERSHEY_SIMPLEX, 1, color[random.randint(0, 254)], 1)
            
            if model == 'Exit':
                cv.destroyAllWindows() 
                capture.release()
                break
            
            # 更新图像显示
            imgbox.value = cv.imencode('.jpg', img)[1].tobytes() 
            
        except KeyboardInterrupt:
            capture.release()

# 启动程序
display(controls_box,output)
threading.Thread(target=camera, ).start()
代码说明:本实验实现了两种颜色追踪模式:预设颜色追踪和自定义取色追踪。系统通过OpenCV处理摄像头采集的图像,利用HSV颜色空间进行颜色识别。核心流程为:摄像头采集图像→根据选择的模式进行颜色识别(预设颜色或学习颜色)→计算目标位置与中心的偏差→通过PID算法控制机械臂运动→实时更新显示。界面提供了丰富的交互按钮,可实现模式切换、追踪控制和程序退出等功能,机械臂通过Arm_Lib库实现精准运动控制,确保目标始终保持在视野中心。