|
void BufferCore::_chainAsVector( |
|
const std::string & target_frame, TimePoint target_time, |
|
const std::string & source_frame, TimePoint source_time, |
|
const std::string & fixed_frame, |
|
std::vector<std::string> & output) const |
|
{ |
|
std::string error_string; |
|
|
|
output.clear(); // empty vector |
|
|
|
std::unique_lock<std::mutex> lock(frame_mutex_); |
|
|
|
TransformAccum accum; |
|
|
|
// Get source frame/time using getFrame |
|
CompactFrameID source_id = lookupFrameNumber(source_frame); |
|
CompactFrameID fixed_id = lookupFrameNumber(fixed_frame); |
|
CompactFrameID target_id = lookupFrameNumber(target_frame); |
|
|
|
std::vector<CompactFrameID> source_frame_chain; |
|
tf2::TF2Error retval = walkToTopParent( |
|
accum, source_time, fixed_id, source_id, &error_string, |
|
&source_frame_chain); |
|
if (retval != tf2::TF2Error::TF2_NO_ERROR) { |
|
switch (retval) { |
|
case tf2::TF2Error::TF2_CONNECTIVITY_ERROR: |
|
throw ConnectivityException(error_string); |
|
case tf2::TF2Error::TF2_EXTRAPOLATION_ERROR: |
|
throw ExtrapolationException(error_string); |
|
case tf2::TF2Error::TF2_LOOKUP_ERROR: |
|
throw LookupException(error_string); |
|
default: |
|
CONSOLE_BRIDGE_logError("Unknown error code: %d", retval); |
|
assert(0); |
|
} |
|
} |
|
|
|
if (source_time != target_time) { |
|
std::vector<CompactFrameID> target_frame_chain; |
|
retval = walkToTopParent( |
|
accum, target_time, target_id, fixed_id, &error_string, |
|
&target_frame_chain); |
|
|
|
if (retval != tf2::TF2Error::TF2_NO_ERROR) { |
|
switch (retval) { |
|
case tf2::TF2Error::TF2_CONNECTIVITY_ERROR: |
|
throw ConnectivityException(error_string); |
|
case tf2::TF2Error::TF2_EXTRAPOLATION_ERROR: |
|
throw ExtrapolationException(error_string); |
|
case tf2::TF2Error::TF2_LOOKUP_ERROR: |
|
throw LookupException(error_string); |
|
default: |
|
CONSOLE_BRIDGE_logError("Unknown error code: %d", retval); |
|
assert(0); |
|
} |
|
} |
|
size_t m = target_frame_chain.size(); |
|
size_t n = source_frame_chain.size(); |
|
while (m > 0u && n > 0u) { |
|
--m; |
|
--n; |
|
if (source_frame_chain[n] != target_frame_chain[m]) { |
|
break; |
|
} |
|
} |
|
// Erase all duplicate items from frame_chain |
|
if (n > 0u) { |
|
source_frame_chain.erase(source_frame_chain.begin() + (n - 1u), source_frame_chain.end()); |
|
} |
|
|
|
if (m < target_frame_chain.size()) { |
|
for (size_t i = 0u; i <= m; ++i) { |
|
source_frame_chain.push_back(target_frame_chain[i]); |
|
} |
|
} |
|
} |
|
|
|
// Write each element of source_frame_chain as string |
|
for (size_t i = 0u; i < source_frame_chain.size(); ++i) { |
|
output.push_back(lookupFrameString(source_frame_chain[i])); |
|
} |
|
} |
|
} // namespace tf2 |
Bug report / Missing functionality
Required Info:
Explanation
In tf2 for ros1 there existed a function to retrieve the chain of two frames as a list of strings. Now migrating to ros2, we need the functionality of this function. The corresponding function of tf2 for ros2 is here:
geometry2/tf2/src/buffer_core.cpp
Lines 1549 to 1631 in c3cafef
However, it is now not wrapped as a listener function but can only be accessed via the private member function
buffer._chain(). The bigger problem is that the implementation seems erroneous. Consider this simple tf tree:Querying
_chainAsVector(target_frame=D, source_frame=C, fixed_frame=A)(regardless of the time), yields the chain['C', 'B']and not as expected['C', 'B', 'A', 'D'].Does anyone have an idea why it is like this?
And also why the implementation changed from ros1 tf2 to ros2 tf2 (compare upper links) while the previous implementation worked just fine?
Is there a similar function that I don't know of that can achieve the same thing (python)?