基于halcon的眼在手外(Eye-to-Hand)标定

前言

        上个月写了一个《基于halcon的眼在手上(Eye-in-Hand)标定》的文章,通过官方的示例代码进行了简单的叙述,想学习的小伙伴可以点击链接进行学习。之前博主认为眼在手上(Eye-in-Hand)的案例更多,或者说是使用场景更多的。但是,最近在学习机械臂的运动规划方向的内容后,发现对于机械臂避障这一块,眼在手上的实施方式是不太可能实现避障的。主要问题在于,眼在手上这种方式,只能看到机械臂前端的物体,而忽略机械臂周围的物体,没有周围物体的位置,那么机械臂在运动过程中,就难以保证机械臂不会碰撞。而眼在手外则可以看到机械臂和机械臂周围的物体,减小机械臂与周围物体碰撞的概率。

        (emmm。。这里得提一下,对机械臂的运动规划这一部分内容通常是在Moveit!中进行的,当然肯定会有在该平台下的手眼标定方案,需要的小伙伴请自行学习。由于我感觉halcon的手眼标定精度是不错的,所以还是记录一下啦~)

halcon示例代码

halcon示例代码

* 
* This example explains how to use the hand eye calibration for the case where
* the camera is stationary with respect to the robot and the calibration
* object is attached to the robot arm.
* In this case, the goal of the hand eye calibration
* is to determine two unknown poses:
* - the pose of the robot base in the coordinate system
*   of the camera (BaseInCamPose).
* - the pose of the calibration object in the coordinate system of the
*   tool (CalObjInToolPose)
* Theoretically, as input the method needs at least 3 poses of the
* calibration object in the camera coordinate system and the corresponding
* poses of the robot tool in the coordinate system of the
* robot base. However it is recommended
* to use at least 10 Poses.
* The poses of the calibration object are obtained from images of the
* calibration object recorded with the stationary camera.
* The calibration object is moved by the robot with respect to the camera.
* To obtain good calibration results, it its essential to position
* the calibration object with respect to the camera so that the object appears
* tilted in the image.
* After the hand eye calibration, the computed transformations are
* extracted and used to compute the pose of the calibration object in the
* camera coordinate system.
dev_update_off ()
* Directories with calibration images and data files
ImageNameStart := '3d_machine_vision/hand_eye/stationarycam_calib3cm_'
DataNameStart := 'hand_eye/stationarycam_'
NumImages := 17
* Read image
read_image (Image, ImageNameStart + '00')
get_image_size (Image, Width, Height)
* Open window
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_set_line_width (2)
dev_set_draw ('margin')
dev_display (Image)
* Set font
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* Load the calibration plate description file.
* Make sure that the file is in the current directory,
* the HALCONROOT/calib directory, or use an absolut path
CalTabFile := 'caltab_30mm.descr'
* Read the initial values for the internal camera parameters
read_cam_par (DataNameStart + 'start_campar.dat', StartCamParam)
* Create the calibration model for the hand eye calibration
create_calib_data ('hand_eye_stationary_cam', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, [], StartCamParam)
set_calib_data_calib_object (CalibDataID, 0, CalTabFile)
set_calib_data (CalibDataID, 'model', 'general', 'optimization_method', 'nonlinear')
disp_message (WindowHandle, 'The calibration data model was created', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* Start the loop over the calibration images
for I := 0 to NumImages - 1 by 1read_image (Image, ImageNameStart + I$'02d')* Search for the calibration plate, extract the marks and the* pose of it, and store the results in the calibration data model of the* hand-eye calibrationfind_calib_object (Image, CalibDataID, 0, 0, I, [], [])get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, I)get_calib_data_observ_points (CalibDataID, 0, 0, I, RCoord, CCoord, Index, CalObjInCamPose)* Visualize the extracted calibration marks and the estimated pose (coordinate system)dev_set_color ('green')dev_display (Image)dev_display (Caltab)dev_set_color ('yellow')disp_cross (WindowHandle, RCoord, CCoord, 6, 0)dev_set_colored (3)disp_3d_coord_system (WindowHandle, StartCamParam, CalObjInCamPose, 0.01)* Read pose of tool in robot base coordinates (ToolInBasePose)read_pose (DataNameStart + 'robot_pose_' + I$'02d' + '.dat', ToolInBasePose)* Set the pose tool in robot base coordinates in the calibration data modelset_calib_data (CalibDataID, 'tool', I, 'tool_in_base_pose', ToolInBasePose)* Uncomment to inspect visualization
*     disp_message (WindowHandle, 'Extracting data from calibration image ' + (I + 1) + ' of ' + NumImages, 'window', 12, 12, 'black', 'true')
*     disp_continue_message (WindowHandle, 'black', 'true')
*     stop ()
endfor
disp_message (WindowHandle, 'All relevant data has been set in the calibration data model', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* Check the input poses for consistency
check_hand_eye_calibration_input_poses (CalibDataID, 0.05, 0.005, Warnings)
if (|Warnings| != 0)* There were problem detected in the input poses. Inspect Warnings and* remove erroneous poses with remove_calib_data and remove_calib_data_observ.dev_inspect_ctrl (Warnings)stop ()
endif
* Perform hand-eye calibration
* Internally before performing the hand-eye calibration the cameras are calibrated
* and the calibrated poses of the calibration object in the camera are used.
dev_display (Image)
disp_message (WindowHandle, 'Performing the hand-eye calibration', 'window', 12, 12, 'black', 'true')
calibrate_hand_eye (CalibDataID, Errors)
* Query the error of the camera calibration
get_calib_data (CalibDataID, 'model', 'general', 'camera_calib_error', CamCalibError)
* Query the camera parameters and the poses
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
* Get poses computed by the hand eye calibration
get_calib_data (CalibDataID, 'camera', 0, 'base_in_cam_pose', BaseInCamPose)
get_calib_data (CalibDataID, 'calib_obj', 0, 'obj_in_tool_pose', ObjInToolPose)
try* Store the camera parameters to filewrite_cam_par (CamParam, DataNameStart + 'final_campar.dat')* Save the hand eye calibration results to filewrite_pose (BaseInCamPose, DataNameStart + 'final_pose_cam_base.dat')write_pose (ObjInToolPose, DataNameStart + 'final_pose_tool_calplate.dat')
catch (Exception)* Do nothing
endtry
* Display calibration errors of the hand-eye calibration
disp_results (WindowHandle, CamCalibError, Errors)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* For the given camera, get the corresponding pose indices and calibration object indices
query_calib_data_observ_indices (CalibDataID, 'camera', 0, CalibObjIdx, PoseIds)
* Compute the pose of the calibration object in the camera coordinate
* system via calibrated poses and the ToolInBasePose and visualize it.
for I := 0 to NumImages - 1 by 1read_image (Image, ImageNameStart + I$'02d')* Obtain the pose of the tool in robot base coordinates used in the calibration.* The index corresponds to the index of the pose of the observation object.get_calib_data (CalibDataID, 'tool', PoseIds[I], 'tool_in_base_pose', ToolInBasePose)dev_display (Image)* Compute the pose of the calibration plate with respect to the camera* and visualize itcalc_calplate_pose_stationarycam (ObjInToolPose, BaseInCamPose, ToolInBasePose, CalObjInCamPose)dev_set_colored (3)disp_3d_coord_system (WindowHandle, CamParam, CalObjInCamPose, 0.01)Message := 'Using the calibration results to display the'Message[1] := 'coordinate system in image ' + (I + 1) + ' of ' + NumImagesdisp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')if (I < NumImages - 1)disp_continue_message (WindowHandle, 'black', 'true')stop ()endif
endfor
* Clear the data model
clear_calib_data (CalibDataID)
* 
* After the hand-eye calibration, the computed pose
* BaseInCamPose can be used in robotic grasping applications.
* To grasp an object with the robot, typically, its pose
* with respect to the camera is determined (which
* is simulated here by setting the object's pose to the
* pose of the calibration object)
ObjInCamPose := CalObjInCamPose
* If the tool coordinate system is placed at the gripper
* and an object detected at ObjInCamPose shall be grasped,
* the pose of the detected object relative
* to the robot base coordinate system has to be computed.
pose_invert (BaseInCamPose, CamInBasePose)
pose_compose (CamInBasePose, ObjInCamPose, ObjInBasePose)

解析

        和眼在手上一致,眼在手外的标定代码前面部分也是一些参数配置。比如:ImageNameStart和DataNameStart是文件地址起始部分路径(文件名相同部分)、NumImages为图像数量。

创建、设置标定模型

下面代码主要是用于创建标定模型:

* Read the initial values for the internal camera parameters
read_cam_par (DataNameStart + 'start_campar.dat', StartCamParam)
* Create the calibration model for the hand eye calibration
create_calib_data ('hand_eye_stationary_cam', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, [], StartCamParam)
set_calib_data_calib_object (CalibDataID, 0, CalTabFile)
set_calib_data (CalibDataID, 'model', 'general', 'optimization_method', 'nonlinear')

read_cam_par        读取相机内参;

create_calib_data        创建标定模型;

set_calib_data_cam_param        将相机内参设置到标定模型中;

set_calib_data_calib_object        获取标定板的描述文件;

set_calib_data        设置标定的一些参数;

读取标定图像

下面是for循环中的内容,主要功能为读取标定图像:

read_image (Image, ImageNameStart + I$'02d')
* Search for the calibration plate, extract the marks and the
* pose of it, and store the results in the calibration data model of the
* hand-eye calibration
find_calib_object (Image, CalibDataID, 0, 0, I, [], [])
get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, I)
get_calib_data_observ_points (CalibDataID, 0, 0, I, RCoord, CCoord, Index, CalObjInCamPose)

read_image        读取图像;

find_calib_object        寻找标定板;

get_calib_data_observ_contours        找到标定板,然后画轮廓;

get_calib_data_observ_points        找到标定板,然后画标定点;

读取工具坐标系位姿

每一张图像对应着一个机械臂末端夹具(工具坐标系)在机械臂基坐标系下的位姿

* Read pose of tool in robot base coordinates (ToolInBasePose)
read_pose (DataNameStart + 'robot_pose_' + I$'02d' + '.dat', ToolInBasePose)
* Set the pose tool in robot base coordinates in the calibration data model
set_calib_data (CalibDataID, 'tool', I, 'tool_in_base_pose', ToolInBasePose)

read_pose        读取工具坐标系在机械臂基坐标系下的位姿;

set_calib_data        将读取的结果设置到标定模型中;

手眼标定

参数读取和设置都完成之后,结下来就是手眼标定啦~

calibrate_hand_eye (CalibDataID, Errors)
* Query the error of the camera calibration
get_calib_data (CalibDataID, 'model', 'general', 'camera_calib_error', CamCalibError)
* Query the camera parameters and the poses
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
* Get poses computed by the hand eye calibration
get_calib_data (CalibDataID, 'camera', 0, 'base_in_cam_pose', BaseInCamPose)
get_calib_data (CalibDataID, 'calib_obj', 0, 'obj_in_tool_pose', ObjInToolPose)

calibrate_hand_eye        手眼标定;

get_calib_data         获取一些标定数据,这个算子有点特别,里面包含很多参数选择,这里就不进行叙述了。想要了解的小伙伴可以去halcon算子里面进行学习;

到这里标定就结束了。下面是保存参数。

write_cam_par (CamParam, DataNameStart + 'final_campar.dat')
write_pose (ToolInCamPose, DataNameStart + 'final_pose_cam_tool.dat')
write_pose (CalObjInBasePose, DataNameStart + 'final_pose_base_calplate.dat')
write_pose (PlaneInBasePose, DataNameStart + 'final_pose_base_plane.dat')

验证    

        在这里就不对验证进行解释了,简单来说就是根据以下三个坐标系进行转换:标定板坐标系相对于基座标系的转换关系、工具坐标系相对于相机坐标系的转换关系、工具坐标系相对于机械臂基座标的转换关系。这里进行一些数学计算,就能获得标定板坐标系在相机坐标系下的位置和姿态。注意这里不是识别标定板的结果,而是根据结果进行验证。

下面是一个比较好的结果(halcon示例结果):

可以看到坐标系和标定板的中心和姿态基本上是吻合的。这就是一个好的结果。  

-------------------------2024.06.27        留个坑,等我有空实验一下--------------

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

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

相关文章

leetcode209:长度最小的子数组

题目链接&#xff1a;209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int n nums.size();if(n 0) return 0;int end 0, start 0, sum 0, ans 0x3f3f3f3f;while…

OpenAI将终止对中国提供服务,国内模型接棒

说起来&#xff0c;OpenAI自始至终就没有对中国提供过服务&#xff0c;OpenAI官方支持的国家和地区&#xff1a;https://platform.openai.com/docs/supported-countries 列表里面没有“Chinese”的选项&#xff0c;那为什么又要明令禁止呢&#xff0c;国类IT高手们&#xff0…

day001 环境的配置与工具的安装

VMware的软件包&#xff1a;https://pan.xunlei.com/s/VNs1KShnlZalTSJtejXXzchlA1?pwdudy5# 其他的软件可以在电脑管家中下载&#xff0c;注意不要安装到c盘&#xff0c;否则影响开机速度。 虚拟机工具&#xff1a;VMware17.5.1 1&#xff0c; 2&#xff0c; 3&#xff0c…

欢乐钓鱼大师攻略:卡鱼骨、典藏鱼、藏宝图怎么钓?

《欢乐钓鱼大师》是一款以钓鱼为核心玩法的休闲模拟手游&#xff0c;通过逼真的画面和丰富的钓鱼体验吸引了大量玩家。本文将为你详细介绍这款游戏的亮点、常见问题以及一些实用的游戏技巧&#xff0c;帮助你在《欢乐钓鱼大师》中获得更愉快的游戏体验。 辅助工具 1. 辅助工具…

内网安全【5】隧道搭建

1.内网穿透工具 Ngrok Frp Spp Nps EW(停更) 一共是这五个 优点&#xff1a;穿透加密数据&#xff0c;中间平台&#xff0c;防追踪&#xff0c;解决网络问题 Sunny-Ngrok内网转发内网穿透 - 国内内网映射服务器 https://github.com/esrrhs/spp https://github.com/fatedie…

计算机网络之数据通信原理(中)

上节内容传送口&#xff1a;数据通信原理基础 1.数据传输方式 1.1并行传输 并行传输: 字符编码的各个比特同时传输 特点&#xff1a; 一个比特时间内可传输一个字符&#xff0c;传输速度快&#xff0c;每个比特传输要求一个单独的信道支持&#xff0c;通信成本高&#xf…

探索网络爬虫技术:原理、实践与挑战

一、引言 在数字化时代&#xff0c;信息如同潮水般汹涌而来。过去&#xff0c;我们可能依赖书籍、报纸或电视来获取信息&#xff0c;但这些渠道的信息量有限&#xff0c;而且筛选过的信息未必能满足我们的需求。如今&#xff0c;互联网为我们提供了海量的信息&#xff0c;但同…

【Sklearn驯化-聚类指标】搞懂机器学习中聚类算法评估指标,轮廓系数、戴维森堡丁指数

【Sklearn驯化-聚类指标】搞懂机器学习中聚类算法评估指标&#xff0c;轮廓系数、戴维森堡丁指数 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#…

快来看,错过了今天就要设置为vip文章了---云原生重塑架构:AutoMQ 基于云构建十倍降本的 Kafka

Apache Kafka在数据流处理系统中的核心地位 Apache Kafka已成为大数据和流计算领域的行业事实标准&#xff0c;其重要性在数据流处理系统中不言而喻。随着数字化转型的加速&#xff0c;越来越多的企业选择基于Kafka来构建其在线业务消息传递系统&#xff0c;使其成为数字化转型…

一文梳理有效提升RAG效果的方法

来源&#xff1a;一文梳理有效提升RAG效果的方法 在大模型实际落地的时候&#xff0c;存在一些问题&#xff0c;主要集中在以下方面&#xff1a; 缺少垂直领域知识&#xff1a;虽然大模型压缩了大量的人类知识&#xff0c;但在垂直场景上明显存在短板&#xff0c;需要专业化的…

如何通过小猪APP分发轻松实现应用内测分发

搞应用开发的朋友们&#xff0c;都知道内测分发这个环节有多重要。没有内测&#xff0c;一款应用基本上是不可能上线的。毕竟&#xff0c;谁也不想自己的产品在上线的那一刻就被用户吐槽得体无完肤。内测分发的好坏&#xff0c;直接影响到应用的质量和用户的第一印象。如何才能…

Web自动化元素定位之xpath定位【超详细】

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Web自动化常见的定位方式 为什么要学习定位 1.让程序操作指定元素&#xff0c;就必须先找到此元…

Linux文件IO深入剖析

目录 一、文件IO引发的项目血案 1、分析 一、Linux文件系统基本概念 1、文件系统接口 2、文件系统缓存 二、文件IO 访问方式概述 1、标准文件访问方式 2、直接IO 3、实现方式 4、缓存同步 5、Linux 文件IO流程图 6、血案解决 一、文件IO引发的项目血案 事件经过&am…

MTK平台Android13实现三方launcher为默认

一、前言 目前有遇到客户的定制需求,希望使用三方的launcher作为默认的launcher使用,一般情况下直接将三方launcher通过内置到系统并通过overlay机制即可很方便的实现launcher的替换,但是存在一个问题,需要增加ROM的维护成本。本文通过设备在使用前联网通过后台下发三方lau…

Potato(土豆)一款轻量级的开源文本标注工具

项目介绍&#xff1a; Potato 是一款轻量级、可移植的Web文本标注工具&#xff0c;被EMNLP 2022 DEMO赛道接受。它旨在帮助用户快速地从零开始创建和部署各种文本标注任务&#xff0c;无需复杂的编程或网页设计。只需简单配置&#xff0c;团队即可在几分钟内启动并运行标注项目…

【论文速读】| LLAMAFUZZ:大语言模型增强的灰盒模糊测试

本次分享论文&#xff1a;LLAMAFUZZ: Large Language Model Enhanced Greybox Fuzzing 基本信息 原文作者&#xff1a;Hongxiang Zhang, Yuyang Rong, Yifeng He, Hao Chen 作者单位&#xff1a;University of California, Davis 关键词&#xff1a;模糊测试&#xff0c;大…

云动态摘要 2024-06-27

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新产品更新 veLinux 2.0 镜像邀测发布 火山引擎 2024-06-26 veLinux 2.0 镜像邀测发布 ECS支持100台实例批量续费/退订 火山引擎 2024-06-26 ECS支持100台实例批量续费/退订 弹性伸缩支持目标追踪规则(邀测) …

花8000元去培训机构学习网络安全值得吗,学成后就业前景如何?

我就是从培训机构学的网络安全&#xff0c;线下五六个月&#xff0c;当时学费不到一万&#xff0c;目前已成功入行。所以&#xff0c;只要你下决心要入这一行&#xff0c;过程中能好好学&#xff0c;那这8000就花得值~ 因为只要学得好&#xff0c;工作两个多月就能赚回学费&am…

Shell (一)Ubuntu的网络配置及软件安装

Ubuntu的配置及软件安装 网络配置 虚拟机提供的网络类型 桥接模式 主机和虚拟机分别拥有不同的ip地址&#xff0c;可以实现和外界设备通信 NAT模式 也可以联网&#xff0c;但是和主机共用同一个ip地址&#xff0c;外界无法识别虚拟机和主机发送的信息 仅主机模式 虚拟机不可…

数据资产与人工智能的融合之路:探讨如何结合AI技术优化数据资产管理,提升企业智能化水平

目录 一、引言 二、数据资产管理的现状与挑战 1、数据资产管理的重要性 2、数据资产管理的挑战 三、人工智能在数据资产管理中的应用 1、数据采集与整合 2、数据清洗与校验 3、数据安全与隐私保护 4、数据分析与挖掘 四、结合AI技术优化数据资产管理的策略 1、制定数…