ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
JointPairwiseRegistration.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// Joint Pairwise Registration (JPR) for within-scan pose refinement.
6//
7// Reimplements the C++ core of the Joint Pairwise Registration method from
8// Q. Huang et al., "Uncertainty Quantification for Multi-Scan Registration",
9// ACM SIGGRAPH 2020 (MIT-licensed reference implementation:
10// https://github.com/huangqx/MultiScanRegistration).
11//
12// The reference is MATLAB/MEX research code operating on object scans; this is
13// a native C++ port adapted to refine the per-frame sensor poses of a single
14// ReUseX scan. Each sensor frame is treated as one JPR "scan": its depth is
15// back-projected to an optical-frame surfel set, its pose is seeded from the
16// stored (RTABMap) world pose, and all frame poses are jointly refined by
17// minimizing point-to-plane distances between overlapping frame pairs.
18//
19// Deviations from the reference (documented intentionally):
20// - Pose increments use a minimal se(3) twist parametrization solved by a
21// sparse Gauss-Newton step, rather than the reference's 12-dim [t; vec(R)].
22// - Nearest-neighbour search uses pcl::KdTreeFLANN instead of the ANN library.
23// - Gauge freedom is fixed by a soft prior to the seed poses (and/or an
24// optional hard-anchored frame), which also prevents drift away from the
25// already-good RTABMap poses we are refining.
26
27#pragma once
28
29#include "reusex/segmentation/Surfel.hpp"
30#include "reusex/segmentation/surfel_extraction.hpp"
31
32#include <vector>
33
34namespace reusex {
35class ProjectDB;
36}
37
38namespace reusex::geometry {
39
41struct JprParams {
42 int max_iterations = 20;
44 float max_corr_distance = 0.10f;
46 45.f;
48 0.05f;
49
50 enum class Kernel { welsch, huber };
52
54 1.0f;
55 int anchor_frame = -1;
56 float convergence_eps = 1e-4f;
57
59};
60
62struct JprResult {
63 int frames = 0;
64 int iterations = 0;
65 double initial_rms = 0.0;
66 double final_rms = 0.0;
67};
68
71 public:
73
76 JprResult refine(std::vector<FrameSurfels> &frames) const;
77
78 private:
79 JprParams params_;
80};
81
95 bool dry_run = false);
96
97} // namespace reusex::geometry
JprResult refine(std::vector< FrameSurfels > &frames) const
Jointly refine the world poses of the given frames in place (each FrameSurfels::world_pose is updated...
JprResult refine_sensor_poses(ProjectDB &db, const JprParams &params, bool dry_run=false)
High-level entry point: extract surfels for every sensor frame in db, jointly refine their poses via ...
Parameters for joint pairwise pose refinement.
SurfelExtractionParams surfel
surfel extraction settings
float max_corr_distance
reject correspondences beyond this (m)
int anchor_frame
frame index (not node_id) to hard-fix; -1 = none
float prior_weight
soft prior pulling poses toward seeds (0 disables)
float convergence_eps
stop when max per-frame ||dxi|| below this
float robust_width
robust kernel width (m): Welsch sigma / Huber delta
float normal_angle_threshold
reject if normals disagree beyond (deg)
int neighbor_window
temporal pairing half-window
int max_iterations
maximum Gauss-Newton outer iterations
Summary statistics from a registration run.
int iterations
outer iterations performed
double initial_rms
mean point-to-plane residual before (m)
double final_rms
mean point-to-plane residual after (m)
int frames
number of frames that participated
Parameters controlling per-frame surfel extraction (back-projection + normal estimation) used by the ...