康耐視visionpro-機器視覺定位引導-經(jīng)驗總結(jié)-來自視覺人粉絲分享

1、機器人吸取電路板,移動到拍照位置,并在電路板上找一個標記點,并且,通過機器人示教把當前電路板能夠準確的放入到目標位置。
2、機器人吸取電路板吸取電路板,在x,y方向進行移動,總共移動4個位置,記錄4個位置的機器人的坐標,以及拍攝圖像

3、使用vp的CogCalibNpointToNpoint工具,并在藍框填入標志點的像素坐標,紅框填入對應(yīng)的機器人坐標。
4.點運行完成標定功能。
5、完成標定后,整個流程如下

在模板匹配中把模板中心進行記錄。然后,調(diào)整標定工具的校正原點

使得模板匹配的模板中心x,y坐標輸出為0,0,表示當前吸取的電路板能夠準確的放入模板位置
下次,再吸取電路板時,執(zhí)行模板匹配后,輸出的x,y坐標就是機器人應(yīng)當移動的x,y的偏移量
這樣x y 就計算完成了。
但往往,因為還有旋轉(zhuǎn)。所以還要計算角度
機器人不用旋轉(zhuǎn)中心進行標定
旋轉(zhuǎn)中心標定方式的說明
在下面的圖例中,紅色為相機視野(FOV),黃色為工件,五星為Mark點。




旋轉(zhuǎn)中心方法用于所有機器人與視覺配合場景
方法 :計算工件實際發(fā)生的偏移量 和旋轉(zhuǎn),結(jié)合機器人的旋轉(zhuǎn)中心進行二次補償后 ,把補償量 發(fā)送給機器人 ,然后機器人把補償量進行抓取或放置即可。
計算 某個點繞另外一旋轉(zhuǎn)定角度后的坐 標,如圖 :A(x,y)繞 B(rx0 ,ry0) 旋轉(zhuǎn)a度后的位置為 C(x0,y0 ),則有如 下關(guān)系式:
x0= cos (a) * (x -rx0)? – sin (a) *(y-ry0) +rx0
y0= cos (a) * (y- ry0) + sin (a) *(x-rx0) +ry0

下面的所有計算旋轉(zhuǎn)與偏移量都是基于上面的公式。


{Cx,Cy } 旋轉(zhuǎn)中心坐標; {Mx,My } 工件 Mark坐標。
{MDx,MDy},Mark偏移量。
{RDx,Rdy}, 發(fā)送給機器人的補償量。
工件發(fā)生平移時,
在拍照位置進行拍照后 ,與開始訓練標準位置時,Mark點成像會產(chǎn)生偏移。
Mark 偏移量 MDx =RDx;MDy =RDy ;
如上圖即相機計算出的 Mark 點偏移量 ,可以直接補償給機器人,然后進行抓取即可。

作為測試 ,可以機器人在拍照位置進行補償后 ,Z軸不變?nèi)缓笤倥恼?,會獲得和拍照位置一樣的圖像。
工件發(fā)生平移與旋轉(zhuǎn)

工件發(fā)生平移和旋轉(zhuǎn)時
在拍照位置進行后 ,與開始訓練標準位置時 ,Mark 點成像會產(chǎn)生偏移;?
Mark 偏移量 MDx #RDx, MDy#RDy ;如左上圖即相機計算出的 MarkMark 點偏移量 ,不能直接補償給機器人 ,需要計算出 RDx 和RDy,和RDr ,MDr 然后補償給機器人 ,機器人補償后才能進行抓取。


作為測試 ,可以機器人在拍照位置進行補償后 ,Z軸不變?nèi)缓笤倥恼?,會獲得和拍照位置一樣的圖像;?
計算過程,旋轉(zhuǎn)角度a

計算 CDx =Cx1– Cx0和 CDy =Cy1– Cy0
CDx = cos (a) * (Cx0 -X0) -sin (a) * Cy0-Y0) + X1 – Cx0
CDy = cos (a) * (Cy0 -Y0 ) + sin (a) * Cx0 -X0 ) + Y1– Cy0
從公式中可以看出,補給機器人的償量由:
旋轉(zhuǎn)中心坐標( Cx0,Cy0 )
標準的工件 (Mark) 坐標點( X0,Y0)
工件移動后新的(Mark)坐標點
工件 (Mark) 旋轉(zhuǎn)角度 a
所以利用旋轉(zhuǎn)中心方法計算給機器人的補償量時,首先要中心坐標,
但是在很多場景下計算旋轉(zhuǎn)中心坐標時要么出了視野,要么轉(zhuǎn)的角度范圍太小等,擬合旋中心都存在誤差,
導致補償精不夠
一定要計算旋轉(zhuǎn)中心坐標嗎?其實不需要。
CDx,Cdy 計算過程 ,旋轉(zhuǎn)角度 a

CDx =?cos (a) * (Cx0 -X0) -sin (a) * (Cy0 -Y0) + X1 – Cx0
= ( cos (a) -1) * (Cx0-X0)-Sin(a)*(Cy0 -Y0) + MDx
=?(cos(a) -1) * StDx -sin (a) * StDy + MDx
?
CDy =?cos ( a) * (Cy0 -Y0 ) + sin (a) * (Cx0 -X0 ) +y1 – Cy0
= ( cos (a) -1) * (Cy0 -Y0 ) + sin (a) * (Cx0 -X0 ) + Mdy
=?(cos(a)? -1) * StDy + sin (a) * StDx + Mdy
從公式中可以看出 StDx= Cx0-X0, StDy = Cy0 -Y0 是個常量, MDx 和Mdy是每次拍照是工件 (Mark )的坐標與準位置工件( Mark)的差值;
StDx 與StDy 怎么計算呢?藍色的為一個二元次方程,我們需要旋轉(zhuǎn)角度即可計算出;?
如果 計算出 StDx 和StDy 則在運行時,直接帶入上述公式,可以很快計算出 CDx,Cdy 這樣給出Robot 的偏移量了,而不需要計算旋轉(zhuǎn)中心確切坐標了
下面介紹如何求解 StDx和StDy
實際操作的時候,感覺上面的文章有點難理解,就還是老老實實去算了圓心,例如讓機器人旋轉(zhuǎn)正15度,和負15度,得到兩個新的坐標。3點求圓心坐標。
點求圓心:??
struct?POINT
????????{? ????
??????????public???double?X;
??????????public???double?Y;? ? ? ? ? ? ? ??
????????}??
????????POINT?RotateCenterCal(POINT?p1, POINT?p2, POINT?p3, POINT?ptCenter)
????????{
????????????//將三點代入圓的方程
????????????double?a = 2 * (p2.X - p1.X);
????????????double?b = 2 * (p2.Y - p1.Y);
????????????double?c = p2.X * p2.X + p2.Y * p2.Y - p1.X * p1.X - p1.Y * p1.Y;
????????????double?d = 2 * (p3.X - p2.X);
????????????double?e = 2 * (p3.Y - p2.Y);
????????????double?f = p3.X * p3.X + p3.Y * p3.Y - p2.X * p2.X - p2.Y * p2.Y;
????????????ptCenter.X = (b * f - e * c) / (b * d - e * a);
????????????ptCenter.Y = (d * c - a * f) / (b * d - e * a);
????????????return?ptCenter;
????????}
之后可以根據(jù)圓心 以及當前取得到的坐標以及旋轉(zhuǎn)量,倒推得到要旋轉(zhuǎn)多少角度和移動多少坐標才能回正。

CDx = cos (a) * (Cx0 -X0) -sin (a) * Cy0-Y0) + X1 – Cx0
CDy = cos (a) * (Cy0 -Y0 ) + sin (a) * Cx0 -X0 ) + Y1– Cy0
從公式中可以看出,補給機器人的償量由:
旋轉(zhuǎn)中心坐標( Cx0,Cy0 )
標準的工件 (Mark) 坐標點( X0,Y0)
工件移動后新的(Mark)坐標點
工件 (Mark) 旋轉(zhuǎn)角度 a
代碼:????private?void?button3_Click(object?sender, EventArgs?e)
????????{ ????//根據(jù)圓心坐標 與角度, ?以及原先的X,Y, 求旋轉(zhuǎn)角度后的新坐標
????????????POINT?p1 = new?POINT();
????????????POINT?p2 = new?POINT();
????????????POINT?presult = new?POINT();
?
????????????p1.X = double.Parse(lastX.Text);
????????????p1.Y = double.Parse(lastY.Text);
????????????double?jiaodu = double.Parse(lastjiaodu.Text);
????????????jiaodu = -jiaodu;
??????????// ?jiaodu = jiaodu * 180 / Math.PI; 無需轉(zhuǎn)換成度數(shù)
????????????p2.X = double.Parse(centerX.Text);
????????????p2.Y = double.Parse(centerY.Text);
?
????????????presult = FindNEWXandY(p1, p2, presult, jiaodu);
?
????????????resultX.Text = presult.X.ToString();
????????????resultY.Text = presult.Y.ToString();
????????}
????????POINT?FindNEWXandY(POINT?p1, POINT?p2,POINT?presult,double?jiaodu)
????????{
????????????//根據(jù)圓心坐標 與 ?原先的X,Y, 求旋轉(zhuǎn)角度后的新坐標
????????????//jiaodu = (Math.PI *jiaodu/180);
????????????double?mc = Math.Cos(jiaodu);
????????????double?ma = Math.Sin(jiaodu);
????????????double?a1 = (p1.X - p2.X) * mc;
????????????double?b1 = (p1.Y - p2.Y) * ma;
????????????presult.X =Math.Round(a1 - b1 + p2.X,3);
????????????double?a2= (p1.Y - p2.Y) * mc;
????????????double?b2 = (p1.X - p2.X) * ma;
????????????presult.Y = Math.Round(a2 + b2 + p2.Y,3);
????????????return?presult;
????????}



因為當時使用的機器人精度較查,誤差還是挺大的。如果項目成型,則會有最終解決方案,目前只是配合測試。先到此結(jié)束