Skip to content

Commit 5286ee0

Browse files
selimrecepmergify[bot]
authored andcommitted
Fix misleading extrapolation time in buffer_core (#832) (#896)
(cherry picked from commit 876d31e)
1 parent ea6cb75 commit 5286ee0

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

tf2/src/buffer_core.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ tf2::TF2Error BufferCore::walkToTopParent(
359359
TF2Error extrapolation_error_code = TF2Error::TF2_NO_ERROR;
360360
std::string extrapolation_error_string;
361361
bool extrapolation_might_have_occurred = false;
362+
TimePoint extrapolation_latest_time = TimePointZero;
362363

363364
while (frame != 0) {
364365
TimeCacheInterfacePtr cache = getFrame(frame);
@@ -379,6 +380,7 @@ tf2::TF2Error BufferCore::walkToTopParent(
379380
// Just break out here... there may still be a path from source -> target
380381
top_parent = frame;
381382
extrapolation_might_have_occurred = true;
383+
extrapolation_latest_time = cache->getLatestTimestamp();
382384
break;
383385
}
384386

@@ -422,6 +424,25 @@ tf2::TF2Error BufferCore::walkToTopParent(
422424

423425
CompactFrameID parent = f.gather(cache, time, error_string, &error_code);
424426
if (parent == 0) {
427+
if (extrapolation_might_have_occurred) {
428+
// Shouldn't treat second walk path failure as extrapolation if the
429+
// first walk path failure is older than the latest data in the cache
430+
TimePoint phase2_latest = cache->getLatestTimestamp();
431+
432+
// prefer source for tie-breaker
433+
bool prefer_phase1 = (extrapolation_latest_time >= phase2_latest);
434+
435+
if (prefer_phase1) {
436+
if (error_string) {
437+
std::stringstream ss;
438+
ss << extrapolation_error_string << ", when looking up transform from frame ["
439+
<< lookupFrameString(source_id) << "] to frame [" << lookupFrameString(target_id)
440+
<< "]";
441+
*error_string = ss.str();
442+
}
443+
return extrapolation_error_code;
444+
}
445+
}
425446
if (error_string) {
426447
std::stringstream ss;
427448
ss << *error_string << ", when looking up transform from frame [" << lookupFrameString(

tf2/test/simple_tf2_core.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,59 @@ TEST(tf2_time, To_From_Duration)
386386
}
387387
}
388388

389+
TEST(tf2_canTransform, ExtrapolationErrorReportsCorrectLatestTime)
390+
{
391+
// this test verifies if correct time difference between transforms
392+
// are reported when transform from a to b fails in both source-to-root
393+
// and root-to-source walks.
394+
tf2::BufferCore tfc;
395+
geometry_msgs::msg::TransformStamped st;
396+
std::string error_msg;
397+
398+
// 1. publish map -> odom (stale by 10s, latest is 90.01)
399+
st.header.frame_id = "map";
400+
st.child_frame_id = "odom";
401+
st.transform.rotation.w = 1.0;
402+
403+
st.header.stamp.sec = 90;
404+
st.header.stamp.nanosec = 0;
405+
tfc.setTransform(st, "authority1");
406+
407+
st.header.stamp.sec = 90;
408+
// 90.01s
409+
st.header.stamp.nanosec = 10000000;
410+
tfc.setTransform(st, "authority1");
411+
412+
// 2. publish odom -> base_link (stale by 0.1s, latest is 99.91)
413+
st.header.frame_id = "odom";
414+
st.child_frame_id = "base_link";
415+
416+
st.header.stamp.sec = 99;
417+
// 99.90s
418+
st.header.stamp.nanosec = 900000000;
419+
tfc.setTransform(st, "authority1");
420+
421+
st.header.stamp.sec = 99;
422+
// 99.91s
423+
st.header.stamp.nanosec = 910000000;
424+
tfc.setTransform(st, "authority1");
425+
426+
// 3. query odom -> base_link at T=100.0s
427+
bool can_transform = tfc.canTransform(
428+
"odom", "base_link",
429+
tf2::timeFromSec(100.0),
430+
&error_msg);
431+
432+
EXPECT_FALSE(can_transform);
433+
434+
// 4. verify the error message:
435+
// the message should report the latest data for odom->base_link (99.91),
436+
// not map->odom (90.01).
437+
EXPECT_NE(error_msg.find("99.91"), std::string::npos);
438+
439+
EXPECT_EQ(error_msg.find("90.01"), std::string::npos);
440+
}
441+
389442
TEST(tf2_convert, Covariance_RowMajor_To_Nested)
390443
{
391444
// test verifies the correct conversion of the flat covariance array to a

0 commit comments

Comments
 (0)