effort_display.cpp
Go to the documentation of this file.
1 #include <OgreSceneNode.h>
2 #include <OgreSceneManager.h>
3 #include <QTimer>
4 
9 #include <rviz/frame_manager.h>
10 
11 #include <boost/foreach.hpp>
12 
13 #include "effort_visual.h"
14 
15 #include "effort_display.h"
16 
17 #include <urdf/model.h>
18 
19 namespace rviz
20 {
21 JointInfo::JointInfo(const std::string name, rviz::Property* parent_category)
22 {
23  name_ = name;
24  effort_ = 0;
25  max_effort_ = 0;
27 
28  // info->category_ = new Property( QString::fromStdString( info->name_ ) , QVariant(), "",
29  // joints_category_);
30  category_ = new rviz::Property(QString::fromStdString(name_), true, "", parent_category,
31  SLOT(updateVisibility()), this);
32 
33  effort_property_ = new rviz::FloatProperty("Effort", 0, "Effort value of this joint.", category_);
35 
37  new rviz::FloatProperty("Max Effort", 0, "Max Effort value of this joint.", category_);
39 }
40 
42 {
43 }
44 
46 {
47 }
48 
49 void JointInfo::setEffort(double e)
50 {
52  effort_ = e;
53 }
55 {
56  return effort_;
57 }
59 {
61  max_effort_ = m;
62 }
64 {
65  return max_effort_;
66 }
67 
69 {
70  return category_->getValue().toBool();
71 }
72 
73 JointInfo* EffortDisplay::getJointInfo(const std::string& joint)
74 {
75  M_JointInfo::iterator it = joints_.find(joint);
76  if (it == joints_.end())
77  {
78  return nullptr;
79  }
80 
81  return it->second;
82 }
83 
84 JointInfo* EffortDisplay::createJoint(const std::string& joint)
85 {
86  JointInfo* info = new JointInfo(joint, joints_category_);
87  joints_.insert(std::make_pair(joint, info));
88  return info;
89 }
90 
93 {
94  alpha_property_ = new rviz::FloatProperty("Alpha", 1.0, "0 is fully transparent, 1.0 is fully opaque.",
95  this, SLOT(updateColorAndAlpha()));
96 
97  width_property_ = new rviz::FloatProperty("Width", 0.02, "Width to drow effort circle", this,
98  SLOT(updateColorAndAlpha()));
99 
100  scale_property_ = new rviz::FloatProperty("Scale", 1.0, "Scale to drow effort circle", this,
101  SLOT(updateColorAndAlpha()));
102 
103  history_length_property_ =
104  new rviz::IntProperty("History Length", 1, "Number of prior measurements to display.", this,
105  SLOT(updateHistoryLength()));
106  history_length_property_->setMin(1);
107  history_length_property_->setMax(100000);
108 
109 
110  robot_description_property_ =
111  new rviz::StringProperty("Robot Description", "robot_description",
112  "Name of the parameter to search for to load the robot description.",
113  this, SLOT(updateRobotDescription()));
114 
115  tf_prefix_property_ = new StringProperty(
116  "TF Prefix", "",
117  "Robot Model normally assumes the link name is the same as the tf frame name. "
118  " This option allows you to set a prefix. Mainly useful for multi-robot situations.",
119  this, SLOT(updateTfPrefix()));
120 
121  joints_category_ = new rviz::Property("Joints", QVariant(), "", this);
122 }
123 
125 {
126  MFDClass::onInitialize();
127  updateHistoryLength();
128 }
129 
131 {
132  // delete robot_model_; // sharead pointer
133 }
134 
135 // Clear the visuals by deleting their objects.
137 {
138  MFDClass::reset();
139  visuals_.clear();
140 }
141 
143 {
144  clearStatuses();
145  context_->queueRender();
146 }
147 
149 {
150  clearStatuses();
151  robot_description_.clear();
152 }
153 
154 // Set the current color and alpha values for each visual.
156 {
157  float width = width_property_->getFloat();
158  float scale = scale_property_->getFloat();
159 
160  for (size_t i = 0; i < visuals_.size(); i++)
161  {
162  visuals_[i]->setWidth(width);
163  visuals_[i]->setScale(scale);
164  }
165 }
166 
168 {
169  if (isEnabled())
170  {
171  load();
172  context_->queueRender();
173  }
174 }
175 
176 // Set the number of past visuals to show.
178 {
179  visuals_.rset_capacity(history_length_property_->getInt());
180 }
181 
183 {
184  // get robot_description
185  std::string content;
186  try
187  {
188  if (!update_nh_.getParam(robot_description_property_->getStdString(), content))
189  {
190  std::string loc;
191  if (update_nh_.searchParam(robot_description_property_->getStdString(), loc))
192  update_nh_.getParam(loc, content);
193  else
194  {
195  clear();
196  setStatus(StatusProperty::Error, "URDF",
197  QString("Parameter [%1] does not exist, and was not found by searchParam()")
198  .arg(robot_description_property_->getString()));
199  // try again in a second
200  QTimer::singleShot(1000, this, SLOT(updateRobotDescription()));
201  return;
202  }
203  }
204  }
205  catch (const ros::InvalidNameException& e)
206  {
207  clear();
208  setStatus(StatusProperty::Error, "URDF",
209  QString("Invalid parameter name: %1.\n%2")
210  .arg(robot_description_property_->getString(), e.what()));
211  return;
212  }
213 
214  if (content.empty())
215  {
216  clear();
217  setStatus(rviz::StatusProperty::Error, "URDF", "URDF is empty");
218  return;
219  }
220 
221  if (content == robot_description_)
222  {
223  return;
224  }
225 
226  robot_description_ = content;
227 
228 
229  robot_model_ = boost::shared_ptr<urdf::Model>(new urdf::Model());
230  if (!robot_model_->initString(content))
231  {
232  ROS_ERROR("Unable to parse URDF description!");
233  setStatus(rviz::StatusProperty::Error, "URDF", "Unable to parse robot model description!");
234  return;
235  }
236  setStatus(rviz::StatusProperty::Ok, "URDF", "Robot model parsed Ok");
237  for (std::map<std::string, urdf::JointSharedPtr>::iterator it = robot_model_->joints_.begin();
238  it != robot_model_->joints_.end(); it++)
239  {
240  urdf::JointSharedPtr joint = it->second;
241  if (joint->type == urdf::Joint::REVOLUTE)
242  {
243  std::string joint_name = it->first;
244  urdf::JointLimitsSharedPtr limit = joint->limits;
245  joints_[joint_name] = createJoint(joint_name);
246  joints_[joint_name]->setMaxEffort(limit->effort);
247  }
248  }
249 }
250 
252 {
253  load();
254 }
255 
257 {
258  clear();
259 }
260 
261 #if 0
262  void EffortDisplay::setRobotDescription( const std::string& description_param )
263  {
264  description_param_ = description_param;
265 
266  propertyChanged(robot_description_property_);
267 
268  if ( isEnabled() )
269  {
270  load();
271  unsubscribe();
272  subscribe();
273  causeRender();
274  }
275  }
276 
277  void EffortDisplay::setAllEnabled(bool enabled)
278  {
279  all_enabled_ = enabled;
280 
281  M_JointInfo::iterator it = joints_.begin();
282  M_JointInfo::iterator end = joints_.end();
283  for (; it != end; ++it)
284  {
285  JointInfo* joint = it->second;
286 
287  setJointEnabled(joint, enabled);
288  }
289 
290  propertyChanged(all_enabled_property_);
291  }
292 
293 #endif
294 // This is our callback to handle an incoming message.
295 void EffortDisplay::processMessage(const sensor_msgs::JointState::ConstPtr& msg)
296 {
297  // Robot model might not be loaded already
298  if (!robot_model_)
299  {
300  return;
301  }
302  // We are keeping a circular buffer of visual pointers. This gets
303  // the next one, or creates and stores it if the buffer is not full
305  if (visuals_.full())
306  {
307  visual = visuals_.front();
308  }
309  else
310  {
311  visual.reset(new EffortVisual(context_->getSceneManager(), scene_node_, robot_model_));
312  }
313 
314  V_string joints;
315  size_t joint_num = msg->name.size();
316  if (joint_num != msg->effort.size())
317  {
318  std::string tmp_error = "Received a joint state msg with different joint names and efforts size!";
319  ROS_ERROR("%s", tmp_error.c_str());
320  setStatus(rviz::StatusProperty::Error, "TOPIC", QString::fromStdString(tmp_error));
321  return;
322  }
323  for (size_t i = 0; i < joint_num; ++i)
324  {
325  std::string joint_name = msg->name[i];
326  JointInfo* joint_info = getJointInfo(joint_name);
327  if (!joint_info)
328  continue; // skip joints..
329 
330  // set effort
331  joint_info->setEffort(msg->effort[i]);
332 
333  // update effort property ???
334  if ((ros::Time::now() - joint_info->last_update_) > ros::Duration(0.2))
335  {
336  joint_info->last_update_ = ros::Time::now();
337  }
338 
339  const urdf::Joint* joint = robot_model_->getJoint(joint_name).get();
340  int joint_type = joint->type;
341  if (joint_type == urdf::Joint::REVOLUTE)
342  {
343  std::string tf_prefix = tf_prefix_property_->getStdString();
344  std::string tf_frame_id = (tf_prefix.empty() ? "" : tf_prefix + "/") + joint->child_link_name;
345  Ogre::Quaternion orientation;
346  Ogre::Vector3 position;
347 
348  // Here we call the rviz::FrameManager to get the transform from the
349  // fixed frame to the frame in the header of this Effort message. If
350  // it fails, we can't do anything else so we return.
351  if (!context_->getFrameManager()->getTransform(tf_frame_id, ros::Time(),
352  // msg->header.stamp, // ???
353  position, orientation))
354  {
355  ROS_DEBUG("Error transforming from frame '%s' to frame '%s'", tf_frame_id.c_str(),
356  qPrintable(fixed_frame_));
357  continue;
358  };
359  tf::Vector3 axis_joint(joint->axis.x, joint->axis.y, joint->axis.z);
360  tf::Vector3 axis_z(0, 0, 1);
361  tf::Quaternion axis_rotation(tf::tfCross(axis_joint, axis_z), tf::tfAngle(axis_joint, axis_z));
362  if (std::isnan(axis_rotation.x()) || std::isnan(axis_rotation.y()) || std::isnan(axis_rotation.z()))
363  axis_rotation = tf::Quaternion::getIdentity();
364 
365  tf::Quaternion axis_orientation(orientation.x, orientation.y, orientation.z, orientation.w);
366  tf::Quaternion axis_rot = axis_orientation * axis_rotation;
367  Ogre::Quaternion joint_orientation(Ogre::Real(axis_rot.w()), Ogre::Real(axis_rot.x()),
368  Ogre::Real(axis_rot.y()), Ogre::Real(axis_rot.z()));
369  visual->setFramePosition(joint_name, position);
370  visual->setFrameOrientation(joint_name, joint_orientation);
371  visual->setFrameEnabled(joint_name, joint_info->getEnabled());
372  }
373  }
374 
375 
376  // Now set or update the contents of the chosen visual.
377  float scale = scale_property_->getFloat();
378  float width = width_property_->getFloat();
379  visual->setWidth(width);
380  visual->setScale(scale);
381  visual->setMessage(msg);
382 
383  visuals_.push_back(visual);
384 }
385 
386 } // end namespace rviz
387 
388 // Tell pluginlib about this class. It is important to do this in
389 // global scope, outside our package's namespace.
void onDisable() override
Derived classes override this to do the actual work of disabling themselves.
~JointInfo() override
void processMessage(const sensor_msgs::JointState::ConstPtr &msg) override
Implement this to process the contents of a message.
void setEffort(double e)
bool getEnabled() const
static int limit(int i)
Definition: parse_color.cpp:34
void reset() override
Called to tell the display to clear its state.
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
std::string name_
ros::Time last_update_
JointInfo(const std::string name, rviz::Property *parent_category)
Property specialized to enforce floating point max/min.
Property specialized to provide max/min enforcement for integers.
Definition: int_property.h:37
void setMaxEffort(double m)
void onEnable() override
Derived classes override this to do the actual work of enabling themselves.
bool setFloat(float new_value)
Float-typed "SLOT" version of setValue().
void subscribe()
JointInfo * getJointInfo(const std::string &joint)
JointInfo * createJoint(const std::string &joint)
static const Quaternion & getIdentity()
TFSIMD_FORCE_INLINE Vector3 tfCross(const Vector3 &v1, const Vector3 &v2)
rviz::FloatProperty * max_effort_property_
std::vector< std::string > V_string
TFSIMD_FORCE_INLINE tfScalar tfAngle(const Vector3 &v1, const Vector3 &v2)
Property specialized for string values.
rviz::FloatProperty * effort_property_
rviz::Property * category_
static Time now()
virtual QVariant getValue() const
Return the value of this Property as a QVariant. If the value has never been set, an invalid QVariant...
Definition: property.cpp:150
void unsubscribe()
void onInitialize() override
Override this function to do subclass-specific initialization.
virtual void setReadOnly(bool read_only)
Prevent or allow users to edit this property from a PropertyTreeWidget.
Definition: property.h:436
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat May 27 2023 02:06:24