00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "robot_model_display.h"
00031 #include "rviz/visualization_manager.h"
00032 #include "rviz/common.h"
00033 #include "rviz/robot/robot.h"
00034 #include "rviz/robot/tf_link_updater.h"
00035 #include "rviz/properties/property.h"
00036 #include "rviz/properties/property_manager.h"
00037
00038 #include <urdf/model.h>
00039
00040 #include <OGRE/OgreSceneNode.h>
00041 #include <OGRE/OgreSceneManager.h>
00042
00043 #include <tf/transform_listener.h>
00044
00045 namespace rviz
00046 {
00047
00048 void linkUpdaterStatusFunction(StatusLevel level, const std::string& link_name, const std::string& text, RobotModelDisplay* display)
00049 {
00050 display->setStatus(level, link_name, text);
00051 }
00052
00053 RobotModelDisplay::RobotModelDisplay( const std::string& name, VisualizationManager* manager )
00054 : Display( name, manager )
00055 , description_param_("robot_description")
00056 , has_new_transforms_( false )
00057 , time_since_last_transform_( 0.0f )
00058 , update_rate_( 0.0f )
00059 {
00060 robot_ = new Robot( vis_manager_, "Robot: " + name_ );
00061
00062 setVisualVisible( true );
00063 setCollisionVisible( false );
00064
00065 setAlpha(1.0f);
00066 }
00067
00068 RobotModelDisplay::~RobotModelDisplay()
00069 {
00070 delete robot_;
00071 }
00072
00073 void RobotModelDisplay::setAlpha( float alpha )
00074 {
00075 alpha_ = alpha;
00076
00077 robot_->setAlpha(alpha_);
00078
00079 propertyChanged(alpha_property_);
00080 }
00081
00082 void RobotModelDisplay::setRobotDescription( const std::string& description_param )
00083 {
00084 description_param_ = description_param;
00085
00086 propertyChanged(robot_description_property_);
00087
00088 if ( isEnabled() )
00089 {
00090 load();
00091 causeRender();
00092 }
00093 }
00094
00095 void RobotModelDisplay::setVisualVisible( bool visible )
00096 {
00097 robot_->setVisualVisible( visible );
00098
00099 propertyChanged(visual_enabled_property_);
00100
00101 causeRender();
00102 }
00103
00104 void RobotModelDisplay::setCollisionVisible( bool visible )
00105 {
00106 robot_->setCollisionVisible( visible );
00107
00108 propertyChanged(collision_enabled_property_);
00109
00110 causeRender();
00111 }
00112
00113 void RobotModelDisplay::setUpdateRate( float rate )
00114 {
00115 update_rate_ = rate;
00116
00117 propertyChanged(update_rate_property_);
00118
00119 causeRender();
00120 }
00121
00122 void RobotModelDisplay::setTFPrefix(const std::string& prefix)
00123 {
00124 tf_prefix_ = prefix;
00125
00126 propertyChanged(tf_prefix_property_);
00127
00128 causeRender();
00129 }
00130
00131 bool RobotModelDisplay::isVisualVisible()
00132 {
00133 return robot_->isVisualVisible();
00134 }
00135
00136 bool RobotModelDisplay::isCollisionVisible()
00137 {
00138 return robot_->isCollisionVisible();
00139 }
00140
00141 void RobotModelDisplay::load()
00142 {
00143 std::string content;
00144 if (!update_nh_.getParam(description_param_, content))
00145 {
00146 std::string loc;
00147 if (update_nh_.searchParam(description_param_, loc))
00148 {
00149 update_nh_.getParam(loc, content);
00150 }
00151 else
00152 {
00153 clear();
00154
00155 std::stringstream ss;
00156 ss << "Parameter [" << description_param_ << "] does not exist, and was not found by searchParam()";
00157 setStatus(status_levels::Error, "URDF", ss.str());
00158 return;
00159 }
00160 }
00161
00162 if (content.empty())
00163 {
00164 clear();
00165 setStatus(status_levels::Error, "URDF", "URDF is empty");
00166 return;
00167 }
00168
00169 if ( content == robot_description_ )
00170 {
00171 return;
00172 }
00173
00174 robot_description_ = content;
00175
00176 TiXmlDocument doc;
00177 doc.Parse(robot_description_.c_str());
00178 if (!doc.RootElement())
00179 {
00180 clear();
00181 setStatus(status_levels::Error, "URDF", "URDF failed XML parse");
00182 return;
00183 }
00184
00185 urdf::Model descr;
00186 if (!descr.initXml(doc.RootElement()))
00187 {
00188 clear();
00189 setStatus(status_levels::Error, "URDF", "URDF failed Model parse");
00190 return;
00191 }
00192
00193 setStatus(status_levels::Ok, "URDF", "URDF parsed OK");
00194 robot_->load( doc.RootElement(), descr );
00195 robot_->update( TFLinkUpdater(vis_manager_->getFrameManager(), boost::bind(linkUpdaterStatusFunction, _1, _2, _3, this), tf_prefix_) );
00196 }
00197
00198 void RobotModelDisplay::onEnable()
00199 {
00200 load();
00201 robot_->setVisible( true );
00202 }
00203
00204 void RobotModelDisplay::onDisable()
00205 {
00206 robot_->setVisible( false );
00207 clear();
00208 }
00209
00210 void RobotModelDisplay::update(float wall_dt, float ros_dt)
00211 {
00212 time_since_last_transform_ += wall_dt;
00213
00214 bool update = update_rate_ < 0.0001f || time_since_last_transform_ >= update_rate_;
00215
00216 if ( has_new_transforms_ || update )
00217 {
00218 robot_->update(TFLinkUpdater(vis_manager_->getFrameManager(), boost::bind(linkUpdaterStatusFunction, _1, _2, _3, this), tf_prefix_));
00219 causeRender();
00220
00221 has_new_transforms_ = false;
00222 time_since_last_transform_ = 0.0f;
00223 }
00224 }
00225
00226 void RobotModelDisplay::targetFrameChanged()
00227 {
00228 has_new_transforms_ = true;
00229 }
00230
00231 void RobotModelDisplay::createProperties()
00232 {
00233 visual_enabled_property_ = property_manager_->createProperty<BoolProperty>( "Visual Enabled", property_prefix_, boost::bind( &RobotModelDisplay::isVisualVisible, this ),
00234 boost::bind( &RobotModelDisplay::setVisualVisible, this, _1 ), parent_category_, this );
00235 setPropertyHelpText(visual_enabled_property_, "Whether to display the visual representation of the robot.");
00236 collision_enabled_property_ = property_manager_->createProperty<BoolProperty>( "Collision Enabled", property_prefix_, boost::bind( &RobotModelDisplay::isCollisionVisible, this ),
00237 boost::bind( &RobotModelDisplay::setCollisionVisible, this, _1 ), parent_category_, this );
00238 setPropertyHelpText(collision_enabled_property_, "Whether to display the collision representation of the robot.");
00239 update_rate_property_ = property_manager_->createProperty<FloatProperty>( "Update Interval", property_prefix_, boost::bind( &RobotModelDisplay::getUpdateRate, this ),
00240 boost::bind( &RobotModelDisplay::setUpdateRate, this, _1 ), parent_category_, this );
00241 setPropertyHelpText(update_rate_property_, "Interval at which to update the links, in seconds. 0 means to update every update cycle.");
00242 FloatPropertyPtr float_prop = update_rate_property_.lock();
00243 float_prop->setMin( 0.0 );
00244 float_prop->addLegacyName("Update Rate");
00245
00246 alpha_property_ = property_manager_->createProperty<FloatProperty>( "Alpha", property_prefix_, boost::bind( &RobotModelDisplay::getAlpha, this ),
00247 boost::bind( &RobotModelDisplay::setAlpha, this, _1 ), parent_category_, this );
00248 setPropertyHelpText(alpha_property_, "Amount of transparency to apply to the links.");
00249 float_prop = alpha_property_.lock();
00250 float_prop->setMin( 0.0 );
00251 float_prop->setMax( 1.0 );
00252
00253 robot_description_property_ = property_manager_->createProperty<StringProperty>( "Robot Description", property_prefix_, boost::bind( &RobotModelDisplay::getRobotDescription, this ),
00254 boost::bind( &RobotModelDisplay::setRobotDescription, this, _1 ), parent_category_, this );
00255 setPropertyHelpText(robot_description_property_, "Name of the parameter to search for to load the robot description.");
00256
00257 tf_prefix_property_ = property_manager_->createProperty<StringProperty>( "TF Prefix", property_prefix_, boost::bind( &RobotModelDisplay::getTFPrefix, this ),
00258 boost::bind( &RobotModelDisplay::setTFPrefix, this, _1 ), parent_category_, this );
00259 setPropertyHelpText(tf_prefix_property_, "Robot Model normally assumes the link name is the same as the tf frame name. This option allows you to set a prefix. Mainly useful for multi-robot situations.");
00260
00261 robot_->setPropertyManager( property_manager_, parent_category_ );
00262 }
00263
00264 void RobotModelDisplay::clear()
00265 {
00266 robot_->clear();
00267 clearStatuses();
00268 robot_description_.clear();
00269 }
00270
00271 void RobotModelDisplay::reset()
00272 {
00273 Display::reset();
00274 has_new_transforms_ = true;
00275 }
00276
00277 }
00278