image_display_base.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <boost/algorithm/string/erase.hpp>
31 #include <boost/foreach.hpp>
32 #include <boost/shared_ptr.hpp>
33 
35 
37 
38 #include "rviz/validate_floats.h"
39 
41 
42 namespace rviz
43 {
44 ImageDisplayBase::ImageDisplayBase() : Display(), sub_(), tf_filter_(), messages_received_(0)
45 {
47  new RosTopicProperty("Image Topic", "",
48  QString::fromStdString(ros::message_traits::datatype<sensor_msgs::Image>()),
49  "sensor_msgs::Image topic to subscribe to.", this, SLOT(updateTopic()));
50 
51  transport_property_ = new EnumProperty("Transport Hint", "raw", "Preferred method of sending images.",
52  this, SLOT(updateTopic()));
53 
54  connect(transport_property_, SIGNAL(requestOptions(EnumProperty*)), this,
56 
58  new IntProperty("Queue Size", 2,
59  "Advanced: set the size of the incoming message queue. Increasing this "
60  "is useful if your incoming TF data is delayed significantly from your"
61  " image data, but it can greatly increase memory usage if the messages are big.",
62  this, SLOT(updateQueueSize()));
64 
66 
68  new BoolProperty("Unreliable", false, "Prefer UDP topic transport", this, SLOT(updateTopic()));
69 }
70 
72 {
73  unsubscribe();
74 }
75 
77 {
80 }
81 
82 void ImageDisplayBase::setTopic(const QString& topic, const QString& datatype)
83 {
84  if (datatype == ros::message_traits::datatype<sensor_msgs::Image>())
85  {
87  topic_property_->setString(topic);
88  }
89  else
90  {
91  int index = topic.lastIndexOf("/");
92  if (index == -1)
93  {
94  ROS_WARN("ImageDisplayBase::setTopic() Invalid topic name: %s", topic.toStdString().c_str());
95  return;
96  }
97  QString transport = topic.mid(index + 1);
98  QString base_topic = topic.mid(0, index);
99 
100  transport_property_->setString(transport);
101  topic_property_->setString(base_topic);
102  }
103 }
104 
105 
106 void ImageDisplayBase::incomingMessage(const sensor_msgs::Image::ConstPtr& msg)
107 {
108  if (!msg || context_->getFrameManager()->getPause())
109  {
110  return;
111  }
112 
114  setStatus(StatusProperty::Ok, "Image", QString::number(messages_received_) + " images received");
115 
116  emitTimeSignal(msg->header.stamp);
117 
118  processMessage(msg);
119 }
120 
121 
122 void ImageDisplayBase::failedMessage(const sensor_msgs::Image::ConstPtr& msg,
124 {
126  context_->getFrameManager()->discoverFailureReason(msg->header.frame_id,
127  msg->header.stamp, "", reason));
128 }
129 
130 
132 {
133  Display::reset();
134  if (tf_filter_)
135  {
136  tf_filter_->clear();
137  update_nh_.getCallbackQueue()->removeByID((uint64_t)tf_filter_.get());
138  }
139 
140  messages_received_ = 0;
141  setStatus(StatusProperty::Warn, "Image", "No Image received");
142 }
143 
145 {
146  uint32_t size = queue_size_property_->getInt();
147  if (tf_filter_)
148  {
149  tf_filter_->setQueueSize(size);
150  subscribe();
151  }
152 }
153 
155 {
156  if (!isEnabled())
157  {
158  return;
159  }
160 
161  try
162  {
163  tf_filter_.reset();
164 
166 
167  if (!topic_property_->getTopicStd().empty() && !transport_property_->getStdString().empty())
168  {
169  // Determine UDP vs TCP transport for user selection.
171  {
172  sub_->subscribe(*it_, topic_property_->getTopicStd(), (uint32_t)queue_size_property_->getInt(),
175  }
176  else
177  {
178  sub_->subscribe(*it_, topic_property_->getTopicStd(), (uint32_t)queue_size_property_->getInt(),
180  }
181 
182 
183  if (targetFrame_.empty())
184  {
185  sub_->registerCallback(boost::bind(&ImageDisplayBase::incomingMessage, this, _1));
186  }
187  else
188  {
191  update_nh_));
192  tf_filter_->registerCallback(boost::bind(&ImageDisplayBase::incomingMessage, this, _1));
193  tf_filter_->registerFailureCallback(boost::bind(&ImageDisplayBase::failedMessage, this, _1, _2));
194  }
195  }
196  setStatus(StatusProperty::Ok, "Topic", "OK");
197  }
198  catch (ros::Exception& e)
199  {
200  setStatus(StatusProperty::Error, "Topic", QString("Error subscribing: ") + e.what());
201  }
202  catch (image_transport::Exception& e)
203  {
204  setStatus(StatusProperty::Error, "Topic", QString("Error subscribing: ") + e.what());
205  }
206 }
207 
209 {
210  // Quick fix for #1372. Can be removed if https://github.com/ros/geometry2/pull/402 is released
211  if (tf_filter_)
212  update_nh_.getCallbackQueue()->removeByID((uint64_t)tf_filter_.get());
213 
214  tf_filter_.reset();
215  sub_.reset();
216 }
217 
219 {
220  if (tf_filter_)
221  {
222  tf_filter_->setTargetFrame(fixed_frame_.toStdString());
223  reset();
224  }
225 }
226 
228 {
230  "image_transport", "image_transport::SubscriberPlugin");
231 
232  BOOST_FOREACH (const std::string& lookup_name, sub_loader.getDeclaredClasses())
233  {
234  // lookup_name is formatted as "pkg/transport_sub", for instance
235  // "image_transport/compressed_sub" for the "compressed"
236  // transport. This code removes the "_sub" from the tail and
237  // everything up to and including the "/" from the head, leaving
238  // "compressed" (for example) in transport_name.
239  std::string transport_name = boost::erase_last_copy(lookup_name, "_sub");
240  transport_name = transport_name.substr(lookup_name.find('/') + 1);
241 
242  // If the plugin loads without throwing an exception, add its
243  // transport name to the list of valid plugins, otherwise ignore
244  // it.
245  try
246  {
248  transport_plugin_types_.insert(transport_name);
249  }
250  catch (const pluginlib::LibraryLoadException& e)
251  {
252  }
253  catch (const pluginlib::CreateClassException& e)
254  {
255  }
256  }
257 }
258 
260 {
261  unsubscribe();
262  reset();
263  subscribe();
265 }
266 
268 {
269  property->clearOptions();
270 
271  std::vector<std::string> choices;
272 
273  choices.push_back("raw");
274 
275  // Loop over all current ROS topic names
277  ros::master::getTopics(topics);
278  ros::master::V_TopicInfo::iterator it = topics.begin();
279  ros::master::V_TopicInfo::iterator end = topics.end();
280  for (; it != end; ++it)
281  {
282  // If the beginning of this topic name is the same as topic_,
283  // and the whole string is not the same,
284  // and the next character is /
285  // and there are no further slashes from there to the end,
286  // then consider this a possible transport topic.
287  const ros::master::TopicInfo& ti = *it;
288  const std::string& topic_name = ti.name;
289  const std::string& topic = topic_property_->getStdString();
290 
291  if (topic_name.find(topic) == 0 && topic_name != topic && topic_name[topic.size()] == '/' &&
292  topic_name.find('/', topic.size() + 1) == std::string::npos)
293  {
294  std::string transport_type = topic_name.substr(topic.size() + 1);
295 
296  // If the transport type string found above is in the set of
297  // supported transport type plugins, add it to the list.
298  if (transport_plugin_types_.find(transport_type) != transport_plugin_types_.end())
299  {
300  choices.push_back(transport_type);
301  }
302  }
303  }
304 
305  for (size_t i = 0; i < choices.size(); i++)
306  {
307  property->addOptionStd(choices[i]);
308  }
309 }
310 
311 } // end namespace rviz
void setStatusStd(StatusProperty::Level level, const std::string &name, const std::string &text)
Show status level and text, using a std::string. Convenience function which converts std::string to Q...
Definition: display.h:163
boost::shared_ptr< tf2_ros::MessageFilter< sensor_msgs::Image > > tf_filter_
virtual void setString(const QString &str)
std::string discoverFailureReason(const std::string &frame_id, const ros::Time &stamp, const std::string &caller_id, tf::FilterFailureReason reason)
Create a description of a transform problem.
void fillTransportOptionList(EnumProperty *property)
Fill list of available and working transport options.
DisplayContext * context_
This DisplayContext pointer is the main connection a Display has into the rest of rviz...
Definition: display.h:287
void failedMessage(const sensor_msgs::Image::ConstPtr &msg, tf2_ros::FilterFailureReason reason)
Callback for messages, whose frame_id cannot resolved.
boost::shared_ptr< T > createInstance(const std::string &lookup_name)
void emitTimeSignal(ros::Time time)
Emit a time signal that other Displays can synchronize to.
Definition: display.cpp:282
ros::NodeHandle update_nh_
A NodeHandle whose CallbackQueue is run from the main GUI thread (the "update" thread).
Definition: display.h:300
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
void setMin(int min)
std::vector< TopicInfo > V_TopicInfo
#define ROS_WARN(...)
std::string getTopicStd() const
void reset() override
Reset display.
Property specialized to provide max/min enforcement for integers.
Definition: int_property.h:37
std::string getStdString()
virtual void removeByID(uint64_t owner_id)=0
QString fixed_frame_
A convenience variable equal to context_->getFixedFrame().
Definition: display.h:312
BoolProperty * unreliable_property_
virtual void processMessage(const sensor_msgs::Image::ConstPtr &msg)=0
Implement this to process the contents of a message.
IntProperty * queue_size_property_
TransportHints & unreliable()
virtual void subscribe()
ROS topic management.
virtual void reset()
Called to tell the display to clear its state.
Definition: display.cpp:287
std::vector< std::string > getDeclaredClasses()
virtual void updateQueueSize()
Update queue size of tf filter.
virtual FrameManager * getFrameManager() const =0
Return the FrameManager instance.
CallbackQueueInterface * getCallbackQueue() const
void fixedFrameChanged() override
Called by setFixedFrame(). Override to respond to changes to fixed_frame_.
void onInitialize() override
Override this function to do subclass-specific initialization.
virtual int getInt() const
Return the internal property value as an integer.
Definition: int_property.h:74
BoolProperty(const QString &name=QString(), bool default_value=false, const QString &description=QString(), Property *parent=nullptr, const char *changed_slot=nullptr, QObject *receiver=nullptr)
virtual std::shared_ptr< tf2_ros::Buffer > getTF2BufferPtr() const =0
Convenience function: returns getFrameManager()->getTF2BufferPtr().
virtual void queueRender()=0
Queues a render. Multiple calls before a render happens will only cause a single render.
bool isEnabled() const
Return true if this Display is enabled, false if not.
Definition: display.cpp:268
EnumProperty * transport_property_
RosTopicProperty * topic_property_
virtual void updateTopic()
Update topic and resubscribe.
std::set< std::string > transport_plugin_types_
void incomingMessage(const sensor_msgs::Image::ConstPtr &msg)
Incoming message callback. Checks if the message pointer is valid, increments messages_received_, then calls processMessage().
void setTopic(const QString &topic, const QString &datatype) override
Set the ROS topic to listen to for this display.
boost::shared_ptr< image_transport::SubscriberFilter > sub_
virtual bool getBool() const
bool setStdString(const std::string &std_str)
virtual void setString(const QString &str)
Set the value of this property to the given string. Does not force the value to be one of the list of...
Enum property.
Definition: enum_property.h:46
boost::scoped_ptr< image_transport::ImageTransport > it_
virtual void setStatus(StatusProperty::Level level, const QString &name, const QString &text)
Show status level and text. This is thread-safe.
Definition: display.cpp:175


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