在工业领域常常会遇到将相机安装在机器手中,由相机快速引导机器手进行工作的方式。其中9点标定的作用是将图像的坐标转化为机器手的坐标。
不同标定文件的区别:不同标定的区别在于:图像坐标系与机器人坐标系是否匹配,单像素精度是否匹配。影响单像素精度是,相机与被测物体的高度差,如果相机与被测物体的高度差不变时,则可以不改变标定文件。
9点标定的作用意义:
标定视野范围,标定视野范围应大于相机视野的2/3以上,以保证相机出现畸变时可以及时发现。
1.计算像素当量,通过9点标定后的计算,可以得出一个由像素值转化为机器手的移动值的一个变化量。当我们标定完后即可得到一个像素当量的固定值。
2.将图像坐标系转化为机器手的同向坐标系。
为什么叫做同向坐标系?
我们标定的时候,需要将图像坐标与对应的机器手的坐标进行一一对应。图像坐标系通常会默认左上角的视野临界点为图像的起始原点即为(0,0)【图像坐标系】。图像往东为X轴的正方向,图像往南为Y轴的正方向。当然我们的机器手由于各种问题往往所体现出来的坐标系是混乱不固定的,且实际的工作单位为机器手,我们相机需要为机器手进行引导,所以即使在机器手坐标系不一的情况下,可以使用9点标定实现将机器手坐标系与图像坐标系联系在一起并计算为坐标系同向的状态。
我们的标定步骤:
1.在安装好设备后开始进行手眼标定
2.确定工作计算的坐标系,在实际生产中视觉计算的坐标系往往是多样化的,根据实际情况进行选择工作坐标系,同时示教时也需要在工作坐标系下。我直接采取机器手的Base0坐标系。原因在于:Base0坐标系时机器手的固定坐标系,此坐标系的原点在机器人的底座上,坐标系的变化只与机器人的安装误差有关系。
3.将机器手移动至方案选定的拍照高度,随后调节相机的焦距,和将光圈调到最大,在相机控制软件调节相机曝光时长,使得物体在视野内清晰可见,同时干扰源尽可能的少。
4.以库卡机器人为例子。将机器人选择为全局坐标系下,即为Base0坐标系(底座坐标系)。移动机器手,使得相机的中心对准被检测物体(或者标定物体的中心),记录当前的机器人坐标X,Y,Z,A等其他数值。
5.设定机器手的移动距离,根据实际情况设置机器手的移动距离,通常将9个点均在画面当中,9个点相连接占用的面积约为视野范围的2/3即可。这里我以20mm作为偏移值。则将视野中心点设置为4号点,机器坐标为(0,0)。则对应的坐标为

例如0号点的机械坐标设定为(-20,-20),则我们在机器手中将X轴移动-20,Y轴移动-20,其他均不改变 。同理我们的其他坐标也是如此。
6.然后生成标定文件进行验证即可
参考Halcon程序
*已知A坐标系的9个点
Ax:=[-20,-20,-20,0,0,0,20,20,20]
Ay:=[-20,0,20,20,0,-20,-20,0,20]
*待识别的B坐标点,和上面的A坐标系点一一对应
Bx:=[]
By:=[]
dev_get_window (WindowHandle)
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('E:/762halcon/标定', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
* Image Acquisition 01: Do something
dev_display (Image)
* 以下过程为在B坐标系找A中的9个点
draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2)
reduce_domain (Image, Rectangle, ImageReduced)
threshold (ImageReduced, Regions, 0, 211)
*找到了B坐标系的点(Row,Column)
area_center (Regions, Area, Row, Column)
Bx:=[Bx,Column]
By:=[By,Row]
endfor
*得到目标变换矩阵HomMat2D
vector_to_hom_mat2d (Bx, By, Ax, Ay, HomMat2D)
*保存变换矩阵
serialize_hom_mat2d (HomMat2D, SerializedItemHandle)
open_file ('my_vector.mat', 'output_binary', FileHandle)
fwrite_serialized_item (FileHandle, SerializedItemHandle)
close_file (FileHandle)
stop ()
*读取变换矩阵,测试
open_file ('my_vector.mat', 'input_binary', FileHandle)
fread_serialized_item (FileHandle, SerializedItemHandle)
deserialize_hom_mat2d (SerializedItemHandle, HomMat2D_9p)
close_file (FileHandle)
tx:=20
ty:=30
affine_trans_point_2d (HomMat2D_9p, tx, ty, Qx, Qy)
7.同时标定坐标系需要与程序的实际情况相对应,如果程序中的是当前坐标-示教坐标,那么我们标定出来的坐标系需要与机器人的坐标系方向正负相反。
库卡机器人参考标定文件程序:
lin_rel{x -15}
lin_rel{y-15} //第一个点
lin_rel{x 15}
lin_rel{x 15}
lin_rel{y 15}
lin_rel{x -15}
lin_rel{x -15}
lin_rel{y 15}
lin_rel{x 15}
lin_rel{x15} //最后一个点
lin_rel{x-15}
lin_rel{y -15} (回到原点)
标定后,图像坐标系与机器人坐标系相反,适用于当前坐标-示教坐标程序。
1.按照机器人移动的照片是斜的。
只要是根据机器人的坐标系移动,无论图像的连线是否是斜的都不影响精度。
2.标定结果有误差。
标定的坐标系问题,如果你在Base0下进行标定,结果出现误差是机器人安装错误,推荐重新正确的安装机器人底座;如果是在其他机器人坐标系下标定,结果出现误差是因为机器人的Z轴发生了变换,但是在当前坐标系下没有变化,实际在Base0下的Z轴开始变化了,可以将坐标系改为在Base0下进行标定。
3.为什么标定时4号点(视野中心)的机械坐标设置为0?
我们在计算的过程的时候,选择视野中的机械坐标为0的好处是,当我们进行示教时候,可以直接记录视野中心的点即为示教点,那么偏移量就可以直接将坐标映射后的坐标+示教的坐标即可得到基于当前坐标系的坐标了,方便计算。









请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow
问题是:除了在“OperatorExpressions”?例如:1%!2 最佳答案 是的,可以创建自定义运算符,但有一些注意事项。Ruby本身并不直接支持它,但是superatorsgem做了一个巧妙的把戏,将运算符链接在一起。这允许您创建自己的运算符,但有一些限制:$geminstallsuperators19然后:require'superators19'classArraysuperator"%~"do|operand|"#{self}percent-tilde#{operand}"endendputs[1]%~[2]#Out
在Ruby中有运算符(operator)。在API中,他们没有命名它的名字,只是:Theclassmustdefinetheoperator...Comparableusestoimplementtheconventionalcomparison......theobjectsinthecollectionmustalsoimplementameaningfuloperator...它叫什么名字? 最佳答案 参见上面的@Tony。然而,它也被称为(俚语)“宇宙飞船运算符(operator)”。
也许这听起来很荒谬,但我想知道这对Ruby是否可行?基本上我有一个功能...defadda,bc=a+breturncend我希望能够将“+”或其他运算符(例如“-”)传递给函数,这样它就类似于...defsuma,b,operatorc=aoperatorbreturncend这可能吗? 最佳答案 两种可能性:以方法/算子名作为符号:defsuma,b,operatora.send(operator,b)endsum42,23,:+或者更通用的解决方案:采取一个block:defsuma,byielda,bendsum42,23,
可能真的很简单,但我很难在网上找到关于这个的文档我在Ruby中有两个activerecord查询,我想通过OR运算符连接在一起@pro=Project.where(:manager_user_id=>current_user.id)@proa=Project.where(:account_manager=>current_user.id)我是ruby的新手,但我自己尝试使用||@pro=Project.where(:manager_user_id=>current_user.id||:account_manager=>current_user.id)这没有用,所以1.我想知道如何在
我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc
ruby中有这样的东西吗?send(+,1,2)我想让这段代码看起来不那么冗余ifop=="+"returnarg1+arg2elsifop=="-"returnarg1-arg2elsifop=="*"returnarg1*arg2elsifop=="/"returnarg1/arg2 最佳答案 是的,只需像这样使用send(或者更好的是public_send):arg1.public_send(op,arg2)这是可行的,因为Ruby中的大多数运算符(包括+、-、*、/、andmore)只需调用方法。所以1+2与1.+(2)相同
我已经开始学习Ruby,我已经阅读了一些教程,甚至还买了一本书(“ProgrammingRuby1.9-ThePragmaticProgrammers'Guide”),我遇到了一些以前从未见过的新东西使用我知道的任何其他语言(我是一名PHP网络开发人员)。block和过程。我想我明白它们是什么,但我不明白的是为什么它们如此伟大,以及我应该在何时何地使用它们。我到处都看到他们说block和过程是Ruby中的一个很棒的特性,但我不理解它们。这里有人能给像我这样的Ruby新手一些解释吗? 最佳答案 block有很多好处。电梯演讲:bloc
您如何找到有关代码中运算符用法的信息(最好是通过Google)?在这种情况下,我想找到这段代码在Ruby中的含义。x=[1,2,3]x.send:[]=,0,2x[0]+x.[](1)+x.send(:[],2)我要你教我如何钓鱼——不要告诉我运算符(operator)是做什么的。当我去Google并尝试搜索符号时,我得到的示例或教程没有涵盖特定的用法。https://stackoverflow.com/questions/1165786/how-to-search-for-punctuation-that-gets-ignored-by-google表示谷歌驳回了这种表示法;我寻找“