草庐IT

使用树莓派4b和OpenCV做机械臂夹取

Wood-S 2023-04-21 原文

文章目录


前言

 本人第一次在csdn上发技术类文章,原谅在此多说一些废话。项目是自己的毕设,比较简单还望不要见笑,如果发现有什么问题欢迎指正。发文章的目的一方面是希望用自己微薄的能力的帮助有需要的人,另一方面想要记录下自己一步一步走过的痕迹,我不知道自己还能走多久,但只要我还在做这些东西就会记录下来,一起努力前进吧。

一、基本功能

主控采用的是树莓派4b,机械臂采用的是社团现成的幻尔机械臂,因为用不到六自由度所以把旋转机械手的舵机拆了下来,摄像头用的是淘宝买的树莓派摄像头20块左右,还买了支架和补光灯用来架设摄像头,夹取平台是自己建模用3d打印机打出来的。

基本功能就是在有物块在平台上时机械臂会自动夹取物体放置在指定位置,主要用到的就是OpenCV的一些库函数和像素点坐标转换一些简单数学运算以及舵机的控制。

二、主要代码

在写代码实现功能之前要先安装好树莓派的一些库,有以下几个东西需要安装好或调试好,安装好OpenCV的库(当时我搞了好长时间),开启摄像头功能,要能用摄像头显示视频,熟悉树莓派的一些基本使用,像是gpio,i2c之类的。

1.图像处理部分

写代码之前一些库的引用

import RPi.GPIO as GPIO
import cv2 as cv
import time
import math
import numpy as np

具体代码,其中摄像头的画面进行了一些截取,只显示放置平台部分方便后续处理,得到的图片坐标是物块在截取图片中以左上角为起点的像素点坐标,我采用的的等比缩放的方法得到实际坐标,即画面尺寸和实际尺寸之间有一定比例,后续要想得到机械臂坐标系坐标还要进行进一步转化。

我的像素点坐标获取借鉴了另一位博主的文章OpenCV-Python学习笔记(使用opencv识别物体的位置,找到中心点位)_pd很不专业的博客-CSDN博客_opencv识别物体并输出坐标点

​
 #获取视频物体坐标
    cap = cv.VideoCapture(0)#选择摄像头
    
    ret,frame = cap.read()
    
    zero = frame[115:365,195:445]#截取画面尺寸
    
    cv.imwrite("tupian.jpg",zero)#存储图片
    zero0 = cv.imread("/home/pi/Desktop/tupian.jpg",1)
    
    zero1 = cv.GaussianBlur(zero0,(5,5),0)#高斯滤波

    zero2 = cv.cvtColor(zero1,cv.COLOR_BGR2GRAY)#颜色空间转换

    ret,zero3 = cv.threshold(zero2,110,255,cv.THRESH_BINARY_INV)#设置阈值,二值化处理

    kai0 = np.ones((5,5),np.uint8)
    zero4 = cv.morphologyEx(zero3,cv.MORPH_OPEN,kai0,iterations=3)#开运算
    
    
    #判断是否有物体
    if(np.mean(zero4)>0):
        print("object")
        
        contours,hierarchy = cv.findContours(zero4,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)#轮廓拟合
        
        cnt0 = contours[0]

        rect0 = cv. minAreaRect(cnt0)
        box0 = cv.boxPoints(rect0)
        box0 = np.int0(box0)
        zero5 = cv.drawContours(zero0,[box0],0,(0,0,255),3)#画矩形框

        M0 = cv.moments(cnt0)# 计算第一条轮廓的各阶矩,字典形式
        center_x0 = int(M0['m10']/M0['m00'])
        center_y0 = int(M0['m01']/M0['m00'])
        cv. circle(zero0,(center_x0,center_y0),7,128,-1)#绘制中心点
        str0 = '(' +str(center_x0)+',' +str(center_y0)+')'#把坐标转化为字符串
        cv.putText(zero0,str0,(center_x0-50,center_y0+40),cv.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2,cv.LINE_AA)#坐标点位绘制在图片上
        print(center_x0,center_y0)#输出像素点坐标

#没有物体输出
    else:
        print("No object")
        
    
    #关闭摄像头
    cap.release()
    cv.destroyAllWindows()

​

中间的转动角度计算与每个人的机械臂夹取方式与运动轨迹规划有关,且本人并没有学过机器人运动学相关知识这部分代码就不展示了,当时看了另一篇博客从中得到启发延伸到自己5自由度的机械臂。

机械臂转动角度计算_AI视觉网奇的博客-CSDN博客_机械臂关节角度

2.舵机控制部分

原先的想法是用舵机驱动板PCA9685来驱动舵机,好处就是只需要用i2c通信就可以输出16路可控pwm,但由于在树莓派上下载的库始终效果不好,而且源码不好修改最终放弃了,值得一提的是因为操作不当还把树莓派的电源芯片烧了,好在最后修好了。

PCA9685

 最后只能用树莓派引脚输出PWM和外接稳压电源来控制舵机,发送完pwm之后要进行消抖要不然数字舵机会不停抖动,由于代码过长且许多都是重复只有参数不同,所以只展示一部分。

GPIO.setmode(GPIO.BOARD)#GPIO采用BOAED模式
GPIO.setwarnings(False)#清除报错
#设置引脚
pins_0 = 12     #GPIO.1云台
pins_1 = 16     #GPIO.4下关节
pins_2 = 18     #GPIO.5上关节
pins_3 = 22     #GPIO.6调整关节
pins_4 = 32     #GPIO.26夹取关节

#引脚为输出模式
GPIO.setup(pins_0,GPIO.OUT)
GPIO.setup(pins_1,GPIO.OUT)
GPIO.setup(pins_2,GPIO.OUT)
GPIO.setup(pins_3,GPIO.OUT)
GPIO.setup(pins_4,GPIO.OUT)

#设置PWM频率为50Hz
pwm0 = GPIO.PWM(pins_0,50)
pwm1 = GPIO.PWM(pins_1,50)
pwm2 = GPIO.PWM(pins_2,50)
pwm3 = GPIO.PWM(pins_3,50)
pwm4 = GPIO.PWM(pins_4,50)

#初始/无动作姿态
pwm0.start(6.55)
pwm1.start(10.23)
pwm2.start(4.077)
pwm3.start(3.56)
pwm4.start(5)
time.sleep(0.2)#消抖
pwm0.ChangeDutyCycle(0)
pwm1.ChangeDutyCycle(0)
pwm2.ChangeDutyCycle(0)
pwm4.ChangeDutyCycle(0)
time.sleep(1)

 实物图

还有许多功能可以改进,譬如多颜色识别等等,由于后续还有考试需要准备所以暂时只能做到这里。

有关使用树莓派4b和OpenCV做机械臂夹取的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐