使用Kronecker积计算手眼标定矩阵AX=XB

使用Kronecker积计算AX=XB

最近使用matlab实现了手眼标定
参考论文 "Solving the Robot-World/Hand-Eye Calibration Problem Using the Kronecker Product"
使用 K积 得到AX=XB的可分离的闭合解

构造 A B 矩阵

eye-to-hand其 A B 矩阵的构造如下
A = [ b a s e i M t o o l ] ∙ [ b a s e j M t o o l ] − 1 B = [ c a m i M c a l ] ∙ [ c a m j M c a l ] − 1 i ≠ j i , j = 1 , 2 , 3 , . . . , n \begin{aligned} & \mathbf{A} =[_{base}^{\quad i}\mathbf{M} ^{tool}]\bullet [_{base}^{\quad j}\mathbf{M} ^{tool}]^{-1} \\ \\ & \mathbf{B}=[_{cam}^{\quad i}\mathbf{M}^{cal}]\bullet [_{cam}^{\quad j}\mathbf{M}^{cal}]^{-1} \\ \\ &i\ne j\quad i,j=1,2,3,...,n \end{aligned} A=[baseiMtool][basejMtool]1B=[camiMcal][camjMcal]1i=ji,j=1,2,3,...,n

eye-in-hand其 A B 矩阵的构造如下
A = [ b a s e i M t o o l ] − 1 ∙ [ b a s e j M t o o l ] B = [ c a m i M c a l ] ∙ [ c a m j M c a l ] − 1 i ≠ j i , j = 1 , 2 , 3 , . . . , n \begin{aligned} & \mathbf{A} =[_{base}^{\quad i}\mathbf{M} ^{tool}]^{-1}\bullet [_{base}^{\quad j}\mathbf{M} ^{tool}] \\ \\ & \mathbf{B}=[_{cam}^{\quad i}\mathbf{M}^{cal}]\bullet [_{cam}^{\quad j}\mathbf{M}^{cal}]^{-1} \\ \\ &i\ne j\quad i,j=1,2,3,...,n \end{aligned} A=[baseiMtool]1[basejMtool]B=[camiMcal][camjMcal]1i=ji,j=1,2,3,...,n
n表示得到的标定样本数量。
baseMtool 表示机器人基坐标系下的末端工具位姿
camMcal 表示相机坐标系中标定板的位姿
通过两两组合可以得到 n(n-1)A B
要求两个位姿 i j 之间的旋转角度尽可能大一些,特别是旋转主轴不能平行
通过奇异性和稳定性等判别,需要剔除一些不好的AB矩阵,比如接近零值

而所需要求的 X 矩阵如下
X = b a s e M c a m ( e y e − t o − h a n d ) X = t o o l M c a m ( e y e − i n − h a n d ) \begin{aligned} &\mathbf{X} =_{base}\mathbf{M} ^{cam} \quad (eye-to-hand)\\ &\mathbf{X} =_{tool}\mathbf{M} ^{cam} \quad (eye-in-hand) \end{aligned} X=baseMcam(eyetohand)X=toolMcam(eyeinhand)
如果相机固定在机架上,与机械臂位置是固定的,所求即为机器人坐标系下的相机位姿
如果相机固定在末端工具上,则与末端位姿不变,所求为在工具坐标系下的相机位姿

具体的构造过程这里不进行赘述,可以比较简单地通过刚性坐标变换和消元方法得到

求解AX=XB

根据前一个步骤获得了m组 AB 矩阵,这里使用两步求解
即从方程中分离旋转与平移分量,先计算旋转分量 RX ,再计算平移分量 tx
A X = X B   [ R A t A 0 1 ] [ R X t X 0 1 ] = [ R X t X 0 1 ] [ R B t B 0 1 ]   [ R A R X R A t X + t A 0 1 ] = [ R X R B R X t B + t X 0 1 ]   { R A R X = R X R B   − − ( 1 ) R A t X + t A = R X t B + t X − − ( 2 ) \begin{aligned} &\mathbf{AX} =\mathbf{XB} \\\ \\ & \begin{bmatrix} \mathbf{RA} & \mathbf{tA} \\ \mathbf{0} & \mathbf{1} \end{bmatrix} \begin{bmatrix} \mathbf{RX} & \mathbf{tX} \\ \mathbf{0} & \mathbf{1} \end{bmatrix}= \begin{bmatrix} \mathbf{RX} & \mathbf{tX} \\ \mathbf{0} & \mathbf{1} \end{bmatrix} \begin{bmatrix} \mathbf{RB} & \mathbf{tB} \\ \mathbf{0} & \mathbf{1} \end{bmatrix}\\ \ \\ & \begin{bmatrix} \mathbf{RA}\mathbf{RX} & \mathbf{RA}\mathbf{tX}+\mathbf{tA} \\ \mathbf{0} & \mathbf{1} \end{bmatrix} = \begin{bmatrix} \mathbf{RX}\mathbf{RB} & \mathbf{RX}\mathbf{tB}+\mathbf{tX} \\ \mathbf{0} & \mathbf{1} \end{bmatrix} \\\ \\ & \begin{cases} \mathbf{RARX} =\mathbf{RXRB} \quad \quad \quad \quad \quad \ \color{Red}-- \color{Red}\left ( 1 \right ) \\ \mathbf{RAtX} +\mathbf{tA} =\mathbf{RXtB} +\mathbf{tX} \quad\color{Red}-- \color{Red}\left ( 2 \right ) \end{cases} \end{aligned}    AX=XB[RA0tA1][RX0tX1]=[RX0tX1][RB0tB1][RARX0RAtX+tA1]=[RXRB0RXtB+tX1]{RARX=RXRB (1)RAtX+tA=RXtB+tX(2)

求解 RX

构造线性方程组Ax=0

首先,显然,RA RB RX 都是旋转矩阵,属于特殊正交群SO(3)
在乘法上是封闭的

这里使用向量化算子vec(*)将矩阵按列向量化
即按列排布
这里涉及到Kronecker积的概念
简单来说就是构造了一个分块矩阵
在这里插入图片描述
Kronecker积有几个性质,用于解算会很方便
v e c ( A X B ) = v e c ( C ) = ( B T ⊗ A ) v e c ( X ) ( A ⊗ B ) T = A T ⊗ B T ( A ⊗ B ) − 1 = A − 1 ⊗ B − 1 ( A ⊗ B ) ( C ⊗ D ) = A C ⊗ B D \begin{aligned} & vec(\mathbf{AXB} )=vec(\mathbf{C} )=({\mathbf{B} }^{T}\otimes \mathbf{A} )vec(\mathbf{X} ) \\ &({\mathbf{A} }\otimes \mathbf{B} )^{T}={\mathbf{A}^{T} }\otimes \mathbf{B}^{T} \\ &({\mathbf{A} }\otimes \mathbf{B} )^{-1}={\mathbf{A}^{-1} }\otimes \mathbf{B}^{-1} \\ &({\mathbf{A} }\otimes \mathbf{B} )({\mathbf{C} }\otimes \mathbf{D})={\mathbf{AC} }\otimes \mathbf{BD} \end{aligned} vec(AXB)=vec(C)=(BTA)vec(X)(AB)T=ATBT(AB)1=A1B1(AB)(CD)=ACBD
由第一个转换公式可以将 RARX=RXRB进行转换计算
R A R X = R X R B R A R X I = I R X R B v e c ( R A R X I ) = v e c ( I R X R B ) − − 通 过 上 述 公 式 转 换 ( I ⊗ R A ) v e c ( R X ) = ( R B T ⊗ I ) v e c ( R X ) ( I ⊗ R A − R B T ⊗ I ) v e c ( R X ) = 0 令 ( I ⊗ R A − R B T ⊗ I ) = K K v e c ( R X ) = 0 \begin{aligned} {\mathbf{RARX} }&= \mathbf{RXRB} \\ {\mathbf{RARX{\color{Red} I} } }&= \mathbf{{\color{Red} I} RXRB}\\ vec({\mathbf{RARX{\color{Red} I} } })&= vec(\mathbf{{\color{Red} I} RXRB}) \quad--通过上述公式转换\\ ({\mathbf{\color{Red} I} \otimes \mathbf{RA}})vec(\mathbf{RX})&= ({\mathbf{RB}^{T} \otimes \mathbf{\color{Red} I}})vec(\mathbf{RX})\\ ({\mathbf{\color{Red} I} \otimes \mathbf{RA}}-{\mathbf{RB}^{T} \otimes \mathbf{\color{Red} I}})vec(\mathbf{RX})&= \mathbf{0} \\ 令({\mathbf{\color{Red} I} \otimes \mathbf{RA}}-{\mathbf{RB}^{T} \otimes \mathbf{\color{Red} I}})=\mathbf{K}\\ \mathbf{K}vec(\mathbf{RX})&=\mathbf{0} \end{aligned} RARXRARXIvec(RARXI)(IRA)vec(RX)(IRARBTI)vec(RX)(IRARBTI)=KKvec(RX)=RXRB=IRXRB=vec(IRXRB)=(RBTI)vec(RX)=0=0
这样就能得到一个 Ax=0 形式的线性方程组
需要注意的是,通过向量化算子,这个 K 矩阵的大小为9x9,而 vec(RX) 是一个大小为 9 的列向量

假设通过上一步得到了m组 AB 值,那就得到m个K矩阵,可以直接堆叠该矩阵,得到一个9m*9大小的矩阵

SVD值分解求解线性方程组Ax=0

通过上一步骤将问题转化为求解 Kvec(RX)=0 的问题
这一步可以使用奇异值分解进行解算
实际上就是一个最小二乘的问题
将K分解为USVV中的最后一列vn对应S中的最小奇异值,能够最小化目标函数||Ax||

vec(RX)=vn
将这个9维的列向量重新排列为3*3的矩阵,即
[ v n 1 v n 4 v n 7 v n 2 v n 5 v n 8 v n 3 v n 6 v n 9 ] = R X \begin{bmatrix} \mathbf{vn}_{1}&\mathbf{vn}_{4} &\mathbf{vn}_{7} \\ \mathbf{vn}_{2}&\mathbf{vn}_{5} &\mathbf{vn}_{8} \\ \mathbf{vn}_{3}&\mathbf{vn}_{6} &\mathbf{vn}_{9} \end{bmatrix}=\mathbf{RX} vn1vn2vn3vn4vn5vn6vn7vn8vn9=RX
需要注意的是,通过这一方式最后得到的RX可能会失去正交性,需要重新正交化
其方法如下
对RX进行奇异值分解,得到U V矩阵
R X = U V T \mathbf{RX}=\mathbf{UV}^{T} RX=UVT
这样得到的新的 RX 就是所求的旋转阵
PS:这里还需要注意一点,旋转矩阵的行列式值应该为1,所以在重新正交化之后,需要计算一下这个旋转矩阵的行列式值,如果等于-1,则需要乘以-1,否则后续的平移向量的求解会有很大问题

求解tX平移矩阵

通过上述的公式(2)
{ R A R X = R X R B   − − ( 1 ) R A t X + t A = R X t B + t X − − ( 2 ) \begin{cases} \mathbf{RARX} =\mathbf{RXRB} \quad \quad \quad \quad \quad \ {\color{red}-- ( 1 )} \\ \mathbf{RAtX} +\mathbf{tA} =\mathbf{RXtB} +\mathbf{tX} \quad {\color{red}-- ( 2 ) } \end{cases} {RARX=RXRB (1)RAtX+tA=RXtB+tX(2)
得到 tX 的表达式
( R A − I ) t X = R X t B − t A 令   R A − I = A , R X t B − t A = b 得 到 线 性 方 程 : A ∙ t X = b (\mathbf{RA}-\mathbf{I})\mathbf{tX}=\mathbf{RXtB}-\mathbf{tA} \\ 令\ \mathbf{RA}-\mathbf{I}=\mathbf{A}, \mathbf{RXtB}-\mathbf{tA}=\mathbf{b}\\ 得到线性方程:\quad \mathbf{A}\bullet \mathbf{tX}=\mathbf{b} (RAI)tX=RXtBtA RAI=A,RXtBtA=b线:AtX=b
其中A为3x3矩阵,b和tX都是三维列向量
同样的,因为有多组 AB
其中Ab都可以堆叠,形成3mx3的矩阵和3m维的列向量
可以在matlab中直接使用A\b来进行求解

X

最终可以得到完整的 旋转矩阵 X
X = [ R X t X 0 1 ] \mathbf{X}=\begin{bmatrix} \mathbf{RX} &\mathbf{tX} \\ \mathbf{0}& 1 \end{bmatrix} X=[RX0tX1]

误差计算

关于误差计算,也需要分为计算RX的误差和tX的误差,但是关于tX的误差其实就包含了RX的误差
所以可以分两步计算
Y 1 = R A R X Y 2 = R X R B E r r = Y 1 − Y 2 \begin{aligned} \mathbf{Y1}&=\mathbf{RARX}\\ \mathbf{Y2}&=\mathbf{RXRB}\\ \mathbf{Err}&=\mathbf{Y1}-\mathbf{Y2} \end{aligned} Y1Y2Err=RARX=RXRB=Y1Y2
再计算 ||Err|| 标量化误差

然后再计算X的整体误差
Y 1 = A X Y 2 = X B E r r = Y 1 − Y 2 \begin{aligned} \mathbf{Y1}&=\mathbf{AX}\\ \mathbf{Y2}&=\mathbf{XB}\\ \mathbf{Err}&=\mathbf{Y1}-\mathbf{Y2} \end{aligned} Y1Y2Err=AX=XB=Y1Y2
同样,计算 Err 矩阵的L2范数来标量化误差

得到的多组 误差 可以取均值或者输出打印为折线图分析统计

MATLAB代码

function [ X ] = AXXB( A,B )
%AXXB 使用了K积方法,计算手眼标定问题中的AX=XB问题
    n=length(A);
    K=[];
    I=eye(3,3);
    for i=1:n
        RA=A(1:3,1:3,i);
        RB=B(1:3,1:3,i);
        K=[K;kron(I,RA)-kron(RB',I)];
    end
    [U,S,V]=svd(K);
    col=length(V);
    RX=-[V(1:3,col),V(4:6,col),V(7:9,col)];

    [Ux,Sx,Vx]=svd(RX);
    RX=Ux*Vx';
    RX=sign(det(RX))*RX;
    [ Error,err,average_err ] = AXXB_Error( A(1:3,1:3,:),B(1:3,1:3,:),RX );
    
    At=[];
    bt=[];
    for i=1:n
        RA=A(1:3,1:3,i);
        tB=B(1:3,4,i);
        tA=A(1:3,4,i);
        At=[At;I-RA];
        bt=[bt;tA-RX*tB];
    end
    tx=At\bt;
    X=[RX,tx;0,0,0,1];
    [ Error,err,average_err ] = AXXB_Error( A,B,X );
end

function [ Error,err,average_err ] = AXXB_Error( A,B,X )
%AXXB_Error 用于简单得到标定的误差
    n=length(A);
    sz=size(A);
    Error=zeros(sz(1),sz(1),n);
    err=zeros(n,1);
    average_err=0;
    Y1=zeros(sz(1),sz(1),n);
    Y2=zeros(sz(1),sz(1),n);
    for i=1:n
        Y1(:,:,i)=A(:,:,i)*X;
        Y2(:,:,i)=X*B(:,:,i);
        Error(:,:,i)=Y1(:,:,i)-Y2(:,:,i);
        err(i)=norm(Error(:,:,i));
        average_err=average_err+err(i);
    end
    average_err=average_err/length(err);
end
  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值