feat(calibration): support configurable board size and chessboard
This commit is contained in:
parent
9b0701fe6b
commit
5f67ef69e4
108
calibration/board_pattern.hpp
Normal file
108
calibration/board_pattern.hpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#ifndef CALIBRATION__BOARD_PATTERN_HPP
|
||||||
|
#define CALIBRATION__BOARD_PATTERN_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
namespace calibration
|
||||||
|
{
|
||||||
|
enum class PatternType
|
||||||
|
{
|
||||||
|
circles_grid,
|
||||||
|
chessboard
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoardPattern
|
||||||
|
{
|
||||||
|
cv::Size pattern_size;
|
||||||
|
double center_distance_mm;
|
||||||
|
PatternType pattern_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string normalize(std::string text)
|
||||||
|
{
|
||||||
|
std::transform(
|
||||||
|
text.begin(), text.end(), text.begin(),
|
||||||
|
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PatternType parse_pattern_type(const YAML::Node & yaml)
|
||||||
|
{
|
||||||
|
if (!yaml["pattern_type"]) return PatternType::circles_grid;
|
||||||
|
|
||||||
|
auto raw = normalize(yaml["pattern_type"].as<std::string>());
|
||||||
|
if (raw == "circles_grid" || raw == "circle_grid" || raw == "circles") {
|
||||||
|
return PatternType::circles_grid;
|
||||||
|
}
|
||||||
|
if (raw == "chessboard" || raw == "checkerboard") {
|
||||||
|
return PatternType::chessboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Unsupported pattern_type: " + raw +
|
||||||
|
". Supported values: circles_grid, chessboard.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string pattern_name(PatternType pattern_type)
|
||||||
|
{
|
||||||
|
return pattern_type == PatternType::chessboard ? "chessboard" : "circles_grid";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BoardPattern load_board_pattern(const YAML::Node & yaml)
|
||||||
|
{
|
||||||
|
BoardPattern board_pattern;
|
||||||
|
board_pattern.pattern_size = cv::Size(yaml["pattern_cols"].as<int>(), yaml["pattern_rows"].as<int>());
|
||||||
|
board_pattern.center_distance_mm = yaml["center_distance_mm"].as<double>();
|
||||||
|
board_pattern.pattern_type = parse_pattern_type(yaml);
|
||||||
|
return board_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool find_pattern_points(
|
||||||
|
const cv::Mat & img, const BoardPattern & board_pattern, std::vector<cv::Point2f> & points)
|
||||||
|
{
|
||||||
|
if (board_pattern.pattern_type == PatternType::circles_grid) {
|
||||||
|
return cv::findCirclesGrid(
|
||||||
|
img, board_pattern.pattern_size, points, cv::CALIB_CB_SYMMETRIC_GRID);
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat gray;
|
||||||
|
if (img.channels() == 1)
|
||||||
|
gray = img;
|
||||||
|
else
|
||||||
|
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
|
||||||
|
|
||||||
|
auto flags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE;
|
||||||
|
auto success = cv::findChessboardCorners(gray, board_pattern.pattern_size, points, flags);
|
||||||
|
if (!success) return false;
|
||||||
|
|
||||||
|
cv::cornerSubPix(
|
||||||
|
gray, points, cv::Size(11, 11), cv::Size(-1, -1),
|
||||||
|
cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 1e-3));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<cv::Point3f> planar_points(
|
||||||
|
const cv::Size & pattern_size, const double center_distance_mm)
|
||||||
|
{
|
||||||
|
std::vector<cv::Point3f> points;
|
||||||
|
points.reserve(static_cast<size_t>(pattern_size.width * pattern_size.height));
|
||||||
|
|
||||||
|
for (int i = 0; i < pattern_size.height; i++) {
|
||||||
|
for (int j = 0; j < pattern_size.width; j++) {
|
||||||
|
points.push_back({static_cast<float>(j * center_distance_mm), static_cast<float>(i * center_distance_mm), 0.0f});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace calibration
|
||||||
|
|
||||||
|
#endif // CALIBRATION__BOARD_PATTERN_HPP
|
||||||
@ -4,6 +4,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
|
#include "calibration/board_pattern.hpp"
|
||||||
#include "src/component/img_tools.hpp"
|
#include "src/component/img_tools.hpp"
|
||||||
|
|
||||||
const std::string keys =
|
const std::string keys =
|
||||||
@ -11,17 +12,6 @@ const std::string keys =
|
|||||||
"{config-path c | configs/calibration.yaml | yaml配置文件路径 }"
|
"{config-path c | configs/calibration.yaml | yaml配置文件路径 }"
|
||||||
"{@input-folder | assets/img_with_q | 输入文件夹路径 }";
|
"{@input-folder | assets/img_with_q | 输入文件夹路径 }";
|
||||||
|
|
||||||
std::vector<cv::Point3f> centers_3d(const cv::Size & pattern_size, const float center_distance)
|
|
||||||
{
|
|
||||||
std::vector<cv::Point3f> centers_3d;
|
|
||||||
|
|
||||||
for (int i = 0; i < pattern_size.height; i++)
|
|
||||||
for (int j = 0; j < pattern_size.width; j++)
|
|
||||||
centers_3d.push_back({j * center_distance, i * center_distance, 0});
|
|
||||||
|
|
||||||
return centers_3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(
|
void load(
|
||||||
const std::string & input_folder, const std::string & config_path, cv::Size & img_size,
|
const std::string & input_folder, const std::string & config_path, cv::Size & img_size,
|
||||||
std::vector<std::vector<cv::Point3f>> & obj_points,
|
std::vector<std::vector<cv::Point3f>> & obj_points,
|
||||||
@ -29,10 +19,7 @@ void load(
|
|||||||
{
|
{
|
||||||
// 读取yaml参数
|
// 读取yaml参数
|
||||||
auto yaml = YAML::LoadFile(config_path);
|
auto yaml = YAML::LoadFile(config_path);
|
||||||
auto pattern_cols = yaml["pattern_cols"].as<int>();
|
auto board_pattern = calibration::load_board_pattern(yaml);
|
||||||
auto pattern_rows = yaml["pattern_rows"].as<int>();
|
|
||||||
auto center_distance_mm = yaml["center_distance_mm"].as<double>();
|
|
||||||
cv::Size pattern_size(pattern_cols, pattern_rows);
|
|
||||||
|
|
||||||
for (int i = 1; true; i++) {
|
for (int i = 1; true; i++) {
|
||||||
// 读取图片
|
// 读取图片
|
||||||
@ -45,11 +32,11 @@ void load(
|
|||||||
|
|
||||||
// 识别标定板
|
// 识别标定板
|
||||||
std::vector<cv::Point2f> centers_2d;
|
std::vector<cv::Point2f> centers_2d;
|
||||||
auto success = cv::findCirclesGrid(img, pattern_size, centers_2d, cv::CALIB_CB_SYMMETRIC_GRID);
|
auto success = calibration::find_pattern_points(img, board_pattern, centers_2d);
|
||||||
|
|
||||||
// 显示识别结果
|
// 显示识别结果
|
||||||
auto drawing = img.clone();
|
auto drawing = img.clone();
|
||||||
cv::drawChessboardCorners(drawing, pattern_size, centers_2d, success);
|
cv::drawChessboardCorners(drawing, board_pattern.pattern_size, centers_2d, success);
|
||||||
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 缩小图片尺寸便于显示完全
|
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 缩小图片尺寸便于显示完全
|
||||||
cv::imshow("Press any to continue", drawing);
|
cv::imshow("Press any to continue", drawing);
|
||||||
cv::waitKey(0);
|
cv::waitKey(0);
|
||||||
@ -60,7 +47,8 @@ void load(
|
|||||||
|
|
||||||
// 记录所需的数据
|
// 记录所需的数据
|
||||||
img_points.emplace_back(centers_2d);
|
img_points.emplace_back(centers_2d);
|
||||||
obj_points.emplace_back(centers_3d(pattern_size, center_distance_mm));
|
obj_points.emplace_back(
|
||||||
|
calibration::planar_points(board_pattern.pattern_size, board_pattern.center_distance_mm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <opencv2/core/eigen.hpp>
|
#include <opencv2/core/eigen.hpp>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
|
#include "calibration/board_pattern.hpp"
|
||||||
#include "src/component/img_tools.hpp"
|
#include "src/component/img_tools.hpp"
|
||||||
#include "src/component/math_tools.hpp"
|
#include "src/component/math_tools.hpp"
|
||||||
|
|
||||||
@ -14,17 +15,6 @@ const std::string keys =
|
|||||||
"{config-path c | configs/calibration.yaml | yaml配置文件路径 }"
|
"{config-path c | configs/calibration.yaml | yaml配置文件路径 }"
|
||||||
"{@input-folder | assets/img_with_q | 输入文件夹路径 }";
|
"{@input-folder | assets/img_with_q | 输入文件夹路径 }";
|
||||||
|
|
||||||
std::vector<cv::Point3f> centers_3d(const cv::Size & pattern_size, const float center_distance)
|
|
||||||
{
|
|
||||||
std::vector<cv::Point3f> centers_3d;
|
|
||||||
|
|
||||||
for (int i = 0; i < pattern_size.height; i++)
|
|
||||||
for (int j = 0; j < pattern_size.width; j++)
|
|
||||||
centers_3d.push_back({j * center_distance, i * center_distance, 0});
|
|
||||||
|
|
||||||
return centers_3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Eigen::Quaterniond read_q(const std::string & q_path)
|
Eigen::Quaterniond read_q(const std::string & q_path)
|
||||||
{
|
{
|
||||||
std::ifstream q_file(q_path);
|
std::ifstream q_file(q_path);
|
||||||
@ -41,14 +31,11 @@ void load(
|
|||||||
{
|
{
|
||||||
// 读取yaml参数
|
// 读取yaml参数
|
||||||
auto yaml = YAML::LoadFile(config_path);
|
auto yaml = YAML::LoadFile(config_path);
|
||||||
auto pattern_cols = yaml["pattern_cols"].as<int>();
|
auto board_pattern = calibration::load_board_pattern(yaml);
|
||||||
auto pattern_rows = yaml["pattern_rows"].as<int>();
|
|
||||||
auto center_distance_mm = yaml["center_distance_mm"].as<double>();
|
|
||||||
R_gimbal2imubody_data = yaml["R_gimbal2imubody"].as<std::vector<double>>();
|
R_gimbal2imubody_data = yaml["R_gimbal2imubody"].as<std::vector<double>>();
|
||||||
auto camera_matrix_data = yaml["camera_matrix"].as<std::vector<double>>();
|
auto camera_matrix_data = yaml["camera_matrix"].as<std::vector<double>>();
|
||||||
auto distort_coeffs_data = yaml["distort_coeffs"].as<std::vector<double>>();
|
auto distort_coeffs_data = yaml["distort_coeffs"].as<std::vector<double>>();
|
||||||
|
|
||||||
cv::Size pattern_size(pattern_cols, pattern_rows);
|
|
||||||
Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R_gimbal2imubody(R_gimbal2imubody_data.data());
|
Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R_gimbal2imubody(R_gimbal2imubody_data.data());
|
||||||
cv::Matx33d camera_matrix(camera_matrix_data.data());
|
cv::Matx33d camera_matrix(camera_matrix_data.data());
|
||||||
cv::Mat distort_coeffs(distort_coeffs_data);
|
cv::Mat distort_coeffs(distort_coeffs_data);
|
||||||
@ -75,10 +62,10 @@ void load(
|
|||||||
|
|
||||||
// 识别标定板
|
// 识别标定板
|
||||||
std::vector<cv::Point2f> centers_2d;
|
std::vector<cv::Point2f> centers_2d;
|
||||||
auto success = cv::findCirclesGrid(img, pattern_size, centers_2d); // 默认是对称圆点图案
|
auto success = calibration::find_pattern_points(img, board_pattern, centers_2d);
|
||||||
|
|
||||||
// 显示识别结果
|
// 显示识别结果
|
||||||
cv::drawChessboardCorners(drawing, pattern_size, centers_2d, success);
|
cv::drawChessboardCorners(drawing, board_pattern.pattern_size, centers_2d, success);
|
||||||
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
||||||
cv::imshow("Press any to continue", drawing);
|
cv::imshow("Press any to continue", drawing);
|
||||||
cv::waitKey(0);
|
cv::waitKey(0);
|
||||||
@ -92,7 +79,8 @@ void load(
|
|||||||
cv::Mat R_gimbal2world_cv;
|
cv::Mat R_gimbal2world_cv;
|
||||||
cv::eigen2cv(R_gimbal2world, R_gimbal2world_cv);
|
cv::eigen2cv(R_gimbal2world, R_gimbal2world_cv);
|
||||||
cv::Mat rvec, tvec;
|
cv::Mat rvec, tvec;
|
||||||
auto centers_3d_ = centers_3d(pattern_size, center_distance_mm);
|
auto centers_3d_ =
|
||||||
|
calibration::planar_points(board_pattern.pattern_size, board_pattern.center_distance_mm);
|
||||||
cv::solvePnP(
|
cv::solvePnP(
|
||||||
centers_3d_, centers_2d, camera_matrix, distort_coeffs, rvec, tvec, false, cv::SOLVEPNP_IPPE);
|
centers_3d_, centers_2d, camera_matrix, distort_coeffs, rvec, tvec, false, cv::SOLVEPNP_IPPE);
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <opencv2/core/eigen.hpp>
|
#include <opencv2/core/eigen.hpp>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
|
#include "calibration/board_pattern.hpp"
|
||||||
#include "src/component/img_tools.hpp"
|
#include "src/component/img_tools.hpp"
|
||||||
#include "src/component/math_tools.hpp"
|
#include "src/component/math_tools.hpp"
|
||||||
|
|
||||||
@ -46,14 +47,11 @@ void load(
|
|||||||
{
|
{
|
||||||
// 读取yaml参数
|
// 读取yaml参数
|
||||||
auto yaml = YAML::LoadFile(config_path);
|
auto yaml = YAML::LoadFile(config_path);
|
||||||
auto pattern_cols = yaml["pattern_cols"].as<int>();
|
auto board_pattern = calibration::load_board_pattern(yaml);
|
||||||
auto pattern_rows = yaml["pattern_rows"].as<int>();
|
|
||||||
auto center_distance_mm = yaml["center_distance_mm"].as<double>();
|
|
||||||
R_gimbal2imubody_data = yaml["R_gimbal2imubody"].as<std::vector<double>>();
|
R_gimbal2imubody_data = yaml["R_gimbal2imubody"].as<std::vector<double>>();
|
||||||
auto camera_matrix_data = yaml["camera_matrix"].as<std::vector<double>>();
|
auto camera_matrix_data = yaml["camera_matrix"].as<std::vector<double>>();
|
||||||
auto distort_coeffs_data = yaml["distort_coeffs"].as<std::vector<double>>();
|
auto distort_coeffs_data = yaml["distort_coeffs"].as<std::vector<double>>();
|
||||||
|
|
||||||
cv::Size pattern_size(pattern_cols, pattern_rows);
|
|
||||||
Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R_gimbal2imubody(R_gimbal2imubody_data.data());
|
Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R_gimbal2imubody(R_gimbal2imubody_data.data());
|
||||||
cv::Matx33d camera_matrix(camera_matrix_data.data());
|
cv::Matx33d camera_matrix(camera_matrix_data.data());
|
||||||
cv::Mat distort_coeffs(distort_coeffs_data);
|
cv::Mat distort_coeffs(distort_coeffs_data);
|
||||||
@ -80,10 +78,10 @@ void load(
|
|||||||
|
|
||||||
// 识别标定板
|
// 识别标定板
|
||||||
std::vector<cv::Point2f> centers_2d;
|
std::vector<cv::Point2f> centers_2d;
|
||||||
auto success = cv::findCirclesGrid(img, pattern_size, centers_2d); // 默认是对称圆点图案
|
auto success = calibration::find_pattern_points(img, board_pattern, centers_2d);
|
||||||
|
|
||||||
// 显示识别结果
|
// 显示识别结果
|
||||||
cv::drawChessboardCorners(drawing, pattern_size, centers_2d, success);
|
cv::drawChessboardCorners(drawing, board_pattern.pattern_size, centers_2d, success);
|
||||||
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
cv::resize(drawing, drawing, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
||||||
cv::imshow("Press any to continue", drawing);
|
cv::imshow("Press any to continue", drawing);
|
||||||
cv::waitKey(0);
|
cv::waitKey(0);
|
||||||
@ -98,7 +96,8 @@ void load(
|
|||||||
cv::Mat R_world2gimbal_cv;
|
cv::Mat R_world2gimbal_cv;
|
||||||
cv::eigen2cv(R_world2gimbal, R_world2gimbal_cv);
|
cv::eigen2cv(R_world2gimbal, R_world2gimbal_cv);
|
||||||
cv::Mat rvec, tvec;
|
cv::Mat rvec, tvec;
|
||||||
auto centers_3d_ = centers_3d(pattern_size, center_distance_mm);
|
auto centers_3d_ =
|
||||||
|
centers_3d(board_pattern.pattern_size, board_pattern.center_distance_mm);
|
||||||
cv::solvePnP(
|
cv::solvePnP(
|
||||||
centers_3d_, centers_2d, camera_matrix, distort_coeffs, rvec, tvec, false, cv::SOLVEPNP_IPPE);
|
centers_3d_, centers_2d, camera_matrix, distort_coeffs, rvec, tvec, false, cv::SOLVEPNP_IPPE);
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,13 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
|
#include "calibration/board_pattern.hpp"
|
||||||
#include "src/device/camera.hpp"
|
#include "src/device/camera.hpp"
|
||||||
#include "src/device/cboard.hpp"
|
#include "src/device/cboard.hpp"
|
||||||
#include "src/component/img_tools.hpp"
|
#include "src/component/img_tools.hpp"
|
||||||
#include "src/component/logger.hpp"
|
#include "src/component/logger.hpp"
|
||||||
#include "src/component/math_tools.hpp"
|
#include "src/component/math_tools.hpp"
|
||||||
|
#include "src/component/yaml.hpp"
|
||||||
|
|
||||||
const std::string keys =
|
const std::string keys =
|
||||||
"{help h usage ? | | 输出命令行参数说明}"
|
"{help h usage ? | | 输出命令行参数说明}"
|
||||||
@ -25,7 +27,8 @@ void write_q(const std::string q_path, const Eigen::Quaterniond & q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void capture_loop(
|
void capture_loop(
|
||||||
const std::string & config_path, const std::string & can, const std::string & output_folder)
|
const std::string & config_path, const std::string & output_folder,
|
||||||
|
const calibration::BoardPattern & board_pattern)
|
||||||
{
|
{
|
||||||
device::CBoard cboard(config_path);
|
device::CBoard cboard(config_path);
|
||||||
device::Camera camera(config_path);
|
device::Camera camera(config_path);
|
||||||
@ -45,8 +48,8 @@ void capture_loop(
|
|||||||
component::draw_text(img_with_ypr, fmt::format("X {:.2f}", zyx[2]), {40, 120}, {0, 0, 255});
|
component::draw_text(img_with_ypr, fmt::format("X {:.2f}", zyx[2]), {40, 120}, {0, 0, 255});
|
||||||
|
|
||||||
std::vector<cv::Point2f> centers_2d;
|
std::vector<cv::Point2f> centers_2d;
|
||||||
auto success = cv::findCirclesGrid(img, cv::Size(10, 7), centers_2d); // 默认是对称圆点图案
|
auto success = calibration::find_pattern_points(img, board_pattern, centers_2d);
|
||||||
cv::drawChessboardCorners(img_with_ypr, cv::Size(10, 7), centers_2d, success); // 显示识别结果
|
cv::drawChessboardCorners(img_with_ypr, board_pattern.pattern_size, centers_2d, success);
|
||||||
cv::resize(img_with_ypr, img_with_ypr, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
cv::resize(img_with_ypr, img_with_ypr, {}, 0.5, 0.5); // 显示时缩小图片尺寸
|
||||||
|
|
||||||
// 按“s”保存图片和对应四元数,按“q”退出程序
|
// 按“s”保存图片和对应四元数,按“q”退出程序
|
||||||
@ -79,13 +82,17 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
auto config_path = cli.get<std::string>(0);
|
auto config_path = cli.get<std::string>(0);
|
||||||
auto output_folder = cli.get<std::string>("output-folder");
|
auto output_folder = cli.get<std::string>("output-folder");
|
||||||
|
auto yaml = component::load(config_path);
|
||||||
|
auto board_pattern = calibration::load_board_pattern(yaml);
|
||||||
|
|
||||||
// 新建输出文件夹
|
// 新建输出文件夹
|
||||||
std::filesystem::create_directory(output_folder);
|
std::filesystem::create_directory(output_folder);
|
||||||
|
|
||||||
component::logger()->info("默认标定板尺寸为10列7行");
|
component::logger()->info(
|
||||||
|
"标定板类型: {}, 尺寸: {}x{}", calibration::pattern_name(board_pattern.pattern_type),
|
||||||
|
board_pattern.pattern_size.width, board_pattern.pattern_size.height);
|
||||||
// 主循环,保存图片和对应四元数
|
// 主循环,保存图片和对应四元数
|
||||||
capture_loop(config_path, "can0", output_folder);
|
capture_loop(config_path, output_folder, board_pattern);
|
||||||
|
|
||||||
component::logger()->warn("注意四元数输出顺序为wxyz");
|
component::logger()->warn("注意四元数输出顺序为wxyz");
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
pattern_cols: 10
|
pattern_cols: 10
|
||||||
pattern_rows: 7
|
pattern_rows: 7
|
||||||
center_distance_mm: 40
|
center_distance_mm: 40
|
||||||
|
pattern_type: circles_grid # circles_grid | chessboard
|
||||||
|
|
||||||
R_gimbal2imubody: [1, 0, 0, 0, 1, 0, 0, 0, 1]
|
R_gimbal2imubody: [1, 0, 0, 0, 1, 0, 0, 0, 1]
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user