机器人制作开源方案 | 桌面级全向底盘--机器视觉

news2024/11/18 5:31:42

      机器视觉是人工智能正在快速发展的一个分支,简单说来机器视觉就是用机器代替人眼来做测量和判断。机器视觉系统是通过机器视觉产品(即图像摄取装置,分CMOS和CCD两种)将被摄取目标转换成图像信号,传送给专用的图像处理系统,得到被摄目标的形态信息,根据像素分布和亮度、颜色等信息,转变成数字化信号;图像系统对这些信号进行各种运算来抽取目标的特征,进而根据判别的结果来控制现场的设备动作。

机器视觉基础主要包含形状识别、颜色检测、颜色追踪、二维码识别等。

      机器视觉系统最基本的特点就是提高生产的灵活性和自动化程度,在一些不适于人工作业的危险工作环境或者人工视觉难以满足要求的场合,常用机器视觉来替代人工视觉。同时在大批量重复性工业生产过程中,用机器视觉检测方法可以大大提高生产的效率和自动化程度。接下来我们将结合机器视觉基础,基于开源的机器人平台,进行形状识别、颜色检测、颜色追踪的应用开发。

1. 形状识别-识别圆形

实现思路

      利用摄像头采集图片信息识别圆形,在界面上显示出圆的圆心坐标。

器材准备

      摄像头、红色和绿色两种圆形图(如下图所示)。

操作步骤

① 下载文末资料中的参考程序visual_experiment_ws\src\shape_detection\scripts\shape_detection_victory.py:

#!/usr/bin/env python

#!-*-coding=utf-8 -*-

import rospy

from sensor_msgs.msg import Image

import cv2

import numpy as np

from cv_bridge import CvBridge, CvBridgeError

import sys

import time

lower_blue=np.array([100,43,46])

upper_blue=np.array([124,255,255])

#lower_blue=np.array([14,143,80])

#upper_blue=np.array([23,255,200])

#lower_red=np.array([0,200,55])

#upper_red=np.array([10,255,130])

#lower_red=np.array([0,150,55])

#upper_red=np.array([10,255,130])

lower_red=np.array([0,43,46])

upper_red=np.array([10,255,255])

lower_green=np.array([40,43,46])

upper_green=np.array([77,255,255])

font = cv2.FONT_HERSHEY_SIMPLEX   # 设置字体样式

kernel = np.ones((5, 5), np.uint8)   # 卷积核

img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)

#cap = cv2.VideoCapture(0)

def areaCal(contour):

    area = 0

    for i in range(len(contour)):

        area += cv2.contourArea(contour[i])

    return area

def image_callback(msg):

           bridge = CvBridge()

           frame = bridge.imgmsg_to_cv2(msg, "bgr8")

           #cv2.imshow("source", frame)

           #ret, frame = Video.read()

           gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)   # 转换为灰色通道

           hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)   # 转换为HSV空间

           mask = cv2.inRange(hsv, lower_red, upper_red)   # 设定掩膜取值范围   [消除噪声]

           #mask = cv2.inRange(hsv, lower_green, upper_green)   # 设定掩膜取值范围 [消除噪声]

           opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)   # 形态学开运算 [消除噪声]

           bila = cv2.bilateralFilter(mask, 10, 200, 200)   # 双边滤波消除噪声 [消除噪声]

           edges = cv2.Canny(opening, 50, 100)   # 边缘识别 [消除噪声]

           mask_green = cv2.inRange(hsv,lower_green,upper_green)

           opening_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)

           bila_green = cv2.bilateralFilter(mask_green, 10, 200, 200)

           edges_green = cv2.Canny(opening_green, 50, 100)

           images,contourss,hierarchvs = cv2.findContours(edges_green,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

           image,contours,hierarchv = cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

           scaling_factor = 0.5

           print "area_red=",areaCal(contours),"area_green=",areaCal(contourss)

           if(areaCal(contours)>50):

             #circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=20, minRadius=20, maxRadius=500)

             circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=20, minRadius=0, maxRadius=0)

             if circles is not None:   # 如果识别出圆

               #print "I found the red circle"

               for circle in circles[0]:

                 x_red=int(circle[0])

                 y_red=int(circle[1])

                 r_red=int(circle[2])

                 cv2.circle(frame, (x_red, y_red), r_red, (0, 0, 255), 3)   # 标记圆

                 cv2.circle(frame, (x_red, y_red), 3, (255, 255, 0), -1)   # 标记圆心

                 text = 'circle' + 'x:   '+str(x_red)+' y:   '+str(y_red)

                 cv2.putText(frame, text, (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)   # 显示圆心位置

           if(areaCal(contourss)>1000):

             #circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=20, minRadius=20, maxRadius=500)

             circles = cv2.HoughCircles(edges_green, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=20, minRadius=0, maxRadius=0)

             if circles is not None:   # 如果识别出圆

               #print "I found the green circle"

               for circle in circles[0]:

                 x_red=int(circle[0])

                 y_red=int(circle[1])

                 r_red=int(circle[2])

                 cv2.circle(frame, (x_red, y_red), r_red, (0, 0, 255), 3)   # 标记圆

                 cv2.circle(frame, (x_red, y_red), 3, (255, 255, 0), -1)   # 标记圆心

                 text = 'circle' + 'x:   '+str(x_red)+' y:   '+str(y_red)

                 cv2.putText(frame, text, (10, 60), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)   # 显示圆心位置

           frame = cv2.resize(frame,None,fx=scaling_factor,fy=scaling_factor,interpolation=cv2.INTER_AREA)

           msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")

           img_pub.publish(msg)

           cv2.waitKey(3)

           '''

           rate = rospy.Rate(20) # 5hz

           scaling_factor = 0.5

           bridge = CvBridge()

           count = 0

           while not rospy.is_shutdown():

             if (True):

               count = count + 1

             else:

               rospy.loginfo("Capturing image failed.")

             if count == 2:

               count = 0

               frame = cv2.resize(frame,None,fx=scaling_factor,fy=scaling_factor,interpolation=cv2.INTER_AREA)

               msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")

               img_pub.publish(msg)

           rate.sleep()         

           '''

def webcamImagePub():

    rospy.init_node('webcam_puber', anonymous=True)

#    img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)

    rospy.Subscriber("/image_raw", Image, image_callback)

    rospy.spin()

if __name__ == '__main__':

    try:

        webcamImagePub()

    except rospy.ROSInterruptException:

        pass

    finally:

        webcamImagePub()


② 打开第一个终端(Ctrl+Alt+T)并输入:roslaunch astra_camera astra.launch 命令(见下图), 等待程序的运行。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

打开第二个终端(Ctrl+Shift+T)并输入命令:roslaunch shape_detection shape_detection_experiment.launch,等待界面的启动。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

③ 放置待识别的圆形图(请把物品放置在摄像头可以采集到的区域),就可以在界面上看到识别结果。如下图所示是分别识别出红色圆形、绿色圆形轮廓,并显示识别出圆心的中心坐标x、y的值。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

2. 颜色识别(红绿蓝)

实现思路

      当把物品放置在摄像头前时,摄像头采集到物品的颜色后,利用开源视觉库进行识别,然后在界面上显示识别颜色的结果(本实验中准备了红、绿、蓝三种物品)。

全向底盘、循迹小车、避障小车、机器视觉、颜色识别、slam导航、人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

颜色识别算法的核心原理

RGB和HSV彩色模型:

      数字图像处理通常采用RGB(红、绿、蓝)和HSV(色调、饱和度、亮度)两种彩色模型,RGB虽然表示比较至直观,但R、G、B数值和色彩三属性并没有直接关系,模型通道并不能很好的反映出物体具体的颜色信息,而HSV模型更符合我们描述和解释颜色的方式,使用HSV的彩色描述会更加直观。

RGB和HSV的区别:

①. RGB模型

三维坐标:

RGB:三原色(Red, Green, Blue)

      原点到白色顶点的中轴线是灰度线,r、g、b三分量相等,强度可以由三分量的向量表示。

      用RGB来理解色彩、深浅、明暗变化。

      色彩变化: 三个坐标轴RGB最大分量顶点与黄紫青YMC色顶点的连线

      深浅变化:RGB顶点和CMY顶点到原点和白色顶点的中轴线的距离

      明暗变化:中轴线的点的位置,到原点,就偏暗,到白色顶点就偏亮

②. HSV模型

倒锥形模型:

倒锥形模型、彩色锥形、全向底盘、循迹小车、避障小车、机器视觉、颜色识别、slam导航、人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源

这个模型就是按色彩、深浅、明暗来描述的。

H是色彩

S是深浅, S = 0时,只有灰度

V是明暗,表示色彩的明亮程度,但与光强无直接联系。

倒锥形模型、彩色锥形、全向底盘、循迹小车、避障小车、机器视觉、颜色识别、slam导航、人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源

③. RGB与HSV的联系

      从上面的直观的理解,把RGB三维坐标的中轴线立起来,并扁化,就能形成HSV的锥形模型了。

      但V与强度无直接关系,因为它只选取了RGB的一个最大分量。而RGB则能反映光照强度(或灰度)的变化。

      v = max(r, g, b)

      由RGB到HSV的转换:

样机方案-【R333】桌面级黑手底盘-4.机器视觉-全向底盘-循迹-避障-机器视觉-颜色识别-slam导航-Ros-人工智能-机器谱robotway-开源-图10

④.HSV色彩范围

样机方案-【R333】桌面级黑手底盘-4.机器视觉-全向底盘-循迹-避障-机器视觉-颜色识别-slam导航-Ros-人工智能-机器谱robotway-开源-图11

操作步骤

① 连接电路:请把摄像头与主机进行连接。

② 下载文末资料中的参考程序visual_experiment_ws\src\color_detection\scripts\color_test_one.py:

#!/usr/bin/env python

#!-*-coding=utf-8 -*-

import rospy

from sensor_msgs.msg import Image

from cv_bridge import CvBridge, CvBridgeError

import cv2

import numpy as np

import serial

import time

import sys

from std_msgs.msg import UInt16

from std_msgs.msg import String

img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)

lower_blue=np.array([100,43,46])

upper_blue=np.array([124,255,255])

lower_red=np.array([0,43,46])

upper_red=np.array([10,255,255])

lower_green=np.array([40,43,46])

upper_green=np.array([77,255,255])

font = cv2.FONT_HERSHEY_SIMPLEX

kernel = np.ones((5, 5), np.uint8)

def areaCal(contour):

    area = 0

    for i in range(len(contour)):

        area += cv2.contourArea(contour[i])

    return area

   

def image_callback(msg):

  bridge = CvBridge()

  img = bridge.imgmsg_to_cv2(msg, "bgr8")

  #cv2.imshow("source", img)

  hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

  mask_red = cv2.inRange(hsv,lower_red,upper_red)

  res = cv2.bitwise_and(img,img,mask=mask_red)

  scaling_factor = 0.5

#   cv2.imshow("res",res)

  image,contours,hierarchv = cv2.findContours(mask_red,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#   print   "red=",areaCal(contours)

  if (areaCal(contours)>5000):

#    print "red color"

    text_red = 'the color is red'

    cv2.putText(img, text_red, (10, 30), font, 1, (0, 0, 255), 2, cv2.LINE_AA, 0)

  mask_blue= cv2.inRange(hsv, lower_blue, upper_blue)

  res_yellow = cv2.bitwise_and(img,img,mask=mask_blue)

  image,contours,hierarchv = cv2.findContours(mask_blue,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

  if(areaCal(contours)>8000):

    text_blue = 'the color is blue'

#    print "blue color"

    cv2.putText(img, text_blue, (10, 60), font, 1, (255, 0, 0), 2, cv2.LINE_AA, 0)

  mask_green=cv2.inRange(hsv, lower_green,upper_green)

  res_green = cv2.bitwise_and(img,img,mask=mask_blue)

  image,contours,hierarchv = cv2.findContours(mask_green,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

  if (areaCal(contours)>5000):

    text_green = 'the color is green'

    cv2.putText(img, text_green, (10, 90), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)

#    print ("green color")

#   else:

#     print( "NONE COLOR" )

  frame = cv2.resize(img,None,fx=scaling_factor,fy=scaling_factor,interpolation=cv2.INTER_AREA)

  msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")

  img_pub.publish(msg)

  cv2.waitKey(3)

#   cv2.waitKey(1)

def main():

    rospy.init_node('image_listener',anonymous=True)

    #image_topic = "/camera/color/image_raw"

    #rospy.Subscriber("/camera/color/image_raw", Image, image_callback)

    rospy.Subscriber("/image_raw", Image, image_callback)

    rospy.spin()

if __name__ == '__main__':

    main()

 ③ 打开终端(Ctrl+Alt+T),输入roslaunch astra_camera astra.launch(见下图), 等待程序的运行。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

打开第二个终端(Ctrl+Shift+T)输入命令:roslaunch color_detection color_detectioning.launch,等待程序的运行。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

④ 界面启动后,放置物品(请把物品放置在摄像头可以采集到的区域),然后摄像头开始识别并在界面上显示识别结果。

下面以蓝色物品为例,当摄像头识别到蓝色物品后,在界面显示结果(the color is blue)。

机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

      大家也可以试着去放置红色、绿色物品,分别识别出的结果如下图所示。当摄像头识别到红色物品后,在界面显示结果(the color is red);当摄像头识别到绿色物品后,在界面显示结果(the color is green)。

检测到红色物品
检测到绿色物品

3. 颜色追踪

实现思路

      摄像头采集到红色物品后,通过串口通信来发布消息,黑手底盘订阅消息后进行相应的运动。

器材准备

      实验中需要用到的器材如下图所示(其中用红色的灭火器来代表待追踪的物体)。

机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

操作步骤

① 下载文末资料中Ros通信的参考程序visual_experiment_ws\src\color_tracking\scripts\ros_arduino_translation_test.py:

#!/usr/bin/env python

#!coding=utf-8

import rospy

from sensor_msgs.msg import Image

from cv_bridge import CvBridge, CvBridgeError

import cv2

import numpy as np

import serial

import time

import sys

from std_msgs.msg import UInt16

from std_msgs.msg import String

#lower_blue=np.array([50,143,146])

#upper_blue=np.array([124,255,255])

#lower_blue=np.array([14,143,80])

#upper_blue=np.array([23,255,200])

lower_blue=np.array([100,43,46])

upper_blue=np.array([124,255,255])

#lower_red=np.array([0,200,55])

#upper_red=np.array([10,255,130])

#lower_red=np.array([0,150,55])

#upper_red=np.array([10,255,130])

lower_red=np.array([0,43,46])

upper_red=np.array([10,255,255])

lower_green=np.array([40,43,46])

upper_green=np.array([77,255,255])

#ser = serial.Serial('/dev/ttyACM0', 57600, timeout=2.0) #2020.8.28 source value=0.5

img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)

data_pub= rospy.Publisher('Color_center_point',String,queue_size=20)

red_flag=0

blue_flag=0

image_flags = 1

cx_string=""

cy_string=""

cx_cy_string=""

send_data = ""

count=0

scaling_factor = 1.0   #2020.8.28 source value=0.5

def areaCal(contour):

    area = 0

    for i in range(len(contour)):

        area += cv2.contourArea(contour[i])

    return area

   

def image_callback(msg):

  global count,send_data

  bridge = CvBridge()

  frame = bridge.imgmsg_to_cv2(msg, "bgr8")

  #cv2.imshow("source", frame)

  hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)

  mask_red = cv2.inRange(hsv,lower_red,upper_red)

  res = cv2.bitwise_and(frame,frame,mask=mask_red)

  #cv2.imshow("res",res)

  image,contours,hierarchv = cv2.findContours(mask_red,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)  

  print "mianji=",areaCal(contours)

  if (areaCal(contours)>5000):

    if(areaCal(contours)>80000):

      send_data="back"

      #ser.write("back\n")

      #print "back"

    elif( areaCal(contours)<50000 and areaCal(contours)>5000 ):

      send_data="forward"

      #ser.write("forward\n")

      #print "forward"

    else:

      send_data="state"

    if len(contours) > 0:

      c = max(contours, key=cv2.contourArea)

      #print "c=",c

      cnt=contours[0]

      cv2.drawContours(frame, c, -1, (0, 0, 255), 3)#画轮廓

      #cv2.imshow("drawcontours",frame)

      M = cv2.moments(c)

      if M["m00"] !=0:

        cx = int(M['m10']/M['m00'])

        cy = int(M['m01']/M['m00'])

        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

        cv2.circle(frame, (cx,cy), 8, (0, 255, 0), -1)

        print "center=",center,"cx=",cx,"cy=",cy

        cx_string=str(cx)

        cy_string=str(cy)

        #cx_cy_string=(cx_string + "-" + cy_string + "\n").encode('utf-8')

        #cx_cy_string=(cx_string + "-" + cy_string + "-" + send_data + "\n").encode('utf-8')

        cx_cy_string=(cx_string + "-" + cy_string + "+" + send_data ).encode('utf-8')

        print (cx_cy_string)

        data_pub.publish(cx_cy_string)

      else:

        cx=0

        cy=0

    else:

      print "no red color something"

      #cv2.imshow("chanle", img)

#      if cv2.waitKey(1) & 0xFF == ord('q'):

#        #break

#        #continue

  if(image_flags==1):

    count = count+1

  else:

    rospy.loginfo("Capturing image failed.")

  if count == 2:

    count = 0

    frame = cv2.resize(frame,None,fx=scaling_factor,fy=scaling_factor,interpolation=cv2.INTER_AREA)

    msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")

    img_pub.publish(msg)

  cv2.waitKey(1)

def main():

    rospy.init_node('image_listener',anonymous=True)

#    img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)

    rospy.Subscriber("/image_raw", Image, image_callback)

    rospy.spin()

if __name__ == '__main__':

    main()


下载文末资料中控制黑手底盘运动的参考程序visual_experiment_ws\src\color_tracking\arduino_program\Color_Tracking_Arduino_Program\Color_Tracking_Arduino_Program.ino:

/*

* rosserial Publisher Example

* Prints "hello world!"

*/

#include <ros.h>

#include <std_msgs/String.h>

#include <Arduino.h>

#include <stdio.h>

#include <string.h>

#define CTL_BAUDRATE 115200 //总线舵机波特率

#define mySerial Serial2

#define SerialBaudrate 57600

#define RGB_LED_NUMBERS 3

#define Bus_servo_Angle_inits 1500

#define ActionDelayTimes 1500

//

#define wheel_speed_forward 0.08    //car forward speed

#define wheel_speed_back -0.08      //car back speed

#define wheel_speed_stop 0.0        //car stop speed

#define wheel_speed_left 0.1       //car turnleft speed

#define wheel_speed_right -0.1     //car turnright speed

#define wheel_speed_left_translation 0.08   //speed of car left translation

#define wheel_speed_right_translation -0.08 //speed of car right translation

char cmd_return[200];

String receive_string="hello";

ros::NodeHandle   nh;

void messageCb( const std_msgs::String &toggle_msg){

   receive_string=toggle_msg.data;

}

ros::Subscriber<std_msgs::String> sub("Color_center_point", &messageCb );

enum{FORWARD=1,BACK,LEFT,RIGHT,LEFT_TRANSLATION,RIGHT_TRANSLATION,STOP}; //the movement state of the car

void setup()

{

  delay(1100);

  Serial.begin(SerialBaudrate);

  mySerial.begin(CTL_BAUDRATE);  

  nh.initNode();

  nh.subscribe(sub);

}

void loop()

{

  if( (receive_string.length())<5 && (receive_string.length())>15 )

  {

     for(int i=0;i<1;i++){

     break;

     }

  }

    else{

       int SpacePosition[2] = {0,0};

       int Data_one = 0;

       int Data_two = 0;

       int numbers_left=0 ,numbers_right=0;

       char num_left[32] = {};

       char num_right[32] = {};

       String x_data="";

       String y_data="";

       String z_data="";

       String new_string = "";                                                                               

       SpacePosition[0] = receive_string.indexOf('-');

       x_data = receive_string.substring(0,SpacePosition[0]);

       //if(x_data.length()>=4){break;}

       new_string = receive_string.substring(SpacePosition[0]+1);

       SpacePosition[1] = new_string.indexOf('+');

       y_data = new_string.substring(0,SpacePosition[1]);

       z_data = new_string.substring(SpacePosition[1]+1);

      Data_one = x_data.toInt();

      Data_two = y_data.toInt();

      //if( (Data_one<=120) && (z_data =="state") ){Car_Move(LEFT_TRANSLATION);}

      if( (Data_one<=280) && (Data_one>=20)){Car_Move(LEFT_TRANSLATION);}

      else if ( (Data_one>=360) && (Data_one<=600) ){Car_Move(RIGHT_TRANSLATION);}

      else if( z_data == "forward" ){Car_Move(FORWARD);}

      else if( z_data == "back" ){Car_Move(BACK );}

      else {Car_Move(STOP);}

     

      receive_string = "";

      x_data="";

      y_data="";

      z_data="";

      new_string="";

    }  

  nh.spinOnce();

  delay(100);

}

② 打开终端(Alt+ctrl+T),输入roslaunch astra_camera astra.launch命令即可,见下图。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

打开第二个终端(shift+ctrl+T),输入roslaunch color_tracking camera_calibration.launch 命令,见下图。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

③ 移动灭火器,观察黑手底盘跟随灭火器运动的效果。

     【注意:请把灭火器放置在摄像头可采集到的区域内;受硬件的影响,移动灭火器的速度建议稍微慢点,可以先把灭火器移动到一个位置,然后观察底盘追踪的效果】

     我们可以在rviz界面里看到摄像头采集到红色目标的中心坐标及面积,供追踪使用(如下图所示)。

端口、终端、机器视觉、开源机器人项目、 人工智能小车、桌面级全向底盘、桌面级应用型底盘、四驱全向底盘、开源机器人、应用型底盘机械设计、全向移动底盘、开源机器人操作系统、麦克纳姆

同时可以观察到底盘进行追踪红色的灭火器,直到运动到靠近灭火器的地方。

程序源代码资料详见 桌面级全向底盘-机器视觉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1001711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷新单年发射纪录:SpaceX成功发射62次猎鹰9号火箭

SpaceX一直都致力于推进航天领域的发展。近日&#xff0c;该公司的猎鹰9号火箭再次刷新了单年发射纪录&#xff0c;目前已经成功发射了62次。除此之外&#xff0c;今年SpaceX还发射了一枚猎鹰火箭和一枚巨型火箭。马斯克表示&#xff0c;他的目标是实现每月10次猎鹰飞行&#x…

1800亿参数,支持中文,3.5万亿训练数据!开源类ChatGPT模型

这个必须推荐一下&#xff1a;1800亿参数&#xff0c;支持中文&#xff0c;3.5万亿训练数据&#xff01;开源类ChatGPT模型 阿联酋阿布扎比技术创新研究所&#xff08;Technology Innovation Institute&#xff0c;简称TII&#xff09;在官网发布了&#xff0c;目前性能最强的…

探索Redis速度之谜

Redis&#xff0c;作为一款高性能的内存数据库&#xff0c;一直以来都因其出色的速度而闻名。然而&#xff0c;Redis的速度之快究竟源自何处&#xff0c;其中隐藏着怎样的奥秘&#xff1f;在这篇博客中&#xff0c;我们将深入探索Redis速度之谜&#xff0c;揭开其快速性能背后的…

MySQL事务详细讲解

文章目录 什么是事务:1.事务有哪些特性2.并发事务会引起什么问题3.事务的隔离级别有哪些4.Read View在MVCC中如何工作Read View 有四个重要的字段使用 InnoDB 存储引擎的数据库表&#xff0c;它的聚簇索引记录中都包含下面两个隐藏列&#xff1a; 5.可重复读是怎么工作的6.读提…

基于模板快速开发

大家好 , 我是苏麟 , 今天说说如何快速开发 . 首先 , 我们要有一套基础模板 . 例如(整合了) : SpirngBoot SpringMVCMybatisMybatisPlusMySQLRedisSwaggerlombok 根据自己的业务场景整合相应的依赖. 第一步: 把初始化模板复制一份 第二步: 把模板改成项目名 第三步: 在IDEA中…

教你!如何使用Postman做接口测试

界面功能介绍 基础操作步骤&#xff1a; 新建请求集是否需要进行授权&#xff0c;如需要授权码&#xff0c;提前授权&#xff0c;避免接下来的每个接口授权编写请求脚本请求脚本&#xff0c;进行断言判断导出测试结果 postman断言语句 判断接口响应的状态码&#xff1a;Statu…

最后一块石头的重量 II【动态规划】

最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&am…

只有个体户执照,可以用来在抖音开店吗?抖店开通问题解答

我是王路飞。 在抖音开店的门槛&#xff0c;本身就是需要有营业执照的。 至于执照的类型&#xff0c;其实主要看商家自己。 如果你是新手商家&#xff0c;之前也没有怎么接触过电商行业&#xff0c;那么用个体执照在抖音开店足够用了&#xff0c;毕竟你要先入门&#xff0c;…

石器时代H5之恐龙宝贝游戏详细图文架设教程

前言 想体验卡通风格的休闲挂机回合制游戏吗&#xff1f;想体验满级VIP的尊贵吗&#xff1f;想体验榜一大佬的无敌寂寞吗&#xff1f;各种极品炫酷时装、坐骑、翅膀、宠物通通给你&#xff0c;就在石器时代 H5 之恐龙宝贝&#xff01; 本文讲解石器时代 H5 之恐龙宝贝架设教程…

iPhone苹果手机来电收到消息闪光灯闪烁通知提醒功能怎么开启?

iPhone苹果手机来电收到消息闪光灯闪烁通知提醒功能怎么开启&#xff1f; 1、打开iPhone苹果手机上的「设置」&#xff1b; 2、在苹果iPhone手机设置内找到并点击打开「辅助功能」&#xff1b; 3、在苹果iPhone手机辅助功能内找到并点击打开「音频/视觉」&#xff1b; 4、在苹…

九月份跳槽了,历经字节测开岗4轮面试,不出意外,还是被刷了....

大多数情况下&#xff0c;测试员的个人技能成长速度&#xff0c;远远大于公司规模或业务的成长速度。所以&#xff0c;跳槽成为了这个行业里最常见的一个词汇。 前几天&#xff0c;我看到有朋友留言说&#xff0c;他在面试字节的测试开发工程师的时候&#xff0c;灵魂拷问三小…

华为交换机:STP的详解和试验

前言 为了解决网络冗余链路所产生的问题,IEEE定义了802.1D协议,即生成树协议STP,利用生成树协议可以避免帧在环路中的增生和无限循环,生成树的主要思想是,当两个交换机之间存在多条链路时,通过一定的算法只激活其中最主要的一条链路,而将其他冗余链路阻塞掉变为备用链路,当主链…

Electron和vue3集成(可用于生产打包)

注意&#xff1a;我使用的是node版本16.20.1&#xff0c;因为electron-builder插件仅支持到node17、不支持node18&#xff0c;而node16是LTS版本&#xff0c;所以我选择16 1、初始化vue项目 npm install -g vue vue create 项目名称cd 项目目录 我尝试了用脚手架初始化方式&…

LVS负载均衡群集 1:NAT地址转换模式

文章目录 1. 群集概述1.1 什么是群集1.2 群集的分类1.2.1 负载均衡集群&#xff08;Load Balance Cluster&#xff09;1.2.2 高可用群集 (High Availbility Cluster)1.2.3 高性能运输群集 (High Performance Computer Cluster) 1.3 群集的目的 2. 负载均衡集群2.1 集群架构2.1.…

iOS pod repo push 报错 ld: file not found: libarclite_iphoneos.a 问题解决方案

背景 Xcode 升级 14.3 之后&#xff0c;在Xcode 运行项目会收到以下错误 File not found: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a 项目中可以通过以下方法解决编译错误&#xff0c;就是在 …

【论文精读】Hierarchical Text-Conditional Image Generation with CLIP Latents

Hierarchical Text-Conditional Image Generation with CLIP Latents 前言Abstract1 Introduction2 Method2.1 Decoder2.2 Prior 3 Image Manipulations3.1 Variations3.2 Interpolations3.3 Text Diffs 4 Probing the CLIP Latent Space5 Text-to-Image Generation6 Related W…

论文阅读-A General Language for Modeling Social Media Account Behavior

论文链接&#xff1a;https://arxiv.org/pdf/2211.00639v1.pdf 目录 摘要 1 Introduction 2 Related work 2.1 Automation 2.2 Coordination 3 Behavioral Language for Online Classification 3.1 BLOC alphabets 3.1.1 Action alphabet 3.1.2 Content alphabets 3.…

【C++】源文件.cpp和头文件.h分离编程

优势介绍 将C代码分为头文件&#xff08;.h&#xff09;和源文件&#xff08;.cpp&#xff09;的做法有以下几个好处&#xff1a; 模块化和代码组织&#xff1a;将函数和类的声明&#xff08;包括函数原型、类的成员和属性等&#xff09;放在头文件中&#xff0c;将函数和类的…

感知哈希-图片相似度分析

‍本文作者是360奇舞团开发工程师 引言 最近在做小程序换肤功能&#xff0c;因为不同主题色的小程序对应了不同图片库&#xff0c;项目内图片引用的方式又是线上URL地址配置形式&#xff0c;新加一套图片时&#xff0c;就要将图片和线上URL链接对比之后&#xff0c;配置到对应的…

linux日志轮转工具logrotate

目录 一、日志轮转工具的由来 二、如何去使用logrotate工具 2.1 使用cron驱动logrotate 2.2 使用systemd的timer驱动logrotate 三、logrotate命令的子命令解析 四、logrotate的配置 4.1 配置文件的位置 4.2 配置项的具体含义 一、日志轮转工具的由来 在Linux环境中能够…