Tsai手眼标定算法

A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration(Tsai手眼标定算法)

符号定义

坐标系定义

G i G_i Gi: 手爪(末端执行器)的坐标系。

C i C_i Ci: 相机的坐标系。

C W CW CW: 对于相机的世界坐标系(一般由标定板确定)。

R W RW RW: 机器人基座坐标系。

坐标系变换定义

  1. 手爪——>基座
    [ R g i T g i 0 1 ] \begin{bmatrix} R_{gi} & T_{gi}\\ 0 &1 \end{bmatrix} [Rgi0Tgi1]

  2. camera world ——>camera
    [ R c i T c i 0 1 ] \begin{bmatrix} R_{ci} & T_{ci}\\ 0 &1 \end{bmatrix} [Rci0Tci1]

  3. 手爪——>手爪
    [ R g i j T g i j 0 1 ] \begin{bmatrix} R_{gij} & T_{gij}\\ 0 &1 \end{bmatrix} [Rgij0Tgij1]

  4. camera——>camera
    [ R c i j T c i j 0 1 ] \begin{bmatrix} R_{cij} & T_{cij}\\ 0 &1 \end{bmatrix} [Rcij0Tcij1]

  5. camera——>手爪
    [ R c g T c g 0 1 ] \begin{bmatrix} R_{cg} & T_{cg}\\ 0 &1 \end{bmatrix} [Rcg0Tcg1]

θ R \theta_R θR: 旋转矩阵 R R R的旋转角

P g i j P_{gij} Pgij: 旋转矩阵 R g i j R_{gij} Rgij对应的旋转向量,它可以用于表示 G i G_i Gi G j G_j Gj的旋转变换

P c i j P_{cij} Pcij: 同上

P c g P_{cg} Pcg: 旋转矩阵 R c g R_{cg} Rcg对应的旋转向量

P c g ′ = 1 2 cos ⁡ ( θ R c 8 2 ) P c g = 1 4 − ∣ P c g ∣ 2 P c g P_{c g}^{\prime}=\frac{1}{2 \cos \left(\frac{\theta_{R_{c 8}}}{2}\right)} P_{c g}=\frac{1}{\sqrt{4-\left|P_{c g}\right|^{2}}} P_{c g} Pcg=2cos(2θRc8)1Pcg=4Pcg2 1Pcg

S k e w ( V ) Skew(V) Skew(V): 反对称矩阵,相当于 V × V\times V× V V V是3维列向量
S k e w ( V ) = [ 0 − v z v y v z 0 − v x − v y v x 0 ] Skew(V)= \begin{bmatrix} 0 & -v_z & v_y\\ v_z & 0 & -v_x\\ -v_y & v_x & 0 \end{bmatrix} Skew(V)=0vzvyvz0vxvyvx0
N N N: 数据组数,每组数据由两个位姿组成

计算步骤

  1. 利用罗德里格斯公式将旋转矩阵转换为旋转向量
    { r g i j = rodrigues ( R g i j ) r c i j = rodrigues  ( R c i j ) \left\{\begin{array}{l} r_{g i j}=\text {rodrigues}\left(R_{g i j}\right) \\ r_{c i j}=\text {rodrigues }\left(R_{c i j}\right) \end{array}\right. {rgij=rodrigues(Rgij)rcij=rodrigues (Rcij)

    从线性代数的角度看,旋转向量实际上是旋转矩阵的特征值为1所对应的特征向量

    a. 旋转矩阵必有一个特征值为1

    b. 根据特征值和特征向量的定义有:
    R P r = λ P r λ = 1 RP_r=\lambda P_r \quad \lambda=1 RPr=λPrλ=1
    因此对应的几何意义是该向量经过 R R R旋转作用后依然是自身,那很显然它就是旋转轴

  2. 旋转向量归一化,得到单位旋转轴和旋转角*(将旋转向量解耦)*
    { θ g i j = ∥ r g i j ∥ 2 N r g i j = r g i j θ g i j θ c i j = ∥ r c i j ∥ 2 N r c i j = r c i j θ c i j \left\{\begin{array}{c} \theta_{g i j}=\left\|r_{g i j}\right\|_{2} \quad N_{r_{g i j}}=\frac{r_{g i j}}{\theta_{g i j}} \\ \theta_{c i j}=\| r_{c i j} \|_{2} \quad N_{r_{c i j}}=\frac{r_{c i j}}{\theta_{c i j}} \end{array}\right. {θgij=rgij2Nrgij=θgijrgijθcij=rcij2Nrcij=θcijrcij

  3. 修正的罗德里格斯参数表示姿态变换
    P g i j = 2 sin ⁡ ( θ g i j / 2 ) N r g i j P c i j = 2 sin ⁡ ( θ c i j / 2 ) N r c i j P_{gij}=2\sin(\theta_{gij}/2)N_{rgij}\\ P_{cij}=2\sin(\theta_{cij}/2)N_{rcij} Pgij=2sin(θgij/2)NrgijPcij=2sin(θcij/2)Nrcij

  4. 计算初始的 P c g ′ {P_{cg}}' Pcg

    对于每对位姿,它们之间的旋转变化要尽可能大,然后计算:
    S k e w ( P g i j + P c i j ) P c g ′ = P c i j − P g i j (8) Skew(P_{gij}+P_{cij}){P_{cg}}'=P_{cij}-P_{gij}\tag{8} Skew(Pgij+Pcij)Pcg=PcijPgij(8)
    其中, P g i j P_{gij} Pgij容易由机械臂的正向运动学公式求得, P c i j P_{cij} Pcij容易由机器视觉方法求得,因此式(8)实际上就是 A x = b Ax=b Ax=b的求解问题,可以直接对 A A A求逆,即 x = A − 1 b x=A^{-1}b x=A1b,如果有多组数据,那就构建出优化问题:
    min ⁡ f ( x ) = ∥ A x − b ∥ 2 (12) \min\quad f(x)=\|Ax-b\|^2\tag{12} minf(x)=Axb2(12)
    即优化出外参中的旋转部分

  5. 计算旋转角 θ R g c \theta_{R_{gc}} θRgc

  6. 计算 P c g P_{cg} Pcg
    P c g = 2 P c g ′ 1 + ∣ P c g ′ ∣ 2 P_{c g}=\frac{2 P_{c g}{ }^{\prime}}{\sqrt{1+\left|P_{c g}{}^{\prime}\right|^{2}}} Pcg=1+Pcg2 2Pcg

  7. 利用罗德里格斯计算旋转矩阵 R c g R_{cg} Rcg
    R = ( 1 − ∣ P r ∣ 2 2 ) I + 1 2 ( P r P r T + α ⋅ Skew ⁡ ( P r ) ) R=\left(1-\frac{\left|P_{r}\right|^{2}}{2}\right) I+\frac{1}{2}\left(P_{r} P_{r}^{T}+\alpha \cdot \operatorname{Skew}\left(P_{r}\right)\right) R=(12Pr2)I+21(PrPrT+αSkew(Pr))
    或者
    R = [ n 1 2 + ( 1 − n 1 2 ) cos ⁡ θ n 1 n 2 ( 1 − cos ⁡ θ ) − n 3 sin ⁡ θ n 1 n 3 ( 1 − cos ⁡ θ ) + n 2 sin ⁡ θ n 1 n 2 ( 1 − cos ⁡ θ ) + n 3 sin ⁡ θ n 2 2 + ( 1 − n 2 2 ) cos ⁡ θ n 2 n 3 ( 1 − cos ⁡ θ ) − n 1 sin ⁡ θ n 1 n 3 ( 1 − cos ⁡ θ ) + n 2 sin ⁡ θ n 2 n 3 ( 1 − cos ⁡ θ ) + n 1 sin ⁡ θ n 3 2 + ( 1 − n 3 2 ) cos ⁡ θ ) ] R=\left[\begin{array}{ccc} n_{1}^{2}+\left(1-n_{1}^{2}\right) \cos \theta & n_{1} n_{2}(1-\cos \theta)-n_{3} \sin \theta & n_{1} n_{3}(1-\cos \theta)+n_{2} \sin \theta \\ n_{1} n_{2}(1-\cos \theta)+n_{3} \sin \theta & n_{2}^{2}+\left(1-n_{2}^{2}\right) \cos \theta & n_{2} n_{3}(1-\cos \theta)-n_{1} \sin \theta \\ n_{1} n_{3}(1-\cos \theta)+n_{2} \sin \theta & n_{2} n_{3}(1-\cos \theta)+n_{1} \sin \theta & \left.n_{3}^{2}+\left(1-n_{3}^{2}\right) \cos \theta\right) \end{array}\right] R=n12+(1n12)cosθn1n2(1cosθ)+n3sinθn1n3(1cosθ)+n2sinθn1n2(1cosθ)n3sinθn22+(1n22)cosθn2n3(1cosθ)+n1sinθn1n3(1cosθ)+n2sinθn2n3(1cosθ)n1sinθn32+(1n32)cosθ)

  8. 计算平移向量 T c g T_{cg} Tcg

( R g i j − I ) T c g = R c g T c i j − T g i j (15) \left(R_{g i j}-I\right) T_{c g}=R_{c g} T_{c i j}-T_{g i j}\tag{15} (RgijI)Tcg=RcgTcijTgij(15)

​ 实际上(15)也是一个求解 A x = b Ax=b Ax=b的问题,可以对 A A A求逆计算,如果有多组数据,则类似(12)构建最小二乘的优化问题,即优化得到外参中的平移部分

算法代码

void Tsai_HandEye(Mat Hcg, vector<Mat> Hgij, vector<Mat> Hcij)
{
    CV_Assert(Hgij.size() == Hcij.size());
    int nStatus = Hgij.size();
 
    // 手到手旋转
    Mat Rgij(3, 3, CV_64FC1);
    // 眼到眼旋转
    Mat Rcij(3, 3, CV_64FC1);
 
    // 对应的旋转向量
    Mat rgij(3, 1, CV_64FC1);
    Mat rcij(3, 1, CV_64FC1);
 
    // 旋转角
    double theta_gij;
    double theta_cij;
 
    // 旋转轴
    Mat rngij(3, 1, CV_64FC1);
    Mat rncij(3, 1, CV_64FC1);
 
    // 修正的旋转向量
    Mat Pgij(3, 1, CV_64FC1);
    Mat Pcij(3, 1, CV_64FC1);
 
    Mat tempA(3, 3, CV_64FC1);
    Mat tempb(3, 1, CV_64FC1);
 
    Mat A;
    Mat b;
    Mat pinA;
 
    Mat Pcg_prime(3, 1, CV_64FC1);
    Mat Pcg(3, 1, CV_64FC1);
    Mat PcgTrs(1, 3, CV_64FC1);
 
    Mat Rcg(3, 3, CV_64FC1);
    Mat eyeM = Mat::eye(3, 3, CV_64FC1);
 
    Mat Tgij(3, 1, CV_64FC1);
    Mat Tcij(3, 1, CV_64FC1);
 
    Mat tempAA(3, 3, CV_64FC1);
    Mat tempbb(3, 1, CV_64FC1);
 
    Mat AA;
    Mat bb;
    Mat pinAA;
 
    Mat Tcg(3, 1, CV_64FC1);
 
    // 遍历每组数据
    for (int i = 0; i < nStatus; i++)
    {
        // 从齐次变换矩阵中提取旋转矩阵
        Hgij[i](Rect(0, 0, 3, 3)).copyTo(Rgij);
        Hcij[i](Rect(0, 0, 3, 3)).copyTo(Rcij);
 
        // 罗德里格斯公式:旋转矩阵->旋转向量
        Rodrigues(Rgij, rgij);
        Rodrigues(Rcij, rcij);
 
        // 计算旋转向量的范数,也就是旋转角
        theta_gij = norm(rgij);
        theta_cij = norm(rcij);
 
        // 旋转向量的单位旋转轴
        rngij = rgij / theta_gij;
        rncij = rcij / theta_cij;
 
        // 修正的罗德里格斯参数表示姿态变换
        Pgij = 2 * sin(theta_gij / 2)*rngij;
        Pcij = 2 * sin(theta_cij / 2)*rncij;
 
        // 论文公式(12)
        tempA = skew(Pgij + Pcij);
        tempb = Pcij - Pgij;
 
        A.push_back(tempA);
        b.push_back(tempb);
    }
 
    //Compute rotation
    // 论文公式(12)
    invert(A, pinA, DECOMP_SVD);
    // 求初始的旋转向量P_{cg}'
    Pcg_prime = pinA * b;
    
    // 论文公式(14)
    Pcg = 2 * Pcg_prime / sqrt(1 + norm(Pcg_prime) * norm(Pcg_prime));
    PcgTrs = Pcg.t();   // 矩阵转置
    // 论文公式(10) 旋转向量->旋转矩阵
    Rcg = (1 - norm(Pcg) * norm(Pcg) / 2) * eyeM + 0.5 * (Pcg * PcgTrs + sqrt(4 - norm(Pcg)*norm(Pcg))*skew(Pcg));
 
    //Computer Translation 
    // 计算平移向量, 论文公式(15)
    for (int i = 0; i < nStatus; i++)
    {
        Hgij[i](Rect(0, 0, 3, 3)).copyTo(Rgij);
        Hcij[i](Rect(0, 0, 3, 3)).copyTo(Rcij);
        Hgij[i](Rect(3, 0, 1, 3)).copyTo(Tgij);
        Hcij[i](Rect(3, 0, 1, 3)).copyTo(Tcij);
 
 
        tempAA = Rgij - eyeM;
        tempbb = Rcg * Tcij - Tgij;
 
        AA.push_back(tempAA);
        bb.push_back(tempbb);
    }
 
    invert(AA, pinAA, DECOMP_SVD);
    Tcg = pinAA * bb;
 
    Rcg.copyTo(Hcg(Rect(0, 0, 3, 3)));
    Tcg.copyTo(Hcg(Rect(3, 0, 1, 3)));
    Hcg.at<double>(3, 0) = 0.0;
    Hcg.at<double>(3, 1) = 0.0;
    Hcg.at<double>(3, 2) = 0.0;
    Hcg.at<double>(3, 3) = 1.0;
 
}

参考:

手眼标定Tsai方法的Matlab仿真分析

经典手眼标定算法之Tsai-Lenz

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值