marker_display.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "marker_display.h"
00031 #include "rviz/visualization_manager.h"
00032 #include "rviz/properties/property_manager.h"
00033 #include "rviz/properties/property.h"
00034 #include "rviz/selection/selection_manager.h"
00035 #include "rviz/frame_manager.h"
00036 #include "rviz/validate_floats.h"
00037 
00038 #include "markers/shape_marker.h"
00039 #include "markers/arrow_marker.h"
00040 #include "markers/line_list_marker.h"
00041 #include "markers/line_strip_marker.h"
00042 #include "markers/points_marker.h"
00043 #include "markers/text_view_facing_marker.h"
00044 #include "markers/mesh_resource_marker.h"
00045 #include "markers/triangle_list_marker.h"
00046 
00047 #include <ogre_tools/arrow.h>
00048 #include <ogre_tools/shape.h>
00049 #include <ogre_tools/billboard_line.h>
00050 
00051 #include <tf/transform_listener.h>
00052 
00053 #include <OGRE/OgreSceneNode.h>
00054 #include <OGRE/OgreSceneManager.h>
00055 
00056 namespace rviz
00057 {
00058 
00062 
00063 MarkerDisplay::MarkerDisplay()
00064   : Display()
00065   , marker_topic_("visualization_marker")
00066 {
00067 }
00068 
00069 void MarkerDisplay::onInitialize()
00070 {
00071   tf_filter_ = new tf::MessageFilter<visualization_msgs::Marker>(*vis_manager_->getTFClient(), "", 100, update_nh_);
00072   scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00073 
00074   tf_filter_->connectInput(sub_);
00075   tf_filter_->registerCallback(boost::bind(&MarkerDisplay::incomingMarker, this, _1));
00076   tf_filter_->registerFailureCallback(boost::bind(&MarkerDisplay::failedMarker, this, _1, _2));
00077 }
00078 
00079 MarkerDisplay::~MarkerDisplay()
00080 {
00081   unsubscribe();
00082 
00083   clearMarkers();
00084 
00085   delete tf_filter_;
00086 }
00087 
00088 MarkerBasePtr MarkerDisplay::getMarker(MarkerID id)
00089 {
00090   M_IDToMarker::iterator it = markers_.find(id);
00091   if (it != markers_.end())
00092   {
00093     return it->second;
00094   }
00095 
00096   return MarkerBasePtr();
00097 }
00098 
00099 void MarkerDisplay::clearMarkers()
00100 {
00101   markers_.clear();
00102   markers_with_expiration_.clear();
00103   frame_locked_markers_.clear();
00104   tf_filter_->clear();
00105 
00106   if (property_manager_)
00107   {
00108     M_Namespace::iterator it = namespaces_.begin();
00109     M_Namespace::iterator end = namespaces_.end();
00110     for (; it != end; ++it)
00111     {
00112       property_manager_->deleteProperty(it->second.prop.lock());
00113     }
00114   }
00115 
00116   namespaces_.clear();
00117 }
00118 
00119 void MarkerDisplay::onEnable()
00120 {
00121   subscribe();
00122 
00123   scene_node_->setVisible( true );
00124 }
00125 
00126 void MarkerDisplay::onDisable()
00127 {
00128   unsubscribe();
00129   tf_filter_->clear();
00130 
00131   clearMarkers();
00132 
00133   scene_node_->setVisible( false );
00134 }
00135 
00136 void MarkerDisplay::setMarkerTopic(const std::string& topic)
00137 {
00138   unsubscribe();
00139   marker_topic_ = topic;
00140   subscribe();
00141 
00142   propertyChanged(marker_topic_property_);
00143 }
00144 
00145 void MarkerDisplay::subscribe()
00146 {
00147   if ( !isEnabled() )
00148   {
00149     return;
00150   }
00151 
00152   if (!marker_topic_.empty())
00153   {
00154     array_sub_.shutdown();
00155     sub_.unsubscribe();
00156 
00157     try
00158     {
00159       sub_.subscribe(update_nh_, marker_topic_, 1000);
00160       array_sub_ = update_nh_.subscribe(marker_topic_ + "_array", 1000, &MarkerDisplay::incomingMarkerArray, this);
00161       setStatus(status_levels::Ok, "Topic", "OK");
00162     }
00163     catch (ros::Exception& e)
00164     {
00165       setStatus(status_levels::Error, "Topic", std::string("Error subscribing: ") + e.what());
00166     }
00167   }
00168 }
00169 
00170 void MarkerDisplay::unsubscribe()
00171 {
00172   sub_.unsubscribe();
00173   array_sub_.shutdown();
00174 }
00175 
00176 void MarkerDisplay::deleteMarker(MarkerID id)
00177 {
00178   deleteMarkerStatus(id);
00179 
00180   M_IDToMarker::iterator it = markers_.find(id);
00181   if (it != markers_.end())
00182   {
00183     markers_with_expiration_.erase(it->second);
00184     frame_locked_markers_.erase(it->second);
00185     markers_.erase(it);
00186   }
00187 }
00188 
00189 void MarkerDisplay::setNamespaceEnabled(const std::string& ns, bool enabled)
00190 {
00191   M_Namespace::iterator it = namespaces_.find(ns);
00192   if (it != namespaces_.end())
00193   {
00194     it->second.enabled = enabled;
00195 
00196     std::vector<MarkerID> to_delete;
00197 
00198     // TODO: this is inefficient, should store every in-use id per namespace and lookup by that
00199     M_IDToMarker::iterator marker_it = markers_.begin();
00200     M_IDToMarker::iterator marker_end = markers_.end();
00201     for (; marker_it != marker_end; ++marker_it)
00202     {
00203       if (marker_it->first.first == ns)
00204       {
00205         to_delete.push_back(marker_it->first);
00206       }
00207     }
00208 
00209     {
00210       std::vector<MarkerID>::iterator it = to_delete.begin();
00211       std::vector<MarkerID>::iterator end = to_delete.end();
00212       for (; it != end; ++it)
00213       {
00214         deleteMarker(*it);
00215       }
00216     }
00217   }
00218 }
00219 
00220 bool MarkerDisplay::isNamespaceEnabled(const std::string& ns)
00221 {
00222   M_Namespace::iterator it = namespaces_.find(ns);
00223   if (it != namespaces_.end())
00224   {
00225     return it->second.enabled;
00226   }
00227 
00228   return true;
00229 }
00230 
00231 void MarkerDisplay::setMarkerStatus(MarkerID id, StatusLevel level, const std::string& text)
00232 {
00233   std::stringstream ss;
00234   ss << id.first << "/" << id.second;
00235   std::string marker_name = ss.str();
00236   setStatus(level, marker_name, text);
00237 }
00238 
00239 void MarkerDisplay::deleteMarkerStatus(MarkerID id)
00240 {
00241   std::stringstream ss;
00242   ss << id.first << "/" << id.second;
00243   std::string marker_name = ss.str();
00244   deleteStatus(marker_name);
00245 }
00246 
00247 void MarkerDisplay::incomingMarkerArray(const visualization_msgs::MarkerArray::ConstPtr& array)
00248 {
00249   std::vector<visualization_msgs::Marker>::const_iterator it = array->markers.begin();
00250   std::vector<visualization_msgs::Marker>::const_iterator end = array->markers.end();
00251   for (; it != end; ++it)
00252   {
00253     const visualization_msgs::Marker& marker = *it;
00254     tf_filter_->add(visualization_msgs::Marker::Ptr(new visualization_msgs::Marker(marker)));
00255   }
00256 }
00257 
00258 void MarkerDisplay::incomingMarker( const visualization_msgs::Marker::ConstPtr& marker )
00259 {
00260   boost::mutex::scoped_lock lock(queue_mutex_);
00261 
00262   message_queue_.push_back(marker);
00263 }
00264 
00265 void MarkerDisplay::failedMarker(const visualization_msgs::Marker::ConstPtr& marker, tf::FilterFailureReason reason)
00266 {
00267   std::string error = FrameManager::instance()->discoverFailureReason(marker->header.frame_id, marker->header.stamp, marker->__connection_header ? (*marker->__connection_header)["callerid"] : "unknown", reason);
00268   setMarkerStatus(MarkerID(marker->ns, marker->id), status_levels::Error, error);
00269 }
00270 
00271 bool validateFloats(const visualization_msgs::Marker& msg)
00272 {
00273   bool valid = true;
00274   valid = valid && validateFloats(msg.pose);
00275   valid = valid && validateFloats(msg.scale);
00276   valid = valid && validateFloats(msg.color);
00277   valid = valid && validateFloats(msg.points);
00278   return valid;
00279 }
00280 
00281 void MarkerDisplay::processMessage( const visualization_msgs::Marker::ConstPtr& message )
00282 {
00283   if (!validateFloats(*message))
00284   {
00285     setMarkerStatus(MarkerID(message->ns, message->id), status_levels::Error, "Contains invalid floating point values (nans or infs)");
00286     return;
00287   }
00288 
00289   switch ( message->action )
00290   {
00291   case visualization_msgs::Marker::ADD:
00292     processAdd( message );
00293     break;
00294 
00295   case visualization_msgs::Marker::DELETE:
00296     processDelete( message );
00297     break;
00298 
00299   default:
00300     ROS_ERROR( "Unknown marker action: %d\n", message->action );
00301   }
00302 }
00303 
00304 void MarkerDisplay::processAdd( const visualization_msgs::Marker::ConstPtr& message )
00305 {
00306   //
00307   M_Namespace::iterator ns_it = namespaces_.find(message->ns);
00308   if (ns_it == namespaces_.end())
00309   {
00310     Namespace ns;
00311     ns.name = message->ns;
00312     ns.enabled = true;
00313 
00314     if (property_manager_)
00315     {
00316       ns.prop = property_manager_->createProperty<BoolProperty>(ns.name, property_prefix_, boost::bind(&MarkerDisplay::isNamespaceEnabled, this, ns.name),
00317                                                                               boost::bind(&MarkerDisplay::setNamespaceEnabled, this, ns.name, _1), namespaces_category_, this);
00318       setPropertyHelpText(ns.prop, "Enable/disable all markers in this namespace.");
00319     }
00320 
00321     ns_it = namespaces_.insert(std::make_pair(ns.name, ns)).first;
00322   }
00323 
00324   if (!ns_it->second.enabled)
00325   {
00326     return;
00327   }
00328 
00329   deleteMarkerStatus(MarkerID(message->ns, message->id));
00330 
00331   bool create = true;
00332   MarkerBasePtr marker;
00333 
00334   M_IDToMarker::iterator it = markers_.find( MarkerID(message->ns, message->id) );
00335   if ( it != markers_.end() )
00336   {
00337     marker = it->second;
00338     markers_with_expiration_.erase(marker);
00339     if ( message->type == marker->getMessage()->type )
00340     {
00341       create = false;
00342     }
00343     else
00344     {
00345       markers_.erase( it );
00346     }
00347   }
00348 
00349   if ( create )
00350   {
00351     switch ( message->type )
00352     {
00353     case visualization_msgs::Marker::CUBE:
00354     case visualization_msgs::Marker::CYLINDER:
00355     case visualization_msgs::Marker::SPHERE:
00356       {
00357         marker.reset(new ShapeMarker(this, vis_manager_, scene_node_));
00358       }
00359       break;
00360 
00361     case visualization_msgs::Marker::ARROW:
00362       {
00363         marker.reset(new ArrowMarker(this, vis_manager_, scene_node_));
00364       }
00365       break;
00366 
00367     case visualization_msgs::Marker::LINE_STRIP:
00368       {
00369         marker.reset(new LineStripMarker(this, vis_manager_, scene_node_));
00370       }
00371       break;
00372     case visualization_msgs::Marker::LINE_LIST:
00373       {
00374         marker.reset(new LineListMarker(this, vis_manager_, scene_node_));
00375       }
00376       break;
00377     case visualization_msgs::Marker::SPHERE_LIST:
00378     case visualization_msgs::Marker::CUBE_LIST:
00379     case visualization_msgs::Marker::POINTS:
00380       {
00381         marker.reset(new PointsMarker(this, vis_manager_, scene_node_));
00382       }
00383       break;
00384     case visualization_msgs::Marker::TEXT_VIEW_FACING:
00385       {
00386         marker.reset(new TextViewFacingMarker(this, vis_manager_, scene_node_));
00387       }
00388       break;
00389     case visualization_msgs::Marker::MESH_RESOURCE:
00390       {
00391         marker.reset(new MeshResourceMarker(this, vis_manager_, scene_node_));
00392       }
00393       break;
00394 
00395     case visualization_msgs::Marker::TRIANGLE_LIST:
00396     {
00397       marker.reset(new TriangleListMarker(this, vis_manager_, scene_node_));
00398     }
00399     break;
00400     default:
00401       ROS_ERROR( "Unknown marker type: %d", message->type );
00402     }
00403 
00404     markers_.insert(std::make_pair(MarkerID(message->ns, message->id), marker));
00405   }
00406 
00407   if (marker)
00408   {
00409     marker->setMessage(message);
00410 
00411     if (message->lifetime.toSec() > 0.0001f)
00412     {
00413       markers_with_expiration_.insert(marker);
00414     }
00415 
00416     if (message->frame_locked)
00417     {
00418       frame_locked_markers_.insert(marker);
00419     }
00420 
00421     causeRender();
00422   }
00423 }
00424 
00425 void MarkerDisplay::processDelete( const visualization_msgs::Marker::ConstPtr& message )
00426 {
00427   deleteMarker(MarkerID(message->ns, message->id));
00428   causeRender();
00429 }
00430 
00431 void MarkerDisplay::update(float wall_dt, float ros_dt)
00432 {
00433   V_MarkerMessage local_queue;
00434 
00435   {
00436     boost::mutex::scoped_lock lock(queue_mutex_);
00437 
00438     local_queue.swap( message_queue_ );
00439   }
00440 
00441   if ( !local_queue.empty() )
00442   {
00443     V_MarkerMessage::iterator message_it = local_queue.begin();
00444     V_MarkerMessage::iterator message_end = local_queue.end();
00445     for ( ; message_it != message_end; ++message_it )
00446     {
00447       visualization_msgs::Marker::ConstPtr& marker = *message_it;
00448 
00449       processMessage( marker );
00450     }
00451   }
00452 
00453   {
00454     S_MarkerBase::iterator it = markers_with_expiration_.begin();
00455     S_MarkerBase::iterator end = markers_with_expiration_.end();
00456     for (; it != end;)
00457     {
00458       MarkerBasePtr marker = *it;
00459       if (marker->expired())
00460       {
00461         S_MarkerBase::iterator copy = it;
00462         ++it;
00463         deleteMarker(marker->getID());
00464       }
00465       else
00466       {
00467         ++it;
00468       }
00469     }
00470   }
00471 
00472   {
00473     S_MarkerBase::iterator it = frame_locked_markers_.begin();
00474     S_MarkerBase::iterator end = frame_locked_markers_.end();
00475     for (; it != end; ++it)
00476     {
00477       MarkerBasePtr marker = *it;
00478       marker->updateFrameLocked();
00479     }
00480   }
00481 }
00482 
00483 void MarkerDisplay::targetFrameChanged()
00484 {
00485 }
00486 
00487 void MarkerDisplay::fixedFrameChanged()
00488 {
00489   tf_filter_->setTargetFrame( fixed_frame_ );
00490 
00491   clearMarkers();
00492 }
00493 
00494 void MarkerDisplay::reset()
00495 {
00496   Display::reset();
00497   clearMarkers();
00498 }
00499 
00500 void MarkerDisplay::createProperties()
00501 {
00502   marker_topic_property_ = property_manager_->createProperty<ROSTopicStringProperty>( "Marker Topic", property_prefix_, boost::bind( &MarkerDisplay::getMarkerTopic, this ),
00503                                                                                 boost::bind( &MarkerDisplay::setMarkerTopic, this, _1 ), parent_category_, this );
00504   setPropertyHelpText(marker_topic_property_, "visualization_msgs::Marker topic to subscribe to.  <topic>_array will also automatically be subscribed with type visualization_msgs::MarkerArray.");
00505   ROSTopicStringPropertyPtr topic_prop = marker_topic_property_.lock();
00506   topic_prop->setMessageType(ros::message_traits::datatype<visualization_msgs::Marker>());
00507 
00508   namespaces_category_ = property_manager_->createCategory("Namespaces", property_prefix_, parent_category_, this);
00509 }
00510 
00511 } // namespace rviz


rviz_qt
Author(s): Dave Hershberger
autogenerated on Fri Dec 6 2013 20:56:52