From 195a6e172c27b12c0aeb72523684ae2a9b664d5c Mon Sep 17 00:00:00 2001
From: Fabian Reister <fabian.reister@kit.edu>
Date: Sat, 4 Feb 2023 16:35:00 +0100
Subject: [PATCH] urdf factory: parsing primitive approximation model

---
 VirtualRobot/Import/URDF/SimoxURDFFactory.cpp | 151 +++++++++++++++++-
 VirtualRobot/Import/URDF/SimoxURDFFactory.h   |  10 +-
 2 files changed, 153 insertions(+), 8 deletions(-)

diff --git a/VirtualRobot/Import/URDF/SimoxURDFFactory.cpp b/VirtualRobot/Import/URDF/SimoxURDFFactory.cpp
index 27dce262f..03c1cb01c 100644
--- a/VirtualRobot/Import/URDF/SimoxURDFFactory.cpp
+++ b/VirtualRobot/Import/URDF/SimoxURDFFactory.cpp
@@ -6,7 +6,10 @@
 
 #include <Eigen/Geometry>
 
+#include "Primitive.h"
+#include <urdf_model/link.h>
 #include <urdf_model/model.h>
+#include <urdf_model/pose.h>
 #include <urdf_parser/urdf_parser.h>
 
 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
@@ -146,7 +149,7 @@ namespace VirtualRobot
         return robo;
     }
 
-    Eigen::Matrix4f SimoxURDFFactory::convertPose(const urdf::Pose& p)
+    Eigen::Matrix4f SimoxURDFFactory::convertPose(const urdf::Pose& p) const
     {
         const float scale = 1000.0f; // mm
         Eigen::Matrix4f res;
@@ -211,6 +214,93 @@ namespace VirtualRobot
         return result;
     }
 
+    Primitive::PrimitivePtr SimoxURDFFactory::convertPrimitive(const urdf::Collision& col) const
+    {
+        const urdf::Geometry& g = *col.geometry;
+        const urdf::Pose& p = col.origin;
+
+        return convertPrimitive(g, p);
+    }
+
+
+    Primitive::PrimitivePtr SimoxURDFFactory::convertPrimitive(const urdf::Visual& col) const
+    {
+        const urdf::Geometry& g = *col.geometry;
+        const urdf::Pose& p = col.origin;
+
+        return convertPrimitive(g, p);
+    }
+
+    Primitive::PrimitivePtr SimoxURDFFactory::convertPrimitive(const urdf::Geometry& g, const urdf::Pose& p) const
+    {
+        auto origin = convertPose(p);
+        if (g.type == urdf::Geometry::CYLINDER)
+        {
+            // inventor and urdf differ in the conventions for cylinders
+            origin = origin * MathTools::axisangle2eigen4f(Eigen::Vector3f::UnitX(), M_PI_2);
+        }
+
+        constexpr float scaleMtoMM = 1000;
+
+        switch (g.type)
+        {
+            case urdf::Geometry::BOX:
+            {
+                const urdf::Box* b = dynamic_cast<const urdf::Box*>(&g);
+
+                auto box = std::make_shared<Primitive::Box>();
+                box->width = b->dim.x * scaleMtoMM;
+                box->height = b->dim.y * scaleMtoMM;
+                box->depth = b->dim.z * scaleMtoMM ;
+
+                box->transform = origin;
+
+                return box;
+            }
+            break;
+
+            case urdf::Geometry::SPHERE:
+            {
+                const urdf::Sphere* s = dynamic_cast<const urdf::Sphere*>(&g);
+
+                auto sphere = std::make_shared<Primitive::Sphere>();
+                sphere->radius = s->radius * scaleMtoMM;
+
+                sphere->transform = origin;
+                return sphere;
+            }
+            break;
+
+
+            case urdf::Geometry::CYLINDER:
+            {
+                const urdf::Cylinder* c = dynamic_cast<const urdf::Cylinder*>(&g);
+
+                auto cylinder = std::make_shared<Primitive::Cylinder>();
+                cylinder->height = c->length * scaleMtoMM;
+                cylinder->radius = c->radius * scaleMtoMM;
+
+                cylinder->transform = origin;
+                return cylinder;
+
+            }
+            break;
+
+            case urdf::Geometry::MESH:
+            {
+                // not a primitive
+                return nullptr;
+            }
+            break;
+
+            default:
+                VR_WARNING << "urdf::Geometry type nyi..." << std::endl;
+        }
+
+        return nullptr;
+
+    }
+
     VirtualRobot::VisualizationNodePtr SimoxURDFFactory::convertVisu(std::shared_ptr<urdf::Geometry> g, urdf::Pose& pose, const std::string& basePath)
     {
 
@@ -274,6 +364,37 @@ namespace VirtualRobot
         return res;
     }
 
+    std::vector<Primitive::PrimitivePtr> SimoxURDFFactory::convertToPrimitives(const std::vector<std::shared_ptr<urdf::Collision>>& col_array) const
+    {
+        std::vector<Primitive::PrimitivePtr> primitives;
+
+        for (const auto & visu : col_array)
+        {
+            if(auto primitive = convertPrimitive(*visu))
+            {
+                primitives.push_back(primitive);
+            }
+        }
+
+        return primitives;
+    }
+
+     std::vector<Primitive::PrimitivePtr> SimoxURDFFactory::convertToPrimitives(const std::vector<std::shared_ptr<urdf::Visual>>& col_array) const
+    {
+        std::vector<Primitive::PrimitivePtr> primitives;
+
+        for (const auto & visu : col_array)
+        {
+            if(auto primitive = convertPrimitive(*visu))
+            {
+                primitives.push_back(primitive);
+            }
+        }
+
+        return primitives;
+    }
+
+
     VisualizationNodePtr SimoxURDFFactory::convertVisuArray(std::vector<std::shared_ptr<urdf::Collision> > col_array, const string& basePath)
     {
         VirtualRobot::VisualizationNodePtr res;
@@ -322,11 +443,9 @@ namespace VirtualRobot
 
     RobotNodePtr SimoxURDFFactory::createBodyNode(const std::string& name, RobotPtr robo, std::shared_ptr<urdf::Link> urdfBody, const std::string& basePath, bool useColModelsIfNoVisuModel)
     {
-        RobotNodePtr result;
-
         if (!urdfBody)
         {
-            return result;
+            return {};
         }
 
         VirtualRobot::RobotNodeFactoryPtr fixedNodeFactory = VirtualRobot::RobotNodeFactory::fromName(VirtualRobot::RobotNodeFixedFactory::getName(), NULL);
@@ -336,16 +455,21 @@ namespace VirtualRobot
         VirtualRobot::VisualizationNodePtr rnVisu;
         VirtualRobot::CollisionModelPtr rnCol;
 
+        std::vector<Primitive::PrimitivePtr> visuPrimitives;
+        std::vector<Primitive::PrimitivePtr> colPrimitives;
+
         if (urdfBody->visual && urdfBody->visual)
         {
             if (urdfBody->visual_array.size() > 1)
             {
                 // visual points to first entry in array
                 rnVisu = convertVisuArray(urdfBody->visual_array, basePath);
+                visuPrimitives = convertToPrimitives(urdfBody->visual_array);
             }
             else
             {
                 rnVisu = convertVisu(urdfBody->visual->geometry, urdfBody->visual->origin, basePath);
+                visuPrimitives = convertToPrimitives({urdfBody->visual});
             }
         }
 
@@ -355,10 +479,12 @@ namespace VirtualRobot
             if (urdfBody->collision_array.size() > 1)
             {
                 v = convertVisuArray(urdfBody->collision_array, basePath);
+                colPrimitives = convertToPrimitives(urdfBody->collision_array);
             }
             else
             {
                 v = convertVisu(urdfBody->collision->geometry, urdfBody->collision->origin, basePath);
+                colPrimitives = convertToPrimitives({urdfBody->collision});
             }
 
             if (v)
@@ -397,11 +523,22 @@ namespace VirtualRobot
         }
 
         Eigen::Vector3f idVec3 = Eigen::Vector3f::Zero();
-        result = fixedNodeFactory->createRobotNode(robo, name, rnVisu, rnCol, 0, 0, 0, preJointTransform, idVec3, idVec3, physics);
+        RobotNodePtr node = fixedNodeFactory->createRobotNode(robo, name, rnVisu, rnCol, 0, 0, 0, preJointTransform, idVec3, idVec3, physics);
 
-        robo->registerRobotNode(result);
+        robo->registerRobotNode(node);
 
-        return result;
+        if(not visuPrimitives.empty())
+        {
+            node->getPrimitiveApproximation().addModel(visuPrimitives, "urdf_visu");
+        }
+
+        if(not colPrimitives.empty())
+        {
+            node->getPrimitiveApproximation().addModel(colPrimitives, "urdf_col");
+        }
+
+
+        return node;
     }
 
     RobotNodePtr SimoxURDFFactory::createJointNode(RobotPtr robo, std::shared_ptr<urdf::Joint> urdfJoint)
diff --git a/VirtualRobot/Import/URDF/SimoxURDFFactory.h b/VirtualRobot/Import/URDF/SimoxURDFFactory.h
index 6be93aaac..37b44cc7e 100644
--- a/VirtualRobot/Import/URDF/SimoxURDFFactory.h
+++ b/VirtualRobot/Import/URDF/SimoxURDFFactory.h
@@ -27,6 +27,7 @@
 #include <VirtualRobot/Robot.h>
 #include <VirtualRobot/Import/RobotImporterFactory.h>
 
+#include <urdf_model/link.h>
 #include <urdf_model/model.h>
 
 namespace VirtualRobot
@@ -77,12 +78,19 @@ namespace VirtualRobot
     protected:
         RobotNodePtr createBodyNode(const std::string& name, RobotPtr robot, std::shared_ptr<urdf::Link> urdfBody, const std::string& basePath, bool useColModelsIfNoVisuModel = true);
         RobotNodePtr createJointNode(RobotPtr robot, std::shared_ptr<urdf::Joint> urdfJoint);
-        Eigen::Matrix4f convertPose(const urdf::Pose& p);
+        Eigen::Matrix4f convertPose(const urdf::Pose& p) const;
         VirtualRobot::VisualizationNodePtr convertVisu(std::shared_ptr<urdf::Geometry> g, urdf::Pose& pose, const std::string& basePath);
         VirtualRobot::VisualizationNodePtr convertVisuArray(std::vector<std::shared_ptr<urdf::Visual> > visu_array, const std::string& basePath);
         VirtualRobot::VisualizationNodePtr convertVisuArray(std::vector<std::shared_ptr<urdf::Collision> > visu_array, const std::string& basePath);
         std::string getFilename(const std::string& f, const std::string& basePath);
 
+        Primitive::PrimitivePtr convertPrimitive(const urdf::Geometry& g, const urdf::Pose& p) const;
+        Primitive::PrimitivePtr convertPrimitive(const urdf::Visual& col) const;
+        Primitive::PrimitivePtr convertPrimitive(const urdf::Collision& col) const;
+
+        std::vector<Primitive::PrimitivePtr> convertToPrimitives(const std::vector<std::shared_ptr<urdf::Collision>>& col_array) const;
+        std::vector<Primitive::PrimitivePtr> convertToPrimitives(const std::vector<std::shared_ptr<urdf::Visual>>& col_array) const;
+
         bool useColModelsIfNoVisuModel;
     };
 
-- 
GitLab