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_link.h"
00031 #include "robot.h"
00032 #include "properties/property.h"
00033 #include "properties/property_manager.h"
00034 #include "visualization_manager.h"
00035 #include "selection/selection_manager.h"
00036 #include "mesh_loader.h"
00037
00038 #include "ogre_tools/stl_loader.h"
00039 #include "ogre_tools/object.h"
00040 #include "ogre_tools/shape.h"
00041 #include "ogre_tools/axes.h"
00042
00043 #include <urdf/model.h>
00044 #include <urdf_interface/link.h>
00045
00046 #include <OGRE/OgreSceneNode.h>
00047 #include <OGRE/OgreSceneManager.h>
00048 #include <OGRE/OgreRibbonTrail.h>
00049 #include <OGRE/OgreEntity.h>
00050 #include <OGRE/OgreSubEntity.h>
00051 #include <OGRE/OgreMaterialManager.h>
00052 #include <OGRE/OgreMaterial.h>
00053 #include <OGRE/OgreTextureManager.h>
00054
00055 #include <ros/console.h>
00056
00057 #include <resource_retriever/retriever.h>
00058
00059 #include <boost/filesystem.hpp>
00060
00061 namespace fs=boost::filesystem;
00062
00063 namespace rviz
00064 {
00065
00066 class RobotLinkSelectionHandler : public SelectionHandler
00067 {
00068 public:
00069 RobotLinkSelectionHandler(RobotLink* link);
00070 virtual ~RobotLinkSelectionHandler();
00071
00072 virtual void createProperties(const Picked& obj, PropertyManager* property_manager);
00073
00074 private:
00075 RobotLink* link_;
00076 };
00077
00078 RobotLinkSelectionHandler::RobotLinkSelectionHandler(RobotLink* link)
00079 : link_(link)
00080 {
00081 }
00082
00083 RobotLinkSelectionHandler::~RobotLinkSelectionHandler()
00084 {
00085 }
00086
00087 void RobotLinkSelectionHandler::createProperties(const Picked& obj, PropertyManager* property_manager)
00088 {
00089 std::stringstream ss;
00090 ss << link_->getName() << " Link " << link_->getName();
00091
00092 CategoryPropertyWPtr cat = property_manager->createCategory( "Link " + link_->getName(), ss.str(), CategoryPropertyWPtr(), (void*)obj.handle );
00093 properties_.push_back(cat);
00094
00095 properties_.push_back(property_manager->createProperty<Vector3Property>( "Position", ss.str(), boost::bind( &RobotLink::getPositionInRobotFrame, link_ ),
00096 Vector3Property::Setter(), cat, (void*)obj.handle ));
00097
00098 properties_.push_back(property_manager->createProperty<QuaternionProperty>( "Orientation", ss.str(), boost::bind( &RobotLink::getOrientationInRobotFrame, link_ ),
00099 QuaternionProperty::Setter(), cat, (void*)obj.handle ));
00100 }
00101
00102 RobotLink::RobotLink(Robot* parent, VisualizationManager* manager)
00103 : parent_(parent)
00104 , scene_manager_(manager->getSceneManager())
00105 , property_manager_(0)
00106 , vis_manager_(manager)
00107 , visual_mesh_( NULL )
00108 , collision_mesh_( NULL )
00109 , visual_node_( NULL )
00110 , collision_node_( NULL )
00111 , position_(Ogre::Vector3::ZERO)
00112 , orientation_(Ogre::Quaternion::IDENTITY)
00113 , trail_( NULL )
00114 , axes_( NULL )
00115 , selection_object_(NULL)
00116 {
00117 }
00118
00119 RobotLink::~RobotLink()
00120 {
00121 if ( visual_mesh_ )
00122 {
00123 scene_manager_->destroyEntity( visual_mesh_ );
00124 }
00125
00126 if ( collision_mesh_ )
00127 {
00128 scene_manager_->destroyEntity( collision_mesh_ );
00129 }
00130
00131 if ( trail_ )
00132 {
00133 scene_manager_->destroyRibbonTrail( trail_ );
00134 }
00135
00136 delete axes_;
00137
00138 if (selection_object_)
00139 {
00140 vis_manager_->getSelectionManager()->removeObject(selection_object_);
00141 }
00142
00143 if (property_manager_)
00144 {
00145 property_manager_->deleteByUserData(this);
00146 }
00147 }
00148
00149 bool RobotLink::isValid()
00150 {
00151 return visual_mesh_ || collision_mesh_;
00152 }
00153
00154 void RobotLink::load(TiXmlElement* root_element, urdf::Model& descr, const urdf::LinkConstPtr& link, bool visual, bool collision)
00155 {
00156 name_ = link->name;
00157
00158 if ( visual )
00159 {
00160 createVisual( root_element, link );
00161 }
00162
00163 if ( collision )
00164 {
00165 createCollision( root_element, link );
00166 }
00167
00168 if (collision || visual)
00169 {
00170 createSelection( descr, link );
00171 }
00172
00173 if ( property_manager_ )
00174 {
00175 createProperties();
00176 }
00177 }
00178
00179 void RobotLink::setAlpha(float a)
00180 {
00181 M_SubEntityToMaterial::iterator it = materials_.begin();
00182 M_SubEntityToMaterial::iterator end = materials_.end();
00183 for (; it != end; ++it)
00184 {
00185 const Ogre::MaterialPtr& material = it->second;
00186
00187 Ogre::ColourValue color = material->getTechnique(0)->getPass(0)->getDiffuse();
00188 color.a = a;
00189 material->setDiffuse( color );
00190
00191 if ( a < 0.9998 )
00192 {
00193 material->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
00194 material->setDepthWriteEnabled( false );
00195 }
00196 else
00197 {
00198 material->setSceneBlending( Ogre::SBT_REPLACE );
00199 material->setDepthWriteEnabled( true );
00200 }
00201 }
00202 }
00203
00204 Ogre::MaterialPtr getMaterialForLink(TiXmlElement* root_element, const urdf::LinkConstPtr& link)
00205 {
00206 if (!link->visual || !link->visual->material)
00207 {
00208 return Ogre::MaterialManager::getSingleton().getByName("RVIZ/Red");
00209 }
00210
00211 static int count = 0;
00212 std::stringstream ss;
00213 ss << "Robot Link Material" << count;
00214
00215 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(ss.str(), ROS_PACKAGE_NAME);
00216 mat->getTechnique(0)->setLightingEnabled(true);
00217 if (link->visual->material->texture_filename.empty())
00218 {
00219 const urdf::Color& col = link->visual->material->color;
00220 mat->getTechnique(0)->setAmbient(col.r * 0.5, col.g * 0.5, col.b * 0.5);
00221 mat->getTechnique(0)->setDiffuse(col.r, col.g, col.b, col.a);
00222 }
00223 else
00224 {
00225 std::string filename = link->visual->material->texture_filename;
00226 if (!Ogre::TextureManager::getSingleton().resourceExists(filename))
00227 {
00228 resource_retriever::Retriever retriever;
00229 resource_retriever::MemoryResource res;
00230 try
00231 {
00232 res = retriever.get(filename);
00233 }
00234 catch (resource_retriever::Exception& e)
00235 {
00236 ROS_ERROR("%s", e.what());
00237 }
00238
00239 if (res.size != 0)
00240 {
00241 Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(res.data.get(), res.size));
00242 Ogre::Image image;
00243 std::string extension = fs::extension(fs::path(filename));
00244
00245 if (extension[0] == '.')
00246 {
00247 extension = extension.substr(1, extension.size() - 1);
00248 }
00249
00250 try
00251 {
00252 image.load(stream, extension);
00253 Ogre::TextureManager::getSingleton().loadImage(filename, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image);
00254 }
00255 catch (Ogre::Exception& e)
00256 {
00257 ROS_ERROR("Could not load texture [%s]: %s", filename.c_str(), e.what());
00258 }
00259 }
00260 }
00261
00262 Ogre::Pass* pass = mat->getTechnique(0)->getPass(0);
00263 Ogre::TextureUnitState* tex_unit = pass->createTextureUnitState();;
00264 tex_unit->setTextureName(filename);
00265 }
00266
00267 return mat;
00268 }
00269
00270 void RobotLink::createEntityForGeometryElement(TiXmlElement* root_element, const urdf::LinkConstPtr& link, const urdf::Geometry& geom, const urdf::Pose& origin, Ogre::SceneNode* parent_node, Ogre::Entity*& entity, Ogre::SceneNode*& scene_node, Ogre::SceneNode*& offset_node)
00271 {
00272 scene_node = parent_node->createChildSceneNode();
00273 offset_node = scene_node->createChildSceneNode();
00274
00275 static int count = 0;
00276 std::stringstream ss;
00277 ss << "Robot Link" << count++;
00278 std::string entity_name = ss.str();
00279
00280 Ogre::Vector3 scale(Ogre::Vector3::UNIT_SCALE);
00281
00282 Ogre::Vector3 offset_position(Ogre::Vector3::ZERO);
00283 Ogre::Quaternion offset_orientation(Ogre::Quaternion::IDENTITY);
00284
00285
00286 {
00287 Ogre::Vector3 position( origin.position.x, origin.position.y, origin.position.z );
00288 Ogre::Quaternion orientation( Ogre::Quaternion::IDENTITY );
00289 orientation = orientation * Ogre::Quaternion( origin.rotation.w, origin.rotation.x, origin.rotation.y, origin.rotation.z );
00290
00291 offset_position = position;
00292 offset_orientation = orientation;
00293 }
00294
00295 switch (geom.type)
00296 {
00297 case urdf::Geometry::SPHERE:
00298 {
00299 const urdf::Sphere& sphere = static_cast<const urdf::Sphere&>(geom);
00300 entity = ogre_tools::Shape::createEntity(entity_name, ogre_tools::Shape::Sphere, scene_manager_);
00301
00302 scale = Ogre::Vector3( sphere.radius*2, sphere.radius*2, sphere.radius*2 );
00303 break;
00304 }
00305 case urdf::Geometry::BOX:
00306 {
00307 const urdf::Box& box = static_cast<const urdf::Box&>(geom);
00308 entity = ogre_tools::Shape::createEntity(entity_name, ogre_tools::Shape::Cube, scene_manager_);
00309
00310 scale = Ogre::Vector3( box.dim.x, box.dim.y, box.dim.z );
00311
00312 break;
00313 }
00314 case urdf::Geometry::CYLINDER:
00315 {
00316 const urdf::Cylinder& cylinder = static_cast<const urdf::Cylinder&>(geom);
00317
00318 Ogre::Quaternion rotX;
00319 rotX.FromAngleAxis( Ogre::Degree(90), Ogre::Vector3::UNIT_X );
00320 offset_orientation = offset_orientation * rotX;
00321
00322 entity = ogre_tools::Shape::createEntity(entity_name, ogre_tools::Shape::Cylinder, scene_manager_);
00323 scale = Ogre::Vector3( cylinder.radius*2, cylinder.length, cylinder.radius*2 );
00324 break;
00325 }
00326 case urdf::Geometry::MESH:
00327 {
00328 const urdf::Mesh& mesh = static_cast<const urdf::Mesh&>(geom);
00329
00330 if ( mesh.filename.empty() )
00331 return;
00332
00333 scale = Ogre::Vector3(mesh.scale.x, mesh.scale.y, mesh.scale.z);
00334
00335 std::string model_name = mesh.filename;
00336 loadMeshFromResource(model_name);
00337
00338 try
00339 {
00340 entity = scene_manager_->createEntity( ss.str(), model_name );
00341 }
00342 catch( Ogre::Exception& e )
00343 {
00344 ROS_ERROR( "Could not load model '%s' for link '%s': %s\n", model_name.c_str(), link->name.c_str(), e.what() );
00345 }
00346 break;
00347 }
00348 default:
00349 ROS_WARN("Unsupported geometry type for element: %d", geom.type);
00350 break;
00351 }
00352
00353 if ( entity )
00354 {
00355 offset_node->attachObject(entity);
00356 offset_node->setScale(scale);
00357 offset_node->setPosition(offset_position);
00358 offset_node->setOrientation(offset_orientation);
00359
00360 if (default_material_name_.empty())
00361 {
00362 default_material_ = getMaterialForLink(root_element, link);
00363
00364 static int count = 0;
00365 std::stringstream ss;
00366 ss << default_material_->getName() << count++ << "Robot";
00367 std::string cloned_name = ss.str();
00368
00369 default_material_ = default_material_->clone(cloned_name);
00370 default_material_name_ = default_material_->getName();
00371 }
00372
00373 for (uint32_t i = 0; i < entity->getNumSubEntities(); ++i)
00374 {
00375
00376 Ogre::SubEntity* sub = entity->getSubEntity(i);
00377 const std::string& material_name = sub->getMaterialName();
00378
00379 if (material_name == "BaseWhite" || material_name == "BaseWhiteNoLighting")
00380 {
00381 sub->setMaterialName(default_material_name_);
00382 }
00383 else
00384 {
00385
00386
00387 static int count = 0;
00388 std::stringstream ss;
00389 ss << material_name << count++ << "Robot";
00390 std::string cloned_name = ss.str();
00391 sub->getMaterial()->clone(cloned_name);
00392 sub->setMaterialName(cloned_name);
00393 }
00394
00395 materials_[sub] = sub->getMaterial();
00396 }
00397 }
00398 }
00399
00400 void RobotLink::createCollision(TiXmlElement* root_element, const urdf::LinkConstPtr& link)
00401 {
00402 if (!link->collision || !link->collision->geometry)
00403 return;
00404
00405 createEntityForGeometryElement(root_element, link, *link->collision->geometry, link->collision->origin, parent_->getCollisionNode(), collision_mesh_, collision_node_, collision_offset_node_);
00406 }
00407
00408 void RobotLink::createVisual(TiXmlElement* root_element, const urdf::LinkConstPtr& link )
00409 {
00410 if (!link->visual || !link->visual->geometry)
00411 return;
00412
00413 createEntityForGeometryElement(root_element, link, *link->visual->geometry, link->visual->origin, parent_->getVisualNode(), visual_mesh_, visual_node_, visual_offset_node_);
00414 }
00415
00416 void RobotLink::createSelection(const urdf::Model& descr, const urdf::LinkConstPtr& link)
00417 {
00418 selection_handler_ = RobotLinkSelectionHandlerPtr(new RobotLinkSelectionHandler(this));
00419 SelectionManager* sel_man = vis_manager_->getSelectionManager();
00420 selection_object_ = sel_man->createHandle();
00421 sel_man->addObject(selection_object_, selection_handler_);
00422
00423 M_SubEntityToMaterial::iterator it = materials_.begin();
00424 M_SubEntityToMaterial::iterator end = materials_.end();
00425 for (; it != end; ++it)
00426 {
00427 const Ogre::MaterialPtr& material = it->second;
00428
00429 sel_man->addPickTechnique(selection_object_, material);
00430 }
00431
00432 if (visual_mesh_)
00433 {
00434 selection_handler_->addTrackedObject(visual_mesh_);
00435 }
00436
00437 if (collision_mesh_)
00438 {
00439 selection_handler_->addTrackedObject(collision_mesh_);
00440 }
00441 }
00442
00443 void RobotLink::setPropertyManager(PropertyManager* property_manager)
00444 {
00445 property_manager_ = property_manager;
00446 }
00447
00448 void RobotLink::createProperties()
00449 {
00450 ROS_ASSERT( property_manager_ );
00451
00452 std::stringstream ss;
00453 ss << parent_->getName() << " Link " << name_;
00454
00455 CategoryPropertyWPtr cat = property_manager_->createCategory( name_, ss.str(), parent_->getLinksCategory(), this );
00456
00457
00458 trail_property_ = property_manager_->createProperty<BoolProperty>( "Show Trail", ss.str(), boost::bind( &RobotLink::getShowTrail, this ),
00459 boost::bind( &RobotLink::setShowTrail, this, _1 ), cat, this );
00460 setPropertyHelpText(trail_property_, "Enable/disable a 2 meter \"ribbon\" which follows this link.");
00461
00462 axes_property_ = property_manager_->createProperty<BoolProperty>( "Show Axes", ss.str(), boost::bind( &RobotLink::getShowAxes, this ),
00463 boost::bind( &RobotLink::setShowAxes, this, _1 ), cat, this );
00464 setPropertyHelpText(axes_property_, "Enable/disable showing the axes of this link.");
00465
00466 position_property_ = property_manager_->createProperty<Vector3Property>( "Position", ss.str(), boost::bind( &RobotLink::getPositionInRobotFrame, this ),
00467 Vector3Property::Setter(), cat, this );
00468 setPropertyHelpText(position_property_, "Position of this link, in the current Fixed Frame. (Not editable)");
00469 orientation_property_ = property_manager_->createProperty<QuaternionProperty>( "Orientation", ss.str(), boost::bind( &RobotLink::getOrientationInRobotFrame, this ),
00470 QuaternionProperty::Setter(), cat, this );
00471 setPropertyHelpText(orientation_property_, "Orientation of this link, in the current Fixed Frame. (Not editable)");
00472
00473 CategoryPropertyPtr cat_prop = cat.lock();
00474 cat_prop->collapse();
00475 }
00476
00477
00478 Ogre::Vector3 RobotLink::getPositionInRobotFrame()
00479 {
00480 return position_;
00481 }
00482
00483 Ogre::Quaternion RobotLink::getOrientationInRobotFrame()
00484 {
00485 return orientation_;
00486 }
00487
00488 void RobotLink::setShowTrail(bool show)
00489 {
00490 if ( show )
00491 {
00492 if ( !trail_ )
00493 {
00494 if ( visual_node_ )
00495 {
00496 static int count = 0;
00497 std::stringstream ss;
00498 ss << "Trail for link " << name_ << count++;
00499 trail_ = scene_manager_->createRibbonTrail( ss.str() );
00500 trail_->setMaxChainElements( 100 );
00501 trail_->setInitialWidth( 0, 0.01f );
00502 trail_->setInitialColour( 0, 0.0f, 0.5f, 0.5f );
00503 trail_->addNode( visual_node_ );
00504 trail_->setTrailLength( 2.0f );
00505 parent_->getOtherNode()->attachObject( trail_ );
00506 }
00507 else
00508 {
00509 ROS_WARN( "No visual node for link %s, cannot create a trail", name_.c_str() );
00510 }
00511 }
00512 }
00513 else
00514 {
00515 if ( trail_ )
00516 {
00517 scene_manager_->destroyRibbonTrail( trail_ );
00518 trail_ = NULL;
00519 }
00520 }
00521
00522 propertyChanged(trail_property_);
00523 }
00524
00525 bool RobotLink::getShowTrail()
00526 {
00527 return trail_ != NULL;
00528 }
00529
00530 void RobotLink::setShowAxes(bool show)
00531 {
00532 if ( show )
00533 {
00534 if ( !axes_ )
00535 {
00536 static int count = 0;
00537 std::stringstream ss;
00538 ss << "Axes for link " << name_ << count++;
00539 axes_ = new ogre_tools::Axes( scene_manager_, parent_->getOtherNode(), 0.1, 0.01 );
00540 }
00541 }
00542 else
00543 {
00544 if ( axes_ )
00545 {
00546 delete axes_;
00547 axes_ = NULL;
00548 }
00549 }
00550
00551 propertyChanged(axes_property_);
00552 }
00553
00554 bool RobotLink::getShowAxes()
00555 {
00556 return axes_ != NULL;
00557 }
00558
00559 void RobotLink::setTransforms( const Ogre::Vector3& visual_position, const Ogre::Quaternion& visual_orientation,
00560 const Ogre::Vector3& collision_position, const Ogre::Quaternion& collision_orientation, bool apply_offset_transforms )
00561 {
00562 position_ = visual_position;
00563 orientation_ = visual_orientation;
00564
00565 if ( visual_node_ )
00566 {
00567 visual_node_->setPosition( visual_position );
00568 visual_node_->setOrientation( visual_orientation );
00569 }
00570
00571 if ( collision_node_ )
00572 {
00573 collision_node_->setPosition( collision_position );
00574 collision_node_->setOrientation( collision_orientation );
00575 }
00576
00577 if (property_manager_)
00578 {
00579 propertyChanged(position_property_);
00580 propertyChanged(orientation_property_);
00581 }
00582
00583
00584 if ( axes_ )
00585 {
00586 axes_->setPosition( position_ );
00587 axes_->setOrientation( orientation_ );
00588 }
00589 }
00590
00591 void RobotLink::setToErrorMaterial()
00592 {
00593 if (visual_mesh_)
00594 {
00595 visual_mesh_->setMaterialName("BaseWhiteNoLighting");
00596 }
00597
00598 if (collision_mesh_)
00599 {
00600 collision_mesh_->setMaterialName("BaseWhiteNoLighting");
00601 }
00602 }
00603
00604 void RobotLink::setToNormalMaterial()
00605 {
00606 M_SubEntityToMaterial::iterator it = materials_.begin();
00607 M_SubEntityToMaterial::iterator end = materials_.end();
00608 for (; it != end; ++it)
00609 {
00610 it->first->setMaterial(it->second);
00611 }
00612 }
00613
00614 }
00615