diff --git a/VirtualRobot/Nodes/RobotNode.cpp b/VirtualRobot/Nodes/RobotNode.cpp index 8298691bfc22221a3daf83ba7a676d53841392a0..077b2d7ab09ebf176ca677d959e82ffc2a9abc17 100644 --- a/VirtualRobot/Nodes/RobotNode.cpp +++ b/VirtualRobot/Nodes/RobotNode.cpp @@ -538,11 +538,11 @@ namespace VirtualRobot RobotNodePtr RobotNode::clone(RobotPtr newRobot, bool cloneChildren, RobotNodePtr initializeWithParent, CollisionCheckerPtr colChecker, - float scaling, + std::optional<float> scaling, bool preventCloningMeshesIfScalingIs1) { - // If scaling is <= 0 this->scaling is used instead. This enables different scalings while still able to clone the robot - auto actualScaling = scaling > 0 ? scaling : this->scaling; + const float actualScaling = scaling.value_or(this->scaling); + const float scalingFactor = scaling.has_value() ? scaling.value() / this->scaling : 1.0f; ReadLockPtr lock = getRobot()->getReadLock(); @@ -556,20 +556,20 @@ namespace VirtualRobot VisualizationNodePtr clonedVisualizationNode; - const bool deepMeshClone = !preventCloningMeshesIfScalingIs1 || std::abs(scaling - 1) <= 0; + const bool deepMeshClone = !preventCloningMeshesIfScalingIs1 || std::abs(scalingFactor - 1) <= 1e-12; if (visualizationModel) { - clonedVisualizationNode = visualizationModel->clone(deepMeshClone, actualScaling); + clonedVisualizationNode = visualizationModel->clone(deepMeshClone, scalingFactor); } CollisionModelPtr clonedCollisionModel; if (collisionModel) { - clonedCollisionModel = collisionModel->clone(colChecker, actualScaling, deepMeshClone); + clonedCollisionModel = collisionModel->clone(colChecker, scalingFactor, deepMeshClone); } - RobotNodePtr result = _clone(newRobot, clonedVisualizationNode, clonedCollisionModel, colChecker, scaling > 0 ? scaling : 1.0f); + RobotNodePtr result = _clone(newRobot, clonedVisualizationNode, clonedCollisionModel, colChecker, scalingFactor); if (!result) { diff --git a/VirtualRobot/Nodes/RobotNode.h b/VirtualRobot/Nodes/RobotNode.h index 454973471658e6eecc0698d000484b2e83b69dc8..1e2c571211c3c0b099b9970f686ae0ffa414be21 100644 --- a/VirtualRobot/Nodes/RobotNode.h +++ b/VirtualRobot/Nodes/RobotNode.h @@ -32,6 +32,7 @@ #include <Eigen/Core> +#include <optional> #include <string> #include <vector> #include <map> @@ -271,7 +272,7 @@ namespace VirtualRobot bool cloneChildren = true, RobotNodePtr initializeWithParent = RobotNodePtr(), CollisionCheckerPtr colChecker = CollisionCheckerPtr(), - float scaling = 1.0f, + std::optional<float> scaling = std::nullopt, bool preventCloningMeshesIfScalingIs1 = false); inline float getJointValueOffset() const diff --git a/VirtualRobot/Primitive.h b/VirtualRobot/Primitive.h index 9d03fef485396abd4c647cdfce38adde4fa8a806..0977163be8d85009654d7c94df33440cf04017a2 100644 --- a/VirtualRobot/Primitive.h +++ b/VirtualRobot/Primitive.h @@ -22,6 +22,8 @@ namespace VirtualRobot virtual std::unique_ptr<Primitive> clone() const = 0; + virtual void scaleLinear(float scalingFactor) = 0; + protected: Primitive(int type) : type(type), transform(Eigen::Matrix4f::Identity()) {} std::string getTransformString(int tabs = 0); @@ -47,6 +49,14 @@ namespace VirtualRobot clone->transform = transform; return clone; } + + void scaleLinear(float scalingFactor) final + { + transform.block(0, 3, 3, 1) *= scalingFactor; + width *= scalingFactor; + height *= scalingFactor; + depth *= scalingFactor; + } }; class VIRTUAL_ROBOT_IMPORT_EXPORT Sphere : public Primitive @@ -64,6 +74,12 @@ namespace VirtualRobot clone->transform = transform; return clone; } + + void scaleLinear(float scalingFactor) final + { + transform.block(0, 3, 3, 1) *= scalingFactor; + radius *= scalingFactor; + } }; class VIRTUAL_ROBOT_IMPORT_EXPORT Cylinder : public Primitive @@ -82,6 +98,13 @@ namespace VirtualRobot clone->transform = transform; return clone; } + + void scaleLinear(float scalingFactor) final + { + transform.block(0, 3, 3, 1) *= scalingFactor; + height *= scalingFactor; + radius *= scalingFactor; + } }; /** @@ -103,6 +126,13 @@ namespace VirtualRobot clone->transform = transform; return clone; } + + void scaleLinear(float scalingFactor) final + { + transform.block(0, 3, 3, 1) *= scalingFactor; + height *= scalingFactor; + radius *= scalingFactor; + } }; typedef std::shared_ptr<Primitive> PrimitivePtr; diff --git a/VirtualRobot/Robot.cpp b/VirtualRobot/Robot.cpp index ea1b6d6e698d919d9b0d8c1de7941b063238a20c..86643243dbec2439c1c739517da975ce66d0dd23 100644 --- a/VirtualRobot/Robot.cpp +++ b/VirtualRobot/Robot.cpp @@ -766,7 +766,7 @@ namespace VirtualRobot bool cloneRNS, bool cloneEEFs, CollisionCheckerPtr collisionChecker, - float scaling, + std::optional<float> scaling, bool preventCloningMeshesIfScalingIs1) { THROW_VR_EXCEPTION_IF(!startJoint, " StartJoint is nullptr"); @@ -787,7 +787,7 @@ namespace VirtualRobot RobotNodePtr rootNew = startJoint->clone(result, true, RobotNodePtr(), colChecker, scaling, preventCloningMeshesIfScalingIs1); THROW_VR_EXCEPTION_IF(!rootNew, "Clone failed..."); result->setRootNode(rootNew); - result->setScaling(scaling > 0 ? scaling : this->scaling); + result->setScaling(scaling.value_or(this->scaling)); std::vector<RobotNodePtr> rn = result->getRobotNodes(); @@ -849,7 +849,7 @@ namespace VirtualRobot } RobotPtr Robot::cloneScaling() { - return clone(getName(), CollisionCheckerPtr(), -1.0f); + return clone(); } Eigen::Matrix4f Robot::getGlobalPoseForRobotNode( @@ -905,7 +905,7 @@ namespace VirtualRobot VirtualRobot::RobotPtr Robot::clone(const std::string& name, CollisionCheckerPtr collisionChecker, - float scaling, + std::optional<float> scaling, bool preventCloningMeshesIfScalingIs1) { VirtualRobot::RobotPtr result = extractSubPart(this->getRootNode(), @@ -929,7 +929,7 @@ namespace VirtualRobot } RobotPtr Robot::clone(CollisionCheckerPtr collisionChecker, - float scaling, + std::optional<float> scaling, bool preventCloningMeshesIfScalingIs1) { return clone(getName(), collisionChecker, scaling, preventCloningMeshesIfScalingIs1); diff --git a/VirtualRobot/Robot.h b/VirtualRobot/Robot.h index 1ab3255d1128438ff71ff27369eefe55df24a82d..868c00deb126dcac31e13277eb3f37cfef1e549c 100644 --- a/VirtualRobot/Robot.h +++ b/VirtualRobot/Robot.h @@ -303,7 +303,7 @@ namespace VirtualRobot bool cloneRNS = true, bool cloneEEFs = true, CollisionCheckerPtr collisionChecker = CollisionCheckerPtr(), - float scaling = 1.0f, + std::optional<float> scaling = std::nullopt, bool preventCloningMeshesIfScalingIs1 = false); /*! @@ -315,13 +315,14 @@ namespace VirtualRobot */ virtual RobotPtr clone(const std::string& name, CollisionCheckerPtr collisionChecker = CollisionCheckerPtr(), - float scaling = 1.0f, + std::optional<float> scaling = std::nullopt, bool preventCloningMeshesIfScalingIs1 = false); virtual RobotPtr clone(CollisionCheckerPtr collisionChecker = CollisionCheckerPtr(), - float scaling = 1.0f, + std::optional<float> scaling = std::nullopt, bool preventCloningMeshesIfScalingIs1 = false); - /*! @brief Clones this robot and keeps the current scaling for the robot and each robot node */ + /*! @brief Clones this robot and keeps the current scaling for the robot and each robot node. */ + [[deprecated("Use clone() instead. Which now contains scaling as an optional.")]] virtual RobotPtr cloneScaling(); //! Just storing the filename. diff --git a/VirtualRobot/RobotFactory.cpp b/VirtualRobot/RobotFactory.cpp index e49afc9cb4e22e1fccceaf54eb3987e565d74434..22869b7ff279acdfc121fbadba0cc1f3f050a514 100644 --- a/VirtualRobot/RobotFactory.cpp +++ b/VirtualRobot/RobotFactory.cpp @@ -344,6 +344,80 @@ namespace VirtualRobot return true; } + void RobotFactory::scaleLinear(RobotNode &node, float sizeScaling, float weightScaling) + { + Eigen::Matrix4f localTransformation = node.getLocalTransformation(); + localTransformation.block(0, 3, 3, 1) *= sizeScaling; + node.setLocalTransformation(localTransformation); + + if (node.optionalDHParameter.isSet) + { + node.optionalDHParameter.setAInMM(node.optionalDHParameter.aMM() * sizeScaling); + node.optionalDHParameter.setDInMM(node.optionalDHParameter.dMM() * sizeScaling); + } + + node.setMass(node.getMass() * weightScaling); + node.setCoMLocal(node.getCoMLocal() * sizeScaling); + node.setInertiaMatrix(node.getInertiaMatrix() * pow(sizeScaling, 2) * weightScaling); + node.setScaling(node.getScaling() * sizeScaling); + } + + void RobotFactory::scaleLinear(Robot &robot, float sizeScaling, float weightScaling, + const std::map<std::string, float> &customSegmentLengths, + const std::map<std::string, float>& customSizeScaling) + { + for (auto node : robot.getRobotNodes()) + { + float model_height_scaling = sizeScaling; + + const auto segLengthIt = customSegmentLengths.find(node->getName()); + const auto sizeScaleIt = customSizeScaling.find(node->getName()); + + if (sizeScaleIt != customSizeScaling.end()) + { + model_height_scaling = sizeScaleIt->second; + } + + if (segLengthIt != customSegmentLengths.end()) + { + if (sizeScaleIt != customSizeScaling.end()) + { + VR_WARNING << "Custom segment length ignored for node " << node->getName() + << " because custom height scaling was already specified "; + } + else + { + const float l = node->getLocalTransformation().block(0, 3, 3, 1).norm(); + if (l != 0.0f) + model_height_scaling = 1.0f / l * segLengthIt->second; + } + } + + for (auto sensor : node->getSensors()) + { + Eigen::Matrix4f lt = sensor->getParentNodeToSensorTransformation(); + lt.block(0, 3, 3, 1) *= model_height_scaling; + sensor->setRobotNodeToSensorTransformation(lt); + } + + scaleLinear(*node.get(), model_height_scaling, weightScaling); + + if (auto vis = node->visualizationModel) + { + node->setVisualization(node->visualizationModel->clone(true, model_height_scaling)); + } + + if (auto col = node->getCollisionModel()) + { + node->setCollisionModel(col->clone(node->getCollisionChecker(), model_height_scaling, true)); + } + + node->getPrimitiveApproximation().scaleLinear(model_height_scaling); + } + robot.setScaling(robot.getScaling() * sizeScaling); + robot.setMass(robot.getMass() * weightScaling); + } + RobotPtr RobotFactory::cloneChangeStructure(RobotPtr robot, robotStructureDef& newStructure) { VR_ASSERT(robot); diff --git a/VirtualRobot/RobotFactory.h b/VirtualRobot/RobotFactory.h index 0b5303446453bcd3bf55baee5bffc92b7308374a..e73cbe19fe49bbe0680d8ff24d5f820fb391fd69 100644 --- a/VirtualRobot/RobotFactory.h +++ b/VirtualRobot/RobotFactory.h @@ -147,6 +147,21 @@ namespace VirtualRobot static bool detach(RobotPtr robot, RobotNodePtr rn); + static void scaleLinear(RobotNode& node, float sizeScaling, float weightScaling = 1.); + + /** + * Method to linearly scale the size (in all axes) and the weight of the robot, e.g. for the MMM reference model. + * This includes scaling all kinematic and dynamic properties as well as the visualization, collision and primitive approximation models. + * @param robot + * @param sizeScaling linear scaling factor in x,y,z-direction + * @param weightScaling linear weight factor + * @param customSegmentLengths (Optional) RobotNode name -> custom translation length. Takes priority over sizeScaling + * @param customSizeScaling (Optional) RobotNode name -> custom size scaling. Takes priority over customSegmentLengths. + */ + static void scaleLinear(Robot& robot, float sizeScaling, float weightScaling = 1., + const std::map<std::string, float>& customSegmentLengths = std::map<std::string, float>(), + const std::map<std::string, float>& customSegmentSizeScaling = std::map<std::string, float>()); + protected: // some internal stuff diff --git a/VirtualRobot/SceneObject.cpp b/VirtualRobot/SceneObject.cpp index 734ec473976bfd677d1607a1853d0a6e8c878e24..96925f44c617a5d5f33ec9123d6e803e5d8d6892 100644 --- a/VirtualRobot/SceneObject.cpp +++ b/VirtualRobot/SceneObject.cpp @@ -1662,4 +1662,20 @@ namespace VirtualRobot return defaultPrimitives.empty() && primitives.empty(); } + void SceneObject::PrimitiveApproximation::scaleLinear(float scalingFactor) + { + for (auto& primitive : this->defaultPrimitives) + { + primitive->scaleLinear(scalingFactor); + } + + for (auto& [id, primitives] : this->primitives) + { + for (auto& primitive : primitives) + { + primitive->scaleLinear(scalingFactor); + } + } + } + } // namespace diff --git a/VirtualRobot/SceneObject.h b/VirtualRobot/SceneObject.h index aefd37fc17badf91da02a82b8691284a7be07e23..3fb7348e3d1443b39797732a2d15fbda53b9acd7 100644 --- a/VirtualRobot/SceneObject.h +++ b/VirtualRobot/SceneObject.h @@ -105,6 +105,8 @@ namespace VirtualRobot bool empty() const; + void scaleLinear(float scalingFactor); + private: std::vector<Primitive::PrimitivePtr> defaultPrimitives; std::map<std::string, std::vector<Primitive::PrimitivePtr>> primitives;