机器人制作开源方案 | 桌面级机械臂--应用设计

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

      机器视觉基础主要包含二维码识别颜色识别等。

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

1. 视觉二维码识别

      二维码的应用渗透到生活的方方面面,如手机购物、微信登录等,二维码常见的分类有矩阵式、堆叠式/行排式。具有代表性的矩阵式二维条码有Code One、Maxi Code、QR Code、 Data Matrix等;具有代表性的行排式二维条码有Code 16K、Code 49、PDF417等。

      二维码的使用分为:生成二维码、识别已生成的二维码。这里我们主要是识别已生成的二维码(矩阵式二维码)。

设计思路

      本实验主要是基于矩阵式二维码进行识别。QR码(Quick Response Code)是在正方形二维矩阵内通过黑白标识编码二进制位从而编码数据。

实现思路

      利用摄像头采集二维码信息,利用zbar库识别后把结果显示在屏幕上。

器材准备

      生成QR Code码(可以用在线编辑器生成)、摄像头。

      下面是为本实验准备的二维码:(当然大家也可以直接打开微信二维码进行识别)

操作步骤

第一步:连接电路。将摄像头与控制盒进行连接。

第二步:下载文末资料中的参考程序color_experiment_ws\src\qr_detection\scripts\QrCode_Detection.py:

#!/usr/bin/env python#!coding=utf-8#write by leo at 2018.04.26#function:#1, Get live_video from the webcam.#2, With ROS publish Image_info (to yolo and so on).#3, Convert directly, don't need to save pic at local.# import the necessary packagesimport simple_barcode_detectionimport zbarfrom PIL import Imageimport rospyfrom sensor_msgs.msg import Image as lllimport cv2import numpy as npfrom cv_bridge import CvBridge, CvBridgeErrorimport sysimport time# create a readerscanner = zbar.ImageScanner()# configure the readerscanner.parse_config('enable')font=cv2.FONT_HERSHEY_SIMPLEXcamera=cv2.VideoCapture(0)def webcamImagePub():# init ros_noderospy.init_node('webcam_puber', anonymous=True)img_pub = rospy.Publisher('webcam/image_raw', lll, queue_size=2)rate = rospy.Rate(20) # 5hzscaling_factor = 0.5bridge = CvBridge()if not camera.isOpened():sys.stdout.write("Webcam is not available!")return -1count = 0# loop until press 'esc' or 'q'while not rospy.is_shutdown():# get a frame and show(ret, frame) = camera.read()box = simple_barcode_detection.detect(frame)if np.all(box != None):min=np.min(box,axis=0)max=np.max(box,axis=0)roi=frame[min[1]-10:max[1]+10,min[0]-10:max[0]+10]#print roi.shaperoi=cv2.cvtColor(roi,cv2.COLOR_BGR2RGB)pil= Image.fromarray(frame).convert('L')width, height = pil.sizeraw = pil.tobytes()zarimage = zbar.Image(width, height, 'Y800', raw)scanner.scan(zarimage)for symbol in zarimage:print 'decoded', symbol.type, 'symbol', '"%s"' %symbol.datacv2.drawContours(frame, [box], -1, (0, 255, 0), 2)cv2.putText(frame,symbol.data,(20,100),font,1,(0,255,0),4)# resize the frameif ret:count = count + 1else:rospy.loginfo("Capturing image failed.")if count == 2:count = 0frame = 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)#            print '** start ***'rate.sleep()if __name__ == '__main__':try:webcamImagePub()except rospy.ROSInterruptException:pass#    except IndexError:#pass#    except VIDEOIOERROR:#pass#    except Unabletostopthestream:#passfinally:webcamImagePub()

 第三步:运行程序并查看效果。

打开终端,输入roslaunch qr_detection qr_detection_experiment.launch命令(见下图),等待程序的运行启动界面。

界面启动后,添加Image并设置其参数,设置成功后出现以下三幅图像画面。

图1
图2
图3

把QR code类型的二维码放置在摄像头下,稍后就会在界面上显示结果(如下图所示)。

2. 形状识别—识别圆形

实现思路

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

器材准备

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

操作步骤

第一步:连接电路,将摄像头与主机进行连接。(温馨提示:做实验时,大家可以灵活的把摄像头放置在圆形图片上方,以便于采集图形信息)

第二步:下载文末资料中的参考程序color_experiment_ws\src\shape_detection\scripts\shape_detection_victory.py:

#!/usr/bin/env python#!coding=utf-8import rospyfrom sensor_msgs.msg import Imageimport cv2from cv_bridge import CvBridgeimport numpy as np#red,green,blue[h,s,v]lower_blue=np.array([50,143,146])upper_blue=np.array([124,255,255])lower_red=np.array([0,200,55])upper_red=np.array([10,255,130])lower_green=np.array([40,43,46])upper_green=np.array([77,255,255])Video = cv2.VideoCapture(0)ret = Video.set(3, 640)   # 设置帧宽ret = Video.set(4, 480)   # 设置帧高font = cv2.FONT_HERSHEY_SIMPLEX   # 设置字体样式kernel = np.ones((5, 5), np.uint8)   # 卷积核def areaCal(contour):area = 0for i in range(len(contour)):area += cv2.contourArea(contour[i])return areadef talker():pub = rospy.Publisher('/tutorial/image', Image, queue_size=1)rospy.init_node('talker', anonymous=True)rate = rospy.Rate(30)bridge = CvBridge()#Video = cv2.VideoCapture(1)while not rospy.is_shutdown():if Video.isOpened() is True: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)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)   # 显示圆心位置#cv2.drawContours(img,contours,-1,(0,0,255),3)cv2.waitKey(3)pub.publish(bridge.cv2_to_imgmsg(frame, "bgr8"))rate.sleep()if __name__ == '__main__':try:talker()except rospy.ROSInterruptException:pass

 第三步:运行程序并查看效果。

打开终端,输入roslaunch shape_detection shape_detection_experiment.launch 命令(见下图), 等待程序的运行启动界面。

界面启动后,添加Image并设置其参数,设置成功后出现以下三幅图像画面。

图1
图2
图3

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

3. 颜色识别(红绿蓝)

实现思路

      摄像头采集红绿蓝的物品颜色后,利用开源视觉库进行识别,把结果显示在屏幕上。

颜色识别算法

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模型

      倒锥形模型:

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

H是色彩

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

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

③. RGB与HSV的联系

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

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

     v = max(r, g, b)

     由RGB到HSV的转换:

④.HSV色彩范围

操作步骤

第一步:连接电路。将摄像头与主机进行连接。

第二步:下载文末资料中的参考程序color_experiment_ws\src\color_detection\scripts\color_test_one.py:

#!/usr/bin/env python#!coding=utf-8#write by leo at 2018.04.26#function:#1, Get live_video from the webcam.#2, With ROS publish Image_info (to yolo and so on).#3, Convert directly, don't need to save pic at local.import rospyfrom sensor_msgs.msg import Imageimport cv2import numpy as npfrom cv_bridge import CvBridge, CvBridgeErrorimport sysimport timecap = cv2.VideoCapture(0)#lower_blue=np.array([50,143,146])#upper_blue=np.array([124,255,255])lower_blue=np.array([40,143,146])upper_blue=np.array([124,255,255])lower_red=np.array([0,200,55])upper_red=np.array([10,255,130])lower_green=np.array([40,43,46])upper_green=np.array([77,255,255])font = cv2.FONT_HERSHEY_SIMPLEXdef areaCal(contour):area = 0for i in range(len(contour)):area += cv2.contourArea(contour[i])return areadef webcamImagePub():# init ros_noderospy.init_node('webcam_puber', anonymous=True)# queue_size should be small in order to make it 'real_time'# or the node will pub the past_frameimg_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)rate = rospy.Rate(20) # 5hz# define picture to_down' coefficient of ratioscaling_factor = 0.5# the 'CVBridge' is a python_class, must have a instance.# That means "cv2_to_imgmsg() must be called with CvBridge instance"bridge = CvBridge()if not cap.isOpened():sys.stdout.write("Webcam is not available!")return -1count = 0# loop until press 'esc' or 'q'while not rospy.is_shutdown():# get a frame and showret, frame = cap.read()#       cv2.imshow('Capture', frame)# change to hsv modelhsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)#cv2.imshow("imageHSV",hsv)# get maskmask = cv2.inRange(hsv, lower_blue, upper_blue)#       cv2.imshow('Mask', mask)# detect blueres = cv2.bitwise_and(frame, frame, mask=mask)#        cv2.imshow('Result', res)#       cv2.imshow('SOURCE', frame)image,contours,hierarchv = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)blue_area=areaCal(contours)hsvs = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)masks = cv2.inRange(hsvs, lower_red, upper_red)ress = cv2.bitwise_and(frame, frame, mask=masks)images,contourss,hierarchvs = cv2.findContours(masks,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)red_area=areaCal(contourss)hsvss = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)maskss = cv2.inRange(hsvss, lower_green, upper_green)resss = cv2.bitwise_and(frame, frame, mask=maskss)imagess,contoursss,hierarchvss = cv2.findContours(maskss,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)green_area=areaCal(contoursss)print "blue=",blue_area,"red=",red_area,"green=",green_area,"the color is blue"if(areaCal(contours)>300):#print("the color is blue")#print "blue=",blue_area,"red=",red_area,"green=",green_area,"the color is blue"text = 'the color is blue'cv2.putText(frame, text, (10, 30), font, 1, (255, 0, 0), 2, cv2.LINE_AA, 0)             else :if(areaCal(contourss)>3500):#print ("Thered",areaCal(contours))#print "blue=",blue_area,"red=",red_area,"green=",green_area,"the color is blue red"text = 'the color is red'cv2.putText(frame, text, (10, 60), font, 1, (0, 0, 255), 2, cv2.LINE_AA, 0)                         else:if(areaCal(contoursss)>3500):#print "blue=",blue_area,"red=",red_area,"green=",green_area,"the color is blue green"text = 'the color is green'cv2.putText(frame, text, (10, 90), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)                                 else:qwer=0# resize the frameif ret:count = count + 1else:rospy.loginfo("Capturing image failed.")if count == 2:count = 0frame = 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()if __name__ == '__main__':try:webcamImagePub()except rospy.ROSInterruptException:pass#    except IndexError:#   pass#    except VIDEOIOERROR:#   pass#    except Unabletostopthestream:#   passfinally:webcamImagePub()

第三步:运行程序并查看效果。

打开终端,输入roslaunch color_detection color_detectioning.launch命令(见下图), 等待程序的运行启动界面。

界面启动后,添加Image并设置其参数,设置成功后出现以下三幅图像画面。

图一
图2
图3

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

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

蓝色物块检测环境
检测后返回的结果

大家也可以试着去放置红色、绿色物品(识别结果见下面两幅图)。

红色物块检测环境
检测后返回的结果
绿色物块检测环境
检测后返回的结果

4. 键盘控制运动

实现思路

      按下键盘上指定的键,实现底盘、大臂、小臂朝不同方向运动。

操作步骤

      第一步:下载文末资料中的参考程序color_experiment_ws\src\visual_recognition\arduino_program\keyboard_control_arm\keyboard_control_arm.ino:

/*_______________________________________________________________________________________________________________________________________________________【实验功能】ros中键盘控制机械臂运动。【实验接线】按照实验教程接线即可。【实验思路】上位机(树莓派)通过串口发布按键信息,下位机(Arduino)接收到信息后,进行简单数据处理,最后将处理后的数据转换为机械臂相应的动作。【实验操作】按照实验教程接线。将该程序下载到arduino开发板,接着启动上位机(树莓派)程序。完成后,按下键盘不同的按键,观察机械臂动作。键盘指令包含:u:控制转台左转       o:控制转台右转j:控制大臂前伸       l:控制转台后缩m:控制小臂上抬       >:控制小臂下降create :2020.7.17   By Boris.yuan_________________________________________________________________________________________________________________________________________*///DUE控制版需要启用USE_USBON或USE_NATIVE_USB,UNO不需要//#define USE_USBCON          //PAOGRAMMING PORT//#define USE_NATIVE_USB      //NATIVE USB PORT#define ActionDelayTimes 1500//#include <SoftwareSerial.h>#include <Servo.h>#include <ros.h>#include <ros/time.h>#include <geometry_msgs/Vector3.h>#define mySerial Serial1ros::NodeHandle   nh;void XYRun(double vx, double vy, double w);void messageCb( const geometry_msgs::Vector3& vel_cmd)   {XYSetVel(vel_cmd.x, vel_cmd.y, vel_cmd.z);}ros::Subscriber<geometry_msgs::Vector3> vel_cmd_sub("vel_cmd", &messageCb );geometry_msgs::Vector3 pose_message;ros::Publisher pose_feedback_pub("pose_feedback", &pose_message);geometry_msgs::Vector3 vel_message;ros::Publisher vel_feedback_pub("vel_feedback", &vel_message);int servo_port[4] = {10, 11, 12, 13};//x,y,z,afloat value_init[4] = {88, 88, 96, 86};//x,y,z,aconst int kMessagePubRate = 5;unsigned long message_pub_time = 0;const int kReadMotorDeltaT = 5;unsigned long position_read_time = 0;float current_x = 0, current_y = 0, current_a = 0;float current_vx = 0, current_vy = 0, current_va = 0;float sudu = 0.87;void setup(){delay(1000);mySerial.begin(115200);Serial.begin(57600);Bus_servo_angle_init(); delay(1500);nh.initNode();nh.subscribe(vel_cmd_sub);nh.advertise(pose_feedback_pub);nh.advertise(vel_feedback_pub);position_read_time = millis();message_pub_time = millis();}void loop(){if (millis() > position_read_time){XYread();position_read_time += kReadMotorDeltaT;}if (millis() > message_pub_time){pose_message.x = current_x;pose_message.y = current_y;pose_message.z = current_a;vel_message.x = current_vx;vel_message.y = current_vy;vel_message.z = current_va;pose_feedback_pub.publish(&pose_message);vel_feedback_pub.publish(&vel_message);message_pub_time += 1000.0 / kMessagePubRate;}nh.spinOnce();}

第二步:打开终端,输入roslaunch visual_recognition keyboard_control_arm.launch 命令(见下图), 等待程序的运行启动界面。

终端

第三步:尝试按下【u、o、j、l、m、.】观察运动,包括底盘左转、右转、大臂向前伸、大臂向后伸、小臂下降、小臂上升。(注意:字母均为小写;按键盘时,稍微有点间隔,给转动留时间)

键盘命令及含义表

5. 颜色识别与搬运

实现思路

      摄像头识别不同颜色的物块后,机械爪开始抓取把其搬运到不同的区域。

操作步骤

第一步:连接电路(见下图)。

第二步:下载文末资料中的参考程序color_experiment_ws\src\color_sorting\arduino_program\arm_driver\arm_driver.ino:

/*-----------------------------------------------------------------------------------------------------------------实验功能:【实现颜色分拣。】实验思路:【上位机(即树莓派)检测到颜色(红色、蓝色),通过串口将发送不同颜色物体的字符串。下位机Arduino Mega2560接收到字符串后,执行相应的动作指令。本实验中,上位机检测到红色后,通过串口发送“reds”,当下位机Arduino接收到“reds”后,将红色物体向左边搬运。同理,上位机检测到蓝色后,串口发送“blues”,下位机接收到“blues”后,将物体搬运到机械臂的右侧。 】实验操作:【将该程序下载到Arduino开发板后,按照教程启动上位机程序,将红色或者蓝色物体置于机械臂指定位置后,观察机械臂抓取不同颜色物体的动作是否与教程视频中相吻合。】实验接线(主要接线):机械臂通信口-------------(机械臂)电控箱机械爪(舵机)---------------(执行器)电控箱其他线路按照教材图片连接。Created 2020.7.16     By:Boris.yuan-----------------------------------------------------------------------------------------------------------------*/#include <Servo.h>#include <stdio.h>#include <string.h>#define CTL_BAUDRATE 115200 //总线舵机波特率#define SERIAL_PRINTLN Serial1#define SerialBaudrate 57600String receive_string = "";int catch_red_numbers=0;int catch_blue_numbers=0;unsigned long old_time = millis();unsigned long new_time = millis();void setup() {// put your setup code here, to run once:delay(1100);Serial.begin(SerialBaudrate);SERIAL_PRINTLN.begin(CTL_BAUDRATE);Bus_servo_angle_init();delay(2000);//   Arm_Catch_Red_Object();delay(1000);//   Arm_Catch_Blue_Object();delay(1000);}void loop() {// put your main code here, to run repeatedly:while(Serial.available()>0){new_time = millis();receive_string=Serial.readStringUntil('\n');if(receive_string=="reds"){catch_red_numbers++;new_time = millis();//      if(catch_red_numbers == 1)//      {//        //old_time = millis();//        receive_string="";//        //Arm_Catch_Red_Object();//      }//      if(catch_red_numbers == 2)//      {//        //old_time = millis();//        receive_string="";//        //Arm_Catch_Red_Object();//      }     if(catch_red_numbers == 1){old_time = millis();receive_string="";Arm_Catch_Red_Object();}if(new_time-old_time>25000){catch_red_numbers=0;}}if(receive_string=="blues"){catch_blue_numbers++;new_time = millis();//      if(catch_blue_numbers == 3)//      {//        //old_time = millis();//        receive_string="";//        //Arm_Catch_Blue_Object();//      }//      if(catch_blue_numbers == 3)//      {//        //old_time = millis();//        receive_string="";//        //Arm_Catch_Blue_Object();//      }           if(catch_blue_numbers == 1){old_time = millis();receive_string="";Arm_Catch_Blue_Object();}if(new_time-old_time>26000){catch_blue_numbers=0;}}receive_string = "";}}

 第三步:运行程序并查看效果。

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

打开第二个终端(shift+ctrl+T),输入rviz命令,等待rviz界面启动。

界面启动后,添加Image并设置其参数,设置成功后出现以下三幅图像画面。

图一

图2
图3

      放置物品(请把物品放置在摄像头可以采集到的区域),然后开始识别并进行搬运。下面以红色物品为例,当摄像头识别到红色物品后,机械爪把此物品搬运到一侧;当摄像头识别到蓝色物品时,把蓝色物品搬运到另一侧。这样就完成了按颜色识别物品并搬运的过程。

      提示:颜色识别搬运时,待识别的物品周边尽量不要有过多的杂色,否则会误识别颜色。

6. 颜色识别与追踪

实现思路

      摄像头采集到物品颜色后,随着该颜色物品的运动而缓慢移动,实现追踪效果。

器材准备

      本实验中需要用到的器材如下图所示,其中键盘、鼠标、红色物品可自行准备。

操作步骤

第一步:下载文末资料中的参考程序color_experiment_ws\src\color_tracking\arduino_program\color_tracking_Red_Things\color_tracking_Red_Things.ino:

/*-----------------------------------------------------------------------------------------------------------------实验功能:【实现颜色(红色)追踪】实验思路:【上位机实现颜色检测(红色物体),检测到红色物体后,提取红色物体的中心点坐标想(x,y),之后通过检测红色物体的面积大小进而判断红色物体距离摄像头的远近(本实验通过比较检测红色物体面积的当前值与设定红色物体面积的标定值进行比较,进而判断红色物体距离摄像头的远近),判断结束后,会将红色物体的中心点坐标(即(x,y))及红色物体距离摄像头远近的数值(本实验使用的是字符串)通过串口发送给下位机Arduino Mega2560,下位机接收到数据后,机械臂按照该数据进行相应的动作。】实验操作:【将该程序下载到Arduino开发板,之后按照教程启动树莓派例程,观察机械臂是否会跟随红色物体移动。】实验接线(主要接线):机械臂通信口-------------(机械臂)电控箱机械爪(舵机)---------------(执行器)电控箱其他线路按照教材图片连接。Created 2020.7.16     By:Boris.yuan-----------------------------------------------------------------------------------------------------------------*/#include <Servo.h>#include <stdio.h>#include <string.h>#define CTL_BAUDRATE 115200 //总线舵机波特率#define SERIAL_PRINTLN Serial1#define SerialBaudrate 57600#define RGB_LED_NUMBERS 3#define Bus_servo_Angle_inits 1500String receive_string = "";enum{RED=1,GREEN,BLUE,NONE_COLOR};int catch_red_numbers=0;int catch_blue_numbers=0;unsigned long old_time = millis();unsigned long new_time = millis();int value_move[3]={1500,1500,1500};int last_value[3]={0,0,0};void setup() {// put your setup code here, to run once:delay(1100);Serial.begin(SerialBaudrate);SERIAL_PRINTLN.begin(CTL_BAUDRATE);Bus_servo_angle_init();delay(2000);}void loop() {while(Serial.available()>0){new_time = millis();receive_string=Serial.readStringUntil('\n');if( (receive_string.length())<3 && (receive_string.length())>8 ){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="";       SpacePosition[0] = receive_string.indexOf('-');   for(int j=0;j<SpacePosition[0];j++) {numbers_left++;if(receive_string[j] == 'c'){receive_string[j]='0';}x_data+=receive_string[j];}if(receive_string == "back"){value_move[1] -=3;}else if(receive_string == "forward"){value_move[1] +=3;}         for(int k=SpacePosition[0]+1,m=0;k<receive_string.length();k++,m++) {numbers_right++;if(receive_string[k] == 'c'){receive_string[k]='0';}if(numbers_right>=4){;}else{y_data+=receive_string[k];}}   Data_one=x_data.toInt();Data_two=y_data.toInt();if(Data_one !=0 ){last_value[0] = Data_one;}if(Data_one ==0){Data_one = last_value[0];}if(Data_two !=0 ){last_value[2] = Data_two;}if(Data_two ==0){Data_two = last_value[2];}if( Data_one<=280 ){value_move[0] +=2;}if( Data_one>=368 ){value_move[0] -=2;}if( Data_two<=230-50 ){value_move[2] +=2;}if( Data_two>=250+50 ){value_move[2] -=2;}ArmServoTos(value_move[0],value_move[1],value_move[2],50);//delay(100);}  receive_string = "";}}

第二步:打开终端(Alt+ctrl+T),输入roslaunch color_tracking color_tracking_sth.launch 命令即可,见下图。

终端打开、电脑终端、机器人应用、机械臂应用、机器人视觉识别、机器视觉

打开第二个终端(shift+ctrl+T),输入rviz命令,等待rviz界面启动。

终端打开、电脑终端、机器人应用、机械臂应用、机器人视觉识别、机器视觉

界面启动后,添加Image并设置其参数,设置成功后出现以下三幅图像画面。

桌面级机械臂、机械臂、3自由度机械臂、小型桌面机械臂、桌面机械臂、桌面级协作机械臂
图1
图2
图3

第三步:放置物品(请把物品放置在摄像头可以采集到的区域),开始追踪。下面以红色物品为例,当摄像头识别到红色物品后,随着红色物品的运动缓慢移动,实现追踪效果。(注意:受硬件的影响,物品的移动速度要稍微慢一些)。

图1
图2 上位机采集的图片信息及画轮廓

程序源代码资料详见 桌面级机械臂-应用设计

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android学习之路(14) Context详解

一. 简介 在 Android 开发中、亦或是面试中都离不开四大组件的身影&#xff0c;而在创建或启动这些组件时&#xff0c;并不能直接通过 new 关键字后跟类名来创建实例对象&#xff0c;而是需要有它们各自的上下文环境&#xff0c;也就是本篇文章要讨论的 Context。 1.1 Contex…

ComPtr源码分析

ComPtr源码分析 ComPtr是微软提供的用来管理COM组件的智能指针。DirectX的API是由一系列的COM组件来管理的&#xff0c;形如ID3D12Device&#xff0c;IDXGISwapChain等的接口类最终都继承自IUnknown接口类&#xff0c;这个接口类包含AddRef和Release两个方法&#xff0c;分别用…

Qt6中使用Qt Charts

官方文档&#xff1a;Qt Charts 6.5.2 如果你是使用 CMake 构建的&#xff0c;则应在 CMakeLists.txt 中添加如下两行代码&#xff1a; find_package(Qt6 REQUIRED COMPONENTS Charts)target_link_libraries(mytarget PRIVATE Qt6::Charts) 其中 mytarget 为你的项目名称。一共…

aardio语言的通用数据表维护

import win.ui; /*DSG{{*/ var winform win.form(text"通用数据表维护";right617;bottom427;bgcolor15780518) winform.add( buttonAdd{cls"button";text"增加空行";left469;top40;right564;bottom80;flat1;z2}; buttonDel{cls"button&quo…

应用爆炸式增长,看F5如何做好网络安全防护

近年来&#xff0c;应用的数量呈现爆炸式增长。出行、支付、订单&#xff0c;开会&#xff0c;数字化的形式都在取代传统的消费&#xff0c;业务开展、工作内容都在发生着巨大的变化。随着数字化进程的加速&#xff0c;安全风险、安全问题暴露得越来越多。作为拥有强大安全基因…

【雷达原理】雷达信号级建模与仿真

目录 前言一、LFMCW信号概述1.1 优点1.2 缺点 二、LFMCW信号模型2.1 发射信号模型2.2 接收信号模型2.3 信号混频 三、MATLAB仿真3.1 仿真结果3.2 代码 四、参考文献 前言 雷达信号形式多种多样&#xff0c;按照雷达的体制进行分类&#xff0c;有脉冲雷达和连续波雷达。脉冲雷达…

Nacos docker实现nacos高可用集群项目

目录 Nacos是什么&#xff1f; Nacos在公司里的运用是什么&#xff1f; 使用docker构建nacos容器高可用集群 实验规划图&#xff1a;​编辑 1、拉取nacos镜像 2、创建docker网桥&#xff08;实现集群内的机器的互联互通&#xff08;所有的nacos和mysql&#xff09;&#x…

pytorch代码实现之空间通道重组卷积SCConv

空间通道重组卷积SCConv 空间通道重组卷积SCConv&#xff0c;全称Spatial and Channel Reconstruction Convolution&#xff0c;CPR2023年提出&#xff0c;可以即插即用&#xff0c;能够在减少参数的同时提升性能的模块。其核心思想是希望能够实现减少特征冗余从而提高算法的效…

WebDAV之π-Disk派盘 + 天悦日记

天悦日记是一款清爽简约的日记记录工具,通过天悦日记app随时随地快速写日记,更有智能数据统计分析报表,多端同步多种备份,本地备份和基于WebDAV协议的云端备份。跨平台使用,支持多设备、多平台无差别使用。天悦日记将每一天经历都清晰记录在手机,一目了然知道曾经的经历,…

Linux初探 - 概念上的理解和常见指令的使用

目录 Linux背景 Linux发展史 GNU 应用场景 发行版本 从概念上认识Linux 操作系统的概念 用户的概念 路径与目录 Linux下的文件 时间戳的概念 常规权限 特殊权限 Shell的概念 常用指令 ls tree stat clear pwd echo cd touch mkdir rmdir rm cp mv …

uboot顶层Makefile前期所做工作说明四

一. uboot顶层 Makefile文件 uboot 顶层 Makefile&#xff0c;就是 uboot源码工程的根目录下的 Makefile文件。 本文继续对 uboot顶层 Makefile的前期准备工作进行介绍。续上一篇文章内容的学习&#xff0c;如下&#xff1a; uboot顶层Makefile前期所做工作说明三_凌肖战的博…

DAMO-YOLO训练自己的数据集,使用onnxruntime推理部署

DAMO-YOLO训练自己的数据集&#xff0c;使用onnxruntime推理部署 DAMO-YOLO 是阿里达摩院智能计算实验室开发的一种兼顾速度与精度的目标检测算法&#xff0c;在高精度的同时&#xff0c;保持了很高的推理速度。 DAMO-YOLO 是在 YOLO 框架基础上引入了一系列新技术&#xff0…

Java的环境配置

目录 window系统安装java下载JDK配置环境变量JAVA_HOME 设置PATH设置CLASSPATH 设置测试JDK是否安装成功 Linux&#xff0c;UNIX&#xff0c;Solaris&#xff0c;FreeBSD环境变量设置流行JAVA开发工具使用 Eclipse 运行第一个 Java 程序 window系统安装java 下载JDK 首先我们…

爬虫进阶-反爬破解5(selenium的优势和点击操作+chrome的远程调试能力+通过Chrome隔离实现一台电脑登陆多个账号)

目录 一、selenium的优势和点击操作 二、chrome的远程调试能力 三、通过Chrome隔离实现一台电脑登陆多个账号 一、selenium的优势和点击操作 1.环境搭建 工具&#xff1a;Chrome浏览器chromedriverselenium win用户&#xff1a;chromedriver.exe放在python.exe旁边 MacO…

Unity汉化一个插件 制作插件汉化工具

我是编程一个菜鸟&#xff0c;英语又不好&#xff0c;有的插件非常牛&#xff01;我想学一学&#xff0c;页面全是英文&#xff0c;完全不知所措&#xff0c;我该怎么办啊...尝试在Unity中汉化一个插件 效果&#xff1a; 思路&#xff1a; 如何在Unity中把一个自己喜欢的插件…

新装Ubuntu系统的一些配置

背景&#xff1a; 最近办公要在Ubuntu系统上进行&#xff0c;于是自己安装了一个Ubuntu22.04系统&#xff0c;记录下新系统做的一些基本配置。 环境 &#xff1a; 系统&#xff1a;Ubuntu-22.04内核&#xff1a;6.2.0-26-generic架构&#xff1a;x86_64 一、 配置root密码 新…

Centos7 完全断网离线环境下安装MySQL 8.0.33 图文教程

Centos7 完全断网离线环境安装MySQL 8.0.33 图文教程 1.1前言1.2 下载离线安装包1.3 将下载好的离线安装包上传到Centos 7 服务器1.3.1 方式一:联网环境下可利用rz命令进行文件上传1.3.2 方式二:断网环境下使用 XFtp 等软件工具进行上传1.4 解压安装包1.5 执行安装脚本1.6 重…

Linux TCP和UDP协议

目录 TCP协议TCP协议的面向连接1.三次握手2.四次挥手 TCP协议的可靠性1.TCP状态转移——TIME_WAIT 状态TIME_WAIT 状态存在的意义&#xff1a;&#xff08;1&#xff09;可靠的终止TCP连接。&#xff08;2&#xff09;让迟来的TCP报文有足够的时间被识别并被丢弃。 2.应答确认、…

信息安全技术概论-李剑-持续更新

图片和细节来源于 用户 xiejava1018 一.概述 随着计算机网络技术的发展&#xff0c;与时代的变化&#xff0c;计算机病毒也经历了从早期的破坏为主到勒索钱财敲诈经济为主&#xff0c;破坏方式也多种多样&#xff0c;由早期的破坏网络到破坏硬件设备等等 &#xff0c;这也…

类和对象:构造函数,析构函数与拷贝构造函数

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器…