Skip to content

Commit c722950

Browse files
committed
robot_model_display: arrange scene nodes of links in URDF's tree structure in order to avoid jittering of movable links due to tf latency.
1 parent e22bf62 commit c722950

File tree

8 files changed

+105
-21
lines changed

8 files changed

+105
-21
lines changed

src/rviz/default_plugin/robot_model_display.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,25 @@ void RobotModelDisplay::update(float wall_dt, float /*ros_dt*/)
229229

230230
if (has_new_transforms_ || update)
231231
{
232+
Ogre::Vector3 position;
233+
Ogre::Quaternion orientation;
234+
if (context_->getFrameManager()->getTransform(robot_->getRootLink()->getName(), ros::Time(),
235+
position, orientation))
236+
{
237+
robot_->setPosition(position);
238+
robot_->setOrientation(orientation);
239+
linkUpdaterStatusFunction(StatusProperty::Ok, robot_->getRootLink()->getName(), "Transform OK",
240+
this);
241+
}
242+
else
243+
{
244+
std::stringstream ss;
245+
ss << "No transform from [" << robot_->getRootLink()->getName() << "] to ["
246+
<< fixed_frame_.toStdString() << "]";
247+
linkUpdaterStatusFunction(StatusProperty::Error, robot_->getRootLink()->getName(), ss.str(), this);
248+
}
249+
250+
232251
robot_->update(TFLinkUpdater(context_->getFrameManager(),
233252
boost::bind(linkUpdaterStatusFunction, _1, _2, _3, this),
234253
tf_prefix_property_->getStdString()));

src/rviz/robot/link_updater.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ namespace rviz
4040
class LinkUpdater
4141
{
4242
public:
43-
virtual bool getLinkTransforms(const std::string& link_name,
43+
virtual bool getLinkTransforms(const std::string& parent_link_name,
44+
const std::string& link_name,
4445
Ogre::Vector3& visual_position,
4546
Ogre::Quaternion& visual_orientation,
4647
Ogre::Vector3& collision_position,

src/rviz/robot/robot.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,14 @@ void Robot::clear()
218218

219219
RobotLink* Robot::LinkFactory::createLink(Robot* robot,
220220
const urdf::LinkConstSharedPtr& link,
221+
Ogre::SceneNode* parent_visual_node,
222+
Ogre::SceneNode* parent_collision_node,
221223
const std::string& parent_joint_name,
222224
bool visual,
223225
bool collision)
224226
{
225-
return new RobotLink(robot, link, parent_joint_name, visual, collision);
227+
return new RobotLink(robot, link, parent_visual_node, parent_collision_node, parent_joint_name, visual,
228+
collision);
226229
}
227230

228231
RobotJoint* Robot::LinkFactory::createJoint(Robot* robot, const urdf::JointConstSharedPtr& joint)
@@ -244,20 +247,26 @@ void Robot::load(const urdf::ModelInterface& urdf, bool visual, bool collision)
244247
// Create properties for each link.
245248
// Properties are not added to display until changedLinkTreeStyle() is called (below).
246249
{
247-
typedef std::map<std::string, urdf::LinkSharedPtr> M_NameToUrdfLink;
248-
M_NameToUrdfLink::const_iterator link_it = urdf.links_.begin();
249-
M_NameToUrdfLink::const_iterator link_end = urdf.links_.end();
250-
for (; link_it != link_end; ++link_it)
250+
// traverse URDF tree in depth first order and copy tree structure for links' scene nodes
251+
std::vector<std::tuple<urdf::LinkConstSharedPtr, Ogre::SceneNode*, Ogre::SceneNode*>> link_stack_;
252+
link_stack_.emplace_back(urdf.getRoot(), root_visual_node_, root_collision_node_);
253+
while (!link_stack_.empty())
251254
{
252-
const urdf::LinkConstSharedPtr& urdf_link = link_it->second;
255+
urdf::LinkConstSharedPtr urdf_link = std::get<0>(link_stack_.back());
256+
Ogre::SceneNode* parent_visual_node = std::get<1>(link_stack_.back());
257+
Ogre::SceneNode* parent_collision_node = std::get<2>(link_stack_.back());
258+
link_stack_.pop_back();
259+
253260
std::string parent_joint_name;
254261

255262
if (urdf_link != urdf.getRoot() && urdf_link->parent_joint)
256263
{
257264
parent_joint_name = urdf_link->parent_joint->name;
258265
}
259266

260-
RobotLink* link = link_factory_->createLink(this, urdf_link, parent_joint_name, visual, collision);
267+
RobotLink* link =
268+
link_factory_->createLink(this, urdf_link, parent_visual_node, parent_collision_node,
269+
parent_joint_name, visual, collision);
261270

262271
if (urdf_link == urdf.getRoot())
263272
{
@@ -267,6 +276,9 @@ void Robot::load(const urdf::ModelInterface& urdf, bool visual, bool collision)
267276
links_[urdf_link->name] = link;
268277

269278
link->setRobotAlpha(alpha_);
279+
280+
for (const auto& c : urdf_link->child_links)
281+
link_stack_.emplace_back(c, link->getVisualTreeNode(), link->getCollisionTreeNode());
270282
}
271283
}
272284

@@ -709,8 +721,8 @@ void Robot::update(const LinkUpdater& updater)
709721

710722
Ogre::Vector3 visual_position, collision_position;
711723
Ogre::Quaternion visual_orientation, collision_orientation;
712-
if (updater.getLinkTransforms(link->getName(), visual_position, visual_orientation,
713-
collision_position, collision_orientation))
724+
if (updater.getLinkTransforms(link->getParentLinkName(), link->getName(), visual_position,
725+
visual_orientation, collision_position, collision_orientation))
714726
{
715727
// Check if visual_orientation, visual_position, collision_orientation, and collision_position are
716728
// NaN.

src/rviz/robot/robot.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ class Robot : public QObject
199199

200200
virtual RobotLink* createLink(Robot* robot,
201201
const urdf::LinkConstSharedPtr& link,
202+
Ogre::SceneNode* parent_visual_node,
203+
Ogre::SceneNode* parent_collision_node,
202204
const std::string& parent_joint_name,
203205
bool visual,
204206
bool collision);

src/rviz/robot/robot_link.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,16 @@ static std::map<const RobotLink*, std::string> errors;
151151

152152
RobotLink::RobotLink(Robot* robot,
153153
const urdf::LinkConstSharedPtr& link,
154+
Ogre::SceneNode* parent_visual_node,
155+
Ogre::SceneNode* parent_collision_node,
154156
const std::string& parent_joint_name,
155157
bool visual,
156158
bool collision)
157159
: robot_(robot)
158160
, scene_manager_(robot->getDisplayContext()->getSceneManager())
159161
, context_(robot->getDisplayContext())
160162
, name_(link->name)
163+
, parent_link_name_(link->getParent() ? link->getParent()->name : "")
161164
, parent_joint_name_(parent_joint_name)
162165
, visual_node_(nullptr)
163166
, collision_node_(nullptr)
@@ -198,8 +201,12 @@ RobotLink::RobotLink(Robot* robot,
198201

199202
link_property_->collapse();
200203

201-
visual_node_ = robot_->getVisualNode()->createChildSceneNode();
202-
collision_node_ = robot_->getCollisionNode()->createChildSceneNode();
204+
// create scene nodes in a tree structure analog to URDF tree
205+
// we use visual_node_ and collision_node_ as leafs in order not to hide child links when set to invisible
206+
visual_tree_node_ = parent_visual_node->createChildSceneNode();
207+
visual_node_ = visual_tree_node_->createChildSceneNode();
208+
collision_tree_node_ = parent_collision_node->createChildSceneNode();
209+
collision_node_ = collision_tree_node_->createChildSceneNode();
203210

204211
// create material for coloring links
205212
color_material_ = Ogre::MaterialPtr(new Ogre::Material(
@@ -306,6 +313,8 @@ RobotLink::~RobotLink()
306313

307314
scene_manager_->destroySceneNode(visual_node_);
308315
scene_manager_->destroySceneNode(collision_node_);
316+
scene_manager_->destroySceneNode(visual_tree_node_);
317+
scene_manager_->destroySceneNode(collision_tree_node_);
309318

310319
if (trail_)
311320
{
@@ -872,16 +881,16 @@ void RobotLink::setTransforms(const Ogre::Vector3& visual_position,
872881
const Ogre::Vector3& collision_position,
873882
const Ogre::Quaternion& collision_orientation)
874883
{
875-
if (visual_node_)
884+
if (visual_tree_node_)
876885
{
877-
visual_node_->setPosition(visual_position);
878-
visual_node_->setOrientation(visual_orientation);
886+
visual_tree_node_->setPosition(visual_position);
887+
visual_tree_node_->setOrientation(visual_orientation);
879888
}
880889

881-
if (collision_node_)
890+
if (collision_tree_node_)
882891
{
883-
collision_node_->setPosition(collision_position);
884-
collision_node_->setOrientation(collision_orientation);
892+
collision_tree_node_->setPosition(collision_position);
893+
collision_tree_node_->setOrientation(collision_orientation);
885894
}
886895

887896
position_property_->setVector(visual_position);

src/rviz/robot/robot_link.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class RobotLink : public QObject
8282
public:
8383
RobotLink(Robot* robot,
8484
const urdf::LinkConstSharedPtr& link,
85+
Ogre::SceneNode* parent_visual_node,
86+
Ogre::SceneNode* parent_collision_node,
8587
const std::string& parent_joint_name,
8688
bool visual,
8789
bool collision);
@@ -99,6 +101,10 @@ class RobotLink : public QObject
99101
{
100102
return name_;
101103
}
104+
const std::string& getParentLinkName() const
105+
{
106+
return parent_link_name_;
107+
}
102108
const std::string& getParentJointName() const
103109
{
104110
return parent_joint_name_;
@@ -119,6 +125,14 @@ class RobotLink : public QObject
119125
{
120126
return collision_node_;
121127
}
128+
Ogre::SceneNode* getVisualTreeNode() const
129+
{
130+
return visual_tree_node_;
131+
}
132+
Ogre::SceneNode* getCollisionTreeNode() const
133+
{
134+
return collision_tree_node_;
135+
}
122136
Robot* getRobot() const
123137
{
124138
return robot_;
@@ -200,6 +214,7 @@ private Q_SLOTS:
200214
DisplayContext* context_;
201215

202216
std::string name_; ///< Name of this link
217+
std::string parent_link_name_;
203218
std::string parent_joint_name_;
204219
std::vector<std::string> child_joint_names_;
205220

@@ -226,6 +241,8 @@ private Q_SLOTS:
226241

227242
Ogre::SceneNode* visual_node_; ///< The scene node the visual meshes are attached to
228243
Ogre::SceneNode* collision_node_; ///< The scene node the collision meshes are attached to
244+
Ogre::SceneNode* visual_tree_node_; ///< The scene node above visual_node is attached to
245+
Ogre::SceneNode* collision_tree_node_; ///< The scene node above collision_node is attached to
229246

230247
Ogre::RibbonTrail* trail_;
231248

src/rviz/robot/tf_link_updater.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,47 @@ TFLinkUpdater::TFLinkUpdater(FrameManager* frame_manager,
4343
{
4444
}
4545

46-
bool TFLinkUpdater::getLinkTransforms(const std::string& _link_name,
46+
bool TFLinkUpdater::getLinkTransforms(const std::string& _parent_link_name,
47+
const std::string& _link_name,
4748
Ogre::Vector3& visual_position,
4849
Ogre::Quaternion& visual_orientation,
4950
Ogre::Vector3& collision_position,
5051
Ogre::Quaternion& collision_orientation) const
5152
{
53+
if (_parent_link_name.empty())
54+
{
55+
visual_position = Ogre::Vector3::ZERO;
56+
visual_orientation = Ogre::Quaternion::IDENTITY;
57+
collision_position = Ogre::Vector3::ZERO;
58+
collision_orientation = Ogre::Quaternion::IDENTITY;
59+
return true;
60+
}
61+
std::string parent_link_name = concat(tf_prefix_, _parent_link_name);
5262
std::string link_name = concat(tf_prefix_, _link_name);
5363

5464
Ogre::Vector3 position;
5565
Ogre::Quaternion orientation;
56-
if (!frame_manager_->getTransform(link_name, ros::Time(), position, orientation))
66+
67+
geometry_msgs::TransformStamped tf;
68+
try
69+
{
70+
tf = frame_manager_->getTF2BufferPtr()->lookupTransform(parent_link_name, link_name, ros::Time());
71+
}
72+
catch (std::runtime_error& e)
5773
{
5874
std::stringstream ss;
5975
ss << "No transform from [" << link_name << "] to [" << frame_manager_->getFixedFrame() << "]";
6076
setLinkStatus(StatusProperty::Error, link_name, ss.str());
77+
ROS_DEBUG("Error transforming from frame '%s' to frame '%s': %s", link_name.c_str(),
78+
parent_link_name.c_str(), e.what());
6179
return false;
6280
}
6381

82+
position =
83+
Ogre::Vector3(tf.transform.translation.x, tf.transform.translation.y, tf.transform.translation.z);
84+
orientation = Ogre::Quaternion(tf.transform.rotation.w, tf.transform.rotation.x,
85+
tf.transform.rotation.y, tf.transform.rotation.z);
86+
6487
setLinkStatus(StatusProperty::Ok, link_name, "Transform OK");
6588

6689
// Collision/visual transforms are the same in this case

src/rviz/robot/tf_link_updater.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class TFLinkUpdater : public LinkUpdater
5252
TFLinkUpdater(FrameManager* frame_manager,
5353
const StatusCallback& status_cb = StatusCallback(),
5454
const std::string& tf_prefix = std::string());
55-
bool getLinkTransforms(const std::string& link_name,
55+
bool getLinkTransforms(const std::string& parent_link_name,
56+
const std::string& link_name,
5657
Ogre::Vector3& visual_position,
5758
Ogre::Quaternion& visual_orientation,
5859
Ogre::Vector3& collision_position,

0 commit comments

Comments
 (0)