struct mola::KeyframePointCloudMap::TCreationOptions
Overview
#include <KeyframePointCloudMap.h> struct TCreationOptions: public mrpt::config::CLoadableOptions { // fields uint32_t max_search_keyframes = 3; uint32_t k_correspondences_for_cov = 20; uint32_t min_correspondences_for_cov = 5; double max_distance_for_cov = 1.0; double rotation_distance_weight = 2.0; uint32_t num_diverse_keyframes = 1; bool use_view_direction_filter = true; double max_view_angle_deg = 120.0; bool serialize_kdtrees = false; bool serialize_covariances = false; bool approximate_cov = false; // methods void loadFromConfigFile( const mrpt::config::CConfigFileBase& c, const std::string& s ); void dumpToTextStream(std::ostream& out) const; void writeToStream(mrpt::serialization::CArchive& out) const; void readFromStream(mrpt::serialization::CArchive& in); };
Fields
uint32_t max_search_keyframes = 3
Maximum number of key-frames to search for NN.
uint32_t min_correspondences_for_cov = 5
Minimum number of neighbors (including the query point itself) that must actually be found to compute a per-point covariance via plane regularization. Points whose key-frame has fewer than this many neighbors available fall back to an isotropic (unregularized) covariance, since a plane/line fit from too few samples is unreliable and noise-sensitive. Must be >= 3 and <= k_correspondences_for_cov.
double max_distance_for_cov = 1.0
Maximum distance [meters] allowed between a query point and a candidate neighbor for it to be used in the per-point covariance estimation. Without this bound, sparse/low-density regions would pull in far-away “neighbors” that do not represent the local surface, producing meaningless covariance ellipsoids. Points with fewer than min_correspondences_for_cov neighbors within this radius fall back to an isotropic covariance (see above).
double rotation_distance_weight = 2.0
Weight converting angular distance [rad] to equivalent linear distance [m] for keyframe proximity ranking. Higher values favor angularly-close (similar orientation) frames.
uint32_t num_diverse_keyframes = 1
Number of keyframe slots (out of max_search_keyframes) reserved for angularly diverse and/or more distant keyframes. Must be < max_search_keyframes.
bool use_view_direction_filter = true
If true (default), and if both the reference and query point clouds contain per-point view-direction fields (“view_x”, “view_y”, “view_z” - unit vectors pointing FROM the point TOWARD the sensor at acquisition time), then a cov-to-cov pairing is accepted only when the angle between the two view directions is at most max_view_angle_deg.
The rationale is that two points on opposite sides of a thin surface (e.g. a wall seen from the front vs. the back, or a thin pole) will have nearly anti-parallel view vectors. Pairing them would produce a badly conditioned or outright wrong ICP residual. 120° is a reasonable default: it rejects pairs whose view directions differ by more than 120° (cos < -0.5) while keeping pairs seen from “similar enough” directions.
Setting this to false, or to a threshold ≥ 180°, effectively disables the filter even when view fields are present.
Contract: the “view_x/y/z” fields stored in a keyframe’s point cloud (KeyFrame::pointcloud_) MUST be expressed in the local KF frame, not in the global/map frame. KeyFrame::updatePointsGlobal() rotates them to the global frame using mp2p_icp::rotateViewDirectionFields() (see mp2p_icp/pointcloud_field_utils.h). Any code that inserts points carrying these fields into a keyframe (e.g. mp2p_icp_filters::FilterMerge) must call the same helper to rotate the fields alongside the point coordinates, or this filter will silently compare vectors expressed in inconsistent frames.
double max_view_angle_deg = 120.0
Maximum allowed angle [degrees] between the view-direction vectors of a candidate cov-to-cov pair. Only used when use_view_direction_filter is true and the view fields are present. Default: 120°.
bool serialize_kdtrees = false
If true, each keyframe’s per-cloud 3D KD-tree index is serialized alongside its points (see KeyframePointCloudMap serialization), so it does NOT have to be rebuilt when the map is loaded. This trades a larger .mm file for faster startup in localization-only use. Requires an MRPT build providing the KD-tree save/load API (feature-detected at compile time); when unavailable this option is silently a no-op on write. Default false. Typically enabled offline by the mm-kf-bake-kdtrees tool.
bool serialize_covariances = false
If true, each keyframe’s per-point covariances (the cached_cov_local_ produced by the plane-regularized SVD in computeCovariancesAndDensity()) are serialized alongside its points, so they do NOT have to be recomputed when the map is loaded. Covariance computation (one K-NN query + 3×3 SVD per point) is the single most expensive part of warming a freshly-loaded keyframe for ICP, so persisting it removes the multi-second stall paid the first time each keyframe becomes active in localization-only operation.
Unlike serialize_kdtrees, this needs no special MRPT API and works on any build. The stored covariances are the local-frame ones; the cheap per-pose global rotation (updateCovariancesGlobal()) is still done at runtime. Trades a larger .mm file (one 3×3 float matrix per point) for faster startup. Default false. Typically enabled offline by the mm-kf-bake-kdtrees tool.
bool approximate_cov = false
If true, nn_search_cov2cov() (used by mp2p_icp::Matcher_Cov2Cov, i.e. GICP-style pipelines) skips building the merged, multi-keyframe submap that icp_get_prepared_as_global() otherwise assembles for the active KF set. Instead, each active keyframe’s own already-built KD-tree and per-point covariances (both cached at insertion time, in the KF’s local neighborhood only) are queried directly: for every query point, one KD-tree lookup is done per active keyframe (“N” lookups instead of 1 on a merged cloud), and the overall closest one is kept, together with that keyframe’s own cached covariance at that point.
This trades exactness for speed: the reference covariance at the matched point is estimated only from neighbors within the same source keyframe, whereas the exact (default) mode computes it from neighbors in the merged cloud, which may include points contributed by other active keyframes. It also avoids the merged-cloud allocation, copy and KD-tree (re)build entirely, which can be a significant fraction of icp_get_prepared_as_global() ‘s cost when the active set has several sizeable keyframes.
Only affects nn_search_cov2cov(). The generic NearestNeighborsCapable entry points (nn_single_search(), nn_multiple_search(), nn_radius_search()) still require the merged submap and are not supported in this mode. Default false (exact, merged-cloud behavior, unchanged).