robot_state_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 /* Author: Ioan Sucan */
00031 
00032 #include <moveit/robot_state_rviz_plugin/robot_state_display.h>
00033 #include <moveit/robot_state/conversions.h>
00034 
00035 #include <rviz/visualization_manager.h>
00036 #include <rviz/robot/robot.h>
00037 #include <rviz/robot/robot_link.h>
00038 
00039 #include <rviz/properties/property.h>
00040 #include <rviz/properties/string_property.h>
00041 #include <rviz/properties/bool_property.h>
00042 #include <rviz/properties/float_property.h>
00043 #include <rviz/properties/ros_topic_property.h>
00044 #include <rviz/properties/color_property.h>
00045 #include <rviz/display_context.h>
00046 #include <rviz/frame_manager.h>
00047 #include <tf/transform_listener.h>
00048 
00049 #include <OGRE/OgreSceneManager.h>
00050 
00051 namespace moveit_rviz_plugin
00052 {
00053 
00054 // ******************************************************************************************
00055 // Base class contructor
00056 // ******************************************************************************************
00057 RobotStateDisplay::RobotStateDisplay() :
00058   Display(),
00059   update_state_(false)
00060 {
00061   robot_description_property_ =
00062     new rviz::StringProperty( "Robot Description", "robot_description", "The name of the ROS parameter where the URDF for the robot is loaded",
00063                               this,
00064                               SLOT( changedRobotDescription() ), this );
00065 
00066   robot_state_topic_property_ =
00067     new rviz::RosTopicProperty( "Robot State Topic", "display_robot_state",
00068                                 ros::message_traits::datatype<moveit_msgs::DisplayRobotState>(),
00069                                 "The topic on which the moveit_msgs::RobotState messages are received",
00070                                 this,
00071                                 SLOT( changedRobotStateTopic() ), this );
00072 
00073   // Planning scene category -------------------------------------------------------------------------------------------
00074   root_link_name_property_ =
00075     new rviz::StringProperty( "Robot Root Link", "", "Shows the name of the root link for the robot model",
00076                               this,
00077                               SLOT( changedRootLinkName() ), this );
00078   root_link_name_property_->setReadOnly(true);
00079 
00080   robot_alpha_property_ =
00081     new rviz::FloatProperty( "Robot Alpha", 1.0f, "Specifies the alpha for the robot links",
00082                              this,
00083                              SLOT( changedRobotSceneAlpha() ), this );
00084   robot_alpha_property_->setMin( 0.0 );
00085   robot_alpha_property_->setMax( 1.0 );
00086 
00087   attached_body_color_property_ = new rviz::ColorProperty( "Attached Body Color", QColor(150, 50, 150), "The color for the attached bodies",
00088                                                            this,
00089                                                            SLOT( changedAttachedBodyColor() ), this );
00090 
00091   enable_link_highlight_ = new rviz::BoolProperty("Show Highlights", true, "Specifies whether link highlighting is enabled",
00092                                                   this, SLOT( changedEnableLinkHighlight() ), this);
00093   enable_visual_visible_ = new rviz::BoolProperty("Visual Enabled", true, "Whether to display the visual representation of the robot.",
00094                                                   this, SLOT( changedEnableVisualVisible() ), this);
00095   enable_collision_visible_ = new rviz::BoolProperty("Collision Enabled", false, "Whether to display the collision representation of the robot.",
00096                                                   this, SLOT( changedEnableCollisionVisible() ), this);
00097 
00098   show_all_links_ = new rviz::BoolProperty("Show All Links", true, "Toggle all links visibility on or off.",
00099                                            this, SLOT( changedAllLinks() ), this);
00100 }
00101 
00102 // ******************************************************************************************
00103 // Deconstructor
00104 // ******************************************************************************************
00105 RobotStateDisplay::~RobotStateDisplay()
00106 {
00107 }
00108 
00109 void RobotStateDisplay::onInitialize()
00110 {
00111   Display::onInitialize();
00112   robot_.reset(new RobotStateVisualization(scene_node_, context_, "Robot State", this));
00113   changedEnableVisualVisible();
00114   changedEnableCollisionVisible();
00115   robot_->setVisible(true);
00116 }
00117 
00118 void RobotStateDisplay::reset()
00119 {
00120   robot_->clear();
00121   rdf_loader_.reset();
00122 
00123   loadRobotModel();
00124   Display::reset();
00125 
00126   changedEnableVisualVisible();
00127   changedEnableCollisionVisible();
00128   robot_->setVisible(true);
00129 }
00130 
00131 void RobotStateDisplay::changedAllLinks()
00132 {
00133   Property *links_prop = subProp("Links");
00134   QVariant value(show_all_links_->getBool());
00135 
00136   for (int i=0 ; i<links_prop->numChildren() ; ++i)
00137   {
00138     Property *link_prop = links_prop->childAt(i);
00139     link_prop->setValue(value);
00140   }
00141 }
00142 
00143 void RobotStateDisplay::setHighlight(const std::string& link_name, const std_msgs::ColorRGBA& color)
00144 {
00145   rviz::RobotLink *link = robot_->getRobot().getLink(link_name);
00146   if (link)
00147   {
00148     link->setColor(color.r, color.g, color.b);
00149     link->setRobotAlpha(color.a * robot_alpha_property_->getFloat());
00150   }
00151 }
00152 
00153 void RobotStateDisplay::unsetHighlight(const std::string& link_name)
00154 {
00155   rviz::RobotLink *link = robot_->getRobot().getLink(link_name);
00156   if (link)
00157   {
00158     link->unsetColor();
00159     link->setRobotAlpha(robot_alpha_property_->getFloat());
00160   }
00161 }
00162 
00163 void RobotStateDisplay::changedEnableLinkHighlight()
00164 {
00165   if (enable_link_highlight_->getBool())
00166   {
00167     for (std::map<std::string, std_msgs::ColorRGBA>::iterator it = highlights_.begin() ;
00168          it != highlights_.end() ;
00169          ++it)
00170     {
00171       setHighlight(it->first, it->second);
00172     }
00173   }
00174   else
00175   {
00176     for (std::map<std::string, std_msgs::ColorRGBA>::iterator it = highlights_.begin() ;
00177          it != highlights_.end() ;
00178          ++it)
00179     {
00180       unsetHighlight(it->first);
00181     }
00182   }
00183 }
00184 
00185 void RobotStateDisplay::changedEnableVisualVisible()
00186 {
00187   robot_->setVisualVisible(enable_visual_visible_->getBool());
00188 }
00189 
00190 void RobotStateDisplay::changedEnableCollisionVisible()
00191 {
00192   robot_->setCollisionVisible(enable_collision_visible_->getBool());
00193 }
00194 
00195 static bool operator!=(const std_msgs::ColorRGBA& a, const std_msgs::ColorRGBA& b)
00196 {
00197   return a.r != b.r ||
00198          a.g != b.g ||
00199          a.b != b.b ||
00200          a.a != b.a;
00201 }
00202 
00203 void RobotStateDisplay::setRobotHighlights(const moveit_msgs::DisplayRobotState::_highlight_links_type& highlight_links)
00204 {
00205   if (highlight_links.empty() && highlights_.empty())
00206     return;
00207 
00208   std::map<std::string, std_msgs::ColorRGBA> highlights;
00209   for (moveit_msgs::DisplayRobotState::_highlight_links_type::const_iterator it = highlight_links.begin() ;
00210        it != highlight_links.end() ;
00211        ++it)
00212   {
00213     highlights[it->id] = it->color;
00214   }
00215 
00216   if (enable_link_highlight_->getBool())
00217   {
00218     std::map<std::string, std_msgs::ColorRGBA>::iterator ho = highlights_.begin();
00219     std::map<std::string, std_msgs::ColorRGBA>::iterator hn = highlights.begin();
00220     while (ho != highlights_.end() || hn != highlights.end())
00221     {
00222       if (ho == highlights_.end())
00223       {
00224         setHighlight(hn->first, hn->second);
00225         ++hn;
00226       }
00227       else if (hn == highlights.end())
00228       {
00229         unsetHighlight(ho->first);
00230         ++ho;
00231       }
00232       else if (hn->first < ho->first)
00233       {
00234         setHighlight(hn->first, hn->second);
00235         ++hn;
00236       }
00237       else if (hn->first > ho->first)
00238       {
00239         unsetHighlight(ho->first);
00240         ++ho;
00241       }
00242       else if (hn->second != ho->second)
00243       {
00244         setHighlight(hn->first, hn->second);
00245         ++ho;
00246         ++hn;
00247       }
00248       else
00249       {
00250         ++ho;
00251         ++hn;
00252       }
00253     }
00254   }
00255 
00256   swap(highlights, highlights_);
00257 }
00258 
00259 void RobotStateDisplay::changedAttachedBodyColor()
00260 {
00261   if (robot_)
00262   {
00263     QColor color = attached_body_color_property_->getColor();
00264     std_msgs::ColorRGBA color_msg;
00265     color_msg.r = color.redF();
00266     color_msg.g = color.greenF();
00267     color_msg.b = color.blueF();
00268     color_msg.a = robot_alpha_property_->getFloat();
00269     robot_->setDefaultAttachedObjectColor(color_msg);
00270     update_state_ = true;
00271   }
00272 }
00273 
00274 void RobotStateDisplay::changedRobotDescription()
00275 {
00276   if (isEnabled())
00277     reset();
00278 }
00279 
00280 void RobotStateDisplay::changedRootLinkName()
00281 {
00282 }
00283 
00284 void RobotStateDisplay::changedRobotSceneAlpha()
00285 {
00286   if (robot_)
00287   {
00288     robot_->setAlpha(robot_alpha_property_->getFloat());
00289     QColor color = attached_body_color_property_->getColor();
00290     std_msgs::ColorRGBA color_msg;
00291     color_msg.r = color.redF();
00292     color_msg.g = color.greenF();
00293     color_msg.b = color.blueF();
00294     color_msg.a = robot_alpha_property_->getFloat();
00295     robot_->setDefaultAttachedObjectColor(color_msg);
00296     update_state_ = true;
00297   }
00298 }
00299 
00300 void RobotStateDisplay::changedRobotStateTopic()
00301 {
00302   robot_state_subscriber_.shutdown();
00303   robot_state_subscriber_ = root_nh_.subscribe(robot_state_topic_property_->getStdString(), 10, &RobotStateDisplay::newRobotStateCallback, this);
00304   robot_->clear();
00305   loadRobotModel();
00306 }
00307 
00308 void RobotStateDisplay::newRobotStateCallback(const moveit_msgs::DisplayRobotStateConstPtr &state_msg)
00309 {
00310   if (!kmodel_)
00311     return;
00312   if (!kstate_)
00313     kstate_.reset(new robot_state::RobotState(kmodel_));
00314   // possibly use TF to construct a robot_state::Transforms object to pass in to the conversion functio?
00315   robot_state::robotStateMsgToRobotState(state_msg->state, *kstate_);
00316   setRobotHighlights(state_msg->highlight_links);
00317   update_state_ = true;
00318 }
00319 
00320 void RobotStateDisplay::setLinkColor(const std::string& link_name, const QColor &color)
00321 {
00322   setLinkColor(&robot_->getRobot(), link_name, color );
00323 }
00324 
00325 void RobotStateDisplay::unsetLinkColor(const std::string& link_name)
00326 {
00327   unsetLinkColor(&robot_->getRobot(), link_name);
00328 }
00329 
00330 void RobotStateDisplay::setLinkColor(rviz::Robot* robot,  const std::string& link_name, const QColor &color )
00331 {
00332   rviz::RobotLink *link = robot->getLink(link_name);
00333 
00334   // Check if link exists
00335   if (link)
00336     link->setColor( color.redF(), color.greenF(), color.blueF() );
00337 }
00338 
00339 void RobotStateDisplay::unsetLinkColor(rviz::Robot* robot, const std::string& link_name )
00340 {
00341   rviz::RobotLink *link = robot->getLink(link_name);
00342 
00343   // Check if link exists
00344   if (link)
00345     link->unsetColor();
00346 }
00347 
00348 // ******************************************************************************************
00349 // Load
00350 // ******************************************************************************************
00351 void RobotStateDisplay::loadRobotModel()
00352 {
00353   if (!rdf_loader_)
00354     rdf_loader_.reset(new rdf_loader::RDFLoader(robot_description_property_->getStdString()));
00355 
00356   if (rdf_loader_->getURDF())
00357   {
00358     const boost::shared_ptr<srdf::Model> &srdf = rdf_loader_->getSRDF() ? rdf_loader_->getSRDF() : boost::shared_ptr<srdf::Model>(new srdf::Model());
00359     kmodel_.reset(new robot_model::RobotModel(rdf_loader_->getURDF(), srdf));
00360     robot_->load(*kmodel_->getURDF());
00361     kstate_.reset(new robot_state::RobotState(kmodel_));
00362     kstate_->setToDefaultValues();
00363     bool oldState = root_link_name_property_->blockSignals(true);
00364     root_link_name_property_->setStdString(getRobotModel()->getRootLinkName());
00365     root_link_name_property_->blockSignals(oldState);
00366     update_state_ = true;
00367     setStatus( rviz::StatusProperty::Ok, "RobotState", "Planning Model Loaded Successfully" );
00368   }
00369   else
00370     setStatus( rviz::StatusProperty::Error, "RobotState", "No Planning Model Loaded" );
00371 
00372   highlights_.clear();
00373 }
00374 
00375 void RobotStateDisplay::onEnable()
00376 {
00377   Display::onEnable();
00378   loadRobotModel();
00379   if (robot_)
00380   {
00381     changedEnableVisualVisible();
00382     changedEnableCollisionVisible();
00383     robot_->setVisible(true);
00384   }
00385   calculateOffsetPosition();
00386 }
00387 
00388 // ******************************************************************************************
00389 // Disable
00390 // ******************************************************************************************
00391 void RobotStateDisplay::onDisable()
00392 {
00393   if (robot_)
00394     robot_->setVisible(false);
00395   Display::onDisable();
00396 }
00397 
00398 void RobotStateDisplay::update(float wall_dt, float ros_dt)
00399 {
00400   Display::update(wall_dt, ros_dt);
00401   if (robot_ && update_state_)
00402   {
00403     update_state_ = false;
00404     robot_->update(kstate_);
00405   }
00406 }
00407 
00408 // ******************************************************************************************
00409 // Calculate Offset Position
00410 // ******************************************************************************************
00411 void RobotStateDisplay::calculateOffsetPosition()
00412 {
00413   if (!getRobotModel())
00414     return;
00415 
00416   ros::Time stamp;
00417   std::string err_string;
00418   if (context_->getTFClient()->getLatestCommonTime(fixed_frame_.toStdString(), getRobotModel()->getModelFrame(), stamp, &err_string) != tf::NO_ERROR)
00419     return;
00420 
00421   tf::Stamped<tf::Pose> pose(tf::Pose::getIdentity(), stamp, getRobotModel()->getModelFrame());
00422 
00423   if (context_->getTFClient()->canTransform(fixed_frame_.toStdString(), getRobotModel()->getModelFrame(), stamp))
00424   {
00425     try
00426     {
00427       context_->getTFClient()->transformPose(fixed_frame_.toStdString(), pose, pose);
00428     }
00429     catch (tf::TransformException& e)
00430     {
00431       ROS_ERROR( "Error transforming from frame '%s' to frame '%s'", pose.frame_id_.c_str(), fixed_frame_.toStdString().c_str() );
00432     }
00433   }
00434 
00435   Ogre::Vector3 position(pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z());
00436   const tf::Quaternion &q = pose.getRotation();
00437   Ogre::Quaternion orientation( q.getW(), q.getX(), q.getY(), q.getZ() );
00438   scene_node_->setPosition(position);
00439   scene_node_->setOrientation(orientation);
00440 }
00441 
00442 void RobotStateDisplay::fixedFrameChanged()
00443 {
00444   Display::fixedFrameChanged();
00445   calculateOffsetPosition();
00446 }
00447 
00448 
00449 } // namespace moveit_rviz_plugin


visualization
Author(s): Ioan Sucan , Dave Coleman
autogenerated on Mon Oct 6 2014 02:34:03