diff --git a/GeometricPlanning/ArticulatedObjectGeometricPlanningHelper.cpp b/GeometricPlanning/ArticulatedObjectGeometricPlanningHelper.cpp index 6002c8e9537044d6aebd9a1513c88b317085c607..5eb382bfd405d8c0c4888493038488c14b4cfb9d 100644 --- a/GeometricPlanning/ArticulatedObjectGeometricPlanningHelper.cpp +++ b/GeometricPlanning/ArticulatedObjectGeometricPlanningHelper.cpp @@ -21,11 +21,11 @@ #include "VirtualRobot/VirtualRobotException.h" #include <GeometricPlanning/ParametricPath.h> +#include <GeometricPlanning/assert/assert.h> #include <GeometricPlanning/path_primitives/CircleSegment.h> #include <GeometricPlanning/path_primitives/Line.h> #include <GeometricPlanning/path_primitives/PathPrimitive.h> #include <GeometricPlanning/types.h> -#include <GeometricPlanning/assert/assert.h> namespace simox::geometric_planning @@ -41,11 +41,13 @@ namespace simox::geometric_planning ArticulatedObjectGeometricPlanningHelper::getPathForNode(const std::string& nodeName) const { const auto node = articulatedObject->getRobotNode(nodeName); + REQUIRE(node != nullptr); simox::geometric_planning::ArticulatedObjectGeometricPlanningHelper helper( articulatedObject); const auto parents = node->getAllParents(); + REQUIRE(not parents.empty()); // VR_INFO << parents.size() << " parents for " << nodeName; @@ -78,6 +80,7 @@ namespace simox::geometric_planning const auto parentJoint = std::find_if(parents.begin(), parents.end(), isJoint); const auto& joint = *parentJoint; + REQUIRE(joint != nullptr); const auto parametricPath = helper.getPathForNode(node->getName(), joint->getName()); @@ -133,7 +136,7 @@ namespace simox::geometric_planning // ARMARX_DEBUG << "Radius: " << radius; REQUIRE_MESSAGE(joint->getJointLimitHigh() > joint->getJointLimitLow(), - "Not implemented yet. Do so by flipping the z axis of the joint."); + "Not implemented yet. Do so by flipping the z axis of the joint."); const ParameterRange parameterRange{ .min = 0, .max = joint->getJointLimitHigh() - joint->getJointLimitLow()}; @@ -162,8 +165,7 @@ namespace simox::geometric_planning joint_plane__joint_plane_P_node_initial.x()); // ARMARX_DEBUG << VAROUT(yaw); - const Pose joint_plane_T_joint_reference( - Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitZ())); + const Pose joint_plane_T_joint_reference(Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitZ())); subpart->setJointValue(joint->getName(), joint->getJointLimitLow()); @@ -172,7 +174,7 @@ namespace simox::geometric_planning const Pose root_T_joint = root_T_global * global_T_joint; const Pose root_T_joint_reference(root_T_joint * joint_T_joint_plane * - joint_plane_T_joint_reference); + joint_plane_T_joint_reference); const auto jointReferenceNode = std::make_shared<VirtualRobot::RobotNodeFixed>( subpart, nodeJointReference, root_T_joint_reference.matrix()); @@ -180,7 +182,8 @@ namespace simox::geometric_planning // TODO check if node already exists and unregister if needed subpart->registerRobotNode(jointReferenceNode); - CHECK(!jointReferenceNode->initialize(subpart->getRootNode())); + CHECK_MESSAGE(jointReferenceNode->initialize(subpart->getRootNode()), + "Failed to initialize node `" << jointReferenceNode->getName() << "`!"); // reset joint state joint->setJointValue(initialJointValue); diff --git a/GeometricPlanning/CMakeLists.txt b/GeometricPlanning/CMakeLists.txt index 3e784bd4d695c0d9bbdacdb762bf51aafe5c55bf..371f3f52179e1b97ec1029cbb43d87dfef8f073b 100644 --- a/GeometricPlanning/CMakeLists.txt +++ b/GeometricPlanning/CMakeLists.txt @@ -31,6 +31,7 @@ SET(SOURCES path_primitives/Circle.cpp path_primitives/CircleSegment.cpp path_primitives/Line.cpp + visualization.cpp ) SET(HEADERS @@ -43,6 +44,7 @@ SET(HEADERS path_primitives/CircleSegment.h path_primitives/Line.h assert/assert.h + visualization.h ) ADD_LIBRARY(GeometricPlanning SHARED) # sources will be added later diff --git a/GeometricPlanning/visualization.cpp b/GeometricPlanning/visualization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dc943d41c6bb581b8936ec7eb34557b3742ee8a --- /dev/null +++ b/GeometricPlanning/visualization.cpp @@ -0,0 +1,117 @@ +#include "visualization.h" + +#include <cmath> + +#include <Eigen/Geometry> + +#include <SimoxUtility/color/Color.h> +#include <VirtualRobot/Nodes/RobotNode.h> +#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h> +#include <VirtualRobot/Visualization/VisualizationFactory.h> + +#include <GeometricPlanning/ParametricPath.h> +#include <GeometricPlanning/assert/assert.h> +#include <GeometricPlanning/path_primitives/CircleSegment.h> +#include <GeometricPlanning/path_primitives/Line.h> +#include <Inventor/SbMatrix.h> +#include <Inventor/SbRotation.h> +#include <Inventor/SbVec3f.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTransform.h> + +namespace simox::geometric_planning +{ + constexpr float defaultWidth = 5.f; + constexpr std::size_t numberOfCircleParts = 20; + inline const simox::Color DefaultColor = simox::Color::blue(); + + constexpr float + scaleColor(const auto colorVal) + { + return colorVal / 255.f; + } + + namespace detail + { + SoNode* + visualizePathLine(const geometric_planning::ParametricPath& path) + { + const auto startPos = path.getPose(path.parameterRange().min); + const auto endPos = path.getPose(path.parameterRange().max); + + return VirtualRobot::CoinVisualizationFactory::createCoinLine( + startPos.matrix(), + endPos.matrix(), + defaultWidth, + scaleColor(DefaultColor.r), + scaleColor(DefaultColor.g), + scaleColor(DefaultColor.b)); + } + + + SoNode* + visualizeCircleSegment(const geometric_planning::ParametricPath& path) + { + const auto* circleSegment = + dynamic_cast<geometric_planning::CircleSegment*>(path.path.get()); + REQUIRE(circleSegment != nullptr); + + const float circleCompletion = + (circleSegment->parameterRange().max - circleSegment->parameterRange().min) / + (2 * M_PIf32); + + // circle centered at origin + auto* circleNode = VirtualRobot::CoinVisualizationFactory::createCoinPartCircle( + circleSegment->getRadius(), + circleCompletion, + defaultWidth, + scaleColor(DefaultColor.r), + scaleColor(DefaultColor.g), + scaleColor(DefaultColor.b), + numberOfCircleParts); + + + const Pose global_T_path_origin(path.frame->getGlobalPose()); + + const SbVec3f translation(global_T_path_origin.translation().x(), + global_T_path_origin.translation().y(), + global_T_path_origin.translation().z()); + + const SbVec3f scale(1., 1., 1.); + + const Eigen::AngleAxisf rot(global_T_path_origin.linear()); + const SbRotation rotation(SbVec3f(rot.axis().x(), rot.axis().y(), rot.axis().z()), + rot.angle()); + + SbMatrix transf; + transf.setTransform(translation, rotation, scale); + + auto* t = new SoMatrixTransform(); + t->matrix.setValue(transf); + + auto* separator = new SoSeparator(); + separator->addChild(t); + separator->addChild(circleNode); + return separator; + } + } // namespace detail + + + SoNode* + visualize(const geometric_planning::ParametricPath& path) + { + if (dynamic_cast<geometric_planning::Line*>(path.path.get()) != nullptr) + { + return detail::visualizePathLine(path); + } + + if (dynamic_cast<geometric_planning::CircleSegment*>(path.path.get()) != nullptr) + { + return detail::visualizeCircleSegment(path); + } + + REQUIRE_MESSAGE(false, "Unknown parametric path"); + return nullptr; + } + +} // namespace simox::geometric_planning diff --git a/GeometricPlanning/visualization.h b/GeometricPlanning/visualization.h new file mode 100644 index 0000000000000000000000000000000000000000..5dc38d42e89cf1619b13774f7468224da5290284 --- /dev/null +++ b/GeometricPlanning/visualization.h @@ -0,0 +1,18 @@ + +#pragma once + +class SoNode; + +namespace simox::geometric_planning +{ + class ParametricPath; + + SoNode* visualize(const ParametricPath& path); + + namespace detail + { + SoNode* visualizePathLine(const ParametricPath& path); + SoNode* visualizeCircleSegment(const ParametricPath& path); + } // namespace detail + +} // namespace simox::geometric_planning