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();