50 Eigen::Vector3d nvec = plane.head<3>();
51 Eigen::Vector3d p0 = -plane[3] * nvec;
53 (std::abs(nvec.z()) < 0.9) ? Eigen::Vector3d::UnitZ() : Eigen::Vector3d::UnitX();
54 Eigen::Vector3d e1 = nvec.cross(tmp).normalized();
55 Eigen::Vector3d e2 = nvec.cross(e1).normalized();
56 Eigen::Matrix3d plane_to_norm;
57 plane_to_norm.col(0) = e1;
58 plane_to_norm.col(1) = e2;
59 plane_to_norm.col(2) = p0;
60 return plane_to_norm.inverse();
67 item.image_uv = camera.template unproject<double>(item.image_uv);
76 Eigen::Matrix3d h_norm_to_obj = hres.hmtx.inverse();
77 if (std::abs(h_norm_to_obj(2, 2)) > 1e-15) {
78 h_norm_to_obj /= h_norm_to_obj(2, 2);
81 std::vector<Eigen::Vector3d> points;
82 points.reserve(view.
laser_uv.size());
83 for (
const auto& lpix : view.
laser_uv) {
84 Eigen::Vector2d norm = camera.template unproject<double>(lpix);
85 Eigen::Vector3d hp = h_norm_to_obj * Eigen::Vector3d(norm.x(), norm.y(), 1.0);
86 Eigen::Vector2d plane_xy = hp.hnormalized();
87 Eigen::Vector3d obj_pt(plane_xy.x(), plane_xy.y(), 0.0);
88 points.push_back(pose * obj_pt);
93inline double plane_rms(
const std::vector<Eigen::Vector3d>& pts,
const Eigen::Vector4d& plane) {
94 const double ss = std::accumulate(pts.begin(), pts.end(), 0.0, [&](
double acc,
const auto& p) {
95 double r = plane.head<3>().dot(p) + plane[3];
98 return std::sqrt(ss /
static_cast<double>(pts.size()));
103 const CameraT& camera,
107 LineScanCalibrationResult result;
108 std::vector<Eigen::Vector3d> all_points;
109 for (
const auto& view : views) {
111 all_points.insert(all_points.end(), pts.begin(), pts.end());
113 if (all_points.size() < 3) {
114 throw std::invalid_argument(
"Not enough laser points to fit a plane");
117 if (opts.use_ransac) {
119 if (!ransac_result.success) {
120 throw std::runtime_error(
"RANSAC plane fitting failed");
122 result.plane = ransac_result.plane;
123 result.summary =
"ransac";
124 result.inlier_count = ransac_result.inliers.size();
125 if (!ransac_result.inliers.empty()) {
126 std::vector<Eigen::Vector3d> inlier_points(ransac_result.inliers.size());
128 ransac_result.inliers.begin(), ransac_result.inliers.end(), inlier_points.begin(),
129 [&all_points](
int idx) { return all_points[static_cast<std::size_t>(idx)]; });
130 result.rms_error =
plane_rms(inlier_points, result.plane);
132 result.rms_error =
plane_rms(all_points, result.plane);
136 result.summary =
"linear_svd";
137 result.inlier_count = all_points.size();
138 result.rms_error =
plane_rms(all_points, result.plane);
142 result.covariance.setZero();