ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
optimize.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#pragma once
6#include "global-params.hpp"
7
8// Included for the sole purpose of MIRRORING the library defaults below
9// (docs/STANDARDS.md §4): a CLI default that references the library's own
10// value cannot silently drift away from it.
11#include <reusex/slam/PlaneGraphOptimizer.hpp>
12
13#include <CLI/CLI.hpp>
14#include <filesystem>
15#include <memory>
16#include <string>
17
18namespace fs = std::filesystem;
19
24 // Per-frame plane detection. Defaults are the "mid-density" sweet spot
25 // measured on the office + MuSHRoom-honka scans: with per-observation inlier
26 // weighting on, this beats the conservative (max=4/200/obs=5) defaults on
27 // BOTH GT-free flatness and laser GT F-score, and is the first pose stage to
28 // improve flatness without degrading GT (see docs/research/…). More/denser
29 // planes than this only help when combined with inlier weighting.
32 float ransac_distance = 0.02f;
33 float ransac_normal_angle = 20.0f;
35
36 // Cross-frame association.
37 float assoc_normal_angle = 10.0f;
38 float assoc_distance = 0.10f;
40 float assoc_overlap_margin = 0.30f;
42
43 // Alternating rounds.
44 int assoc_rounds = 2;
45 float assoc_round_tol = 0.02f;
46
47 // Factor-graph noise.
48 float odometry_sigma_rot = 0.005f;
49 float odometry_sigma_trans = 0.01f;
51 std::string odometry_noise = "fixed"; // fixed | motion
52 float odometry_weight_min = 0.5f;
53 float odometry_weight_max = 3.0f;
54 bool odometry_robust = false;
56 float plane_sigma_normal = 0.24f;
57 float plane_sigma_distance = 0.19f;
58 std::string plane_noise = "inliers"; // uniform | inliers | fit
60 float plane_weight_min = 0.5f;
61 float plane_weight_max = 3.0f;
62 float plane_sigma_scale = 1.0f;
63 bool no_plane_factors = false;
64 float prior_sigma_rot = 0.001f;
65 float prior_sigma_trans = 0.001f;
66
67 // Solver.
68 bool no_gnc = false;
69 float gnc_inlier_cost = 5.67f;
70 int iterations = 100;
71 unsigned seed = 42;
72
73 // Wide-baseline loop closure (P2; off by default). Defaults mirror the
74 // LoopClosureOptions in the library header.
75 bool loop_closure = false;
76 std::string loop_proposal =
77 "auto"; // auto | spatial | appearance | exhaustive
79 float loop_max_distance = 2.5f;
80 float loop_max_view_angle = 45.0f;
84 float loop_ratio_test = 0.85f;
86 float loop_max_seed_disagreement = 0.0f; // 0 = disabled (correct drift)
87 float loop_min_seed_disagreement = 0.10f; // absolute FLOOR of the gate (#339)
89 0.00555f; // scale-relative part: fraction of trajectory extent (#339)
90 // Trust loop edges: give them their own generous-but-finite GNC-TLS inlier
91 // threshold (Huber under --no-gnc) instead of the shared --gnc-inlier-cost.
92 bool loop_trust = false;
95 bool loop_no_pcm = false; // disable pairwise-consistency filtering
96
97 // Panorama-derived wide-baseline loop edges (#236; off by default). Defaults
98 // mirror reusex::geometry::PlaneGraphOptions::panorama_loops so the library
99 // stays the single source of truth (docs/STANDARDS.md §4).
100 bool use_panoramas = false;
112
113 // External loop edges (license-clean learned-matcher bridge). Path to a JSON
114 // file (schema "reusex.loop_edges.v1") produced by an out-of-process matcher
115 // (XFeat / EfficientLoFTR / MapAnything, or an offline MASt3R ceiling
116 // oracle). Unioned with any internally-detected --loop-closure edges. Empty =
117 // none.
118 std::string loop_edges_file;
119 // Seed-disagreement gate for external edges (drop edges agreeing with the
120 // seed within this many m; keeps the bridge a no-op on a well-posed scan).
121 // Absolute FLOOR; the effective gate is max(fraction * extent, floor) (#339).
123 // Scale-relative part of that gate: fraction of the trajectory's extent.
124 // 0.0278 == 0.50 m on the 18.01 m office scan (#339).
126
127 // Surfel extraction (shared with `rux register`).
128 float surfel_voxel = 0.03f;
129 float min_distance = 0.0f;
130 float max_distance = 4.0f;
131 // Mirrors the plane-graph override of the shared surfel default (8 -> 6).
135
136 bool dry_run = false;
137};
138
139void setup_subcommand_optimize(CLI::App &app,
140 std::shared_ptr<RuxOptions> global_opt);
142 const RuxOptions &global_opt);
void setup_subcommand_optimize(CLI::App &app, std::shared_ptr< RuxOptions > global_opt)
int run_subcommand_optimize(SubcommandOptimizeOptions const &opt, const RuxOptions &global_opt)
Options for the rux optimize subcommand (global plane-landmark pose-graph optimization).
Definition optimize.hpp:23
double loop_edges_min_disagreement_fraction
Definition optimize.hpp:125
bool no_gnc
disable Graduated Non-Convexity (plain LM)
Definition optimize.hpp:68
float loop_min_seed_disagreement_fraction
Definition optimize.hpp:88
double max_pano_distance
Reject a resection whose panorama centre sits further than this from the frame (m).
int max_edges_per_panorama
Cap the edges contributed per panorama (highest joint inlier support first).
int max_features
ORB features per image.
int max_frames
Panorama alignment matches a temporal window around the timestamp-seed frame (PanoramaAlignmentOption...
int n_yaw
perspective slices around the equator
int min_frame_inliers
Accept a frame's independent resection above this many gated inliers.
Parameters for plane-landmark pose-graph optimization.
PanoramaLoopOptions panorama_loops
Panorama-derived wide-baseline loop edges (issue #236; off by default, --use-panoramas).
SurfelExtractionParams surfel
Surfel extraction settings.
float loop_trust_inlier_cost
GNC-TLS inlier threshold applied ONLY to loop-edge factors when loop_edges_trusted is set (same units...
int sampling_factor
per-pixel subsampling (1=all, 2=half, ...)