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