• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

基于ros框架和opencv颜色捕捉功能,实现机器人充当守门员

人工智能 否极 2703次浏览 0个评论

首先展示实现效果,AI守门员请求出战:https://v.douyin.com/erE3dJo/

实现条件:

1.有一个ROS框架的麦克纳姆轮智能机器人(可左右横向移动的机器人);

2.能够发布摄像头信息;

3.对opencv的基本API有一定的了解。

算法思路:

1.订阅摄像头信息,用cv_bridge转换为可处理的opencv图;

2.通过opencv的颜色过滤功能,实时捕捉“足球”的位置;

3..根据足球位置和PID算法,移动机器人,使机器人始终保持在“足球”的正前方。

可结合注释阅读核心源代码(摄像头发布代码和机器人移动代码,因机器人种类的不同,不能一概而论,因此这里就谈了):

#!/usr/bin/env python
#-*- coding: utf-8 -*-
from __future__ import print_function


import sys
import rospy
import time
import cv2
from std_msgs.msg import String
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import numpy as np
from sensor_msgs.msg import CompressedImage
from geometry_msgs.msg import Twist, Vector3

class image_converter:

  def __init__(self):
    # 定义处理前图像订阅器
    self.image_sub = rospy.Subscriber("/usb_cam/image_raw",Image,self.callback)
    # 定义处理后图像发布器
    self.image_pub = rospy.Publisher("/image_topic_2",Image, queue_size =3)
    # 定义原图和opencv图转换器
    self.bridge = CvBridge()
    # 定义机器人速度控制器
    self.cmdVelPublisher = rospy.Publisher('/cmd_vel', Twist, queue_size =3)
    # 定义PID,其中320为视频X方向中心点。P=0.005
    self.PID_controller_distance = simplePID(320, 0.005,0, 0)

  def callback(self,data):
    # 将原图转为opencv图
    try:
      frame = self.bridge.imgmsg_to_cv2(data, "bgr8")
    except CvBridgeError as e:
      print(e)
    # 选取“足球”红色的取值范围
    color_lower=np.array([0,43,46])
    color_upper = np.array([10, 255, 255])
    # 捕捉“足球”
    frame_=cv2.GaussianBlur(frame,(5,5),0)                    
    hsv=cv2.cvtColor(frame_,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(hsv,color_lower,color_upper)  
    mask=cv2.erode(mask,None,iterations=2)
    mask=cv2.dilate(mask,None,iterations=2)
    mask=cv2.GaussianBlur(mask,(3,3),0)     
    cnts=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2] 
    if len(cnts)>0:
      cnt = max (cnts,key=cv2.contourArea)
      (color_x,color_y),color_radius=cv2.minEnclosingCircle(cnt)
      if color_radius > 20:
        cv2.circle(frame,(int(color_x),int(color_y)),int(color_radius),(255,0,255),2) 
        print(color_x,color_y,color_radius)
        # 将opencv图转为原图并发布
        try:
          self.image_pub.publish(self.bridge.cv2_to_imgmsg(frame, "bgr8"))
        except CvBridgeError as e:
          print(e)
      # PID控制,让小车始终保持在球的正前方
        go_distance = self.PID_controller_distance.update(color_x)
        # rospy.loginfo("pid_distance:{}".format(go_distance))
        velocity = Twist()
        velocity.linear = Vector3(0,go_distance,0)
        velocity.angular= Vector3(0., 0.,0.)
        self.cmdVelPublisher.publish(velocity)
    # (rows,cols,channels) = frame.shape
    # print(rows,cols,channels)

class simplePID:
	'''very simple discrete PID controller'''
	def __init__(self, target, P, I, D):
        # rospy.loginfo('PID initialised with P:{}, I:{}, D:{}'.format(P,I,D))
		self.Kp		=np.array(P)
		self.Ki		=np.array(I)
		self.Kd		=np.array(D)
		self.setPoint   =np.array(target)
		
		self.last_error=0
		self.integrator = 0
		self.integrator_max = float('inf')
		self.timeOfLastCall = None 
		
		
	def update(self, current_value):
		current_value=np.array(current_value)
		if(self.timeOfLastCall is None):
			# the PID was called for the first time. we don't know the deltaT yet
			# no controll signal is applied
			self.timeOfLastCall = time.clock()
			return np.zeros(np.size(current_value))

		
		error = self.setPoint - current_value
		P =  error
		# rospy.loginfo(P)
		currentTime = time.clock()
		deltaT      = (currentTime-self.timeOfLastCall)

		# integral of the error is current error * time since last update
		self.integrator = self.integrator + (error*deltaT)
		I = self.integrator
		
		# derivative is difference in error / time since last update
		D = (error-self.last_error)/deltaT
		
		self.last_error = error
		self.timeOfLastCall = currentTime
		
		# return controll signal
		return self.Kp*P + self.Ki*I + self.Kd*D


if __name__ == '__main__':
  rospy.init_node('image_converter', anonymous=True)
  ic = image_converter()
  print('start')
  try:
    rospy.spin()
  except rospy.ROSInterruptException:
    print('exception')


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明基于ros框架和opencv颜色捕捉功能,实现机器人充当守门员
喜欢 (0)

您必须 登录 才能发表评论!

加载中……