ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to use FilterChain without data copy?

asked 2019-07-10 10:26:22 -0600

seanarm gravatar image

updated 2019-07-10 11:07:30 -0600

I am using a filters::FilterChain<sensor_msgs::LaserScan> to filter lidar data. I made two custom filters. My lidar callback looks like this:

void lidarCB(const sensor_msgs::LaserScanPtr& msg)                                                                                          
{                                                                        
    // no copy                                                                                          
    sensor_msgs::LaserScan& scan = *msg;                                                                                          
    filterChain_->update(scan, scan);                                                                                    
    lidarPub_.publish(scan);
}

In my custom filters, I only operate on the second argument of the update() function because input and output should be exactly the same. What I'm finding is that this does not work as soon as more than one filter is added. And in fact, the two arguments provided to my custom filters' update() functions are not the same object when comparing using std::addressof.

bool update(const sensor_msgs::LaserScan& input, sensor_msgs::LaserScan& filtered)
{
    if (std::addressof(input) != std::addressof(filtered))
    {
        // error!
    }
}

Is there any way to send lidar data through a filter chain using the same object/reference?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2020-01-24 09:35:08 -0600

updated 2020-01-24 09:40:55 -0600

Hi,

sorry for the late response.

if you really have multiple in-place filters FilterChain is not your friend in this case. You could avoid this by using Ptr msgs (or wrapped in another datatype).

f(const LaserScanPtr& in, LaserScanPtr& out)
{
   //allowed since you are modifying the data and not the ptr
   modify(in);
   //Just ptr copy
   out = in;
}

But note that since you get it from the callback and it is a const Ptr there, at least the input will be copied. once. All filters in the chain must support this type of course. Probably the designers did not want to rely on the filter plugins to check if they need to copy the input first because there are also a lot of non in-pace filters anyway (hence in is const to signal that).

So still why is in != out addresswise?

FilterChain has two internal buffers of datatype LaserScan in your case.

FilterChain length 1: call filter0.update(scan, scan) in your case. FilterChain length 2: calls filter0.update(scan, buffer0) and filter1.update(buffer0, scan).

For more filters it keeps toggling two input buffers (0, 1) until the final one.

edit flag offensive delete link more

Comments

Ah you have a non const callback sorry. In your case it would work without copying the input once, but be aware that nodelets have const msgs as requirement for the callback which want to use zero copy.

Besides filter does not require the caller to copy the data before passing it to the chain, it might want to pass the same to multiple filters. So beware if you mix filters or callers that are not aware of that.

ritualmaster gravatar image ritualmaster  ( 2020-01-24 09:50:40 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2019-07-10 10:26:22 -0600

Seen: 263 times

Last updated: Jan 24 '20