【仿真】UR机器人手眼标定与实时视觉追踪(单目)

c565f3a591a95aa227708cc334d7abe5.png

这段代码实现了一个机器人视觉引导系统,主要功能包括:

  1. 连接仿真环境,控制UR机器人。

  2. 相机标定:

  • 使用棋盘格图案进行相机内参标定

  • 通过移动机器人采集多组图像

  • 使用calibrateCamera函数计算相机内参

手眼标定:

  • 采集机器人末端位姿和对应的棋盘格图像

  • 使用calibrateHandEye函数计算相机相对机器人末端的变换矩阵

视觉引导:

  • 实时检测棋盘格位置

  • 计算棋盘格相对相机的位姿

  • 结合手眼标定结果,计算机器人末端目标位置

  • 控制机器人移动到目标位置

交互式跟踪:

  • 在仿真器中实时检测棋盘格

  • 控制机器人末端跟随棋盘格移动

主要使用了OpenCV进行图像处理和位姿估计,scipy进行旋转矩阵计算,以及仿真环境的API进行机器人控制。

这个系统展示了如何将机器视觉与机器人控制结合,实现基于视觉的机器人引导。它涵盖了相机标定、手眼标定、视觉检测和机器人控制等机器人视觉系统的核心组件。

仿真脚本分析

这些脚本包含了 机器人控制、相机设置以及深度图像处理的功能。每个脚本都有其特定的用途,如机器人运动控制、视觉处理和深度图像处理。

1. 机械臂线程脚本lua

移动回调函数:用于设置机器人关节的位置。-- 如果关节是动态启用的,设置目标位置 -- 否则,直接设置关节位置。

移动到指定配置的函数:-- 获取当前关节位置-- 使用 sim.moveToConfig 函数进行运动规划。

线程主函数:-- 获取机器人的 6 个关节句柄,-- 设置运动参数(速度、加速度、跃度);-- 将角度值转换为弧度。

2. 机械臂自定义脚本python

仿真开始时初始化:导入必要的模块, 在 IK 插件环境中基于场景中机器人的运动学构建运动链和两个 IK 组(无阻尼和有阻尼){获取场景中的对象[基座 末端 目标],创建IK环境,创建无阻尼 IK 组,创建有阻尼 IK 组}

动作:IK求解器将机器人关节的运动与物理世界仿真同步。

3. 相机脚本lua

初始化:-- 获取深度相机对象,-- 添加深度视图,-- 获取彩色相机对象, -- 添加彩色视图.

4. 深度相机脚本

视觉传感器的回调函数,当有图像数据时被调用:-- 初始化返回值,-- 默认不触发其他处理,-- 初始化返回的数据包为空。-- 将深度图转换为工作图像,-- 对工作图像进行强度缩放{在保持图像最亮和最暗点不变的情况下,对图像进行均匀的强度调整,且这种调整不依赖于像素的深度信息。这通常用于简单的图像亮度标准化,以便后续的图像处理步骤(如特征检测、边缘识别等)能在更统一的条件下进行。},- 将处理后的工作图像应用回视觉传感器图像。

手眼标定程序

函数

1. 连接到仿真器

创建远程API实例,获取仿真器sim接口,在加载场景前停止当前模拟(前提已打开仿真器),加载场景,开始模拟。返回客户端和sim实例。

2. 获取对象句柄

获取机器人基座句柄,获取机器人末端执行器句柄,获取摄像头的彩色图句柄,获取深度图句柄,获取机器人目标点句柄。返回以上句柄。

3. 将摄像头的彩色图转换为opencv的图像格式

从摄像头获取图像(返回图像和分辨率),将获取的图像数据转换为numpy数组(分辨率x,分辨率y,3),将图像上下翻转以符合OpenCV的图像表示方式

4. 设置对象的位姿矩阵

5. 获取对象的位姿矩阵

创建一个4x4的单位矩阵,获取并设置对象的位姿矩阵,返回位姿矩阵。

6. 计算位姿误差

计算平移误差,计算转转矩阵之间的误差,将旋转误差转换为角度,返回旋转误差和平移误差。

7. 等待机器人移动到位(目标点,获取位姿函数,获取线速度和角速度函数)

记录开始时间,初始化旋转误差和平移误差为无穷大。进入循环:{计算已经过去的事件,检查是否超时如果超时返回失败和上一误差记录,等待一段时间,获取当前位姿,获取线速度和角速度,计算线速度的平均值,计算角速度的平均值,计算当前位姿和目标位姿之间的误差。如果旋转误差平移误差和速度都小于预设的阈值,则返回成功}

8. 设置目标位姿并等待移动到位

设置目标位姿,等待机器人移动到目标位姿并返回结果。

主程序

设置numpy打印选项,保留小数点后三位,不使用科学计数法

指定场景文件路径

设置 等待间隔时间、超时时间、接受的旋转误差范围、接受的平移误差范围、接受的停止速度

---------- 连接仿真器

连接到仿真器

获取句柄

---------- 设置视觉参数,例如停止条件、棋盘格大小等,并且执行了棋盘格角点的检测和显示结果

设置寻找角点的终止条件

设置相机校正的标志

设置棋盘格大小为10x7  

设置棋盘格大小 0.025米

创建存放对象点的数组 10x7x3

设置对象点的x和y坐标 70x2,z为0

---------- 获取相机的彩色图像,并转换为灰度图,然后检测棋盘格角点,并显示检测结果

获取彩色图像,获取图像的高度和宽度,将彩色图转换为灰度图,检测棋盘格角点,优化角点的位置。显示检测到的棋盘格角点。

cd7231b418b125ac2928e8bde40bf618.png

---------- 获取机器人末端执行器和摄像头当前的位姿,并且执行了位姿的调整与更新,展示了调整后的图像

获取机器人末端执行器当前的位姿,打印当前位姿,定义位姿的调整参数并进行位姿调整{定义平移调整参数 z移动负值,绕x旋转小角度},创建平移矩阵,计算旋转矩阵,更新位姿变换矩阵并计算末端目标位姿,设置机器人的目标位姿并等待直到达到目标位姿。

43829fddd8284a193e5d8e0139ddfec6.png

获取BGR图片反转RGB并显示

a514e9f1328ca5e40bb0577ab21c7891.png

重置机器人到初始位姿,再次获取BGR图片翻转为RGB并显示

8a877ac53c0cbfb12fcd9e12ae514cae.png03c5a9d5a399902da7e6aee5a95965f1.png

---------- 生成的变换矩阵

定义变换范围:x轴、y轴、z轴平移范围、绕x、y轴旋转的角度范围,z轴设置不旋转。

定义存储生成的矩阵列表,遍历平移范围和角度范围所有的可能组合{ 定义平移4X4矩阵,定义旋转4X4矩阵,根据欧拉角设置旋转矩阵的R[:3,:3],合并旋转和平移矩阵,添加到变换矩阵列表}

---------- 每个位姿变换矩阵尝试获取相应的图像并进行处理

初始化用于相机标定的列表:存储图像中检测到的角点,存储对象的世界坐标系中的点,存储末端执行器的位姿,存储捕获的图像。

遍历每个位姿变换矩阵尝试获取相应图像并进行处理

计算目标变换,设置模拟环境中的位姿并等待运动完成,如果没有返回值继续执行下一位姿。 获取当前摄像机BGR图像,获取末端执行器的位姿,将图像转换为灰度图,检测棋盘角点(如果没返回值继续下一位姿),打印位移和旋转误差,精确化角点位置,在图像中绘制检测到的角点并将BGR转换为RGB以显示。储存数据(图像中检测到的角点加入列表,对象在世界坐标系中的点加入列表,末端执行器位姿加入列表,BGR图像加入列表)

位移和旋转误差及图像

 0.0 6.4243363e-06

d76eb8877ca232a0e972252726c63eb1.png3b83a15b1d5b6f62408f73fab0ec57c4.png

0.0 3.3219899e-06

2d7635e603806ac00d87d89911e8b962.pnge2792e9455d59626d7e559521470dc7a.png

…… 很多图(略)

0.0 1.6598583e-06

c2f6089fb79e6bd898178c01ff4e1b5f.png2040005a5a43cd2d09a94245c0b5f7d3.png

---------- 根据收集的数据进行相机标定

输出相机的内参矩阵 

输出相机的畸变系数

---------- 初始化用于手眼标定的列表

对每个标定点,计算解算体位姿,并准备进行手眼标定:

使用solvePnP求解相机位姿,如果求解成功(绘制并显示坐标轴,计算目标相对于相机的位姿变换矩阵,将这次的位姿变换加入手眼标定的列表中

列表包括:

机器人手爪(或末端执行器)相对于机器人基座的旋转矩阵的集合。每个矩阵代表在不同的手爪位置或姿态下,手爪相对于基座的旋转关系。

机器人手爪相对于机器人基座的平移向量的集合。与旋转矩阵集合对应,每个向量代表在不同的手爪位置或姿态下,手爪相对于基座的平移关系。

目标物体(通常是一个已知图案,如棋盘格)相对于相机的旋转矩阵的集合。每个矩阵代表在不同的相机位置或姿态下,目标物体相对于相机的旋转关系。

目标物体相对于相机的平移向量的集合。与旋转矩阵集合对应,每个向量代表在不同的相机位置或姿态下,目标物体相对于相机的平移关系。

bca832aaad2defb6ca12ea221d33f9f1.pngbce016edebaa4d27892d493522263470.png5a669be8cb1247dc9b815edf3568ac14.png

4bf3b019c09713c50aa845e59f50a43e.png27028db593e989592b3b66857a950b4d.png6ea4cf833a2bdb77f2135ab8f92c6a50.png

……

(很多图)略

b13a466666a83d669eaea87a28f5006e.png

利用前面求得的各个位姿数据,通过cv2.calibrateHandEye函数计算工具末端点(Tool Center Point, TCP)在相机标系中的位姿。cv2.calibrateHandEye函数通过分析机器人手爪与标定物在机器人基座和相机视野中的多个不同位置和姿态下的相对变换,然后求解得到一个从相机坐标系到机器人手爪坐标系(或反向)的稳定且准确的空间变换关系,使得在执行精确任务(如精准抓取、目标跟踪等)时能够有效地利用视觉信息。

4473d035e0993364ea946b7fd246114f.png

将位姿从OpenGL坐标系转换到OpenCV坐标系。定义从opengl坐标系到opencv坐标系的变换矩阵,从仿真场景中获取并输出从机械臂末端到相机的位姿变换矩阵。

------------初始化另一系列位姿变换矩阵用于进一步的实验

定义平移和旋转范围,x,y的平移,z平移设定为0,绕x、y、z轴的旋转角度范围,初始化变换矩阵列表。根据范围生成所有可能得变换矩阵(创建平移矩阵,初始化旋转矩阵为单位矩阵,设置旋转矩阵的前三行三列为由欧拉角zyx构成的旋转矩阵,计算最终的变换矩阵,实现旋转后平移的效果。将变换矩阵添加到列表中)

定义两个特定的变换矩阵:定义棋盘坐标系向棋盘中心平移的变换矩阵、定义向后(z负向)平移的变换矩阵

获取初始目标框架位置:获取棋盘格基座句柄,获取棋盘格基坐标系相对机器人基座的位姿记为目标框架初始位姿。重置机器人末端执行器和棋盘初始位姿。

-----------对每一个位姿变换矩阵,尝试移动棋盘并获取图像

尝试移动棋盘到新的位姿,如果设置失败则跳过此次循环。获取相机图像,转换为灰度图,寻找棋盘格角点,如果未找到角点跳过此次循环。打印旋转和平移误差,对角点进行亚像素级精细化,使用solvePnP求解相机位姿,如果失败则跳过此次循环。 构造世界到相机的变换矩阵(初始化4x4齐次矩阵,设置旋转部分,设置平移部分,进一步调整至中心位置),可视化并显示结果。

计算新的末端执行器位置(从场景获取末端执行器在机器人基座标系下的位姿X相机在末端执行器下的位姿X棋盘格中心坐标系在相机坐标系下的位姿X向后移动的平移矩阵X相机坐标系在棋盘格中心坐标系下的位姿)

移动机器人末端执行器到新的计算位置。实现实时跟踪

获取并显示移动后的图像

1a3bfdad317a02507f1db750943766c9.png

重置机器人臂和棋盘到初始位姿

----------- 交互式跟踪棋盘仿真器中棋盘的动作

获取摄像机当前的BGR图像,将BGR图像转换为灰度图像,寻找棋盘格角点,如果没有找到角点,继续下一次循环,对角点坐标进行精细化,使用solvePnP求解相机位姿,如果求解失败,继续下一次循环,根据求解结果构造从世界坐标系到相机坐标系的变换矩阵,计算棋盘中心到棋盘原点的位姿变换,获取机械臂末端相对于基座的当前位姿,计算新的机器人臂位姿,使摄像头对准棋盘中心,设置机器人臂到新的位姿并等待移动完成。

fea5df7a665a158cb0c2abd46f9f2c41.png

交互式实时追踪棋盘格

实现了在仿真环境中对棋盘进行实时追踪的功能。通过不断捕获摄像头的图像,并识别出棋盘格角点的位置,进而计算出棋盘相对于摄像头的位姿变换。此后,根据预先通过手眼标定计算得到的机器人末端执行器到相机的变换关系,以及棋盘中心相对于世界坐标系的位姿变换,计算出机器人末端执行器应该达到的新位姿,并通过仿真器的API命令机器人移动到这个新位姿。通过这样的过程,机器人末端的摄像头能实时调整位置以紧随棋盘移动,实现了对棋盘的动态追踪。


作者陈晓永:智能装备专业高级工程师,软件工程师。机器人自动化产线仿真动画制作 

The End

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

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

相关文章

Qt小项目 | 实现迅雷设置界面

文章目录 一、手写代码实现迅雷设置界面 一、手写代码实现迅雷设置界面 使用Qt控件(如:QListWidget与QScrollArea等)与布局实现腾讯会议登陆界面。设置界面除基本设置界面外,其他界面都是以图片的形式嵌入到项目中并没有手写代码。…

每日一学(1)

目录 1、ConCurrentHashMap为什么不允许key为null? 2、ThreadLocal会出现内存泄露吗? 3、AQS理解 4、lock 和 synchronized的区别 1、ConCurrentHashMap为什么不允许key为null? 底层 putVal方法 中 如果key || value为空 抛出…

npm ERR! ..... reason: certificate has expired(淘宝镜像过期)

在执行npm install命令时,报错如下 npm ERR! request to https://registry.npm.taobao.org/babel/plugin-syntax-dynamic-import/download/babel/plugin-syntax-dynamic-import-7.8.3.tgz failed, reason: certificate has expired原因:淘宝证书过期 解…

【新闻】金融专业“免进”!私募巨头招聘涌现“新剧情”

A股市场在2024年逐渐出现新的运行特征,这不禁让部分主动投资的私募巨头公司重新登上招聘舞台。 但这一次,他们的招聘方向出现了新的变动。 有些机构有意识的为公司投研团队招聘“衔接”岗,有些则把重点放在了投研动作的交易层。 但这都不如…

如何使用代理 IP 防止多个 Facebook 帐户关联 - 最佳实践

在社交媒体被广泛应用的今天,Facebook作为全球最大的社交网络平台之一,面临着很多挑战,其中之一就是用户行为的管理和安全。 为了防止多个账户之间的关联和滥用,Facebook需要采取一系列措施,其中包括使用静态住宅代理…

云计算运维工程师的突发状况处理

云计算运维工程师在应对突发的故障和紧急情况时,需要采取一系列迅速而有效的措施来最小化服务中断的时间并恢复系统的稳定性。 以下是一些关键步骤和策略: 快速响应: 立即识别并确认故障的性质和范围。通知团队成员和相关的利益相关者,确保所有人了解当前情况。故障诊断:…

【论文阅读】-- MultiStream:探索分层时间序列的多分辨率流图方法

MultiStream: A Multiresolution Streamgraph Approach to Explore Hierarchical Time Series 摘要1 引言2相关工作2.1 堆叠图和流图可视化2.2 时间序列的层次结构2.3 交互技术 3 需求分析4 视觉映射和功能4.1 设计原理总结4.2 概述4.3 多分辨率视图4.4 控制器4.5 层次管理器 5…

探索ChatGPT在程序员日常工作的多种应用

引言 在现代科技迅猛发展的今天,人工智能的应用已经深入到我们生活和工作的各个方面。作为程序员,我们时常面临大量繁杂的任务,从代码编写、错误调试到项目管理和团队协作,每一项都需要花费大量的时间和精力。近年来,…

基于信息论的高动态范围图像评价算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于信息论的高动态范围图像评价算法matlab仿真,利用一种自然图像的概率模型对图像的熵与成像动态范围之间的关系进行了数值模拟,得到了具有普遍意义上…

【数据库】Oracle安装报错(口令设置问题)

目录 一、问题场景: 二、问题描述 三、原因分析: 四、解决方案: 方法一: 方法二: 一、问题场景: Oracle安装 二、问题描述 Oracle安装意外中断导致【口令管理】用户没有取消勾选/修改密码 三、原因…

mybatis中动态sql语句like concat(“%“,#{xm},“%“)

1、动态SQL是一种可以根据不同条件生成不同SQL语句的技术,随着用户输入或外部条件变化而变化的SQL语句 2、SQL语句中的like模糊查询 xm like %小米%,但开发中经常用到 xm like concat("%",#{xm},"%"),可以防止sql注入…

程序员必备的ChatGPT技巧:从代码调试到项目管理

近年来,随着人工智能技术的迅猛发展,ChatGPT作为一种强大的对话式AI工具,已经广泛应用于各个领域。而对于程序员来说,ChatGPT不仅可以帮助他们解决编程中的各种问题,还能在项目管理中发挥重要作用。本篇博客将详细介绍…

探索小众爱好:打造个人韧性与特色之路

在这个信息爆炸的时代,我们很容易陷入“千篇一律”的漩涡中,无论是生活方式还是兴趣爱好,似乎都趋向于某种“流行”或“热门”。然而,真正的个性与魅力,往往来源于那些不为大众所知的小众爱好。今天,我想和…

2024 最新运营小工具 API 推荐,助力高效工作

在当今数字化运营的时代,各种高效便捷的 API 服务成为了企业和个人提升运营效率、获取精准数据的得力助手。无论是进行市场调研、拓展业务,还是优化网络资源配置,都离不开这些强大的工具。本文将为您详细介绍一系列实用的运营小工具 API 服务…

教你如何一键高效下载视频号直播视频

在当今视频号直播盛行的时代,错过精彩直播内容再也不是遗憾!地瓜网络技术倾情推出“视频号直播视频下载器”,为您捕捉每一个直播瞬间。本文将简明扼要地指导您如何利用这款神器下载视频号直播与回放视频,让超清MP4视频轻松入库&am…

SQL实现UUIDv7

当我们选择数据库的主键类型时,通常会考虑自增数字或者 UUID。但是这两种类型都有优缺点,自增字段简单有序,性能良好,最大的问题是无法保证全局唯一性,分布式场景受限;UUID 具有全局唯一性,适合…

react学习——17react中todoList案列

1、项目目录 2、App.js //创建“外壳”组件APP import React, {Component} from "react"; //引入Header组件 import Header from "./components/Header"; //引入List组件 import List from "./components/List"; //引入Footer组件 import Foot…

计算机视觉全系列实战教程 (十四):图像金字塔(高斯金字塔、拉普拉斯金字塔)

1.图像金字塔 (1)下采样 从G0 -> G1、G2、G3 step01:对图像Gi进行高斯核卷积操作(高斯滤波)step02:删除所有的偶数行和列 void cv::pyrDown(cv::Mat &imSrc, //输入图像cv::Mat &imDst, //下采样后的输出图像cv::Si…

切线与切平面的可视化

切线与切平面的可视化 flyfish 切线的可视化 import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation, PillowWriter# 定义一个简单的一元函数,例如 f(x) x^2 def func(x):return x**2# 计算函数的导数 def deriva…

SpringBoot使用AutoConfigure实现依赖库自动导入配置

我们知道导入配置有两种,一种是Value,一种是ConfigurationProperties,将对应的类标记为Component即可导入。但是被注解标识的类创建Bean有一个前提,只对启动类所在的包路径下的所有带有Component等注解的类才会创建Bean。如果我们…