【仿真】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,一经查实,立即删除!

相关文章

组合式api和选项式api该怎么选

Vue的组合式API(Composition API)和选项式API(Options API)在Vue.js框架中提供了两种不同的组件开发方式。下面我将从区别和联系、开发中如何选择两个方面进行详细解释。 区别 设计思想: 选项式API:基于组…

AI问答-医疗:什么是“手术报台”

手术报台并不是传统意义上的医疗工具或设备,而是一个与手术耗材追溯管理相关的系统或工具。以下是对手术报台的详细解释: 一、定义与功能 手术报台系统,如医迈德手术报台系统,是一款面向医院跟台人员的微信小程序。 它通过手术耗…

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

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

clang: ThreadSafetyAnalysis 可以实现静态检查

最近看ovs的代码,发现了这个功能,看着非常有必要使用,在代码编译阶段可以帮助发现同步问题 #if __has_feature(c_thread_safety_attributes) /* "clang" annotations for thread safety check.** OVS_LOCKABLE indicates that the…

SoftwareSerial库【学习】

SoftwareSerial.h 文件解析 这个头文件定义了用于 ESP8266 和 ESP32 的软件串口实现的接口和一些功能。下面是关键部分的详细解释: 1. 文件头部注释 /* SoftwareSerial.h - Implementation of the Arduino software serial for ESP8266/ESP32. ... */这是文件的版…

shell脚本if/else使用示例

if判断字符串是否为空实例 #!/bin/bashread -p "input string > " str if [ -z "$str" ] thenecho "str是空" elseecho "str非空" fiif判断整数是否为…

每日一学(1)

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

深度解析RocketMq源码-高可用存储组件(四)Dledger框架日志同步流程

1.绪论 在深度解析RocketMq源码-高可用存储组件(一) raft协议详解-CSDN博客 中讲过,raft协议中,日志同步主要有两个地方,一个是leader会跟follower同步数据,另一个是在新leader诞生的时候,会与…

6.浏览器缓存

上一篇👉: 浏览器存储 浏览器缓存 文章目录 浏览器缓存1. 浏览器缓存机制的理解初次加载资源强制缓存阶段协商缓存阶段服务器响应版本控制策略 2 浏览器资源缓存的位置Service Worker缓存Memory Cache(内存缓存)Disk Cache(磁盘缓…

更换Homebrew镜像源

Homebrew 是 macOS 上非常受欢迎的包管理工具,但有时由于网络问题,从默认源下载软件包可能会非常缓慢。为了解决这个问题,我们可以将 Homebrew 的源更换为国内的镜像,以提高下载速度。以下是更换 Homebrew 镜像源的通用步骤及错误…

【Pytorch实战教程】基于投影梯度下降(PGD)方法的对抗样本生成

文章目录 1. 总体介绍2. 完整代码3. 投影梯度下降(PGD)方法的详细介绍3.1. 背景3.2. PGD方法简介3.3. PGD攻击算法步骤3.4. PGD攻击的实现3.5. 代码解释3.6. 核心代码解释:4 补充说明x = inputs.detach()的详细解释1. 总体介绍 使用PyTorch实现基于投影梯度下降(Projected…

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原因:淘宝证书过期 解…

vue2面试题——指令

1. 如何自定义指令 全局指令:在main.js里面写 /* 全局自定义指令 */ // main.js文件 import Vue from vue import App from ./App.vue import router from ./router import store from ./storeVue.config.productionTip falseVue.directive(demo,{inserted: functi…

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

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

小公司全栈是归宿吗?

在软件开发领域,特别是在小公司或初创公司中,全栈开发者的角色确实相对普遍和重要。然而,说“全栈是归宿”可能过于绝对,因为每个开发者的职业路径和兴趣点都是不同的。 以下是关于全栈开发在小公司的一些考虑: 需求…

JS实现:计算不同时区的当地时间

国内的时间都以北京时间为准(即东八区的时间),如何计算同一时间下其它时区的当地时间呢? 通常的做法,是计算出时区差,然后进行加减。 还有另一种方法,就是先把本地时间转为 0时区的utc时间&…

如何使用代理 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…

使用 ADB 查看 Android 设备的 CPU 使用率(详解)

在 Android 开发和调试过程中,监控设备的性能数据至关重要。CPU 使用率是一个关键的性能指标,它能够帮助开发者识别应用的性能瓶颈和优化机会。本文将详细介绍如何使用 Android Debug Bridge (ADB) 查看设备的 CPU 使用率,并解释终端上各个参…