Calibration Library 1.0.0
A C++ library for camera calibration and vision-related geometric transformations
Loading...
Searching...
No Matches
handeye.cpp
Go to the documentation of this file.
2
3// std
4#include <array>
5#include <stdexcept>
6#include <vector>
7
8// ceres
9#include <ceres/ceres.h>
10
11#include "detail/ceresutils.h"
14
15namespace calib {
16
17struct HandeyeBlocks final : public ProblemParamBlocks {
18 std::array<double, 4> quat;
19 std::array<double, 3> tran;
20
21 static auto create(const Eigen::Isometry3d& init_pose) -> HandeyeBlocks {
22 HandeyeBlocks blocks;
23 Eigen::Quaterniond quat_init(init_pose.linear());
24 blocks.quat = {quat_init.w(), quat_init.x(), quat_init.y(), quat_init.z()};
25 blocks.tran = {init_pose.translation().x(), init_pose.translation().y(),
26 init_pose.translation().z()};
27 return blocks;
28 }
29
30 [[nodiscard]]
31 auto get_param_blocks() const -> std::vector<ParamBlock> override {
32 return {{quat.data(), quat.size(), 3}, {tran.data(), tran.size(), 3}};
33 }
34
35 void populate_result(HandeyeResult& result) const {
36 Eigen::Quaterniond quat_final(quat[0], quat[1], quat[2], quat[3]);
37 quat_final.normalize();
38 Eigen::Isometry3d pose = Eigen::Isometry3d::Identity();
39 pose.linear() = quat_final.toRotationMatrix();
40 pose.translation() = Eigen::Vector3d(tran[0], tran[1], tran[2]);
41 result.g_se3_c = pose;
42 }
43};
44
45static auto build_problem(const std::vector<MotionPair>& pairs, const OptimOptions& opts,
46 HandeyeBlocks& blocks) -> ceres::Problem {
47 ceres::Problem problem;
48 for (const auto& motion_pair : pairs) {
49 auto* cost = AxXbResidual::create(motion_pair);
50 ceres::LossFunction* loss =
51 opts.huber_delta > 0
52 ? static_cast<ceres::LossFunction*>(new ceres::HuberLoss(opts.huber_delta))
53 : nullptr;
54 problem.AddResidualBlock(cost, loss, blocks.quat.data(), blocks.tran.data());
55 }
56 problem.SetManifold(blocks.quat.data(), new ceres::QuaternionManifold());
57 return problem;
58}
59
60auto optimize_handeye(const std::vector<Eigen::Isometry3d>& base_se3_gripper,
61 const std::vector<Eigen::Isometry3d>& camera_se3_target,
62 const Eigen::Isometry3d& init_gripper_se3_ref, const OptimOptions& options)
63 -> HandeyeResult {
64 constexpr double k_min_angle_deg = 0.5;
65 auto pairs = build_all_pairs(base_se3_gripper, camera_se3_target, k_min_angle_deg);
66 auto blocks = HandeyeBlocks::create(init_gripper_se3_ref);
67 ceres::Problem problem = build_problem(pairs, options, blocks);
68 HandeyeResult result;
69 solve_problem(problem, options, &result.core);
70 blocks.populate_result(result);
71 if (options.compute_covariance) {
72 auto optcov = compute_covariance(blocks, problem);
73 if (optcov.has_value()) {
74 result.core.covariance = std::move(optcov.value());
75 }
76 }
77 return result;
78}
79
80auto estimate_and_optimize_handeye(const std::vector<Eigen::Isometry3d>& base_se3_gripper,
81 const std::vector<Eigen::Isometry3d>& camera_se3_target,
82 double min_angle_deg, const OptimOptions& options)
83 -> HandeyeResult {
84 Eigen::Isometry3d init_pose =
85 estimate_handeye_dlt(base_se3_gripper, camera_se3_target, min_angle_deg);
86 return optimize_handeye(base_se3_gripper, camera_se3_target, init_pose, options);
87}
88
89} // namespace calib
Hand-eye calibration algorithms and utilities.
Linear multi-camera extrinsics initialisation (DLT)
auto optimize_handeye(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &camera_se3_target, const Eigen::Isometry3d &init_gripper_se3_ref, const OptimOptions &options={}) -> HandeyeResult
Refines the hand-eye calibration transformation using an optimization process.
Definition handeye.cpp:60
auto estimate_and_optimize_handeye(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &camera_se3_target, double min_angle_deg=1.0, const OptimOptions &options={}) -> HandeyeResult
Estimates and refines the hand-eye transformation.
Definition handeye.cpp:80
auto compute_covariance(const ProblemParamBlocks &problem_param_blocks, ceres::Problem &problem, double sum_squared_residuals=0, size_t total_residuals=0) -> std::optional< Eigen::MatrixXd >
Definition ceresutils.h:69
auto estimate_handeye_dlt(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &camera_se3_target, double min_angle_deg=1.0) -> Eigen::Isometry3d
Estimates the hand-eye transformation using the Tsai-Lenz algorithm with all pairs of input transform...
static auto build_problem(const std::vector< BundleObservation > &observations, const BundleOptions &opts, BundleBlocks< CameraT > &blocks) -> ceres::Problem
Definition bundle.cpp:84
auto build_all_pairs(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &cam_se3_target, double min_angle_deg=1.0, bool reject_axis_parallel=true, double axis_parallel_eps=1e-3) -> std::vector< MotionPair >
Generate all valid motion pairs from pose sequences.
void solve_problem(ceres::Problem &problem, const OptimOptions &opts, OptimResult *result)
Definition ceresutils.h:27
static auto create(const MotionPair &mp)
auto get_param_blocks() const -> std::vector< ParamBlock > override
Definition handeye.cpp:31
static auto create(const Eigen::Isometry3d &init_pose) -> HandeyeBlocks
Definition handeye.cpp:21
void populate_result(HandeyeResult &result) const
Definition handeye.cpp:35
std::array< double, 4 > quat
Definition handeye.cpp:18
std::array< double, 3 > tran
Definition handeye.cpp:19
Eigen::Isometry3d g_se3_c
Estimated hand-eye transform (gripper -> camera)
Definition handeye.h:18
OptimResult core
Core optimization result.
Definition handeye.h:17
Eigen::MatrixXd covariance
Definition optimize.h:37
const double * data
Definition ceresutils.h:46