Skip to content
Snippets Groups Projects
Commit b09faf2e authored by Joseph Mirabel's avatar Joseph Mirabel Committed by olivier stasse
Browse files

[TF2] Add a signal that says whether the transform is available.

parent e537910c
No related branches found
No related tags found
No related merge requests found
...@@ -5,18 +5,45 @@ ...@@ -5,18 +5,45 @@
namespace dynamicgraph { namespace dynamicgraph {
namespace internal { namespace internal {
sot::MatrixHomogeneous& TransformListenerData::getTransform(sot::MatrixHomogeneous& res, int time) { sot::MatrixHomogeneous& TransformListenerData::getTransform(sot::MatrixHomogeneous& res, int time)
{
availableSig.recompute(time);
bool available = availableSig.accessCopy();
if (!available) {
failbackSig.recompute(time);
res = failbackSig.accessCopy();
return res;
}
const geometry_msgs::TransformStamped::_transform_type::_rotation_type&
quat = transform.transform.rotation;
const geometry_msgs::TransformStamped::_transform_type::_translation_type&
trans = transform.transform.translation;
res.linear() = sot::Quaternion(quat.w, quat.x, quat.y, quat.z).matrix();
res.translation() << trans.x, trans.y, trans.z;
return res;
}
bool& TransformListenerData::isAvailable(bool& available, int time)
{
static const ros::Time origin(0); static const ros::Time origin(0);
bool useFailback = false; available = false;
ros::Duration elapsed; ros::Duration elapsed;
std::string msg; std::string msg;
if (buffer.canTransform(toFrame, fromFrame, origin, &msg)) { if (buffer.canTransform(toFrame, fromFrame, origin, &msg)) {
transform = buffer.lookupTransform(toFrame, fromFrame, origin); transform = buffer.lookupTransform(toFrame, fromFrame, origin);
elapsed = ros::Time::now() - transform.header.stamp; if (transform.header.stamp == origin) {
useFailback = elapsed > max_elapsed; // This is likely a TF2 static transform.
available = true;
} else {
elapsed = ros::Time::now() - transform.header.stamp;
available = (elapsed <= max_elapsed);
}
if (useFailback) { if (!available) {
std::ostringstream oss; std::ostringstream oss;
oss << "Use failback " << signal.getName() << " at time " << time oss << "Use failback " << signal.getName() << " at time " << time
<< ". Time since last update of the transform: " << elapsed; << ". Time since last update of the transform: " << elapsed;
...@@ -27,24 +54,11 @@ sot::MatrixHomogeneous& TransformListenerData::getTransform(sot::MatrixHomogeneo ...@@ -27,24 +54,11 @@ sot::MatrixHomogeneous& TransformListenerData::getTransform(sot::MatrixHomogeneo
oss << "Unable to get transform " << signal.getName() << " at time " oss << "Unable to get transform " << signal.getName() << " at time "
<< time << ": " << msg; << time << ": " << msg;
entity->SEND_WARNING_STREAM_MSG(oss.str()); entity->SEND_WARNING_STREAM_MSG(oss.str());
useFailback = true; available = false;
}
if (useFailback)
{
failbackSig.recompute(time);
res = failbackSig.accessCopy();
return res;
} }
return available;
const geometry_msgs::TransformStamped::_transform_type::_rotation_type&
quat = transform.transform.rotation;
const geometry_msgs::TransformStamped::_transform_type::_translation_type&
trans = transform.transform.translation;
res.linear() = sot::Quaternion(quat.w, quat.x, quat.y, quat.z).matrix();
res.translation() << trans.x, trans.y, trans.z;
return res;
} }
} // namespace internal } // namespace internal
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(RosTfListener, "RosTfListener"); DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(RosTfListener, "RosTfListener");
......
...@@ -18,16 +18,18 @@ class RosTfListener; ...@@ -18,16 +18,18 @@ class RosTfListener;
namespace internal { namespace internal {
struct TransformListenerData { struct TransformListenerData {
typedef SignalTimeDependent<sot::MatrixHomogeneous, int> signal_t; typedef SignalTimeDependent<bool, int> AvailableSignal_t;
typedef SignalPtr<sot::MatrixHomogeneous, int> signalIn_t; typedef SignalTimeDependent<sot::MatrixHomogeneous, int> MatrixSignal_t;
typedef SignalPtr<sot::MatrixHomogeneous, int> DefaultSignal_t;
RosTfListener* entity; RosTfListener* entity;
tf2_ros::Buffer& buffer; tf2_ros::Buffer& buffer;
const std::string toFrame, fromFrame; const std::string toFrame, fromFrame;
geometry_msgs::TransformStamped transform; geometry_msgs::TransformStamped transform;
ros::Duration max_elapsed; ros::Duration max_elapsed;
signal_t signal; AvailableSignal_t availableSig;
signalIn_t failbackSig; MatrixSignal_t signal;
DefaultSignal_t failbackSig;
TransformListenerData(RosTfListener* e, tf2_ros::Buffer& b, TransformListenerData(RosTfListener* e, tf2_ros::Buffer& b,
const std::string& to, const std::string& from, const std::string& to, const std::string& from,
...@@ -37,16 +39,24 @@ struct TransformListenerData { ...@@ -37,16 +39,24 @@ struct TransformListenerData {
, toFrame(to) , toFrame(to)
, fromFrame(from) , fromFrame(from)
, max_elapsed(0.5) , max_elapsed(0.5)
, availableSig(signame+"_available")
, signal(signame) , signal(signame)
, failbackSig(NULL, signame+"_failback") , failbackSig(NULL, signame+"_failback")
{ {
signal.setFunction( signal.setFunction(
boost::bind(&TransformListenerData::getTransform, this, _1, _2)); boost::bind(&TransformListenerData::getTransform, this, _1, _2));
availableSig.setFunction(
boost::bind(&TransformListenerData::isAvailable, this, _1, _2));
availableSig.setNeedUpdateFromAllChildren(true);
failbackSig.setConstant (sot::MatrixHomogeneous::Identity()); failbackSig.setConstant (sot::MatrixHomogeneous::Identity());
signal.addDependency(failbackSig); signal.addDependencies(failbackSig << availableSig);
} }
sot::MatrixHomogeneous& getTransform(sot::MatrixHomogeneous& res, int time); sot::MatrixHomogeneous& getTransform(sot::MatrixHomogeneous& res, int time);
bool& isAvailable(bool& isAvailable, int time);
}; };
} // namespace internal } // namespace internal
...@@ -82,11 +92,13 @@ class RosTfListener : public Entity { ...@@ -82,11 +92,13 @@ class RosTfListener : public Entity {
addCommand("setMaximumDelay", command::makeCommandVoid2(*this, &RosTfListener::setMaximumDelay, docstring)); addCommand("setMaximumDelay", command::makeCommandVoid2(*this, &RosTfListener::setMaximumDelay, docstring));
} }
~RosTfListener() { ~RosTfListener()
{
for (Map_t::const_iterator _it = listenerDatas.begin(); _it != listenerDatas.end(); ++_it) delete _it->second; for (Map_t::const_iterator _it = listenerDatas.begin(); _it != listenerDatas.end(); ++_it) delete _it->second;
} }
void add(const std::string& to, const std::string& from, const std::string& signame) { void add(const std::string& to, const std::string& from, const std::string& signame)
{
if (listenerDatas.find(signame) != listenerDatas.end()) if (listenerDatas.find(signame) != listenerDatas.end())
throw std::invalid_argument("A signal " + signame + " already exists in RosTfListener " + getName()); throw std::invalid_argument("A signal " + signame + " already exists in RosTfListener " + getName());
...@@ -95,7 +107,7 @@ class RosTfListener : public Entity { ...@@ -95,7 +107,7 @@ class RosTfListener : public Entity {
TransformListenerData* tld = TransformListenerData* tld =
new TransformListenerData(this, buffer, to, from, signalName.str()); new TransformListenerData(this, buffer, to, from, signalName.str());
signalRegistration(tld->signal << tld->failbackSig); signalRegistration(tld->signal << tld->availableSig << tld->failbackSig);
listenerDatas[signame] = tld; listenerDatas[signame] = tld;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment