記事ディレクトリ
カメラと IMU の内部基準キャリブレーション、カメラ、IMU、LiDAR 間のジョイント キャリブレーション方法、ツールキットのインストール環境は Ubuntu20.04 環境にあり、使用されるツールは次のとおりです。MATLAB ツールボックス、ROS キャリブレーション ツールキット、kalibr 、OpenCV、imu_utils、calibration_camera_lidar、lidar_imu_calib
1. カメラ (単眼) 内部パラメータのキャリブレーション
1.1 解決策 1: MATLAB ツールボックス
これが最も便利です。(記事) を参照し、matlab を開き、APP を見つけ、三角形をドロップダウンしてその他のオプションを表示し、Camera Calibrator を見つけます (デュアル ターゲット設定用のプログラムも提供します。ここでは単眼のデモを示します)。
撮影したキャリブレーション ボードの写真を追加します (プラン 2 で保存した一連の画像でもかまいません) キャリブレーション ボードを撮影するときは、画面の半分以上を占めるように、前後左右を平行移動させて撮影するのが最適です。 、右、および回転。
キャリブレーション ボードの隣接するチェッカーボード間の実際の距離を入力します。キャリブレーションの精度は、キャリブレーション ボードの精度に大きく依存します。ここでは 35mm です。[OK] をクリックすると、プログラムは自動的に角の点を抽出して一致させます。結果は次のとおりです。 :
半径方向の歪みと接線方向の歪みの両方のキャリブレーションされた歪みパラメーター タイプを選択し、[キャリブレーション] をクリックして計算します。
右側には、フレームごとの平均再投影誤差とすべてのフレームにわたる平均再投影誤差が、各画像フレームのポーズの視覚化とともに表示されます。2 つのフレームの再投影誤差が明らかに大きすぎることがわかります. クリックしてモーション ブラーのある画像を表示します. 左側の対応するフレームの画像を右クリックして削除し, 再計算することができます. 平均再投影最終結果の誤差は 0.16 ピクセルで、精度はすでに非常に高いです。
[出力カメラ キャリブレーション パラメーター] をクリックして、キャリブレーション パラメーター変数を表示します。
1.2 解決策 2: ROS キャリブレーション ツールキットを使用する
私の記事 (リンク)のセクション 7.1 を参照してください。
1.3 解決策 3: キャリブレーション ツール kalibr を使用する
Kalibr は、マルチ IMU キャリブレーション、カメラ IMU キャリブレーション、およびマルチカメラ キャリブレーションの機能を提供します.ここで、マルチカメラ キャリブレーション コマンドは、単一のカメラをキャリブレーションするために使用されます。
1.3.1 kalibr のインストール
# for Ubuntu18.04
# 安装依赖
sudo apt update
sudo apt-get install python-setuptools python-rosinstall ipython libeigen3-dev libboost-all-dev doxygen libopencv-dev ros-melodic-vision-opencv ros-melodic-image-transport-plugins ros-melodic-cmake-modules python-software-properties software-properties-common libpoco-dev python-matplotlib python-scipy python-git python-pip ipython libtbb-dev libblas-dev liblapack-dev python-catkin-tools libv4l-dev
sudo pip install python-igraph --upgrade
# 创建工作空间并下载源码
mkdir -p kalibr_ws/src
cd kalibr_ws/src
git clone https://github.com/ethz-asl/kalibr.git
# 编译
cd ..
source /opt/ros/melodic/setup.bash
catkin init
catkin config --extend /opt/ros/melodic
catkin config --merge-devel # Necessary for catkin_tools >= 0.4.
catkin config --cmake-args -DCMAKE_BUILD_TYPE=Release
catkin_make -DCMAKE_BUILD_TYPE=Release -j4
# for Ubuntu20.04
# 安装依赖
sudo apt update
sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost-all-dev doxygen libopencv-dev ros-noetic-vision-opencv ros-noetic-image-transport-plugins ros-noetic-cmake-modules python3-software-properties software-properties-common libpoco-dev python3-matplotlib python3-scipy python3-git python3-pip libtbb-dev libblas-dev liblapack-dev libv4l-dev python3-catkin-tools python3-igraph libsuitesparse-dev libgtk-3-dev
# 下面两个可能没反映或者错误,请等待和多尝试几次
pip3 install attrdict
pip3 install wxPython
# 创建工作空间并下载源码
mkdir -p kalibr_ws/src
cd kalibr_ws/src
git clone https://github.com/ethz-asl/kalibr.git
# 编译
cd ..
source /opt/ros/noetic/setup.bash
catkin init
catkin config --extend /opt/ros/noetic
catkin config --merge-devel # Necessary for catkin_tools >= 0.4.
catkin config --cmake-args -DCMAKE_BUILD_TYPE=Release
catkin_make -DCMAKE_BUILD_TYPE=Release -j8
1.3.2 キャリブレーションプレートの準備
下図のように、kalibrが推奨するキャリブレーションボードであるAprilgridキャリブレーションボードを用意します。公式 Web サイトにアクセスして、著者が提供するキャリブレーション ボードをダウンロードできますが、科学的にインターネットにアクセスする必要があるため、著者の関数パッケージを使用して生成できます。
rosrun kalibr kalibr_create_target_pdf --type apriltag --nx [NUM_COLS] --ny [NUM_ROWS] --tsize [TAG_WIDTH_M] --tspace [TAG_SPACING_PERCENT]
eg: rosrun kalibr kalibr_create_target_pdf --type apriltag --nx 8 --ny 8 --tsize 0.1 --tspace 0.3
# 作者给的:
eg: rosrun kalibr kalibr_create_target_pdf --type apriltag --nx 6 --ny 6 --tsize 0.088 --tspace 0.3
エラーが報告された場合:「pyx」という名前のモジュールはありません。解決するには、github の問題を参照してください。
sudo apt install python-pyx #18.04
sudo apt install python3-pyx #20.04
現在のディレクトリに pdf ファイルが生成されます。
1.3.3 校正方法
(1) 最初にデータを記録し、自分のカメラを駆動し、データを記録するときに上下左右に移動し、前後に 3 回ずつ回転し、最後にロバスト性を高めるためのランダムな動きがあります。
rosbag record /image_raw -O images.bag
kalibr が推奨するフレーム レートは 4Hz です. これはフレーム ドロップ コマンドです. 元の rosbag の old_topic を 4hz の new_topic にドロップし, rosbag の再生中に new_topic を記録します:
rosrun topic_tools throttle messages old_topic 4.0 new_topic
(2) その後、校正することができます
source devel/setup.bash
rosrun kalibr kalibr_calibrate_cameras --target april_6x6_24x24mm.yaml --bag images.bag --bag-from-to 5 20 --models pinhole-radtan --topics /image_raw --show-extraction
その中で、いくつかのパラメータ ファイルに注意を払う必要があります。
--bag images.bag
: 記録されたパケット パス。--bag-from-to 5 20
袋の5秒目から20秒目までを読むことを指し、最初と最後に多少の激しいジッタがあり、エラーの原因となる可能性があるため、最初と最後の一部を切り取ります。プロセス全体がスムーズで、途切れることはありません。--target april_6x6_24x24mm.yaml
: tagSize と tagSpacing の 2 つのパラメータの作者が具体的に意味を説明したキャリブレーション ボード パラメータ ファイルを、自分で印刷したキャリブレーション ボードに合わせて変更します。
target_type: 'aprilgrid' #gridtype
tagCols: 6 #number of apriltags
tagRows: 6 #number of apriltags
tagSize: 0.088 #size of apriltag, edge to edge [m]
tagSpacing: 0.3 #ratio of space between tags to tagSize
codeOffset: 0 #code offset for the first tag in the aprilboard
--models pinhole-radtan
: カメラ モデル。これはピンホール カメラ モデルです。pinhole-radtan は最も一般的に使用されるカメラ モデルであり、半径方向の歪みと接線方向の歪みを含みます。詳細については、著者によるカメラ モデルの説明を参照してください。--topics /image_raw
: 画像トピック;--show-extraction
: 画像を表示し、抽出された特徴点を確認できます。
キャリブレーションが完了すると、描画結果が自動的にポップアップ表示されます (使用したデータは正しくありません。再投影エラーが少し大きいため、さらにいくつかのデータを記録する必要があります)。
次の結果ファイルを同時に生成します。
- カメラの内部パラメータ:
cam0:
cam_overlaps: []
camera_model: pinhole
distortion_coeffs: [-0.294719325148729, 0.08601391290708914, -0.0003238494917967103, -0.00041999959826033857]
distortion_model: radtan
intrinsics: [461.14152593310064, 459.7917242849438, 363.2138823275693, 235.61324563304655]
resolution: [752, 480]
rostopic: /cam0/image_raw
- キャリブレーション結果のtxtファイル。
- キャリブレーション結果のプロットの pdf。
1.4 解決策 4: キャリブレーションのために OpenCV を呼び出すプログラムを作成する
書籍「OpenCV4クイックスタート」を参照
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <vector>
#include <cstring>
#include <sstream>
#include <cstdlib>
using namespace std;
using namespace cv;
void initUndistAndRemap(vector<Mat> imgs, Mat cameraMatrix, Mat distCoeffs, Size imageSize, vector<Mat> &undistImgs)
{
// 计算映射坐标矩阵
Mat R = Mat::eye(3, 3, CV_32F);
Mat mapx = Mat(imageSize, CV_32FC1);
Mat mapy = Mat(imageSize, CV_32FC1);
// 内参矩阵/畸变系数/...
initUndistortRectifyMap(cameraMatrix, distCoeffs, R, cameraMatrix, imageSize, CV_32FC1, mapx, mapy);
for (int i = 0; i < imgs.size(); i++)
{
Mat undistImg;
remap(imgs[i], undistImg, mapx, mapy, INTER_LINEAR);
undistImgs.push_back(undistImg);
}
}
void undist(vector<Mat> imgs, Mat cameraMatrix, Mat distCoeffs, vector<Mat> &undistImgs)
{
for (int i = 0; i < imgs.size(); i++)
{
Mat undistImg;
// 单幅图像去畸变:畸变图像/去畸变后的图像/内参矩阵/畸变系数
undistort(imgs[i], undistImg, cameraMatrix, distCoeffs);
undistImgs.push_back(undistImg);
}
}
bool LoadData(const string &imagePath, const string &imageFilename, vector<Mat> &imgs)
{
ifstream Left;
Left.open(imageFilename.c_str());
while (!Left.eof())
{
string s;
getline(Left, s);
if (!s.empty())
{
stringstream ss;
ss << s;
double t;
string imageName;
ss >> t;
ss >> imageName;
Mat img = imread(imagePath + "/" + imageName);
imgs.push_back(img);
if (!img.data)
{
cout << "请输入正确的图像文件" << endl;
return 0;
}
}
}
return 1;
}
int main(int argc, char **argv)
{
if (argc != 6)
{
cerr << endl
<< "Usage: ./CameraCalibration path_to_CalibrateImage path_to_calibdata.txt board_size_cols board_size_rows corners_of_checkerboard(mm)" << endl
<< "eg: ./CameraCalibration ../CalibrateData ../CalibrateData/calibdata.txt 9 6 10" << endl;
return 1;
}
// -1 读取数据
vector<Mat> imgs;
LoadData(argv[1], argv[2], imgs);
// 棋盘格内角点行列数
int bcols, brows;
// 棋盘格每个方格的真实尺寸
double side_length;
stringstream ss;
ss << argv[3];
ss >> bcols;
ss.clear();
ss << argv[4];
ss >> brows;
ss.clear();
ss << argv[5];
ss >> side_length;
Size board_size = Size(bcols, brows);
// -2 提取并计算标定板角点像素坐标
// 多副图像分别放入vector<vector<Point2f>>
vector<vector<Point2f>> imgsPoints;
for (int i = 0; i < imgs.size(); i++)
{
Mat img1 = imgs[i], gray1;
cvtColor(img1, gray1, COLOR_BGR2GRAY);
vector<Point2f> img1_points;
// 第一个参数是输入的棋盘格图像
// 第二个参数是棋盘格内部的角点的行列数(注意:不是棋盘格的行列数,而内部角点-不包括边缘-的行列数)
// 第三个参数是检测到的棋盘格角点,类型为std::vector<cv::Point2f>
bool ret = findChessboardCorners(gray1, board_size, img1_points);
// 细化标定板角点坐标(亚像素),Size(5, 5)为细化方格坐标领域范围
find4QuadCornerSubpix(gray1, img1_points, Size(5, 5));
// 第一个参数是棋盘格图像(8UC3)既是输入也是输出
// 第二个参数是棋盘格内部角点的行、列
// 第三个参数是检测到的棋盘格角点
// 第四个参数是cv::findChessboardCorners()的返回值。
drawChessboardCorners(img1, board_size, img1_points, ret);
// string windowNumber = to_string(i);
// imshow("chessboard corners"+windowNumber, img1);
imgsPoints.push_back(img1_points);
}
// -3 使用棋盘格每个内角点的世界坐标
vector<vector<Point3f>> objectPoints; // 空间三维坐标(位于一个平面内,以此为xy坐标平面)
for (int i = 0; i < imgsPoints.size(); i++)
{
vector<Point3f> tempPointSet;
for (int j = 0; j < board_size.height; j++)
{
for (int k = 0; k < board_size.width; k++)
{
// 假设标定板为世界坐标系的z平面,即z=0
Point3f realPoint;
realPoint.x = j * side_length;
realPoint.y = k * side_length;
realPoint.z = 0;
tempPointSet.push_back(realPoint);
}
}
objectPoints.push_back(tempPointSet);
}
// -4 内参及畸变标定
Size imageSize; // 图像尺寸
imageSize.width = imgs[0].cols;
imageSize.height = imgs[0].rows;
// 定义内外参
Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); // 相机内参数矩阵
Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)); // 相机的5个畸变系数
vector<Mat> rvecs, tvecs; // 每幅图像的旋转向量/平移向量
// 调用OpenCV标定函数
calibrateCamera(objectPoints, imgsPoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, 0);
cout << "相机的内参矩阵K=" << endl
<< cameraMatrix << endl;
cout << "相机畸变系数:" << endl
<< distCoeffs << endl;
// -5 保存数据
ofstream calibrateFile;
// 写入数据:
calibrateFile.open("../calibrateCamera.txt"); // 没有自动创建
if (!calibrateFile.is_open()) // 文件是否打开
{
exit(EXIT_FAILURE); // 终止程序
}
calibrateFile << fixed; // 开始写入,与cout相同
calibrateFile.precision(5); // 写入小数精度
calibrateFile << "cameraMatrix K=" << endl
<< cameraMatrix; // 写入数据(覆盖
calibrateFile << endl << "distCoeffs=" << endl
<< distCoeffs;
calibrateFile.close();
// -6 图像去畸变
vector<Mat> undistImgs;
// 使用initUndistortRectifyMap()函数和remap()函数校正图像
initUndistAndRemap(imgs, cameraMatrix, distCoeffs, imageSize, undistImgs); // 畸变图像/前文计算得到的内参矩阵/畸变系数/图像尺寸/去畸变后的图像,自定义函数是为了处理多副图像
// undist(imgs, cameraMatrix, distCoeffs, undistImgs);//用undistort()函数直接计算校正图像,自定义函数是为了处理多副图像
// 显示校正前后的图像(一张示例)
for (int i = 0; i < 1; i++)
{
string windowNumber = to_string(i);
imshow("chessboard corners without undistort -- image" + windowNumber, imgs[i]);
imshow("chessboard corners with undistort -- image" + windowNumber, undistImgs[i]);
imwrite("../chessboard corners without undistort.png", imgs[i]);
imwrite("../chessboard corners with undistort.png", undistImgs[i]);
}
waitKey(0);
// -7 单目投影(重投影):根据成像模型及空间点三位坐标计算图像二维坐标
vector<vector<Point2f>> imagePoints; // 存放二维坐标
// 根据三维坐标和相机与世界坐标系时间的关系估计内角点像素坐标
for (int i = 0; i < imgs.size(); i++)
{
Mat rvec = rvecs[i], tvec = tvecs[i];
vector<Point3f> PointSets = objectPoints[i];
vector<Point2f> imagePoint; // 存放二维坐标
projectPoints(PointSets, rvec, tvec, cameraMatrix, distCoeffs, imagePoint); // 输入三维点/旋转及平移向量/前文计算得到的内参矩阵和畸变矩阵/输出二维点
imagePoints.push_back(imagePoint);
}
// -8 计算重投影误差
vector<vector<double>> ReProjectionError;
vector<vector<double>> ReProjectionErrorX;
vector<vector<double>> ReProjectionErrorY;
double e = 0.0;
for (int i = 0; i < imgs.size(); i++)
{
vector<Point2f> imagePoint = imagePoints[i]; // 存放二维坐标
vector<double> er;
vector<double> erX;
vector<double> erY;
for (int j = 0; j < imagePoint.size(); j++)
{
double eX = imagePoint[j].x - imgsPoints[i][j].x;
double eY = imagePoint[j].y - imgsPoints[i][j].y;
double error = sqrt(pow(eX, 2) + pow(eY, 2));
erX.push_back(eX);
erY.push_back(eY);
er.push_back(error);
e += error;
}
ReProjectionError.push_back(er);
ReProjectionErrorX.push_back(erX);
ReProjectionErrorY.push_back(erY);
}
// 计算估计值和图像中计算的真实时之间的平均误差
cout << "平均重投影误差:" << e / (imagePoints[0].size() * imgs.size()) << endl;
// -9 保存重投影误差数据
ofstream ReProjectionErrorFile;
ReProjectionErrorFile.open("../ReProjectionError.txt");
ofstream ReProjectionErrorFileX;
ReProjectionErrorFileX.open("../ReProjectionErrorX.txt");
ofstream ReProjectionErrorFileY;
ReProjectionErrorFileY.open("../ReProjectionErrorY.txt");
if (!ReProjectionErrorFile.is_open() || !ReProjectionErrorFileX.is_open() || !ReProjectionErrorFileY.is_open())
{
exit(EXIT_FAILURE);
}
ReProjectionErrorFile << fixed;
ReProjectionErrorFile.precision(5);
ReProjectionErrorFileX << fixed;
ReProjectionErrorFileX.precision(5);
ReProjectionErrorFileY << fixed;
ReProjectionErrorFileY.precision(5);
for (int i = 0; i < imgs.size(); i++)
{
for (int j = 0; j < imagePoints[i].size(); j++)
{
ReProjectionErrorFile << ReProjectionError[i][j] << " ";
ReProjectionErrorFileX << ReProjectionErrorX[i][j] << " ";
ReProjectionErrorFileY << ReProjectionErrorY[i][j] << " ";
}
ReProjectionErrorFile << endl;
ReProjectionErrorFileX << endl;
ReProjectionErrorFileY << endl;
}
ReProjectionErrorFile.close();
ReProjectionErrorFileX.close();
ReProjectionErrorFileY.close();
/*
// 圆形标定板角点提取
Mat img2 = imread("../CalibrateData/circle.png");
Mat gray2;
cvtColor(img2, gray2, COLOR_BGR2GRAY);
Size board_size2 = Size(7, 7); //圆形标定板圆心数目(行,列)
vector<Point2f> img2_points;//检测角点,单副图像放入vector<Point2f>
findCirclesGrid(gray2, board_size2, img2_points); //计算圆形标定板检点
find4QuadCornerSubpix(gray2, img2_points, Size(5, 5)); //细化圆形标定板角点坐标
drawChessboardCorners(img2, board_size2, img2_points, true);
imshow("圆形标定板角点检测结果", img2);
waitKey();
*/
return 0;
}
本のデータを例に取ります。
歪み補正前後の違いが分かり、画像の直線が歪まなくなりました
Python を使用して再投影誤差をプロットします。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 编 写:ZARD帧心
import numpy as np
import matplotlib.pyplot as plt
errorX = np.genfromtxt('ReProjectionErrorX.txt') # 将文件中数据加载到数组里
errorY = np.genfromtxt('ReProjectionErrorY.txt')
(m, n) = np.shape(errorX)
error = (errorX**2 + errorY**2)**0.5
# 画每帧图像的重投影误差均值
error_image = np.average(error, axis=1) # 按行求均值
image = range(m)
plt.bar(image, error_image)
plt.xlabel('Image number',{
'Size':30})
plt.ylabel('ReProjection Error (pixel)',{
'Size':30})
plt.xticks(fontsize=30) #x轴刻度字体大小
plt.yticks(fontsize=30) #y轴刻度字体大小
plt.show()
# 画所有角点的重投影误差
x = errorX.reshape(m*n,1)
y = errorY.reshape(m*n,1)
r = error.reshape(m*n,1) # 用于映射颜色的数值
# np.set_printoptions(threshold=np.inf)
# print(r)
# print(max(r))
h = plt.scatter(x, y, c=r, marker='*', alpha=0.8, cmap='viridis')
plt.xlabel('X error (pixel)',{
'Size':30})
plt.ylabel('Y error (pixel)',{
'Size':30})
plt.xticks(fontsize=30) #x轴刻度字体大小
plt.yticks(fontsize=30) #y轴刻度字体大小
cb=plt.colorbar(h) # 显示颜色条
font = {
'weight' : 'normal',
'size' : 30, }
cb.ax.tick_params(labelsize=30) #设置色标刻度字体大小。
cb.set_label('ReProjection Error',fontdict=font) #设置colorbar的标签字体及其大小
plt.show()
以下はScheme 1 MATLABと同じデータを描画した結果で、MATLABとはかけ離れています. 私のコードの書き方に問題があるのかもしれません. 誰かがそれを変更する必要がある場所を見たら, 教えてください, ありがとうあなた
その後、単純な方法を使用して全体的なエラーを排除し、次の結果を得ました。これは、より優れていますが、MATLAB にはまだほど遠いものです。
2. IMU 内部パラメータのキャリブレーション
imu_utils を使用して IMU を調整します。以下を参照してください:記事
(1) 依存関係のインストール
sudo apt-get install libdw-dev
(2) imu_utilsとcode_utilsをダウンロードしますが、gaowenliang のimu_utilsにはユニットの問題があります。imu_utils の mintar バージョンを使用してください
(3) コンパイルする前に、いくつかの問題に注意してください。
- code_utils はeigen 、 OpenCV3、ceresに依存しています。これらは私の以前の記事へのリンクであり、それらのインストール チュートリアルがあります。
- imu_utils と code_utils を同時にコンパイルしないでください。imu_utils は code_utils に依存しているため、最初に code_utils をコンパイルしてから imu_utils をコンパイルしてください。
(4) ワークスペースに配置してコンパイルします。
catkin_make
- コンパイル エラー:
code_utils-master/src/sumpixel_test.cpp:2:24: fatal error: backward.hpp:No such file or directory
、 code_utils の下に見つかりましたsumpixel_test.cpp
。変更します
// #include "backward.hpp"
// 为
#include “code_utils/backward.hpp”
- C++ 標準ライブラリで多くのエラーが発生した場合は、まず C++ 標準を変更することを検討してください。
# set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS "-std=c++14")
(4) imu.bag を記録し、IMU を 30 ~ 120 分間静止させます。長いほど、IMU のバッグを記録します。
rosbag record /imu -O imu.bag
(5) IMU を調整します。例として、imu_utils のサンプル データを次に示します。
rosbag play -r 200 imu_utils/imu.bag #(这里要写你录制的包的路径,200倍速播放)
source ./devel/setup.bash
roslaunch imu_utils A3.launch #示例数据
ここのファイルには、A3.launch
IMU トピックと名前、キャリブレーション期間などのいくつかのパラメーターが含まれていることに注意してください。必要に応じて変更します。
<launch>
<node pkg="imu_utils" type="imu_an" name="imu_an" output="screen">
<param name="imu_topic" type="string" value= "/djiros/imu"/>
<param name="imu_name" type="string" value= "A3"/>
<param name="data_save_path" type="string" value= "$(find imu_utils)/data/"/>
<param name="max_time_min" type="int" value= "150"/>
<param name="max_cluster" type="int" value= "100"/>
</node>
</launch>
キャリブレーションが完了すると、mynteye_imu_param.yaml と複数の txt ファイルが $(find imu_utils)/data/ の下に生成されます。
3. カメラと IMU の共同キャリブレーション
以前にインストールされたキャリブレーション ツール kalibr を使用します。他のチュートリアルで指定されている推奨周波数は、カメラの場合は 20Hz、IMU の場合は 200Hz です。科学的にネットサーフィンができないので、著者から提供されたサンプルデータをダウンロードすることはできません. ここでのデータは、次のブログから取得されます: Ubuntu18.04+kalibr キャリブレーション ツールボックスのインストールとコンパイル
(1) 記録
2 つのニュースを購読する、画像、imu トピック:
rosbag record /imu_raw /image_raw
記録するときは、できるだけスムーズに動くようにしてください.速度が速すぎると、カメラで得られる画質が低下しすぎて、遅すぎてはいけません.イムの各軸を刺激するために、著者はデモンストレーションを提供しますデータ収集の参考に動画で、回転を各 3 回、不規則な動きの期間 (激しく運動しすぎないように注意) を行います。キャリブレーション ボードは完全に印刷されており、データ パケットを記録する際のカメラ距離は 0.8m を推奨します。
(2) キャリブレーション
source devel/setup.bash
rosrun kalibr kalibr_calibrate_imu_camera --target dynamic/april_6x6.yaml --bag dynamic/dynamic.bag --cam dynamic/camchain_mono.yaml --imu dynamic/imu_adis16448.yaml --bag-from-to 5 45 --imu-models scale-misalignment --timeoffset-padding 0.1 --show-extraction
1.3 と同様、パラメーター:
--dynamic/dynamic.bag
: 記録されたパケット パス。--bag-from-to 5 45
バッグ 5 秒から 45 秒まで読み取ります。--target april_6x6.yaml
: キャリブレーション ボード パラメータ ファイル。
target_type: 'aprilgrid' #gridtype
tagCols: 6 #number of apriltags
tagRows: 6 #number of apriltags
tagSize: 0.088 #size of apriltag, edge to edge [m]
tagSpacing: 0.3 #ratio of space between tags to tagSize
codeOffset: 0 #code offset for the first tag in the aprilboard
--cam dynamic/camchain.yaml
: 以前にキャリブレーションされたカメラの内部基準 (このデータを直接使用するのは正しくありません)。kalibr でキャリブレーションされていない場合は、次の形式に従ってファイルを変更する必要がある場合があります。
cam0:
cam_overlaps: [1, 3]
camera_model: pinhole
distortion_coeffs: [-0.0016509958435871643, 0.02437222940989351, -0.03582816956989852,
0.019860839087717054]
distortion_model: equidistant
intrinsics: [461.487246372674, 460.1113992557959, 356.39105303227853, 231.15719697054647]
resolution: [752, 480]
rostopic: /cam0/image_raw
--imu dynamic/imu_adis16448.yaml
: 前の方法で校正された IMU 内部基準を使用し、次の形式に記入します。
rostopic: /imu0
update_rate: 200.0 #Hz
accelerometer_noise_density: 0.01 #continous
accelerometer_random_walk: 0.0002
gyroscope_noise_density: 0.005 #continous
gyroscope_random_walk: 4.0e-06
--imu-models scale-misalignment
: IMUのパラメトリックモデル--timeoffset-padding 0.1
: 値が大きいほど、キャリブレーションの実行時間が長くなります
キャリブレーションが完了すると、結果の図面が自動的にポップアップ表示されます。
同時に、以下を含むいくつかの結果ファイルがデータ フォルダーに生成されます。
- カメラと imu の内部および外部パラメーター間の時間同期の差 (カメラに対する IMU の遅延):
cam0:
T_cam_imu:
- [0.01676354570202121, 0.9998590327410452, -0.000947724452812317, 0.06843047675330072]
- [-0.9998594579273542, 0.016763745309816058, 0.0002030674908090371, -0.014939612219976138]
- [0.00021892627629230532, 0.0009441871264906492, 0.999999530290868, -0.0038646995667698156]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [1, 3]
camera_model: pinhole
distortion_coeffs: [-0.0016509958435871643, 0.02437222940989351, -0.03582816956989852, 0.019860839087717054]
distortion_model: equidistant
intrinsics: [461.487246372674, 460.1113992557959, 356.39105303227853, 231.15719697054647]
resolution: [752, 480]
rostopic: /cam0/image_raw
timeshift_cam_imu: 5.9040012306710654e-05
- IMU の内部および外部パラメータ:
imu0:
T_i_b:
- [1.0, 0.0, 0.0, 0.0]
- [0.0, 1.0, 0.0, 0.0]
- [0.0, 0.0, 1.0, 0.0]
- [0.0, 0.0, 0.0, 1.0]
accelerometer_noise_density: 0.01
accelerometer_random_walk: 0.0002
gyroscope_noise_density: 0.005
gyroscope_random_walk: 4.0e-06
model: calibrated
rostopic: /imu0
time_offset: 0.0
update_rate: 200.0
- キャリブレーション結果のtxtファイル
- 校正結果図面のpdf文書
4. カメラと LiDAR の共同キャリブレーション
キャリブレーション方法はAutowareから分離されたキャリブレーションパッケージcalibration_camera_lidar
です(1) cmakeはnloptを正常にインストールします
git clone https://github.com/stevengj/nlopt.git
cd nlopt
mkdir build && cd build
cmake ..
make
sudo make install
インストールに sudo apt-get install を使用しないように注意してください。catkin_make は後で問題に遭遇します
(2) calibration_camera_lidar をコンパイルします。
catkin_make
- 古いパッケージはメロディックまたはノエティック バージョンの ROS サポートを追加する必要があり、CMakelists.txt 行 72/94/114 を変更します。
# if ("{ROS_VERSION}" MATCHES "(indigo|jade|kinetic)")
if ("{ROS_VERSION}" MATCHES "(indigo|jade|kinetic|melodic|noetic)")
- エラーが報告された場合
jsk_recognition_msgsConfig.cmake
jsk_recognition_msgs-config.cmake
コンパイル用の jsk-recognition-msgs パッケージがないことを説明し、インストールします。
sudo apt-get install ros-<ROS VERSION NAME>-jsk-recognition-msgs
- エラー:
error: ‘CV_RGB’ was not declared in this scope; did you mean ‘CV_YUV2RGB’?
位置プロンプトに従って、エラー位置の CV_RGB を cvScalar に変更します - Error: e
rror: no match for ‘operator=’ (operand types are ‘CvMat’ and ‘cv::Mat’)
これは CvMat と cv::Mat の相互変換の問題です. 間違った 2 つの文を次のように変更してください:
*m_intrinsic = cvMat(m_intrinsic_opencv2to1);
*m_dist = cvMat(m_dist_opencv2to1);
- エラー: 、
cv_image->image
エラーcv_image->image
を に変更しますcvIplImage(cv_image->image)
。異なるバージョンでは、cvIplimage が Iplimage と記述され、cvMat が CvMat と記述される場合があることに注意してください。
上記はすべて OpenCV のバージョンの問題であり、コードは opencv2 をベースに記述されており、opencv3/4 とは互換性がありません。
- CMakeFiles/calibration_publisher.dir/nodes/calibration_publisher/calibration_publisher.cpp.o: 関数内
void cv::operator>><cv::Mat>(cv::FileNode const&, cv::Mat&)': /usr/local/include/opencv2/core/persistence.hpp:1261: undefined reference to
cv::Mat::Mat()'
CMakeLists.txt 内の calibration_publisher ノードの opencv をリンクします
target_link_libraries(calibration_publisher
${catkin_LIBRARIES}
${OpenCV_LIBS})
(3) 録画パッケージ: 車の固定、キャリブレーション ボードの移動を選択します。キャリブレーション ボードの動きは、カメラのキャリブレーションに似ています。車の前面に対して、遠近、左右、さまざまな傾斜姿勢を基準にします。 (Autoware または記録の使用を選択できます); (4) 実行機能rosbasg record TOPIC
パッケージ
:
source devel/setup.bash
# 新开一个终端执行roscore
rosrun calibration_camera_lidar calibration_toolkit
(5) キャリブレーション方法
1) Autoware を使用してデータ セットを再生および一時停止する;
2) 起動後に画像トピックを選択する (公開したトピックに従って選択する);
3) キャリブレーション タイプを選択する: カメラからベロダインへ;
ツールがオートウェアに基づいているため、ここでは点群トピックを に変換する必要があります/points_raw
。点群トピックが間違っている場合は、次の 2 つの方法で変更できます。
- レーダー ドライバのパラメータ設定で、フレーム ID を velodyne に直接変更し、トピックを /points_raw に変更します。
- rosbag をプレイするときは、トピックを変更します
。たとえば、次のようになります。
rosbag play autoware-20221006.bag /rslidar_points:=/points_raw
4) [OK] をクリックしてキャリブレーション インターフェイスをポップアップします. インターフェイスの上のテキスト ボックスに入力するパターン サイズは、キャリブレーション ボード上のチェッカーボードの辺の長さ (m) であり、パターン番号はコーナー サイズです (注:これは、内部コーナー ポイントの数、つまりチェッカーボード グリッドの長さと幅です。-1)
5) キャリブレーションの前に、カメラの内部パラメーターによってキャリブレーションされた yml ファイルをインポートします (この関数パッケージを使用したキャリブレーションの結果である必要があります。次の手順でカメラの内部パラメーターを同時にキャリブレーションするため、この手順は必要ありません)。 、[読み込み] をクリックしてファイルをインポートします。インポートが完了すると、cameramat /distcoeff /imagesize に対応する内部パラメーター値が表示されます。
6) ウィンドウのサイズを調整し、黒い部分をマウスでクリックし、b を押して色を調整し、2 を押してモードを切り替え、視野角を調整し、点群データを表示します LiDAR 可視化調整方法: 点群を移動: 点群の回転: モードの切り替え:
視野上下左右方向键、PgUp、PgDn
角a、d、w、s、q、e
ズーム数字1和数字2
:减号缩小、加号放大
点群のサイズ:o键缩小点云、p放大点云(建议放大,较为清晰)
点群ウィンドウの背景色の変更:b(建议背景全部调整成白色,清晰)
適切なフレームを再生した後、データ セットを一時停止し (キャリブレーション ボードが完成し、画像とポイント クラウドで明確になっています)、[グラブ] をクリックしてデータのフレームを代替キャリブレーション シーケンスに追加します。次に、座標軸がキャリブレーション ボードの中心に当たるように右下隅のレーザー データの角度を調整し、左ボタンをクリックして赤い中心をマークし、キャリブレーション フレームに追加します。赤いマークが間違っている場合は、右クリックして赤いマークをキャンセルできます. この代替フレームに満足できない場合は、右上隅の [削除] をクリックします. 以下に示すように:
約 30 フレームをマークし、[調整] をクリックして調整結果の計算を開始すると、CameraExtrinsicMat /cameramat /distcoeff /imagesize に対応するパラメーター値が表示されます。結果が計算されたら、プロジェクトをクリックしてキャリブレーション ボードのレーザー ポイントを画像に投影し、キャリブレーションが正しいかどうか、画像の赤い点を大まかに確認し、最後に左上隅の [保存] をクリックして、キャリブレーション結果を保存します(カメラの内側と外側を含むジョイントキャリブレーション結果のみを保存します参照:カメラ座標系からレーダー座標系へ。.ymlファイルとして保存します。キャリブレーションに使用されるデータは保存しないでください。が大きすぎる場合は、必要に応じて保存できます)
(7) 結果が保存された後、Autoware を介してカメラと LiDAR キャリブレーションの融合結果を視覚化し、シミュレーションでデータを再生し、センシング インターフェイスで [キャリブレーション パブリッシャー] をクリックして、キャリブレーション結果ファイル、ライダー フレーム ID を読み込みます。 target_frame のキャリブレーション データ; camera_frame ID のキャリブレーション データ内のビジュアル カメラ フレーム; ref 選択列で、yml ファイルを読み込みます
ポイント画像をもう一度クリックし、rviz を開きます。メニュー バーの Panels - Add New Panel を開き、ImageViewPlugin プラグインを選択し、画像と点群のトピックを選択してから、データ セットを再生し続けると、画像と点群の融合を見ることができます
5. LiDAR と IMU の共同キャリブレーション
キャリブレーション パッケージの lidar_imu_calib を使用します。前の 2 つの章のキャリブレーションの後、LiDAR と IMU の外部パラメーターを直接計算できますが、以前のキャリブレーションが正しいかどうか、またはデバイスに視覚センサーがないかどうかを確認することもできます。
5.1 解決策 1: 浙江大学のオープン ソース lidar_IMU_calib
5.2 解決策 2: ライダーの位置合わせ
5.3 解決策 3: lidar_imu_calib
この関数パッケージは、ライダーと imu の間の変換で姿勢コンポーネントのみを調整します (1) github
からソース コードをダウンロードし、独自のワークスペースでコンパイルします。
catkin_make
多数の PCL エラーが発生した場合は、ubuntu 20.04 の ROS バージョンが noetic であり、独自の pcl が pcl-1.10 であるためです.このバージョンは、c++14 以降でコンパイルし、CMakeLists で変更する必要があります. txt (2
) 記録パッケージ: 記録環境は、劣化した環境 (多数の樹木、低木、またはトンネル) ではなく、豊富な構造を持つ建物など、多くの平面および線の特徴を持つ場所である必要があり、車はゆっくりと動きます ( 3)
キャリブレーション
- Launch ファイルで IMU、LiDAR メッセージのトピック名とバッグのパスを変更します。
<launch>
<node pkg="lidar_imu_calib" type="calib_exR_lidar2imu_node" name="calib_exR_lidar2imu_node" output="screen">
<param name="/lidar_topic" value="/velodyne_points"/>
<param name="/imu_topic" value="/imu/data"/>
<param name="/bag_file" value="/media/zard/SLAMData/2017-06-08-15-52-45_3.bag"/>
</node>
</launch>
- 実行機能パッケージ:
roslaunch lidar_imu_calib calib_exR_lidar2imu.launch
関数パッケージは、徐々に追加された LIDAR メッセージを表示し、最後に LIDAR メッセージの数と imu の数を表示し、制約の数を形成し、しばらくすると計算結果が表示されます。