Skip to content

Add in-place filter updates#95

Open
Maik13579 wants to merge 1 commit into
ros:ros2from
Maik13579:add-in-place-filter-updates
Open

Add in-place filter updates#95
Maik13579 wants to merge 1 commit into
ros:ros2from
Maik13579:add-in-place-filter-updates

Conversation

@Maik13579

Copy link
Copy Markdown

As discussed in #94, this adds optional in-place update support for FilterChain<T>.

Filters that can update their input directly can opt in by deriving from InPlaceFilter<T>, while existing FilterBase<T> filters continue to work through the buffered path.

Changes

  • Add InPlaceFilter<T> as a FilterBase<T> subclass.
  • Add FilterChain<T>::update(T & data) for in-place chain execution.
  • Add FilterChain<T>::can_update_fully_in_place() to report whether all configured filters support in-place updates.
  • Keep the existing FilterChain<T>::update(const T &, T &) API and use in-place-capable filters internally where possible.
  • Add InPlaceIncrementFilter<T> next to the existing increment filter and register it in default_plugins.xml.
  • Add tests for in-place, buffered, and mixed filter chains.

Introduce InPlaceFitler<T> as an FilterBase<T> subclass for filters that
can update data in place.

Extend FilterChain<T> with an in-place update path and capability query,
using in-place filters when available and the existing buffered path for
filters without in-place support.
@jonbinney

Copy link
Copy Markdown
Contributor

Thanks for this! I'll review it tomorrow.

@jonbinney

Copy link
Copy Markdown
Contributor

The CI failure looks like it has nothing to do with the code changes - just rolling packages missing at the moment. I'll try re-running it.

@jonbinney jonbinney left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved, with one question to discuss. I also need to debug the CI failure before merging; It'll take me a few days to do that.

T * next = &buffer0_;
for (size_t i = 1; i < reference_pointers_.size(); ++i) {
auto in_place_filter =
dynamic_cast<filters::InPlaceFilter<T> *>(reference_pointers_[i].get());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this dynamic cast need to happen on every update call? It probably only needs to be done once when the filter plugins are loaded, and then the resulting pointers cached, right? I'm just bringing this up to get your thoughts though - I actually don't think the slight speed increase from caching would be enough to justify the increased code complexity.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

A dynamic_cast is not "huge", but it is not free either. I think for filters that run on point clouds or images, the performance boost would likely be negligible compared to the actual filter work. But if someone uses this on higher-frequency data, for example IMU data, I can see the repeated RTTI check being less ideal.

I think caching this once in configure() would be smart, and I do not see it adding much complexity. We can just store the optional inplace pointers directly:

std::vector<InPlaceFilterBase<T> *> inplace_filters_;

Then configure() does the dynamic_cast once when the plugins are loaded, and update() only checks whether the cached pointer is nullptr.

To be honest, I think the cost of the dynamic_cast itself is probably very small, maybe somewhere around 10-200 ns depending on the type hierarchy, compiler, and cache state. So even for something like a 300 Hz IMU pipeline with 10 filters, we would likely still only be talking about a fraction of a millisecond per second overall. (That is only a rough estimate though)

The main reason I lean toward caching it is not because I expect a meaningful performance win, but because the result is static after the plugins are loaded. Whether a filter supports the inplace interface is configuration-time state, not something that changes on every update() call. If we can cache that with a small and straightforward change, I think it makes sense and does not add much complexity.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

But I will leave it up to you. If you prefer caching it, I can make that change.

@Maik13579 Maik13579 Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The CI failure is a bit confusing. ament_cmake_xmllint is listed in the Rolling distribution metadata:

https://github.com/ros/rosdistro/blob/a8ab8e4c579059707963f85076d191beaf0119e1/rolling/distribution.yaml#L325-L326

There also appears to be a prebuilt Noble .deb available for it:

https://packages.ros.org/ros2/ubuntu/pool/main/r/ros-rolling-ament-cmake-xmllint/

So this does not look like the package is simply missing from Rolling. The failure seems to be specifically in rosdep resolving the key for Rolling on Ubuntu Noble.

This will probably get fixed on the ROS infrastructure side, so we can also just wait a few days and rerun the CI.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets leave caching out of this PR. It could always be done in a different PR if we really want it. CI still failing.... I'm traveling so I'll check on it again next week.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Documentation says rolling is now on Ubuntu 26.04 Resolute (https://docs.ros.org/en/rolling/Installation.html)

Ubuntu Noble is 24.04

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

osrf/docker_images#878

ros-controls/mujoco_ros2_control#178

We need to wait until the upstream ros:rolling Docker images are updating

@mergify

mergify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

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.

2 participants