Skip to content

Add trivial FilterDecimate for fast downsampling without spatial awareness#25

Merged
jlblancoc merged 2 commits intodevelopfrom
feat/naive-decimate
Jan 12, 2026
Merged

Add trivial FilterDecimate for fast downsampling without spatial awareness#25
jlblancoc merged 2 commits intodevelopfrom
feat/naive-decimate

Conversation

@jlblancoc
Copy link
Copy Markdown
Member

@jlblancoc jlblancoc commented Jan 12, 2026

Summary by CodeRabbit

  • New Features

    • Added FilterDecimate — point-cloud downsampling with fixed decimation and automatic target-size based decimation.
  • Documentation

    • Added usage docs and configuration examples for FilterDecimate.
  • Tests

    • Added unit tests validating fixed, target-size, and no-op decimation scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 12, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds a new FilterDecimate downsampling filter: implementation, header, build integration, RTTI registration, unit tests, and documentation entries; behavior implements fixed or target-size decimation of point-cloud layers.

Changes

Cohort / File(s) Summary
Filter implementation
mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h, mp2p_icp_filters/src/FilterDecimate.cpp
New FilterDecimate class (inherits FilterBase) with Parameters (input_layer, output_layer, decimation, target_max_size); implements YAML loading, initialization, and filter(...) which samples every N-th point (or computes N from target size) and writes to/creates output layer; MRPT version guards included.
Build & export
mp2p_icp_filters/CMakeLists.txt
Added source and public header entries for the new filter to library build lists.
RTTI registration
mp2p_icp_filters/src/register.cpp
Registered mp2p_icp_filters::FilterDecimate in MRPT initializer for dynamic instantiation.
Unit tests
tests/CMakeLists.txt, tests/test-mp2p_FilterDecimate.cpp
New test and CMake entry exercising fixed decimation, target-size decimation, and no-op cases on a 100-point cloud.
Documentation
docs/source/mp2p_icp_filters.rst
Inserted two identical FilterDecimate reference blocks documenting parameters, usage YAML, and nondeterministic spatial distribution note.
Apps (stylistic changes)
apps/icp-run/main.cpp, apps/mm-filter/main.cpp, apps/mm-georef/main.cpp, apps/mm-info/main.cpp
Minor formatting/brace additions and small parsing change (std::stodstd::stoi) in icp-run; no API changes.

Sequence Diagram(s)

sequenceDiagram
  participant YAML as YAML/config
  participant Filter as FilterDecimate
  participant Map as metric_map_t
  participant Layer as PointLayer (input/output)

  YAML->>Filter: load parameters (input_layer, output_layer, decimation, target_max_size)
  Filter->>Map: access input_layer
  Map->>Layer: return input layer points
  Filter->>Filter: compute decimation N (explicit or from target_max_size)
  alt N <= 1 and different layers
    Filter->>Map: shallow copy input_layer -> output_layer
  else N > 1
    Filter->>Map: GetOrCreatePointLayer(output_layer)
    Filter->>Layer: reserve space / prepareForInsert
    Filter->>Layer: insert every N-th point into output_layer
  end
  Filter->>Map: return modified metric_map_t
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through lists of points and chose each N-th,

tiny footprints left where clouds were dense,
YAML told me where to start and where to send,
I nibbled down the crowd, no biased fence,
Hooray — lighter maps, my little hop is done!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a new FilterDecimate class for downsampling point clouds without spatial awareness, which is clearly reflected across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3e13e3 and c8c0262.

📒 Files selected for processing (4)
  • apps/icp-run/main.cpp
  • apps/mm-filter/main.cpp
  • apps/mm-georef/main.cpp
  • apps/mm-info/main.cpp

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @docs/source/mp2p_icp_filters.rst:
- Around line 281-333: The docs reference a missing image '.. image::
decimate_example.png' in the FilterDecimate section; either add the referenced
screenshot file to the repo (named exactly decimate_example.png) or remove the
image directive and the surrounding rubric/Before → After block (the '.. image::
decimate_example.png' line and the preceding '.. rubric:: Before → After
Screenshot' and related lines) from the docs so the Sphinx build no longer
references a non-existent asset.
🧹 Nitpick comments (3)
mp2p_icp_filters/src/FilterDecimate.cpp (2)

33-39: Consider adding validation for mutually exclusive parameters.

The filter accepts both decimation and target_max_size, but neither is required. If a user provides neither (or both as 0), the filter effectively becomes a no-op or shallow copy. While this may be intentional, a warning or debug log when no decimation is performed could help users catch configuration mistakes.


67-77: Shallow copy may cause unexpected aliasing.

When N <= 1 and layers differ, the output layer becomes a shared reference to the input layer. If downstream filters modify the output layer, they'll also modify the input layer, which may be unexpected.

Consider using a deep copy or documenting this behavior more prominently in the header/docs. The current comment is only visible in the implementation.

tests/test-mp2p_FilterDecimate.cpp (1)

30-104: Consider adding edge case tests for completeness.

The current test suite covers the main functionality well. For more robust coverage, consider adding tests for:

  • Empty input layer (early return path)
  • Same input/output layer with N>1 (in-place semantics)
  • Both decimation=0 and target_max_size=0 (undefined behavior?)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed89d3 and b3e13e3.

📒 Files selected for processing (7)
  • docs/source/mp2p_icp_filters.rst
  • mp2p_icp_filters/CMakeLists.txt
  • mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h
  • mp2p_icp_filters/src/FilterDecimate.cpp
  • mp2p_icp_filters/src/register.cpp
  • tests/CMakeLists.txt
  • tests/test-mp2p_FilterDecimate.cpp
🧰 Additional context used
🧬 Code graph analysis (3)
tests/test-mp2p_FilterDecimate.cpp (2)
mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h (1)
  • mp2p_icp_filters (26-78)
mp2p_icp_filters/src/FilterDecimate.cpp (2)
  • filter (46-102)
  • filter (46-46)
mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h (1)
mp2p_icp_filters/src/FilterDecimate.cpp (5)
  • FilterDecimate (31-31)
  • filter (46-102)
  • filter (46-46)
  • initialize_filter (41-44)
  • initialize_filter (41-41)
mp2p_icp_filters/src/register.cpp (2)
mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h (1)
  • FilterDecimate (43-76)
mp2p_icp_filters/src/FilterDecimate.cpp (1)
  • FilterDecimate (31-31)
🔇 Additional comments (14)
mp2p_icp_filters/src/FilterDecimate.cpp (2)

56-65: LGTM!

The decimation factor calculation correctly prioritizes decimation over target_max_size and safely guards against division by zero.


85-101: API calls are correct and consistent with MRPT version design.

The version-specific signatures for insertPointFrom follow MRPT's intended API evolution:

  • MRPT >= 0x020f03: Context object encapsulates the source point cloud reference, so only point index and context are passed
  • MRPT >= 0x020f00: Context added as parameter alongside explicit source reference
  • Earlier versions: Source point cloud explicitly required

This pattern is used consistently throughout the codebase (FilterDecimateVoxels, FilterSOR, FilterMLS, etc.), confirming the implementation is correct. No changes needed.

tests/CMakeLists.txt (1)

65-65: LGTM!

The test entry follows the established pattern and is correctly positioned alphabetically among the filter tests.

mp2p_icp_filters/src/register.cpp (2)

34-34: LGTM!

The include directive is correctly placed in alphabetical order.


73-73: LGTM!

The RTTI class registration follows the established pattern and alphabetical ordering.

mp2p_icp_filters/CMakeLists.txt (2)

15-15: LGTM!

The source file is correctly added to LIB_SRCS in alphabetical order.


51-51: LGTM!

The public header is correctly added to LIB_PUBLIC_HDRS in alphabetical order.

tests/test-mp2p_FilterDecimate.cpp (4)

1-28: LGTM!

License header, includes, and namespace setup look correct for the test file.


44-59: LGTM!

Test case A correctly validates fixed decimation factor: 100 points with decimation=4 yields 25 points (indices 0, 4, 8, ..., 96).


61-77: LGTM!

Test case B correctly validates target_max_size: N=100/10=10, yielding 10 points.


79-94: LGTM!

Test case C correctly validates no-decimation scenario when target_max_size exceeds input size.

mp2p_icp_filters/include/mp2p_icp_filters/FilterDecimate.h (3)

28-42: LGTM!

The class documentation is thorough—clearly explaining the decimation behavior, accumulation semantics, and the non-deterministic spatial distribution caveat.


43-76: LGTM!

The class structure follows the established FilterBase pattern correctly, with proper MRPT object registration, public filter interface, and nested Parameters struct.


59-60: No action required: output_layer is already validated as a required parameter.

The output_layer field is enforced as required via MCP_LOAD_REQ(c, output_layer) in load_from_yaml() (line 36), so missing it will cause a YAML load error. Additionally, GetOrCreatePointLayer() already throws an exception if an empty layer name is passed with allowEmptyName=false (line 81). The struct default to an empty string is never exposed in normal usage since the parameter must be provided in the YAML config. The shortcut path logic correctly handles both in-place (same layer) and copy (different layer) scenarios.

Likely an incorrect or invalid review comment.

Comment thread docs/source/mp2p_icp_filters.rst
@jlblancoc jlblancoc merged commit c0911c6 into develop Jan 12, 2026
2 of 13 checks passed
@jlblancoc jlblancoc deleted the feat/naive-decimate branch January 12, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant