Tsai算法

Tsai算法主要用于求解手眼标定中的AX=XB问题,它属于二阶段法,先求解旋转R后求平移t

  • 首先,求解R:
    s k e w ( P g i j + P c i j ) P c g ′ = P c i j − P g i j skew(P_{gij}+P_{cij})P'_{cg}=P_{cij}-P_{gij} skew(Pgij+Pcij)Pcg=PcijPgij
    其中: P = 2 s i n θ 2 u T P=2sin\frac{\theta}{2}u^T P=2sin2θuT, ( u , θ ) (u,\theta) (u,θ)为旋转的Rodrigues表示 P c g ′ = 1 4 − ∣ P c g ∣ 2 P c g P'_{cg}=\frac{1}{\sqrt{4-|P_{cg}|^{2}}}P_{cg} Pcg=4Pcg2 1Pcg
    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
    上式是AX=b形式的方程组,可以利用SVD求解出 P c g ′ P'_{cg} Pcg,并通过 P c g = 2 P c g ′ 1 + ∣ P c g ′ ∣ 2 P_{cg}=\frac{2P'_{cg}}{\sqrt{1+|P'_{cg}|^2}} Pcg=1+Pcg2 2Pcg求得 P c g P_{cg} Pcg
    然后,通过
    R = ( 1 − ∣ P ∣ 2 2 ) I + 1 2 ( P P T + 4 − ∣ P ∣ 2 s k e w ( P ) ) R=(1-\frac{|P|^2}{2})I+\frac{1}{2}(PP^T+\sqrt{4-|P|^2}skew(P)) R=(12P2)I+21(PPT+4P2 skew(P))
    得到旋转R

  • 接下来,求解t
    ( R g i j − I ) T c g = R c g T c i j − T g i j (R_{gij}-I)T_{cg}=R_{cg}T_{cij}-T_{gij} (RgijI)Tcg=RcgTcijTgij
    上式同样是AX=b形式的方程组,可以解得t

代码实现:
https://github.com/zjulion/handeyecat

GeoTransform sovleAXequalXB(std::vector<GeoTransform>& vA, std::vector<GeoTransform>& vB)
{
	GeoTransform H;
	H.setIdentity();
	if (vA.size() != vB.size())
	{
		printf("A and B must be same size.\n");
		return H;
	}

	const int n = vA.size();

	RotMat R_a, R_b;
	Geo3d r_a, r_b;

	Eigen::MatrixXf A(n*3, 3);
	Eigen::MatrixXf b(n*3, 1);
	A.setZero();
	b.setZero(); 

	for (int i = 0; i < n; ++i)
	{
		R_a = vA[i].linear();
		R_b = vB[i].linear();
		
		Geo3d rod_a = rodrigues2(R_a);
		Geo3d rod_b = rodrigues2(R_b);

		float theta_a = rod_a.norm();
		float theta_b = rod_b.norm();

		rod_a /= theta_a;
		rod_b /= theta_b;

		Geo3d P_a = 2*sin(theta_a/2)*rod_a;
		Geo3d P_b = 2*sin(theta_b/2)*rod_b;		 

		Eigen::Matrix3f rot = skew(Geo3d(P_b+P_a));
		Geo3d v = P_b - P_a;
		
		A.middleRows(3 * i, 3) = rot;
		b.middleRows(3*i, 3) = v;
	}
	// 3 by 3*n 
	Eigen::MatrixXf pinA = svdInverse(A); 

	// 3 by 1 = 3 by 3*n multi 3*n by 1
	Geo3d H_ba_prime = pinA * b;
	 
	Geo3d H_ba = 2 * H_ba_prime / sqrt(1 + lxsq(H_ba_prime.norm()));

	// 1 by 3
	Eigen::MatrixXf H_ba_Trs = H_ba.transpose();

	RotMat R_ba = (1 - lxsq(H_ba.norm()) / 2) * RotMat::Identity() 
		+ 0.5 * (H_ba * H_ba_Trs + sqrt(4 - lxsq(H_ba.norm()))*skew(H_ba));
	
	A.setZero();
	b.setZero();
	for (int i = 0; i < n; ++i)
	{
		RotMat AA = vA[i].linear() - RotMat::Identity();
		Geo3d bb = R_ba * vB[i].translation() - vA[i].translation();
		A.middleRows(3 * i, 3) = AA;
		b.middleRows(3 * i, 3) = bb;
	}
	pinA = svdInverse(A);
	Geo3d t_ba = pinA * b;
	H.linear() = R_ba;
	H.translation() = t_ba;
	std::string fname("H.txt");	
	printf("Calibration Finished. Saved at %s.\n", fname.c_str());

	cout << "H: \n" << H.matrix() << endl;
	ofstream out(fname);
	out <<"# Calibrated At " << fname  << endl;
	out << H.matrix() << endl;
	out.close(); 

	return H;
}

参考文献:https://ieeexplore.ieee.org/document/34770

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值