test_tf_filter.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * fkie_message_filters
4  * Copyright © 2018-2020 Fraunhofer FKIE
5  * Author: Timo Röhling
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ****************************************************************************/
20 #include "test.h"
24 
25 static void set_tf_transform(tf2::BufferCore& bc, const std::string& target_frame, const std::string& source_frame, const ros::Time& time)
26 {
27  geometry_msgs::TransformStamped tr;
28  tr.header.frame_id = target_frame; // parent
29  tr.header.stamp = time;
30  tr.child_frame_id = source_frame; // child
31  tr.transform.rotation.w = 1;
32  bc.setTransform(tr, "gtest", false);
33 }
34 
36 {
37  using IntegerStamped = Stamped<int>;
38  using Source = mf::UserSource<IntegerStamped>;
39  using TfFilter = mf::TfFilter<Source::Output>;
41 
42  std::size_t callback_counts = 0, failure_counts = 0;
43  tf2::BufferCore bc{ros::Duration(10, 0)};
44  Source src;
45  TfFilter flt;
46  Sink snk;
47  flt.init(bc, 2, nullptr);
48  flt.set_target_frame("target");
49  flt.set_filter_failure_function(
50  [&](const IntegerStamped& i, mf::TfFilterResult reason)
51  {
52  if (reason != mf::TfFilterResult::TransformAvailable) ++failure_counts;
53  }
54  );
55  mf::chain(src, flt, snk);
56  snk.set_processing_function(
57  [&](const IntegerStamped& i) -> bool
58  {
59  ++callback_counts;
60  std::string err;
61  if (!bc.canTransform("target", i.header.frame_id, i.header.stamp, &err)) throw std::logic_error(err.c_str());
62  return true;
63  }
64  );
65  set_tf_transform(bc, "target", "alpha", ros::Time(99, 0));
66  set_tf_transform(bc, "target", "beta", ros::Time(99, 0));
67  // Check that filter will wait when the transform is older than needed
68  src(IntegerStamped(0, "alpha", ros::Time(100, 0)));
69  ASSERT_EQ(0u, callback_counts);
70  ASSERT_EQ(0u, failure_counts);
71  // Check that filter pass the message once the transform updates
72  set_tf_transform(bc, "target", "alpha", ros::Time(101, 0));
73  ASSERT_EQ(1u, callback_counts);
74  ASSERT_EQ(0u, failure_counts);
75  // If the message is older than the cache length, instant fail
76  src(IntegerStamped(0, "alpha", ros::Time(50, 0)));
77  ASSERT_EQ(1u, callback_counts);
78  ASSERT_EQ(1u, failure_counts);
79  // If the transform is available, instant pass
80  src(IntegerStamped(0, "alpha", ros::Time(100, 0)));
81  ASSERT_EQ(2u, callback_counts);
82  ASSERT_EQ(1u, failure_counts);
83  // The filter will wait for unknown transforms
84  src(IntegerStamped(0, "gamma", ros::Time(102, 0)));
85  ASSERT_EQ(1u, failure_counts);
86  // If the queue overflows, the oldest message will be discarded
87  src(IntegerStamped(0, "beta", ros::Time(102, 0)));
88  src(IntegerStamped(0, "alpha", ros::Time(102, 0)));
89  ASSERT_EQ(2u, callback_counts);
90  ASSERT_EQ(2u, failure_counts);
91  // Check that the remaining messages pass
92  set_tf_transform(bc, "target", "alpha", ros::Time(103, 0));
93  set_tf_transform(bc, "target", "beta", ros::Time(103, 0));
94  ASSERT_EQ(4u, callback_counts);
95  ASSERT_EQ(2u, failure_counts);
96  // Fill the queue with messages, nothing should happen
97  src(IntegerStamped(0, "gamma", ros::Time(100, 0)));
98  src(IntegerStamped(0, "gamma", ros::Time(100, 0)));
99  ASSERT_EQ(4u, callback_counts);
100  ASSERT_EQ(2u, failure_counts);
101  // Clear the queue
102  flt.reset();
103  // Check that filter still works and discarded the previous queue without failure notifications
104  src(IntegerStamped(0, "alpha", ros::Time(100, 0)));
105  src(IntegerStamped(0, "beta", ros::Time(100, 0)));
106  ASSERT_EQ(6u, callback_counts);
107  ASSERT_EQ(2u, failure_counts);
108 }
TEST(fkie_message_filters, TfFilter)
bool setTransform(const geometry_msgs::TransformStamped &transform, const std::string &authority, bool is_static=false)
Wait for TF transformations for incoming messages.
Definition: tf_filter.h:72
Primary namespace.
Definition: buffer.h:33
void chain(Filter1 &flt1, Filter2 &flt2, MoreFilters &... filters) noexcept
Convenience function to chain multiple filters.
Definition: filter_impl.h:53
TfFilterResult
TF transformation results.
Definition: tf_filter.h:37
static void set_tf_transform(tf2::BufferCore &bc, const std::string &target_frame, const std::string &source_frame, const ros::Time &time)
Manually operated data source.
Definition: user_source.h:37
Simplified filter with user-defined callback function.
Definition: test.h:52


fkie_message_filters
Author(s): Timo Röhling
autogenerated on Mon Feb 28 2022 22:21:43