經典手眼標定演算法之Tsai-Lenz的OpenCV實現
本文主要是講解經典手眼標定問題中的TSAI-LENZ 文獻方法,參考文獻為“A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration”,並且實現了基於OpenCV的C++程式碼程式,code可去CSDN資源下載,MATLAB版本作者為蘇黎世理工的Christian Wengert,也可在此處下載。
手眼標定問題描述
在機器人校準測量、機器人手眼協調以及機器人輔助測量等領域,都要求知道機器人執行器末端(抓取臂)座標系和感測器(比如用來測量三維空間中目標位置和方向並固定在機器人手上的攝像機)座標系之間的相互關係,確定這種轉換關係在機器人領域就是通常所說的手眼標定。
將手眼標定系統如下圖所示,其中
H_{gij}
為機器人執行器末端座標系之間相對位置姿態的齊次變換矩陣;H_{cij}
為攝像機座標系之間相對位置姿態的齊次變換矩陣;H_{cg}
為像機與機器人執行器末端之間的相對位置姿態齊次矩陣。
經過座標系變換,
H_{gij}
、H_{cij}
和H_{cg}
滿足如下關係: {H_{gij}}{H_{cg}} = {H_{cg}}{H_{cij}} \Leftrightarrow \left( {\begin{array}{*{20}{c}}
{{R_{gij}}}&{{T_{gij}}} \\
{\mathbf{0}}&1
\end{array}} \right)\left( {\begin{array}{*{20}{c}}
{{R_{cg}}}&{{T_{cg}}} \\
{\mathbf{0}}&1
\end{array}} \right) = \left( {\begin{array}{*{20}{c}}
{{R_{cg}}}&{{T_{cg}}} \\
{\mathbf{0}}&1
\end{array}} \right)\left( {\begin{array}{*{20}{c}}
{{R_{cij}}}&{{T_{cij}}} \\
{\mathbf{0}}&1
\end{array}} \right)
將上式展開,可以得到手眼標定的基本方程:
\left\{ {\begin{array}{*{20}{c}}
{{R_{gij}}{R_{cg}} = {R_{cg}}{R_{cij}}} \\
{\left( {{R_{gij}} - I} \right){T_{cg}} = {R_{cg}}{T_{cij}} - {T_{gij}}}
\end{array}} \right.
因此,手眼標定問題也就轉化為從上述方程組中求解出
R_{cg}
和T_{cg}
,下面就按照TSAI文獻所述求解該方程組。
“兩步法”手眼標定
一般用“兩步法”求解基本方程,即先從基本方程上式求解出
R_{cg}
,再代入下式求解出T_{cg}
。在TSAI文獻中引入旋轉軸-旋轉角系統來描述旋轉運動來進行求解該方程組,具體的公式推導可以檢視原始文獻,這裡只歸納計算步驟,不明白的地方可閱讀文獻,計算步驟如下:
Step1:利用羅德里格斯變換將旋轉矩陣轉換為旋轉向量
\left\{ {\begin{array}{*{20}{c}}
{{r_{gij}} = rodrigues\left( {{R_{gij}}} \right)} \\
{{r_{cij}} = rodrigues\left( {{R_{cij}}} \right)}
\end{array}} \right.
Step2:向量歸一化
\left\{ {\begin{array}{*{20}{c}}
{\begin{array}{*{20}{c}}
{{\theta _{gij}} = {{\left\| {{r_{gij}}} \right\|}_2}}&{{N_{{r_{gij}}}} = \frac{{{r_{gij}}}}{{{\theta _{gij}}}}}
\end{array}} \\
{\begin{array}{*{20}{c}}
{{\theta _{cij}} = {{\left\| {{r_{cij}}} \right\|}_2}}&{{N_{{r_{cij}}}} = \frac{{{r_{cij}}}}{{{\theta _{cij}}}}}
\end{array}}
\end{array}} \right.
Step3:修正的羅德里格斯參數列示姿態變化
\left\{ {\begin{array}{*{20}{c}}
{{P_{gij}} = 2\sin \frac{{{\theta _{gij}}}}{2}{N_{{r_{gij}}}}} \\
{{P_{cij}} = 2\sin \frac{{{\theta _{cij}}}}{2}{N_{{r_{cij}}}}}
\end{array}} \right.
Step4:計算初始旋轉向量P′cg P_{cg}^\prime
skew\left( {{P_{gij}} + {P_{cij}}} \right){P_{cg}}^\prime = {P_{cij}}- {P_{gij}}
其中,skew為反對稱運算,假設一個三維向量
V=[v_x;v_y;v_z]
,其反對稱矩陣為: skew\left( V \right) = \left[ {\begin{array}{*{20}{c}}
{\begin{array}{*{20}{c}}
{\text{0}} \\
{{v_z}} \\
{ - {v_y}}
\end{array}}&{\begin{array}{*{20}{c}}
{ - {v_z}} \\
{\text{0}} \\
{{v_x}}
\end{array}}&{\begin{array}{*{20}{c}}
{{v_y}} \\
{ - {v_x}} \\
{\text{0}}
\end{array}}
\end{array}} \right]
Step5:計算旋轉向量Pcg P_{cg}
{P_{cg}} = \frac{{2{P_{cg}}^\prime }}{{\sqrt {1 + {{\left| {{P_{cg}}^\prime } \right|}^2}} }}
Step6:計算旋轉矩陣Rcg R_{cg}
{R_{cg}} = \left( {1 - \frac{{{{\left| {{P_{cg}}} \right|}^2}}}{2}} \right)I + \frac{1}{2}\left( {{P_{cg}}{P_{cg}}^T + \sqrt {4 - {{\left| {{P_{cg}}} \right|}^2}} skew\left( {{P_{cg}}} \right)} \right)
Step7:計算平移向量Tcg T_{cg}
\left( {{R_{gij}} - I} \right){T_{cg}} = {R_{cg}}{T_{cij}} - {T_{gij}}
演算法原始碼
根據上述基本計算步驟,在利用OpenCV 2.0開源庫的基礎上,編寫Tsai手眼標定方法的c++程式,其實現函式程式碼如下:
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;
tempA = skew(Pgij + Pcij);
tempb = Pcij - Pgij;
A.push_back(tempA);
b.push_back(tempb);
}
//Compute rotation
invert(A, pinA, DECOMP_SVD);
Pcg_prime = pinA * b;
Pcg = 2 * Pcg_prime / sqrt(1 + norm(Pcg_prime) * norm(Pcg_prime));
PcgTrs = Pcg.t();
Rcg = (1 - norm(Pcg) * norm(Pcg) / 2) * eyeM + 0.5 * (Pcg * PcgTrs + sqrt(4 - norm(Pcg)*norm(Pcg))*skew(Pcg));
//Computer Translation
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;
}
相關文章
- OpenCV之C++經典案例OpenCVC++
- AQS:JAVA經典之鎖實現演算法(一)AQSJava演算法
- AQS:JAVA經典之鎖實現演算法(二)-ConditionAQSJava演算法
- JavaScript實現經典排序演算法JavaScript排序演算法
- 經典排序演算法PHP實現排序演算法PHP
- 用 PHP 實現經典排序演算法PHP排序演算法
- 張正友標定Opencv實現、標定流程以及影像座標轉為世界座標OpenCV
- Swift實現八種經典排序演算法Swift排序演算法
- 經典排序演算法的 C語言 | Java 實現排序演算法C語言Java
- 機器學習10種經典演算法的Python實現機器學習演算法Python
- opencv的目標跟蹤演算法OpenCV演算法
- 單目標定:從理論到OpenCV實踐OpenCV
- 機器學習經典演算法之EM機器學習演算法
- 機器學習經典演算法之KNN機器學習演算法KNN
- OpenCV----實現目標識別與分割OpenCV
- Lisp經典演算法Lisp演算法
- Java實現十個經典排序演算法(帶動態效果圖)Java排序演算法
- 23個經典設計模式的Swift實現設計模式Swift
- 幾種經典的排序演算法排序演算法
- python opencv如何實現目標區域裁剪功能PythonOpenCV
- 機器學習經典演算法之K-Means機器學習演算法
- 機器學習經典演算法之決策樹機器學習演算法
- 十大經典排序演算法之氣泡排序排序演算法
- 社群發現之標籤傳播演算法(LPA)python實現演算法Python
- Python經典演算法片段Python演算法
- 經典論文復現 | 基於標註策略的實體和關係聯合抽取
- 基於標註策略的實體和關係聯合抽取 | 經典論文復現
- 混合高斯模型實現運動目標檢測(OpenCV內建實現)模型OpenCV
- 十大經典排序演算法動畫解析和 Java 程式碼實現排序演算法動畫Java
- 解讀現代儲存系統背後的經典演算法演算法
- 經典排序演算法回顧:排序演算法
- Python+OpenCV目標跟蹤實現基本的運動檢測PythonOpenCV
- 十大經典排序演算法最強總結(含JAVA程式碼實現)排序演算法Java
- 力扣演算法經典第一題——兩數之和(Java兩種方式實現)力扣演算法Java
- python OpenCV加法操作的實現PythonOpenCV
- 主宰作業系統的經典演算法作業系統演算法
- Dominate【作業系統的經典演算法】作業系統演算法
- 【經典網路結構實現】LeNet-5
- Python3+pygame實現Windows經典掃雷PythonGAMWindows