35 #include "tf2_msgs/TF2Error.h" 38 #include <console_bridge/console.h> 40 #include <boost/foreach.hpp> 50 {tf2 =
tf2::Transform(
tf2::Quaternion(msg.rotation.x, msg.rotation.y, msg.rotation.z, msg.rotation.w), tf2::Vector3(msg.translation.x, msg.translation.y, msg.translation.z));}
68 msg.header.stamp = stamp;
69 msg.header.frame_id = frame_id;
70 msg.child_frame_id = child_frame_id;
75 msg.translation.x = pos.x();
76 msg.translation.y = pos.y();
77 msg.translation.z = pos.z();
78 msg.rotation.x = orient.x();
79 msg.rotation.y = orient.y();
80 msg.rotation.z = orient.z();
81 msg.rotation.w = orient.w();
87 msg.header.stamp = stamp;
88 msg.header.frame_id = frame_id;
89 msg.child_frame_id = child_frame_id;
105 if (frame_id.size() > 0)
106 if (frame_id[0] ==
'/')
113 std::string out = in;
122 if (frame_id.size() == 0)
124 std::stringstream ss;
125 ss <<
"Invalid argument passed to "<< function_name_arg <<
" in tf2 frame_ids cannot be empty";
126 logWarn(
"%s",ss.str().c_str());
132 std::stringstream ss;
133 ss <<
"Invalid argument \"" << frame_id <<
"\" passed to "<< function_name_arg <<
" in tf2 frame_ids cannot start with a '/' like: ";
134 logWarn(
"%s",ss.str().c_str());
143 if (frame_id.empty())
145 std::stringstream ss;
146 ss <<
"Invalid argument passed to "<< function_name_arg <<
" in tf2 frame_ids cannot be empty";
152 std::stringstream ss;
153 ss <<
"Invalid argument \"" << frame_id <<
"\" passed to "<< function_name_arg <<
" in tf2 frame_ids cannot start with a '/' like: ";
160 std::stringstream ss;
161 ss <<
"\"" << frame_id <<
"\" passed to "<< function_name_arg <<
" does not exist. ";
192 for (std::vector<TimeCacheInterfacePtr>::iterator cache_it =
frames_.begin() + 1; cache_it !=
frames_.end(); ++cache_it)
195 (*cache_it)->clearList();
213 geometry_msgs::TransformStamped stripped = transform_in;
214 stripped.header.frame_id =
stripSlash(stripped.header.frame_id);
215 stripped.child_frame_id =
stripSlash(stripped.child_frame_id);
218 bool error_exists =
false;
219 if (stripped.child_frame_id == stripped.header.frame_id)
221 logError(
"TF_SELF_TRANSFORM: Ignoring transform from authority \"%s\" with frame_id and child_frame_id \"%s\" because they are the same", authority.c_str(), stripped.child_frame_id.c_str());
225 if (stripped.child_frame_id ==
"")
227 logError(
"TF_NO_CHILD_FRAME_ID: Ignoring transform from authority \"%s\" because child_frame_id not set ", authority.c_str());
231 if (stripped.header.frame_id ==
"")
233 logError(
"TF_NO_FRAME_ID: Ignoring transform with child_frame_id \"%s\" from authority \"%s\" because frame_id not set", stripped.child_frame_id.c_str(), authority.c_str());
237 if (std::isnan(stripped.transform.translation.x) || std::isnan(stripped.transform.translation.y) || std::isnan(stripped.transform.translation.z)||
238 std::isnan(stripped.transform.rotation.x) || std::isnan(stripped.transform.rotation.y) || std::isnan(stripped.transform.rotation.z) || std::isnan(stripped.transform.rotation.w))
240 logError(
"TF_NAN_INPUT: Ignoring transform for child_frame_id \"%s\" from authority \"%s\" because of a nan value in the transform (%f %f %f) (%f %f %f %f)",
241 stripped.child_frame_id.c_str(), authority.c_str(),
242 stripped.transform.translation.x, stripped.transform.translation.y, stripped.transform.translation.z,
243 stripped.transform.rotation.x, stripped.transform.rotation.y, stripped.transform.rotation.z, stripped.transform.rotation.w
248 bool valid = std::abs((stripped.transform.rotation.w * stripped.transform.rotation.w
249 + stripped.transform.rotation.x * stripped.transform.rotation.x
250 + stripped.transform.rotation.y * stripped.transform.rotation.y
255 logError(
"TF_DENORMALIZED_QUATERNION: Ignoring transform for child_frame_id \"%s\" from authority \"%s\" because of an invalid quaternion in the transform (%f %f %f %f)",
256 stripped.child_frame_id.c_str(), authority.c_str(),
257 stripped.transform.rotation.x, stripped.transform.rotation.y, stripped.transform.rotation.z, stripped.transform.rotation.w);
277 logWarn(
"TF_OLD_DATA ignoring data from the past for frame %s at time %g according to authority %s\nPossible reasons are listed at http://wiki.ros.org/tf/Errors%%20explained", stripped.child_frame_id.c_str(), stripped.header.stamp.toSec(), authority.c_str());
311 return walkToTopParent(f, time, target_id, source_id, error_string, NULL);
316 CompactFrameID source_id, std::string* error_string, std::vector<CompactFrameID>
320 frame_chain->clear();
323 if (source_id == target_id)
326 return tf2_msgs::TF2Error::NO_ERROR;
333 if (retval != tf2_msgs::TF2Error::NO_ERROR)
344 std::string extrapolation_error_string;
345 bool extrapolation_might_have_occurred =
false;
351 frame_chain->push_back(frame);
360 CompactFrameID parent = f.gather(cache, time, &extrapolation_error_string);
365 extrapolation_might_have_occurred =
true;
370 if (frame == target_id)
373 return tf2_msgs::TF2Error::NO_ERROR;
386 std::stringstream ss;
387 ss <<
"The tf tree is invalid because it contains a loop." << std::endl
389 *error_string = ss.str();
391 return tf2_msgs::TF2Error::LOOKUP_ERROR;
398 std::vector<CompactFrameID> reverse_frame_chain;
400 while (frame != top_parent)
404 reverse_frame_chain.push_back(frame);
416 std::stringstream ss;
418 *error_string = ss.str();
421 return tf2_msgs::TF2Error::EXTRAPOLATION_ERROR;
425 if (frame == source_id)
431 frame_chain->swap(reverse_frame_chain);
433 std::reverse(frame_chain->begin(), frame_chain->end());
435 return tf2_msgs::TF2Error::NO_ERROR;
447 std::stringstream ss;
448 ss <<
"The tf tree is invalid because it contains a loop." << std::endl
450 *error_string = ss.str();
452 return tf2_msgs::TF2Error::LOOKUP_ERROR;
456 if (frame != top_parent)
458 if (extrapolation_might_have_occurred)
462 std::stringstream ss;
463 ss << extrapolation_error_string <<
", when looking up transform from frame [" <<
lookupFrameString(source_id) <<
"] to frame [" <<
lookupFrameString(target_id) <<
"]";
464 *error_string = ss.str();
467 return tf2_msgs::TF2Error::EXTRAPOLATION_ERROR;
472 return tf2_msgs::TF2Error::CONNECTIVITY_ERROR;
474 else if (frame_chain){
476 reverse_frame_chain.push_back(frame);
483 int m = reverse_frame_chain.size()-1;
484 int n = frame_chain->size()-1;
485 for (; m >= 0 && n >= 0; --m, --n)
487 if ((*frame_chain)[n] != reverse_frame_chain[m])
496 frame_chain->erase(frame_chain->begin() + (n + 2), frame_chain->end());
498 if (m < reverse_frame_chain.size())
500 for (
int i = m; i >= 0; --i)
502 frame_chain->push_back(reverse_frame_chain[i]);
507 return tf2_msgs::TF2Error::NO_ERROR;
515 : source_to_top_quat(0.0, 0.0, 0.0, 1.0)
516 , source_to_top_vec(0.0, 0.0, 0.0)
517 , target_to_top_quat(0.0, 0.0, 0.0, 1.0)
518 , target_to_top_vec(0.0, 0.0, 0.0)
519 , result_quat(0.0, 0.0, 0.0, 1.0)
520 , result_vec(0.0, 0.0, 0.0)
526 if (!cache->getData(time, st, error_string))
538 source_to_top_vec =
quatRotate(st.rotation_, source_to_top_vec) + st.translation_;
539 source_to_top_quat = st.rotation_ * source_to_top_quat;
543 target_to_top_vec =
quatRotate(st.rotation_, target_to_top_vec) + st.translation_;
544 target_to_top_quat = st.rotation_ * target_to_top_quat;
555 result_vec = source_to_top_vec;
556 result_quat = source_to_top_quat;
561 tf2::Vector3 inv_target_vec =
quatRotate(inv_target_quat, -target_to_top_vec);
562 result_vec = inv_target_vec;
563 result_quat = inv_target_quat;
569 tf2::Vector3 inv_target_vec =
quatRotate(inv_target_quat, -target_to_top_vec);
571 result_vec =
quatRotate(inv_target_quat, source_to_top_vec) + inv_target_vec;
572 result_quat = inv_target_quat * source_to_top_quat;
592 const std::string& source_frame,
597 if (target_frame == source_frame) {
598 geometry_msgs::TransformStamped identity;
599 identity.header.frame_id = target_frame;
600 identity.child_frame_id = source_frame;
601 identity.transform.rotation.w = 1;
608 identity.header.stamp = cache->getLatestTimestamp();
610 identity.header.stamp = time;
613 identity.header.stamp = time;
622 std::string error_string;
624 int retval =
walkToTopParent(accum, time, target_id, source_id, &error_string);
625 if (retval != tf2_msgs::TF2Error::NO_ERROR)
629 case tf2_msgs::TF2Error::CONNECTIVITY_ERROR:
631 case tf2_msgs::TF2Error::EXTRAPOLATION_ERROR:
633 case tf2_msgs::TF2Error::LOOKUP_ERROR:
636 logError(
"Unknown error code: %d", retval);
641 geometry_msgs::TransformStamped output_transform;
643 return output_transform;
649 const std::string& source_frame,
651 const std::string& fixed_frame)
const 653 validateFrameId(
"lookupTransform argument target_frame", target_frame);
654 validateFrameId(
"lookupTransform argument source_frame", source_frame);
657 geometry_msgs::TransformStamped output;
658 geometry_msgs::TransformStamped temp1 =
lookupTransform(fixed_frame, source_frame, source_time);
659 geometry_msgs::TransformStamped temp2 =
lookupTransform(target_frame, fixed_frame, target_time);
665 output.header.stamp = temp2.header.stamp;
666 output.header.frame_id = target_frame;
667 output.child_frame_id = source_frame;
741 return cache->getParent(time, error_string);
756 const ros::Time& time, std::string* error_msg)
const 758 if (target_id == 0 || source_id == 0)
764 *error_msg += std::string(
"target_frame: " +
lookupFrameString(target_id ) +
" does not exist.");
770 *error_msg += std::string(
" ");
778 if (target_id == source_id)
784 if (
walkToTopParent(accum, time, target_id, source_id, error_msg) == tf2_msgs::TF2Error::NO_ERROR)
793 const ros::Time& time, std::string* error_msg)
const 800 const ros::Time& time, std::string* error_msg)
const 803 if (target_frame == source_frame)
806 if (
warnFrameId(
"canTransform argument target_frame", target_frame))
808 if (
warnFrameId(
"canTransform argument source_frame", source_frame))
816 if (target_id == 0 || source_id == 0)
822 *error_msg += std::string(
"canTransform: target_frame " + target_frame +
" does not exist.");
828 *error_msg += std::string(
" ");
830 *error_msg += std::string(
"canTransform: source_frame " + source_frame +
" does not exist.");
839 const std::string& source_frame,
const ros::Time& source_time,
840 const std::string& fixed_frame, std::string* error_msg)
const 842 if (
warnFrameId(
"canTransform argument target_frame", target_frame))
844 if (
warnFrameId(
"canTransform argument source_frame", source_frame))
846 if (
warnFrameId(
"canTransform argument fixed_frame", fixed_frame))
854 if (target_id == 0 || source_id == 0 || fixed_id == 0)
860 *error_msg += std::string(
"canTransform: target_frame " + target_frame +
" does not exist.");
866 *error_msg += std::string(
" ");
868 *error_msg += std::string(
"canTransform: source_frame " + source_frame +
" does not exist.");
872 if (target_id == 0 || source_id == 0)
874 *error_msg += std::string(
" ");
876 *error_msg += std::string(
"fixed_frame: " + fixed_frame +
"does not exist.");
887 if (frame_id >=
frames_.size())
898 M_StringToCompactFrameID::const_iterator map_it =
frameIDs_.find(frameid_str);
904 retval = map_it->second;
911 M_StringToCompactFrameID::iterator map_it =
frameIDs_.find(frameid_str);
929 std::stringstream ss;
930 ss <<
"Reverse lookup of frame id " << frame_id_num <<
" failed!";
943 *out = std::string(
"Could not find a connection between '"+
lookupFrameString(target_frame)+
"' and '"+
945 "Tf has two or more unconnected trees.");
956 std::stringstream mstream;
963 for (
unsigned int counter = 1; counter <
frames_.size(); counter ++)
966 if (frame_ptr == NULL)
969 if( frame_ptr->getData(
ros::Time(), temp))
978 return mstream.str();
989 return rhs.second == id;
998 if (source_id == 0 || target_id == 0)
return tf2_msgs::TF2Error::LOOKUP_ERROR;
1000 if (source_id == target_id)
1005 time = cache->getLatestTimestamp();
1008 return tf2_msgs::TF2Error::NO_ERROR;
1011 std::vector<P_TimeAndFrameID> lct_cache;
1031 if (latest.second == 0)
1037 if (!latest.first.isZero())
1039 common_time = std::min(latest.first, common_time);
1042 lct_cache.push_back(latest);
1044 frame = latest.second;
1047 if (frame == target_id)
1054 return tf2_msgs::TF2Error::NO_ERROR;
1062 std::stringstream ss;
1063 ss<<
"The tf tree is invalid because it contains a loop." << std::endl
1065 *error_string = ss.str();
1067 return tf2_msgs::TF2Error::LOOKUP_ERROR;
1087 if (latest.second == 0)
1092 if (!latest.first.isZero())
1094 common_time = std::min(latest.first, common_time);
1097 std::vector<P_TimeAndFrameID>::iterator it = std::find_if(lct_cache.begin(), lct_cache.end(),
TimeAndFrameIDFrameComparator(latest.second));
1098 if (it != lct_cache.end())
1100 common_parent = it->second;
1104 frame = latest.second;
1107 if (frame == source_id)
1114 return tf2_msgs::TF2Error::NO_ERROR;
1122 std::stringstream ss;
1123 ss<<
"The tf tree is invalid because it contains a loop." << std::endl
1125 *error_string = ss.str();
1127 return tf2_msgs::TF2Error::LOOKUP_ERROR;
1131 if (common_parent == 0)
1134 return tf2_msgs::TF2Error::CONNECTIVITY_ERROR;
1139 std::vector<P_TimeAndFrameID>::iterator it = lct_cache.begin();
1140 std::vector<P_TimeAndFrameID>::iterator end = lct_cache.end();
1141 for (; it != end; ++it)
1143 if (!it->first.isZero())
1145 common_time = std::min(common_time, it->first);
1148 if (it->second == common_parent)
1161 return tf2_msgs::TF2Error::NO_ERROR;
1166 std::stringstream mstream;
1174 mstream.precision(3);
1175 mstream.setf(std::ios::fixed,std::ios::floatfield);
1178 for (
unsigned int counter = 1; counter <
frames_.size(); counter ++)
1195 std::string authority =
"no recorded authority";
1196 std::map<CompactFrameID, std::string>::const_iterator it =
frame_authority_.find(cfid);
1198 authority = it->second;
1201 double rate = cache->getListLength() / std::max((cache->getLatestTimestamp().toSec() -
1202 cache->getOldestTimestamp().toSec() ), 0.0001);
1204 mstream << std::fixed;
1205 mstream.precision(3);
1207 mstream <<
" parent: '" <<
frameIDs_reverse[frame_id_num] <<
"'" << std::endl;
1208 mstream <<
" broadcaster: '" << authority <<
"'" << std::endl;
1209 mstream <<
" rate: " << rate << std::endl;
1210 mstream <<
" most_recent_transform: " << (cache->getLatestTimestamp()).toSec() << std::endl;
1211 mstream <<
" oldest_transform: " << (cache->getOldestTimestamp()).toSec() << std::endl;
1212 if ( current_time > 0 ) {
1213 mstream <<
" transform_delay: " << current_time - cache->getLatestTimestamp().toSec() << std::endl;
1215 mstream <<
" buffer_length: " << (cache->getLatestTimestamp() - cache->getOldestTimestamp()).toSec() << std::endl;
1218 return mstream.str();
1269 if (target_frame == source_frame)
1293 return 0xffffffffffffffffULL;
1395 for (
unsigned int counter = 1; counter <
frameIDs_reverse.size(); counter ++)
1412 std::vector<TransformableTuple> transformables;
1429 ros::Time latest_time;
1453 transformables.push_back(boost::make_tuple(boost::ref(it->second),
1457 boost::ref(req.
time),
1458 boost::ref(result)));
1478 BOOST_FOREACH (TransformableTuple tt, transformables)
1480 tt.get<0>()(tt.get<1>(), tt.get<2>(), tt.get<3>(), tt.get<4>(), tt.get<5>());
1490 std::stringstream mstream;
1491 mstream <<
"digraph G {" << std::endl;
1497 mstream <<
"\"no tf data recieved\"";
1499 mstream.precision(3);
1500 mstream.setf(std::ios::fixed,std::ios::floatfield);
1502 for (
unsigned int counter = 1; counter <
frames_.size(); counter ++)
1504 unsigned int frame_id_num;
1506 if (!counter_frame) {
1509 if(!counter_frame->getData(
ros::Time(), temp)) {
1514 std::string authority =
"no recorded authority";
1515 std::map<unsigned int, std::string>::const_iterator it =
frame_authority_.find(counter);
1517 authority = it->second;
1519 double rate = counter_frame->getListLength() / std::max((counter_frame->getLatestTimestamp().toSec() -
1520 counter_frame->getOldestTimestamp().toSec()), 0.0001);
1522 mstream << std::fixed;
1523 mstream.precision(3);
1527 <<
"Broadcaster: " << authority <<
"\\n" 1528 <<
"Average rate: " << rate <<
" Hz\\n" 1529 <<
"Most recent transform: " << (counter_frame->getLatestTimestamp()).toSec() <<
" ";
1530 if (current_time > 0)
1531 mstream <<
"( "<< current_time - counter_frame->getLatestTimestamp().toSec() <<
" sec old)";
1536 <<
"Buffer length: " << (counter_frame->getLatestTimestamp()-counter_frame->getOldestTimestamp()).toSec() <<
" sec\\n" 1537 <<
"\"];" <<std::endl;
1540 for (
unsigned int counter = 1; counter <
frames_.size(); counter ++)
1542 unsigned int frame_id_num;
1544 if (!counter_frame) {
1545 if (current_time > 0) {
1546 mstream <<
"edge [style=invis];" <<std::endl;
1547 mstream <<
" subgraph cluster_legend { style=bold; color=black; label =\"view_frames Result\";\n" 1548 <<
"\"Recorded at time: " << current_time <<
"\"[ shape=plaintext ] ;\n " 1553 if (counter_frame->getData(
ros::Time(), temp)) {
1561 mstream <<
"edge [style=invis];" <<std::endl;
1562 mstream <<
" subgraph cluster_legend { style=bold; color=black; label =\"view_frames Result\";\n";
1563 if (current_time > 0)
1564 mstream <<
"\"Recorded at time: " << current_time <<
"\"[ shape=plaintext ] ;\n ";
1565 mstream <<
"}" <<
"->" <<
"\"" <<
frameIDs_reverse[counter] <<
"\";" << std::endl;
1569 return mstream.str();
1579 std::string error_string;
1583 std::stringstream mstream;
1593 std::vector<CompactFrameID> source_frame_chain;
1594 int retval =
walkToTopParent(accum, source_time, fixed_id, source_id, &error_string, &source_frame_chain);
1596 if (retval != tf2_msgs::TF2Error::NO_ERROR)
1600 case tf2_msgs::TF2Error::CONNECTIVITY_ERROR:
1602 case tf2_msgs::TF2Error::EXTRAPOLATION_ERROR:
1604 case tf2_msgs::TF2Error::LOOKUP_ERROR:
1607 logError(
"Unknown error code: %d", retval);
1612 std::vector<CompactFrameID> target_frame_chain;
1613 retval =
walkToTopParent(accum, target_time, target_id, fixed_id, &error_string, &target_frame_chain);
1615 if (retval != tf2_msgs::TF2Error::NO_ERROR)
1619 case tf2_msgs::TF2Error::CONNECTIVITY_ERROR:
1621 case tf2_msgs::TF2Error::EXTRAPOLATION_ERROR:
1623 case tf2_msgs::TF2Error::LOOKUP_ERROR:
1626 logError(
"Unknown error code: %d", retval);
1631 if (source_frame_chain.size() > 0 && target_frame_chain.size() > 0 &&
1632 source_frame_chain.back() == target_frame_chain.front())
1634 source_frame_chain.pop_back();
1637 for (
unsigned int i = 0; i < target_frame_chain.size(); ++i)
1639 source_frame_chain.push_back(target_frame_chain[i]);
1644 for (
unsigned int i = 0; i < source_frame_chain.size(); ++i)
1653 return buffer.
walkToTopParent(accum, time, target_id, source_id, error_string, frame_chain);
bool _getParent(const std::string &frame_id, ros::Time time, std::string &parent) const
Fill the parent of a frame.
bool using_dedicated_thread_
A Class which provides coordinate transforms between any two frames in a system.
void setIdentity(geometry_msgs::Transform &tx)
TransformsChangedSignal _transforms_changed_
Signal which is fired whenever new transform data has arrived, from the thread the data arrived in...
static const uint32_t MAX_GRAPH_DEPTH
Maximum graph search depth (deeper graphs will be assumed to have loops)
bool startsWithSlash(const std::string &frame_id)
uint64_t transformable_requests_counter_
std::string allFramesAsString() const
A way to see what frames have been cached Useful for debugging.
TransformableCallbackHandle addTransformableCallback(const TransformableCallback &cb)
Internal use only.
int walkToTopParent(F &f, ros::Time time, CompactFrameID target_id, CompactFrameID source_id, std::string *error_string) const
An exception class to notify of no connection.
bool setTransform(const geometry_msgs::TransformStamped &transform, const std::string &authority, bool is_static=false)
Add transform information to the tf data structure.
boost::signals2::connection _addTransformsChangedListener(boost::function< void(void)> callback)
Add a callback that happens when a new transform has arrived.
bool operator()(const P_TimeAndFrameID &rhs) const
boost::mutex transformable_requests_mutex_
uint32_t TransformableCallbackHandle
const std::string & lookupFrameString(CompactFrameID frame_id_num) const
Number to string frame lookup may throw LookupException if number invalid.
Quaternion inverse() const
Return the inverse of this quaternion.
bool canTransformNoLock(CompactFrameID target_id, CompactFrameID source_id, const ros::Time &time, std::string *error_msg) const
TimeAndFrameIDFrameComparator(CompactFrameID id)
M_TransformableCallback transformable_callbacks_
uint32_t transformable_callbacks_counter_
TimeCacheInterfacePtr allocateFrame(CompactFrameID cfid, bool is_static)
std::pair< ros::Time, CompactFrameID > P_TimeAndFrameID
virtual ~BufferCore(void)
std::string allFramesAsYAML() const
boost::mutex frame_mutex_
A mutex to protect testing and allocating new frames on the above vector.
std::vector< std::string > frameIDs_reverse
A map from CompactFrameID frame_id_numbers to string for debugging and output.
RemoveRequestByCallback(TransformableCallbackHandle handle)
bool operator()(const TransformableRequest &req)
void _removeTransformsChangedListener(boost::signals2::connection c)
An exception class to notify of bad frame number.
bool _frameExists(const std::string &frame_id_str) const
Check if a frame exists in the tree.
void clear()
Clear all data.
bool warnFrameId(const char *function_name_arg, const std::string &frame_id) const
void _chainAsVector(const std::string &target_frame, ros::Time target_time, const std::string &source_frame, ros::Time source_time, const std::string &fixed_frame, std::vector< std::string > &output) const
Backwards compatabilityA way to see what frames are in a chain Useful for debugging.
CompactFrameID validateFrameId(const char *function_name_arg, const std::string &frame_id) const
void cancelTransformableRequest(TransformableRequestHandle handle)
Internal use only.
ros::Duration cache_time_
How long to cache transform history.
ROSTIME_DECL const Time TIME_MAX
bool canTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, std::string *error_msg=NULL) const
Test if a transform is possible.
M_StringToCompactFrameID frameIDs_
TransformableRequestHandle addTransformableRequest(TransformableCallbackHandle handle, const std::string &target_frame, const std::string &source_frame, ros::Time time)
Internal use only.
bool operator()(const TransformableRequest &req)
void createConnectivityErrorString(CompactFrameID source_frame, CompactFrameID target_frame, std::string *out) const
int getLatestCommonTime(CompactFrameID target_frame, CompactFrameID source_frame, ros::Time &time, std::string *error_string) const
Return the latest rostime which is common across the spanning set zero if fails to cross...
V_TransformableRequest transformable_requests_
std::map< CompactFrameID, std::string > frame_authority_
A map to lookup the most recent authority for a given frame.
TimeCacheInterfacePtr getFrame(CompactFrameID c_frame_id) const
An accessor to get a frame, which will throw an exception if the frame is no there.
boost::shared_ptr< TimeCacheInterface > TimeCacheInterfacePtr
bool canTransformInternal(CompactFrameID target_id, CompactFrameID source_id, const ros::Time &time, std::string *error_msg) const
std::string stripSlash(const std::string &in)
TF2SIMD_FORCE_INLINE Vector3 quatRotate(const Quaternion &rotation, const Vector3 &v)
void removeTransformableCallback(TransformableCallbackHandle handle)
Internal use only.
std::string _allFramesAsDot() const
boost::mutex transformable_callbacks_mutex_
void _getFrameStrings(std::vector< std::string > &ids) const
A way to get a std::vector of available frame ids.
std::string allFramesAsStringNoLock() const
A way to see what frames have been cached Useful for debugging. Use this call internally.
V_TimeCacheInterface frames_
RemoveRequestByID(TransformableRequestHandle handle)
TransformableCallbackHandle handle_
CompactFrameID lookupFrameNumber(const std::string &frameid_str) const
String to number for frame lookup with dynamic allocation of new frames.
A class to keep a sorted linked list in time This builds and maintains a list of timestamped data...
int _walkToTopParent(BufferCore &buffer, ros::Time time, CompactFrameID target_id, CompactFrameID source_id, std::string *error_string, std::vector< CompactFrameID > *frame_chain) const
CompactFrameID lookupOrInsertFrameNumber(const std::string &frameid_str)
String to number for frame lookup with dynamic allocation of new frames.
BufferCore(ros::Duration cache_time_=ros::Duration(DEFAULT_CACHE_TIME))
TransformableCallbackHandle handle_
void transformMsgToTF2(const geometry_msgs::Transform &msg, tf2::Transform &tf2)
convert Transform msg to Transform
The Quaternion implements quaternion to perform linear algebra rotations in combination with Matrix3x...
static double QUATERNION_NORMALIZATION_TOLERANCE
void transformTF2ToMsg(const tf2::Transform &tf2, geometry_msgs::Transform &msg)
convert Transform to Transform msg
geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time) const
Get the transform between two frames by frame ID.
void testTransformableRequests()
An exception class to notify that one of the arguments is invalid.
boost::function< void(TransformableRequestHandle request_handle, const std::string &target_frame, const std::string &source_frame, ros::Time time, TransformableResult result)> TransformableCallback
uint64_t TransformableRequestHandle