30 #include <boost/filesystem.hpp> 
   32 #include <OgreEntity.h> 
   33 #include <OgreMaterial.h> 
   34 #include <OgreMaterialManager.h> 
   35 #include <OgreRibbonTrail.h> 
   36 #include <OgreSceneManager.h> 
   37 #include <OgreSceneNode.h> 
   38 #include <OgreSubEntity.h> 
   39 #include <OgreTextureManager.h> 
   40 #include <OgreSharedPtr.h> 
   41 #include <OgreTechnique.h> 
   46 #include <urdf_model/model.h> 
   47 #include <urdf_model/link.h> 
   66 namespace fs = boost::filesystem;
 
  100       new Property(
"Link " + QString::fromStdString(
link_->
getName()), QVariant(), 
"", parent_property);
 
  150 static std::map<const RobotLink*, std::string> 
errors;
 
  153                      const urdf::LinkConstSharedPtr& link,
 
  154                      const std::string& parent_joint_name,
 
  158   , scene_manager_(robot->getDisplayContext()->getSceneManager())
 
  159   , context_(robot->getDisplayContext())
 
  161   , parent_joint_name_(parent_joint_name)
 
  162   , visual_node_(nullptr)
 
  163   , collision_node_(nullptr)
 
  167   , only_render_depth_(false)
 
  168   , is_selectable_(true)
 
  169   , material_mode_flags_(ORIGINAL)
 
  181       new Property(
"Show Trail", 
false, 
"Enable/disable a 2 meter \"ribbon\" which follows this link.",
 
  189                          "Position of this link, in the current Fixed Frame.  (Not editable)",
 
  195                              "Orientation of this link, in the current Fixed Frame.  (Not editable)",
 
  205   std::string material_name = 
"robot link " + link->name + 
":color material";
 
  207       nullptr, material_name, 0, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME));
 
  223   if (collision || visual)
 
  229   std::stringstream desc;
 
  232     desc << 
"Root Link <b>" << 
name_ << 
"</b>";
 
  236     desc << 
"Link <b>" << 
name_ << 
"</b>";
 
  240   if (link->child_joints.empty())
 
  242     desc << 
" has no children.";
 
  246     desc << 
" has " << link->child_joints.size();
 
  248     if (link->child_joints.size() > 1)
 
  250       desc << 
" child joints: ";
 
  254       desc << 
" child joint: ";
 
  257     std::vector<urdf::JointSharedPtr>::const_iterator child_it = link->child_joints.begin();
 
  258     std::vector<urdf::JointSharedPtr>::const_iterator child_end = link->child_joints.end();
 
  259     for (; child_it != child_end; ++child_it)
 
  261       urdf::Joint* child_joint = child_it->get();
 
  262       if (child_joint && !child_joint->name.empty())
 
  265         desc << 
"<b>" << child_joint->name << 
"</b>" << ((child_it + 1 == child_end) ? 
"." : 
", ");
 
  271     desc << 
"  Check/uncheck to show/hide this link in the display.";
 
  274       desc << 
"  This link has collision geometry but no visible geometry.";
 
  278       desc << 
"  This link has visible geometry but no collision geometry.";
 
  283     desc << 
"  This link has NO geometry.";
 
  326   va_start(
args, format);
 
  327   vsnprintf(buffer, 
sizeof(buffer), format, 
args);
 
  361   Ogre::SceneNode::ChildNodeIterator child_it = 
visual_node_->getChildIterator();
 
  362   while (child_it.hasMoreElements())
 
  364     Ogre::SceneNode* child = 
dynamic_cast<Ogre::SceneNode*
>(child_it.getNext());
 
  367       Ogre::SceneNode::ObjectIterator object_it = child->getAttachedObjectIterator();
 
  368       while (object_it.hasMoreElements())
 
  370         Ogre::MovableObject* obj = object_it.getNext();
 
  371         obj->setRenderQueueGroup(group);
 
  379   setRenderQueueGroup(onlyRenderDepth ? Ogre::RENDER_QUEUE_BACKGROUND : Ogre::RENDER_QUEUE_MAIN);
 
  389     Ogre::MaterialPtr& active = item.second.first;
 
  390     const Ogre::MaterialPtr& original = item.second.second;
 
  394       active->setColourWriteEnabled(
false);
 
  395       active->setDepthWriteEnabled(
true);
 
  399       Ogre::ColourValue color = active->getTechnique(0)->getPass(0)->getDiffuse();
 
  400       const float material_alpha = original->getTechnique(0)->getPass(0)->getDiffuse().a;
 
  402       active->setDiffuse(color);
 
  404       if (color.a < 0.9998) 
 
  406         active->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
 
  407         active->setDepthWriteEnabled(
false);
 
  409       else if (active == original)
 
  411         active->setSceneBlending(Ogre::SBT_REPLACE);
 
  412         active->setDepthWriteEnabled(
true);
 
  416         original->copyDetailsTo(active);
 
  421   Ogre::ColourValue color = 
color_material_->getTechnique(0)->getPass(0)->getDiffuse();
 
  425   if (color.a < 0.9998)
 
  462                                                 urdf::MaterialConstSharedPtr material)
 
  466   if (material && !material->name.empty())
 
  468     for (
const auto& visual : link->visual_array)
 
  470       if (visual->material_name == material->name)
 
  472         material = visual->material;
 
  477   if (!material && link->visual && link->visual->material)
 
  478     material = link->visual->material; 
 
  480   std::string name = 
"robot link " + link->name;
 
  482     name += 
":" + material->name;
 
  484   Ogre::MaterialPtr mat = Ogre::MaterialPtr(
 
  485       new Ogre::Material(
nullptr, name, 0, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME));
 
  490     *mat = *Ogre::MaterialManager::getSingleton().getByName(
"RVIZ/ShadedRed");
 
  494   mat->getTechnique(0)->setLightingEnabled(
true);
 
  495   if (material->texture_filename.empty())
 
  497     const urdf::Color& col = material->color;
 
  498     mat->getTechnique(0)->setAmbient(col.r * 0.5, col.g * 0.5, col.b * 0.5);
 
  499     mat->getTechnique(0)->setDiffuse(col.r, col.g, col.b, col.a);
 
  503     std::string filename = material->texture_filename;
 
  504     if (!Ogre::TextureManager::getSingleton().resourceExists(filename))
 
  510         res = retriever.
get(filename);
 
  519         Ogre::DataStreamPtr stream(
new Ogre::MemoryDataStream(res.
data.get(), res.
size));
 
  521         std::string extension = fs::path(filename).extension().string();
 
  523         if (extension[0] == 
'.')
 
  525           extension = extension.substr(1, extension.size() - 1);
 
  530           image.load(stream, extension);
 
  531           Ogre::TextureManager::getSingleton().loadImage(
 
  532               filename, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image);
 
  534         catch (Ogre::Exception& e)
 
  536           ROS_ERROR(
"Could not load texture [%s]: %s", filename.c_str(), e.what());
 
  541     Ogre::Pass* pass = mat->getTechnique(0)->getPass(0);
 
  542     Ogre::TextureUnitState* tex_unit = pass->createTextureUnitState();
 
  544     tex_unit->setTextureName(filename);
 
  551                                                const urdf::Geometry& geom,
 
  552                                                const urdf::MaterialSharedPtr& material,
 
  553                                                const urdf::Pose& origin,
 
  554                                                Ogre::SceneNode* scene_node,
 
  555                                                Ogre::Entity*& entity)
 
  558   Ogre::SceneNode* offset_node = scene_node->createChildSceneNode();
 
  560   static unsigned count = 0;
 
  561   std::stringstream ss;
 
  562   ss << 
"Robot Link" << ++count;
 
  563   std::string entity_name = ss.str();
 
  565   Ogre::Vector3 scale(Ogre::Vector3::UNIT_SCALE);
 
  567   Ogre::Vector3 offset_position(Ogre::Vector3::ZERO);
 
  568   Ogre::Quaternion offset_orientation(Ogre::Quaternion::IDENTITY);
 
  572     Ogre::Vector3 position(origin.position.x, origin.position.y, origin.position.z);
 
  573     Ogre::Quaternion orientation(Ogre::Quaternion::IDENTITY);
 
  574     orientation = orientation * Ogre::Quaternion(origin.rotation.w, origin.rotation.x, origin.rotation.y,
 
  577     offset_position = position;
 
  578     offset_orientation = orientation;
 
  583   case urdf::Geometry::SPHERE:
 
  585     const urdf::Sphere& sphere = 
static_cast<const urdf::Sphere&
>(geom);
 
  588     scale = Ogre::Vector3(sphere.radius * 2, sphere.radius * 2, sphere.radius * 2);
 
  591   case urdf::Geometry::BOX:
 
  593     const urdf::Box& box = 
static_cast<const urdf::Box&
>(geom);
 
  596     scale = Ogre::Vector3(box.dim.x, box.dim.y, box.dim.z);
 
  600   case urdf::Geometry::CYLINDER:
 
  602     const urdf::Cylinder& cylinder = 
static_cast<const urdf::Cylinder&
>(geom);
 
  604     Ogre::Quaternion rotX;
 
  605     rotX.FromAngleAxis(Ogre::Degree(90), Ogre::Vector3::UNIT_X);
 
  606     offset_orientation = offset_orientation * rotX;
 
  609     scale = Ogre::Vector3(cylinder.radius * 2, cylinder.length, cylinder.radius * 2);
 
  612   case urdf::Geometry::MESH:
 
  614     const urdf::Mesh& mesh = 
static_cast<const urdf::Mesh&
>(geom);
 
  616     if (mesh.filename.empty())
 
  620     scale = Ogre::Vector3(mesh.scale.x, mesh.scale.y, mesh.scale.z);
 
  622     const std::string& model_name = mesh.filename;
 
  627         addError(
"Could not load mesh resource '%s'", model_name.c_str());
 
  631     catch (Ogre::InvalidParametersException& e)
 
  633       addError(
"Could not convert mesh resource '%s': %s", model_name.c_str(), e.what());
 
  635     catch (Ogre::Exception& e)
 
  637       addError(
"Could not load model '%s': %s", model_name.c_str(), e.what());
 
  642     ROS_WARN(
"Unsupported geometry type for element: %d", geom.type);
 
  648     offset_node->attachObject(entity);
 
  649     offset_node->setScale(scale);
 
  650     offset_node->setPosition(offset_position);
 
  651     offset_node->setOrientation(offset_orientation);
 
  659     for (uint32_t i = 0; i < entity->getNumSubEntities(); ++i)
 
  662       Ogre::SubEntity* sub = entity->getSubEntity(i);
 
  663       const std::string& material_name = sub->getMaterialName();
 
  665       Ogre::MaterialPtr active, original;
 
  666       if (material_name == 
"BaseWhite" || material_name == 
"BaseWhiteNoLighting")
 
  669         original = sub->getMaterial();
 
  672       active = Ogre::MaterialPtr(
new Ogre::Material(
 
  673           nullptr, material_name, 0, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME));
 
  675       sub->setMaterial(active);
 
  676       materials_[sub] = std::make_pair(active, original);
 
  683   bool valid_collision_found = 
false;
 
  684 #if URDF_MAJOR_VERSION == 0 && URDF_MINOR_VERSION == 2 
  685   std::map<std::string, boost::shared_ptr<std::vector<urdf::CollisionSharedPtr> > >::const_iterator mi;
 
  686   for (mi = link->collision_groups.begin(); mi != link->collision_groups.end(); mi++)
 
  690       std::vector<urdf::CollisionSharedPtr>::const_iterator vi;
 
  691       for (vi = mi->second->begin(); vi != mi->second->end(); vi++)
 
  693         urdf::CollisionSharedPtr collision = *vi;
 
  694         if (collision && collision->geometry)
 
  696           Ogre::Entity* collision_mesh = 
NULL;
 
  702             valid_collision_found = 
true;
 
  709   std::vector<urdf::CollisionSharedPtr>::const_iterator vi;
 
  710   for (vi = link->collision_array.begin(); vi != link->collision_array.end(); vi++)
 
  712     urdf::CollisionSharedPtr collision = *vi;
 
  713     if (collision && collision->geometry)
 
  715       Ogre::Entity* collision_mesh = 
nullptr;
 
  722       valid_collision_found |= collision == link->collision; 
 
  727   if (!valid_collision_found && link->collision && link->collision->geometry)
 
  729     Ogre::Entity* collision_mesh = 
nullptr;
 
  743   bool valid_visual_found = 
false;
 
  744 #if URDF_MAJOR_VERSION == 0 && URDF_MINOR_VERSION == 2 
  745   std::map<std::string, boost::shared_ptr<std::vector<urdf::VisualSharedPtr> > >::const_iterator mi;
 
  746   for (mi = link->visual_groups.begin(); mi != link->visual_groups.end(); mi++)
 
  750       std::vector<urdf::VisualSharedPtr>::const_iterator vi;
 
  751       for (vi = mi->second->begin(); vi != mi->second->end(); vi++)
 
  753         urdf::VisualSharedPtr visual = *vi;
 
  754         if (visual && visual->geometry)
 
  756           Ogre::Entity* visual_mesh = 
NULL;
 
  762             valid_visual_found = 
true;
 
  769   std::vector<urdf::VisualSharedPtr>::const_iterator vi;
 
  770   for (vi = link->visual_array.begin(); vi != link->visual_array.end(); vi++)
 
  772     urdf::VisualSharedPtr visual = *vi;
 
  773     if (visual && visual->geometry)
 
  775       Ogre::Entity* visual_mesh = 
nullptr;
 
  782       valid_visual_found |= visual == link->visual; 
 
  787   if (!valid_visual_found && link->visual && link->visual->geometry)
 
  789     Ogre::Entity* visual_mesh = 
nullptr;
 
  822         static int count = 0;
 
  823         std::stringstream ss;
 
  824         ss << 
"Trail for link " << 
name_ << count++;
 
  826         trail_->setMaxChainElements(100);
 
  827         trail_->setInitialWidth(0, 0.01
f);
 
  828         trail_->setInitialColour(0, 0.0
f, 0.5
f, 0.5
f);
 
  836         ROS_WARN(
"No visual node for link %s, cannot create a trail", 
name_.c_str());
 
  856       static int count = 0;
 
  857       std::stringstream ss;
 
  858       ss << 
"Axes for link " << 
name_ << count++;
 
  877                               const Ogre::Quaternion& visual_orientation,
 
  878                               const Ogre::Vector3& collision_position,
 
  879                               const Ogre::Quaternion& collision_orientation)
 
  923       item.first->setMaterial(item.second.first);
 
  927   auto error_material = Ogre::MaterialManager::getSingleton().getByName(
 
  928       "BaseWhiteNoLighting", Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
 
  932     mesh->setMaterial(material);
 
  934     mesh->setMaterial(material);
 
  939   Ogre::ColourValue color = 
color_material_->getTechnique(0)->getPass(0)->getDiffuse();