diff --git a/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.cpp b/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.cpp index 097a0cf5c7d5004b35b2baa44f8901050c565917..c5737f9681b2b9883538b1e9a25c93871f43631a 100644 --- a/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.cpp +++ b/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.cpp @@ -22,58 +22,98 @@ #include "Armar6GraspProvider.h" +#include <Armar6Skills/libraries/Armar6Tools/Armar6HandV2Helper.h> + +#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h> #include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h> +#include <RobotAPI/libraries/diffik/SimpleDiffIK.h> +#include <RobotAPI/libraries/SimpleJsonLogger/SimpleJsonLoggerEntry.h> #include <ArmarXGui/libraries/RemoteGui/WidgetBuilder.h> #include <ArmarXGui/libraries/StructuralJson/JPathNavigator.h> #include <ArmarXGui/libraries/StructuralJson/StructuralJsonParser.h> -#include <RobotAPI/libraries/SimpleJsonLogger/SimpleJsonLoggerEntry.h> -#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h> + +#include <ArmarXCore/core/rapidxml/wrapper/RapidXmlReader.h> + +#include <pcl/point_types.h> +#include <pcl/common/transforms.h> +#include <pcl/filters/passthrough.h> #include <pcl/filters/approximate_voxel_grid.h> #include <pcl/filters/voxel_grid.h> #include <pcl/filters/statistical_outlier_removal.h> + +#include <SimoxUtility/algorithm/contains.h> +#include <SimoxUtility/algorithm/get_map_keys_values.h> +#include <SimoxUtility/math/pose/transform.h> + #include <VirtualRobot/math/Helpers.h> +#include <VirtualRobot/math/Line.h> #include <VirtualRobot/ManipulationObject.h> #include <VirtualRobot/Visualization/TriMeshModel.h> + #include <cmath> -#include "FitRectangle.h" -#include "RobotAPI/components/ArViz/Client/elements/Color.h" -#include <RobotAPI/libraries/diffik/SimpleDiffIK.h> +#include "FitRectangle.h" +#include "grasping_util.h" -#include <Armar6Skills/libraries/Armar6Tools/Armar6HandV2Helper.h> using namespace math; using namespace armarx; - -std::string Armar6GraspProvider::GraspTypeToString(Armar6GraspProviderModule::GraspType graspType) +Armar6GraspProviderPropertyDefinitions::Armar6GraspProviderPropertyDefinitions(std::string prefix) : + armarx::ComponentPropertyDefinitions(prefix) { - switch (graspType) - { - case Armar6GraspProviderModule::GraspType::Top: - return "Top"; - case Armar6GraspProviderModule::GraspType::Side: - return "Side"; - default: - throw LocalException("Unknown GraspType"); - } + defineOptionalProperty<std::string>("DebugObserverName", "DebugObserver", "Name of the debug observer that should be used"); + defineOptionalProperty<std::string>("DebugDrawerTopicName", "DebugDrawerUpdates", "Name of the debug drawer topic that should be used"); + defineOptionalProperty<std::string>("StaticPlotterName", "StaticPlotter", "Name of the static plotter that should be used"); + + defineOptionalProperty<std::string>("GraspCandidatesTopicName", "GraspCandidatesTopic", "Name of the Grasp Candidate Topic"); + defineOptionalProperty<std::string>("ConfigTopicName", "GraspCandidateProviderConfigTopic", "Name of the Grasp Candidate Provider Config Topic"); + + defineOptionalProperty<std::string>("PointCloudFormat", "XYZRGBL", "Format of the input and output point cloud (XYZRGBA, XYZL, XYZRGBL)"); + defineOptionalProperty<std::string>("RobotStateComponentName", "RobotStateComponent", "Name of the robot state component that should be used"); + defineOptionalProperty<std::string>("providerName", "TabletopSegmentationResult", "name of the point cloud provider"); + defineOptionalProperty<std::string>("serviceProviderName", "TabletopSegmentation", "name of the service provider"); + defineOptionalProperty<std::string>("sourceFrameName", "root", "The source frame name"); + + defineOptionalProperty<uint32_t>("BackgroundLabelId", 1, "Label in the pointcloud for the plane or background.", PropertyDefinitionBase::eModifiable); + defineOptionalProperty<bool>("UseObjectIdMap", false, "Use ID map from config for named objects"); + + defineOptionalProperty<float>("DownsamplingLeafSize", 5.f, "If >0, the pointcloud is downsampled with a leaf size of this value. In mm.", PropertyDefinitionBase::eModifiable); + defineOptionalProperty<size_t>("MininumClusterPointCount", 100, "Minimum number of points per cluster/segmented object to be further processed.", PropertyDefinitionBase::eModifiable); + + defineOptionalProperty<float>("BoundingBoxX1", -200, ""); + defineOptionalProperty<float>("BoundingBoxX2", 200, ""); + defineOptionalProperty<float>("BoundingBoxY1", 0.f, ""); + defineOptionalProperty<float>("BoundingBoxY2", 1300.f, ""); + defineOptionalProperty<float>("BoundingBoxZ1", 975.f, ""); + + defineOptionalProperty<bool>("enablePointCloudsVisu", true, ""); + defineOptionalProperty<bool>("enableVisu", true, ""); + defineOptionalProperty<bool>("enableCandidatesVisu", true, ""); + defineOptionalProperty<bool>("enableBoundigBoxesVisu", false, ""); + defineOptionalProperty<bool>("FlattenInZ", true, ""); + defineOptionalProperty<bool>("UseObjectPoseObserver", false, ""); + defineOptionalProperty<bool>("UseWorkingMemory", false, ""); + defineOptionalProperty<int>("WaitForPointCloudsMS", 200, ""); + + defineOptionalProperty<std::string>("RemoteGuiName", "RemoteGuiProvider", "Name of the remote gui"); + defineOptionalProperty<std::string>("PriorKnowledgeName", "PriorKnowledge", "Name of the PriorKnowledge"); + defineOptionalProperty<std::string>("WorkingMemoryName", "WorkingMemory", "Name of the WorkingMemory"); + + + defineOptionalProperty<int>("colorNonReachableGraspsR", 128, "The red color channel for non reachable grasps"); + defineOptionalProperty<int>("colorNonReachableGraspsG", 128, "The green color channel for non reachable grasps"); + defineOptionalProperty<int>("colorNonReachableGraspsB", 128, "The blue color channel color channel for non reachable grasps"); } -std::string Armar6GraspProvider::PreshapeTypeToString(Armar6GraspProviderModule::PreshapeType preshapeType) +armarx::PropertyDefinitionsPtr Armar6GraspProvider::createPropertyDefinitions() { - switch (preshapeType) - { - case Armar6GraspProviderModule::PreshapeType::Open: - return "Open"; - case Armar6GraspProviderModule::PreshapeType::Preshaped: - return "Preshaped"; - default: - throw LocalException("Unknown GraspType"); - } + return armarx::PropertyDefinitionsPtr(new Armar6GraspProviderPropertyDefinitions(getConfigIdentifier())); } + void Armar6GraspProvider::onInitPointCloudProcessor() { offeringTopic("ServiceRequests"); @@ -82,11 +122,11 @@ void Armar6GraspProvider::onInitPointCloudProcessor() sourceFrameName = getProperty<std::string>("sourceFrameName").getValue(); pointCloudFormat = getProperty<std::string>("PointCloudFormat").getValue(); - boundingBox.z1 = getProperty<float>("BoundingBoxZ1").getValue(); - boundingBox.y1 = getProperty<float>("BoundingBoxY1").getValue(); - boundingBox.y2 = getProperty<float>("BoundingBoxY2").getValue(); - boundingBox.x1 = getProperty<float>("BoundingBoxX1").getValue(); - boundingBox.x2 = getProperty<float>("BoundingBoxX2").getValue(); + boundingBox.min_x() = getProperty<float>("BoundingBoxX1").getValue(); + boundingBox.max_x() = getProperty<float>("BoundingBoxX2").getValue(); + boundingBox.min_y() = getProperty<float>("BoundingBoxY1").getValue(); + boundingBox.max_y() = getProperty<float>("BoundingBoxY2").getValue(); + boundingBox.min_z() = getProperty<float>("BoundingBoxZ1").getValue(); config.enablePointCloudsVisu = getProperty<bool>("enablePointCloudsVisu").getValue(); config.enableVisu = getProperty<bool>("enableVisu").getValue(); @@ -296,11 +336,11 @@ void Armar6GraspProvider::onConnectPointCloudProcessor() // ValueProxy<float> x1Slider = makeSlider ... - makeSlider("x1", -600, 600, boundingBox.x1); - makeSlider("x2", -600, 600, boundingBox.x2); - makeSlider("y1", 0, 1500, boundingBox.y1); - makeSlider("y2", 0, 1500, boundingBox.y2); - makeSlider("z1", 300, 1500, boundingBox.z1); + makeSlider("x1", -600, 600, boundingBox.min_x()); + makeSlider("x2", -600, 600, boundingBox.max_x()); + makeSlider("y1", 0, 1500, boundingBox.min_y()); + makeSlider("y2", 0, 1500, boundingBox.max_y()); + makeSlider("z1", 300, 1500, boundingBox.min_z()); rootLayoutBuilder.addChild(checkBoxLayoutBuilder); makeCheckBox("FlattenInZ", true); makeCheckBox("enableVisu", true); @@ -314,26 +354,26 @@ void Armar6GraspProvider::onConnectPointCloudProcessor() guiTask = new SimplePeriodicTask<>([&]() { guiTab.receiveUpdates(); - boundingBox.x1 = guiTab.getValue<float>("x1").get(); - boundingBox.x2 = guiTab.getValue<float>("x2").get(); - boundingBox.y1 = guiTab.getValue<float>("y1").get(); - boundingBox.y2 = guiTab.getValue<float>("y2").get(); - boundingBox.z1 = guiTab.getValue<float>("z1").get(); + boundingBox.min_x() = guiTab.getValue<float>("x1").get(); + boundingBox.max_x() = guiTab.getValue<float>("x2").get(); + boundingBox.min_y() = guiTab.getValue<float>("y1").get(); + boundingBox.max_y() = guiTab.getValue<float>("y2").get(); + boundingBox.min_z() = guiTab.getValue<float>("z1").get(); flattenInZ = guiTab.getValue<bool>("FlattenInZ").get(); config.enableVisu = guiTab.getValue<bool>("enableVisu").get(); config.enableCandidatesVisu = guiTab.getValue<bool>("enableCandidatesVisu").get(); config.enableBoundigBoxesVisu = guiTab.getValue<bool>("enableBoundigBoxesVisu").get(); config.enablePointCloudsVisu = guiTab.getValue<bool>("enablePointCloudsVisu").get(); - guiTab.getValue<float>("x1_spin").set(boundingBox.x1); - guiTab.getValue<float>("x2_spin").set(boundingBox.x2); - guiTab.getValue<float>("y1_spin").set(boundingBox.y1); - guiTab.getValue<float>("y2_spin").set(boundingBox.y2); - guiTab.getValue<float>("z1_spin").set(boundingBox.z1); + guiTab.getValue<float>("x1_spin").set(boundingBox.min_x()); + guiTab.getValue<float>("x2_spin").set(boundingBox.max_x()); + guiTab.getValue<float>("y1_spin").set(boundingBox.min_y()); + guiTab.getValue<float>("y2_spin").set(boundingBox.max_y()); + guiTab.getValue<float>("z1_spin").set(boundingBox.min_z()); guiTab.sendUpdates(); - //ARMARX_IMPORTANT << VAROUT(boundingBox.z1); + //ARMARX_IMPORTANT << VAROUT(boundingBox.min_z()); }, 10, false, "guiTask"); reportConfigTask = new SimplePeriodicTask<>([&]() @@ -370,82 +410,26 @@ void Armar6GraspProvider::process() } else { - ARMARX_ERROR << "Could not process point cloud, because format '" << pointCloudFormat << "' is not suppoted / unknown"; + ARMARX_ERROR << "Could not process point cloud because format '" << pointCloudFormat << "' is not supported / unknown"; } } -namespace maptools -{ - template<typename TKey, typename TValue> - bool TryGetValue(const std::map<TKey, TValue>& map, const TKey& key, TValue& outVal) - { - typename std::map<TKey, TValue>::const_iterator it = map.find(key); - if (it == map.end()) - { - return false; - } - outVal = it->second; - return true; - } - - template<typename TKey, typename TValue, typename TDefaultValue> - TValue GetValueOrDefault(const std::map<TKey, TValue>& map, const TKey& key, const TDefaultValue& defaultVal) - { - typename std::map<TKey, TValue>::const_iterator it = map.find(key); - if (it == map.end()) - { - return defaultVal; - } - return it->second; - } - template<typename TKey, typename TValue> - bool HasKey(const std::map<TKey, TValue>& map, const TKey& key) - { - return map.count(key) > 0; - } +static viz::Cylinder drawLine(std::string const & name, Eigen::Vector3f fromRobot, Eigen::Vector3f toRobot, const Eigen::Matrix4f& robotToGlobal) +{ + viz::Cylinder cyl = viz::Cylinder(name) + .fromTo(simox::math::transform_position(robotToGlobal, fromRobot), + simox::math::transform_position(robotToGlobal, toRobot)) + .radius(3.0f); + return cyl; } -static void sortBoxExtendsForGraspCandidateGeneration(Eigen::Vector3f& v1, - Eigen::Vector3f& v2, - Eigen::Vector3f& v3, - Eigen::Vector3f& robotExtend1, - Eigen::Vector3f& robotExtend2, - Eigen::Vector3f& robotExtend3) +static viz::Box drawBox(std::string const & name, Eigen::Matrix4f const & poseRobot, const Eigen::Matrix4f& robotToGlobal) { - // These have to be sorted in a specific way - // v3 should point in the direction of Z - // v1 should point along the longer remaining axis (after aligning v3) - Eigen::Vector3f z = Eigen::Vector3f::UnitZ(); - if (std::abs(v1.dot(z)) > 0.8f) - { - std::swap(v1, v3); - std::swap(robotExtend1, robotExtend3); - } - if (std::abs(v2.dot(z)) > 0.8f) - { - std::swap(v2, v3); - std::swap(robotExtend2, robotExtend3); - } - - if (v3.z() < 0.0f) - { - v3 = -v3; - robotExtend3 = -robotExtend3; - } - - if (robotExtend1.norm() < robotExtend2.norm()) - { - Eigen::Vector3f temp = v1; - v1 = v2; - v2 = -temp; - - temp = robotExtend1; - robotExtend1 = robotExtend2; - robotExtend2 = -temp; - } + return viz::Box(name).pose(robotToGlobal * poseRobot); } + void Armar6GraspProvider::processPointCloud() { pcl::PointCloud<pcl::PointXYZRGBL>::Ptr inputCloudPtr(new pcl::PointCloud<pcl::PointXYZRGBL>()); @@ -473,29 +457,6 @@ void Armar6GraspProvider::processPointCloud() Eigen::Matrix4f robotToGlobal = Eigen::Matrix4f::Identity(); - auto drawLine = [&](std::string const & name, Eigen::Vector3f fromRobot, Eigen::Vector3f toRobot, viz::Color color, - viz::Layer & layer) - { - Eigen::Vector4f fromGlobal = robotToGlobal * fromRobot.homogeneous(); - Eigen::Vector4f toGlobal = robotToGlobal * toRobot.homogeneous(); - viz::Cylinder cyl = viz::Cylinder(name) - .fromTo(fromGlobal.head<3>(), toGlobal.head<3>()) - .radius(3.0f) - .color(color); - layer.add(cyl); - }; - - auto drawBox = [&](std::string const & name, Eigen::Matrix4f const & poseRobot, Eigen::Vector3f size, viz::Color color, - viz::Layer & layer) - { - Eigen::Matrix4f poseGlobal = robotToGlobal * poseRobot; - viz::Box box = viz::Box(name) - .pose(poseGlobal) - .size(size) - .color(color); - layer.add(box); - }; - if (waitForPointClouds(providerName, waitForPointCloudsMS)) { getPointClouds<pcl::PointXYZRGBL>(providerName, inputCloudPtr); @@ -516,22 +477,19 @@ void Armar6GraspProvider::processPointCloud() visionx::MetaPointCloudFormatPtr format = getPointCloudFormat(providerName); - - int inputSize = inputCloudPtr->points.size(); - - if (inputSize < 100) + if (inputCloudPtr->points.size() < 100) { ARMARX_INFO << deactivateSpam(60) << "Input size too small! Skipping grasp candidate generation"; return; } - - ARMARX_VERBOSE << "processPointCloud: " << inputCloudPtr->width << "x" << inputCloudPtr->height << " age: " << (TimeUtil::GetTime() - IceUtil::Time::microSeconds(inputCloudPtr->header.stamp)).toMilliSeconds(); + ARMARX_VERBOSE << "processPointCloud: " << inputCloudPtr->width << "x" << inputCloudPtr->height + << " age: " << (TimeUtil::GetTime() - IceUtil::Time::microSeconds(inputCloudPtr->header.stamp)).toMilliSecondsDouble() << " ms"; RemoteRobot::synchronizeLocalCloneToTimestamp(localRobot, robotStateComponent, inputCloudPtr->header.stamp); robotToGlobal = localRobot->getGlobalPose(); Eigen::Matrix4f sourceFrameInRootFrame = Eigen::Matrix4f::Identity(); - if (sourceFrameName == "Global") + if (sourceFrameName == armarx::GlobalFrame) { sourceFrameInRootFrame = localRobot->getRootNode()->getGlobalPose().inverse(); } @@ -544,21 +502,19 @@ void Armar6GraspProvider::processPointCloud() // Transform to global frame pcl::transformPointCloud(*inputCloudPtr, *tmpCloudPtr, sourceFrameInRootFrame); tmpCloudPtr.swap(inputCloudPtr); - tmpCloudPtr->clear(); - //std::vector<Eigen::Vector3f> segmentedPoints; - - uint32_t backgroundLabel = getProperty<uint32_t>("BackgroundLabelId").getValue(); + const uint32_t backgroundLabel = getProperty<uint32_t>("BackgroundLabelId"); std::map<uint32_t, std::vector<Eigen::Vector3f>> labeledPoints; std::map<uint32_t, DrawColor> colorMap; std::map<uint32_t, pcl::PointCloud<pcl::PointXYZRGBL>::Ptr> labeledClouds; for (const pcl::PointXYZRGBL& point : inputCloudPtr->points) { - bool anyNan = ::isnan(point.x) || ::isnan(point.y) || ::isnan(point.z) || ::isnan(point.r) || ::isnan(point.g) || ::isnan(point.b); - if (anyNan) + bool hasNan = std::isnan(point.x) || std::isnan(point.y) || std::isnan(point.z) + || std::isnan(point.r) || std::isnan(point.g) || std::isnan(point.b); + if (hasNan) { continue; } @@ -584,14 +540,14 @@ void Armar6GraspProvider::processPointCloud() colorMap[point.label] = DrawColor {point.r / 255.f, point.g / 255.f, point.b / 255.f, 1.f}; labeledClouds[point.label]->push_back(p); - outputCloudPtr->push_back(p); } - for (const std::pair<uint32_t, pcl::PointCloud<pcl::PointXYZRGBL>::Ptr>& pair : labeledClouds) + + for (const auto& [label, cloud] : labeledClouds) { pcl::PointCloud<pcl::PointXYZRGBL>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGBL>()); pcl::StatisticalOutlierRemoval<pcl::PointXYZRGBL> sor; - sor.setInputCloud(pair.second); + sor.setInputCloud(cloud); sor.setMeanK(50); sor.setStddevMulThresh(1.0); sor.filter(*cloud_filtered); @@ -601,51 +557,41 @@ void Armar6GraspProvider::processPointCloud() } } - - - for (const std::pair<uint32_t, std::vector<Eigen::Vector3f>>& pair : labeledPoints) + for (const auto& [label, allPoints] : labeledPoints) { - std::vector<Eigen::Vector3f> allPoints = pair.second; - uint32_t label = pair.first; - if (label == backgroundLabel) { - ARMARX_VERBOSE << "Skipping background label with " << allPoints.size() << " points"; + ARMARX_VERBOSE << "Skipping background label with " << allPoints.size() << " points."; continue; } std::string objectName = ""; bool isKnownObject = false; if (config.UseObjectIdMap) { - objectName = maptools::GetValueOrDefault(config.ObjectIdMap, (int)label, "UNKNOWN"); - isKnownObject = maptools::HasKey(config.ObjectIdMap, (int)label); + objectName = simox::alg::get_value_or_default(config.ObjectIdMap, int(label), "UNKNOWN"); + isKnownObject = simox::alg::contains_key(config.ObjectIdMap, int(label)); } else { objectName = "OBJ_" + std::to_string(label); } - ARMARX_VERBOSE << VAROUT(objectName) << VAROUT(label) << " " << VAROUT(allPoints.size()); + ARMARX_VERBOSE << VAROUT(objectName) << " | " << VAROUT(label) << " | " << VAROUT(allPoints.size()); if (allPoints.size() < getProperty<size_t>("MininumClusterPointCount").getValue()) { - ARMARX_VERBOSE << /*deactivateSpam(1, objectName) <<*/ "too few points for PCA for " << objectName << " (" << label << ")"; + ARMARX_VERBOSE // << deactivateSpam(1, objectName) + << "Too few points for PCA for " << objectName << " (" << label << ")."; } else { - auto determineGraspType = [&](const Box3D & box) - { - float height = box.Size3(); - float width = box.Size1(); - return width > height ? Armar6GraspProviderModule::GraspType::Top : Armar6GraspProviderModule::GraspType::Side; - }; FitRectangle fitBox(90); Box3D box = fitBox.Fit(allPoints); Eigen::Vector3f center = box.GetPoint(0, 0, 0); - Armar6GraspProviderModule::GraspType graspType = determineGraspType(box); + Armar6GraspProviderModule::GraspType graspType = grasping::determineGraspType(box); - std::string graspTypeStr = maptools::GetValueOrDefault(config.ObjectGraspTypeMap, objectName, "calculate"); + std::string graspTypeStr = simox::alg::get_value_or_default(config.ObjectGraspTypeMap, objectName, "calculate"); if (graspTypeStr == "TopBlob") { graspType = Armar6GraspProviderModule::GraspType::Top; @@ -662,7 +608,7 @@ void Armar6GraspProvider::processPointCloud() Vector2fSeq boxSizePlot; for (size_t i = 0; i < fitBox.results.size(); i++) { - boxSizePlot.push_back(Vector2f {(float)i, fitBox.results.at(i).Volume()}); + boxSizePlot.push_back(Vector2f {float(i), fitBox.results.at(i).Volume()}); } plots[objectName] = boxSizePlot; @@ -805,10 +751,6 @@ void Armar6GraspProvider::processPointCloud() result.extent3 = extractExtent(p3); - - - - // for (const Eigen::Vector3f& p : allPoints) // { // result.points.push_back(Armar6GraspProviderModule::Point {p(0), p(1), p(2)}); @@ -816,14 +758,15 @@ void Armar6GraspProvider::processPointCloud() std::string labelstr = std::to_string(label); - - drawLine("ex1_" + labelstr, l1.Get(result.extent1.p05), l1.Get(result.extent1.p95), viz::Color::red(), layerForPC); - drawLine("ex2_" + labelstr, l2.Get(result.extent2.p05), l2.Get(result.extent2.p95), viz::Color::green(), layerForPC); - drawLine("ex3_" + labelstr, l3.Get(result.extent3.p05), l3.Get(result.extent3.p95), viz::Color::blue(), layerForPC); - - if (config.enableBoundigBoxesVisu) { - drawBox(labelstr + "_bbox", box.GetPose(), box.SizeVec(), viz::Color::blue(128), layerForPC); + layerForPC.add(drawLine("ex1_" + labelstr, l1.Get(result.extent1.p05), l1.Get(result.extent1.p95), robotToGlobal).color(viz::Color::red())); + layerForPC.add(drawLine("ex2_" + labelstr, l2.Get(result.extent2.p05), l2.Get(result.extent2.p95), robotToGlobal).color(viz::Color::green())); + layerForPC.add(drawLine("ex3_" + labelstr, l3.Get(result.extent3.p05), l3.Get(result.extent3.p95), robotToGlobal).color(viz::Color::blue())); + + if (config.enableBoundigBoxesVisu) + { + layerForPC.add(drawBox(labelstr + "_bbox", box.GetPose(), robotToGlobal).size(box.SizeVec()).color(viz::Color::blue(128))); + } } Eigen::Vector3f preferredForwardTop(-1, 1, 0); @@ -953,9 +896,8 @@ void Armar6GraspProvider::processPointCloud() { ssDebug << ", not reachable"; } - - ssDebug << ") " << candidate->side << GraspTypeToString(graspType) << PreshapeTypeToString(grasp.preshape) << " " << ((int)center(0)) << "," << ((int)center(1)) << "," << ((int)center(2)) << std::endl; - + ssDebug << ") " << candidate->side << grasping::graspTypeToString(graspType) << grasping::preshapeTypeToString(grasp.preshape) + << " " << int(center(0)) << "," << int(center(1)) << "," << int(center(2)) << std::endl; resultList.push_back(result); @@ -975,27 +917,11 @@ void Armar6GraspProvider::processPointCloud() if (useObjectPoseObserver) { - // TODO: Reuse code - objpose::ObjectPoseSeq objectPoses = getObjectPoses(); + const objpose::ObjectPoseSeq objectPoses = getObjectPoses(); for (const objpose::ObjectPose& objectPose : objectPoses) { - - - std::optional<simox::OrientedBoxf> oobbRobot = objectPose.oobbRobot(); - if (!oobbRobot) - { - ARMARX_INFO << "Not generating grasp candidates for " << objectPose.objectID - << " because no bounding box was found"; - continue; - } - - auto& id = objectPose.objectID; - calculateGraspCandidatesForBB(objectPose, - id.dataset() + "/" + id.className(), - id.str(), - rns, tcp, - layerForOPO, - candidates, resultList); + calculateGraspCandidatesForObjectPose( + objectPose, rns, tcp, layerForOPO, candidates, resultList); detectedObjects++; } @@ -1004,36 +930,22 @@ void Armar6GraspProvider::processPointCloud() if (useWorkingMemory) { // Get object instance channels from working memory - std::vector<memoryx::ObjectInstanceWrapper> objects = objectInstanceSegment.queryObjects(); - for (memoryx::ObjectInstanceWrapper& object : objects) + const std::vector<memoryx::ObjectInstanceWrapper> objects = objectInstanceSegment.queryObjects(); + for (const memoryx::ObjectInstanceWrapper& object : objects) { - // TODO: Get bounding box for objects - VirtualRobot::ManipulationObjectPtr manipObj = object.manipulationObject; - VirtualRobot::BoundingBox localBB = manipObj->getCollisionModel()->getTriMeshModel()->boundingBox; - - simox::OrientedBoxf oobb = simox::OrientedBoxf(0.5 * (localBB.getMin() + localBB.getMax()), - Eigen::Quaternionf::Identity(), - localBB.getMax() - localBB.getMin()) - .transformed(manipObj->getGlobalPose()); - - /* - calculateGraspCandidatesForBB(oobb, - object.instanceInMemory->getMostProbableClass(), - object.instanceInMemory->getId(), - rns, tcp, - layerForWM, - candidates, resultList); - */ + calculateGraspCandidatesForWorkingMemoryInstance( + object, localRobot, rns, tcp, layerForWM, candidates, resultList); + detectedObjects++; } - } - debugObserver->setDebugDatafield(getName(), "objects", new Variant(ssDebug.str())); - staticPlotter->addPlot(getName() + "::ObjectSizes", plots); - + { + debugObserver->setDebugDatafield(getName(), "objects", new Variant(ssDebug.str())); + staticPlotter->addPlot(getName() + "::ObjectSizes", plots); - arviz.commit({layerForPC, layerForOPO, layerForWM}); + arviz.commit({layerForPC, layerForOPO, layerForWM}); + } /*debugObserver->setDebugDatafield(getName(), "center_x", new Variant(center(0))); debugObserver->setDebugDatafield(getName(), "center_y", new Variant(center(1))); @@ -1047,8 +959,11 @@ void Armar6GraspProvider::processPointCloud() std::unique_lock lock(resultMutex); this->resultList = resultList; processCount++; - debugObserver->setDebugDatafield(getName(), "processCount", new Variant(processCount)); - debugObserver->setDebugDatafield(getName(), "detectedObjects", new Variant(detectedObjects)); + debugObserver->setDebugChannel(getName(), + { + { "processCount", new Variant(processCount) }, + { "detectedObjects", new Variant(detectedObjects) } + }); } ARMARX_VERBOSE << "Reporting grasp candidates"; graspCandidatesTopic->reportGraspCandidates(getName(), candidates); @@ -1066,22 +981,6 @@ void Armar6GraspProvider::processPointCloud() } } -armarx::PropertyDefinitionsPtr Armar6GraspProvider::createPropertyDefinitions() -{ - return armarx::PropertyDefinitionsPtr(new Armar6GraspProviderPropertyDefinitions( - getConfigIdentifier())); -} - - -bool Armar6GraspProvider::BoundingBox::isInside(float x, float y, float z) -{ - return x >= x1 && x <= x2 && - y >= y1 && y <= y2 && - z >= z1 && z <= z2; -} - - - /* CapturedPointSeq armarx::Armar6GraspProvider::getSegmentedPoints(const Ice::Current&) @@ -1135,65 +1034,67 @@ Ice::Int Armar6GraspProvider::getProcessCount(const Ice::Current&) } -void Armar6GraspProvider::calculateGraspCandidatesForBB( +void Armar6GraspProvider::calculateGraspCandidatesForObjectPose( const objpose::ObjectPose& objectPose, - std::string const& className, - std::string const& instanceName, VirtualRobot::RobotNodeSetPtr const& rns, VirtualRobot::RobotNodePtr const& tcp, viz::Layer& layer, grasping::GraspCandidateSeq& candidatesOut, Armar6GraspProviderModule::ResultSeq& resultListOut) -/* -void Armar6GraspProvider::calculateGraspCandidatesForBB( - const simox::OrientedBoxf& oobbRobot, - std::string const& className, - std::string const& instanceName, - VirtualRobot::RobotNodeSetPtr const& rns, - VirtualRobot::RobotNodePtr const& tcp, - viz::Layer& layer, - grasping::GraspCandidateSeq& candidatesOut, - Armar6GraspProviderModule::ResultSeq& resultListOut) -*/ { - std::optional<simox::OrientedBoxf> oobbRobotOpt = objectPose.oobbRobot(); - if (!oobbRobotOpt) + std::optional<simox::OrientedBoxf> oobbRobot = objectPose.oobbRobot(); + if (!oobbRobot) { + ARMARX_INFO << "Not generating grasp candidates for " << objectPose.objectID + << " because no bounding box was found"; return; } - const simox::OrientedBoxf oobbRobot = *oobbRobotOpt; + const std::string className = objectPose.objectID.getClassID().str(); + const std::string instanceName = objectPose.objectID.str(); + calculateGraspCandidatesForBB(*oobbRobot, objectPose.robotPose, + className, instanceName, rns, tcp, layer, candidatesOut, resultListOut); +} - auto determineGraspType = [&](const Box3D & box) - { - float height = box.Size3(); - float width = box.Size1(); - return width > height ? Armar6GraspProviderModule::GraspType::Top : Armar6GraspProviderModule::GraspType::Side; - }; +void Armar6GraspProvider::calculateGraspCandidatesForWorkingMemoryInstance( + const memoryx::ObjectInstanceWrapper& object, + const VirtualRobot::RobotPtr& robot, + const VirtualRobot::RobotNodeSetPtr& rns, + const VirtualRobot::RobotNodePtr& tcp, + viz::Layer& layer, + grasping::GraspCandidateSeq& candidatesOut, + Armar6GraspProviderModule::ResultSeq& resultListOut) +{ + // TODO: Get bounding box for objects + VirtualRobot::ManipulationObjectPtr manipObj = object.manipulationObject; + VirtualRobot::BoundingBox localBB = manipObj->getCollisionModel()->getTriMeshModel()->boundingBox; - Eigen::Matrix4f robotToGlobal = localRobot->getGlobalPose(); + const Eigen::Matrix4f objectPoseInRobot = object.instanceInMemory->getPose()->toRootEigen(robot); - auto drawLine = [&](std::string const & name, Eigen::Vector3f fromRobot, Eigen::Vector3f toRobot, viz::Color color, - viz::Layer & layer) - { - Eigen::Vector4f fromGlobal = robotToGlobal * fromRobot.homogeneous(); - Eigen::Vector4f toGlobal = robotToGlobal * toRobot.homogeneous(); - viz::Cylinder cyl = viz::Cylinder(name) - .fromTo(fromGlobal.head<3>(), toGlobal.head<3>()) - .radius(3.0f) - .color(color); - layer.add(cyl); - }; + const simox::OrientedBoxf oobbInRobot = simox::OrientedBoxf( + 0.5 * (localBB.getMin() + localBB.getMax()), + Eigen::Quaternionf::Identity(), + localBB.getMax() - localBB.getMin()) + .transformed(objectPoseInRobot); - auto drawBox = [&](std::string const & name, Eigen::Matrix4f const & poseRobot, Eigen::Vector3f size, viz::Color color, - viz::Layer & layer) - { - Eigen::Matrix4f poseGlobal = robotToGlobal * poseRobot; - viz::Box box = viz::Box(name) - .pose(poseGlobal) - .size(size) - .color(color); - layer.add(box); - }; + const std::string className = object.instanceInMemory->getMostProbableClass(); + const std::string instanceName = object.instanceInMemory->getId(); + + calculateGraspCandidatesForBB(oobbInRobot, localRobot->getGlobalPose(), + className, instanceName, rns, tcp, layer, candidatesOut, resultListOut); +} + +void Armar6GraspProvider::calculateGraspCandidatesForBB( + const simox::OrientedBoxf& oobbRobot, + const Eigen::Matrix4f& robotPose, + const std::string& className, + const std::string& instanceName, + const VirtualRobot::RobotNodeSetPtr& rns, + const VirtualRobot::RobotNodePtr& tcp, + viz::Layer& layer, + grasping::GraspCandidateSeq& candidatesOut, + Armar6GraspProviderModule::ResultSeq& resultListOut) +{ + const Eigen::Matrix4f robotToGlobal = localRobot->getGlobalPose(); Eigen::Vector3f bbCenter = oobbRobot.center(); // We need to take half the extends @@ -1206,15 +1107,14 @@ void Armar6GraspProvider::calculateGraspCandidatesForBB( Eigen::Vector3f v3 = bbExtend3.normalized(); // We need to order the extends by size! - sortBoxExtendsForGraspCandidateGeneration(v1, v2, v3, - bbExtend1, bbExtend2, bbExtend3); + grasping::sortBoxExtendsForGraspCandidateGeneration(v1, v2, v3, bbExtend1, bbExtend2, bbExtend3); Box3D box(bbCenter, bbExtend1, bbExtend2, bbExtend3); Eigen::Vector3f center = box.GetPoint(0, 0, 0); - Armar6GraspProviderModule::GraspType graspType = determineGraspType(box); + Armar6GraspProviderModule::GraspType graspType = grasping::determineGraspType(box); // TODO: Here we can add fixed grasp types in the config for specific object classes! - std::string graspTypeStr = maptools::GetValueOrDefault(config.ObjectGraspTypeMap, className, "calculate"); + std::string graspTypeStr = simox::alg::get_value_or_default(config.ObjectGraspTypeMap, className, "calculate"); if (graspTypeStr == "TopBlob") { graspType = Armar6GraspProviderModule::GraspType::Top; @@ -1333,13 +1233,13 @@ void Armar6GraspProvider::calculateGraspCandidatesForBB( std::string label = instanceName; std::string labelstr = label; - drawLine("ex1_" + labelstr, center - v1, center + v1, viz::Color::red(), layer); - drawLine("ex2_" + labelstr, center - v2, center + v2, viz::Color::green(), layer); - drawLine("ex3_" + labelstr, center - v3, center + v3, viz::Color::blue(), layer); + layer.add(drawLine("ex1_" + labelstr, center - v1, center + v1, robotToGlobal).color(viz::Color::red())); + layer.add(drawLine("ex2_" + labelstr, center - v2, center + v2, robotToGlobal).color(viz::Color::green())); + layer.add(drawLine("ex3_" + labelstr, center - v3, center + v3, robotToGlobal).color(viz::Color::blue())); if (config.enableBoundigBoxesVisu) { - drawBox(labelstr + "_bbox", box.GetPose(), box.SizeVec(), viz::Color::blue(128), layer); + layer.add(drawBox(labelstr + "_bbox", box.GetPose(), robotToGlobal).size(box.SizeVec()).color(viz::Color::blue(128))); } Eigen::Vector3f preferredForwardTop(-1, 1, 0); @@ -1410,7 +1310,7 @@ void Armar6GraspProvider::calculateGraspCandidatesForBB( result.side = "Right"; result.graspDirection = graspType; - candidate->robotPose = new Pose(objectPose.robotPose); //localRobot->getGlobalPose()); + candidate->robotPose = new Pose(robotPose); candidate->graspPose = new Pose(grasp.pose); // TODO: What should we put into the group number? // TODO: Make a member variable for keeping track of groupNrs for object instances @@ -1456,7 +1356,7 @@ void Armar6GraspProvider::calculateGraspCandidatesForBB( std::string modelFile = "Armar6RT/robotmodel/Armar6-SH/Armar6-" + graspSide + "Hand-v3.xml"; viz::Robot hand = viz::Robot(labelstr + "_grasp") .file("Armar6RT", modelFile) - .pose(objectPose.robotPose * graspPose * tcp2handRoot) + .pose(robotPose * graspPose * tcp2handRoot) .overrideColor(color) .joints(fingerJointsVisu); layer.add(hand); @@ -1466,5 +1366,3 @@ void Armar6GraspProvider::calculateGraspCandidatesForBB( resultListOut.push_back(result); } } - - diff --git a/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.h b/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.h index 001358df1f9f49849288b311235d4249e3cdbfc0..276d1088625c8b9f6f8ab532fb1303d3d1260813 100644 --- a/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.h +++ b/source/Armar6Skills/components/Armar6GraspProvider/Armar6GraspProvider.h @@ -22,38 +22,39 @@ #pragma once +#include <mutex> -#include "RobotAPI/components/ArViz/Client/elements/Color.h" -#include <ArmarXCore/core/Component.h> - -#include <VisionX/components/pointcloud_core/PointCloudProcessor.h> -#include <Armar6Skills/interface/Armar6GraspProviderInterface.h> -#include <RobotAPI/interface/units/GraspCandidateProviderInterface.h> -#include <RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseClientPlugin.h> +#include <SimoxUtility/shapes/AxisAlignedBoundingBox.h> #include <VirtualRobot/Robot.h> -#include <RobotAPI/interface/core/RobotState.h> - -#include <pcl/point_types.h> - -#include <RobotAPI/components/DebugDrawer/DebugDrawerHelper.h> -#include <pcl/common/transforms.h> -#include <pcl/filters/passthrough.h> - -#include <Armar6Skills/libraries/Armar6Tools/Armar6GraspTrajectory.h> -#include <ArmarXCore/core/rapidxml/wrapper/RapidXmlReader.h> +#include <ArmarXCore/core/Component.h> #include <ArmarXCore/core/services/tasks/TaskUtil.h> + #include <ArmarXGui/interface/RemoteGuiInterface.h> #include <ArmarXGui/interface/StaticPlotterInterface.h> #include <ArmarXGui/libraries/RemoteGui/WidgetProxy.h> + +#include <RobotAPI/interface/units/GraspCandidateProviderInterface.h> +#include <RobotAPI/interface/core/RobotState.h> +#include <RobotAPI/components/ArViz/Client/elements/Color.h> +#include <RobotAPI/components/DebugDrawer/DebugDrawerHelper.h> +#include <RobotAPI/components/ObjectPoseObserver/plugins/ObjectPoseClientPlugin.h> #include <RobotAPI/libraries/RobotStatechartHelpers/RobotNameHelper.h> #include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h> + #include <MemoryX/libraries/helpers/VirtualRobotHelpers/ObjectInstanceSegmentWrapper.h> -#include <VirtualRobot/math/Line.h> +#include <VisionX/components/pointcloud_core/PointCloudProcessor.h> + +#include <Armar6Skills/interface/Armar6GraspProviderInterface.h> +#include <Armar6Skills/libraries/Armar6Tools/Armar6GraspTrajectory.h> -#include <mutex> + +namespace armarx +{ + class RapidXmlReaderNode; +} namespace armarx { @@ -63,61 +64,14 @@ namespace armarx * @class Armar6GraspProviderPropertyDefinitions * @brief */ - class Armar6GraspProviderPropertyDefinitions: - public armarx::ComponentPropertyDefinitions + class Armar6GraspProviderPropertyDefinitions : + public armarx::ComponentPropertyDefinitions { public: - Armar6GraspProviderPropertyDefinitions(std::string prefix): - armarx::ComponentPropertyDefinitions(prefix) - { - defineOptionalProperty<std::string>("DebugObserverName", "DebugObserver", "Name of the debug observer that should be used"); - defineOptionalProperty<std::string>("DebugDrawerTopicName", "DebugDrawerUpdates", "Name of the debug drawer topic that should be used"); - defineOptionalProperty<std::string>("StaticPlotterName", "StaticPlotter", "Name of the static plotter that should be used"); - - defineOptionalProperty<std::string>("GraspCandidatesTopicName", "GraspCandidatesTopic", "Name of the Grasp Candidate Topic"); - defineOptionalProperty<std::string>("ConfigTopicName", "GraspCandidateProviderConfigTopic", "Name of the Grasp Candidate Provider Config Topic"); - - defineOptionalProperty<std::string>("PointCloudFormat", "XYZRGBL", "Format of the input and output point cloud (XYZRGBA, XYZL, XYZRGBL)"); - defineOptionalProperty<std::string>("RobotStateComponentName", "RobotStateComponent", "Name of the robot state component that should be used"); - defineOptionalProperty<std::string>("providerName", "TabletopSegmentationResult", "name of the point cloud provider"); - defineOptionalProperty<std::string>("serviceProviderName", "TabletopSegmentation", "name of the service provider"); - defineOptionalProperty<std::string>("sourceFrameName", "root", "The source frame name"); - - defineOptionalProperty<uint32_t>("BackgroundLabelId", 1, "Label in the pointcloud for the plane or background.", PropertyDefinitionBase::eModifiable); - defineOptionalProperty<bool>("UseObjectIdMap", false, "Use ID map from config for named objects"); - - defineOptionalProperty<float>("DownsamplingLeafSize", 5.f, "If >0, the pointcloud is downsampled with a leaf size of this value. In mm.", PropertyDefinitionBase::eModifiable); - defineOptionalProperty<size_t>("MininumClusterPointCount", 100, "Minimum number of points per cluster/segmented object to be further processed.", PropertyDefinitionBase::eModifiable); - - defineOptionalProperty<float>("BoundingBoxZ1", 975.f, ""); - defineOptionalProperty<float>("BoundingBoxY1", 0.f, ""); - defineOptionalProperty<float>("BoundingBoxY2", 1300.f, ""); - - defineOptionalProperty<float>("BoundingBoxX1", -200, ""); - defineOptionalProperty<float>("BoundingBoxX2", 200, ""); - - defineOptionalProperty<bool>("enablePointCloudsVisu", true, ""); - defineOptionalProperty<bool>("enableVisu", true, ""); - defineOptionalProperty<bool>("enableCandidatesVisu", true, ""); - defineOptionalProperty<bool>("enableBoundigBoxesVisu", false, ""); - defineOptionalProperty<bool>("FlattenInZ", true, ""); - defineOptionalProperty<bool>("UseObjectPoseObserver", false, ""); - defineOptionalProperty<bool>("UseWorkingMemory", false, ""); - defineOptionalProperty<int>("WaitForPointCloudsMS", 200, ""); - - defineOptionalProperty<std::string>("RemoteGuiName", "RemoteGuiProvider", "Name of the remote gui"); - defineOptionalProperty<std::string>("PriorKnowledgeName", "PriorKnowledge", "Name of the PriorKnowledge"); - defineOptionalProperty<std::string>("WorkingMemoryName", "WorkingMemory", "Name of the WorkingMemory"); - - - defineOptionalProperty<int>("colorNonReachableGraspsR", 128, "The red color channel for non reachable grasps"); - defineOptionalProperty<int>("colorNonReachableGraspsG", 128, "The green color channel for non reachable grasps"); - defineOptionalProperty<int>("colorNonReachableGraspsB", 128, "The blue color channel color channel for non reachable grasps"); - } + Armar6GraspProviderPropertyDefinitions(std::string prefix); }; - /** * @defgroup Component-Armar6GraspProvider Armar6GraspProvider * @ingroup Armar6Skills-Components @@ -136,27 +90,13 @@ namespace armarx , virtual public ArVizComponentPluginUser { public: - /** - * @see armarx::ManagedIceObject::getDefaultName() - */ + + /// @see armarx::ManagedIceObject::getDefaultName() std::string getDefaultName() const override { return "Armar6GraspProvider"; } - struct BoundingBox - { - float x1 = -10000; - float x2 = 10000; - float y1 = -10000; - float y2 = 10000; - float z1 = -10000; - float z2 = 10000; - - bool isInside(float x, float y, float z); - }; - - struct Config { @@ -190,11 +130,8 @@ namespace armarx { return enableCandidatesVisu && IceUtil::Time::now() > disableCandidatesVisuUntil; } - }; - - struct GraspDescription { Eigen::Matrix4f pose; @@ -202,43 +139,28 @@ namespace armarx Armar6GraspProviderModule::PreshapeType preshape; }; - static std::string GraspTypeToString(Armar6GraspProviderModule::GraspType graspType); - static std::string PreshapeTypeToString(Armar6GraspProviderModule::PreshapeType preshapeType); - protected: - /** - * @see visionx::PointCloudProcessor::onInitPointCloudProcessor() - */ + + /// @see PropertyUser::createPropertyDefinitions() + armarx::PropertyDefinitionsPtr createPropertyDefinitions() override; + + /// @see visionx::PointCloudProcessor::onInitPointCloudProcessor() void onInitPointCloudProcessor() override; - /** - * @see visionx::PointCloudProcessor::onConnectPointCloudProcessor() - */ + /// @see visionx::PointCloudProcessor::onConnectPointCloudProcessor() void onConnectPointCloudProcessor() override; - /** - * @see visionx::PointCloudProcessor::onDisconnectPointCloudProcessor() - */ + /// @see visionx::PointCloudProcessor::onDisconnectPointCloudProcessor() void onDisconnectPointCloudProcessor() override; - /** - * @see visionx::PointCloudProcessor::onExitPointCloudProcessor() - */ + /// @see visionx::PointCloudProcessor::onExitPointCloudProcessor() void onExitPointCloudProcessor() override; - /** - * @see visionx::PointCloudProcessor::process() - */ + /// @see visionx::PointCloudProcessor::process() void process() override; void processPointCloud(); - /** - * @see PropertyUser::createPropertyDefinitions() - */ - armarx::PropertyDefinitionsPtr createPropertyDefinitions() override; - - // GraspCandidateProviderInterface interface public: void requestService(const std::string& providerName, Ice::Int relativeTimeoutMS, const Ice::Current&) override; @@ -251,23 +173,45 @@ namespace armarx private: + void readConfig(); std::map<std::string, Eigen::Matrix3f> readQuaternionMap(const RapidXmlReaderNode& node); std::map<int, std::string> readObjectIdMap(const RapidXmlReaderNode& node); std::map<std::string, std::string> readObjectGraspTypeMap(const RapidXmlReaderNode& node); std::map<std::string, Eigen::Vector3f> readVectorMap(const RapidXmlReaderNode& node); std::map<std::string, float> readPreshapeVisu(const RapidXmlReaderNode& node); + void calculateReferenceOrientations(); grasping::ProviderInfoPtr getProviderInfo(); - void calculateGraspCandidatesForBB(const objpose::ObjectPose& objectPose, // simox::OrientedBoxf const& bb, - std::string const& className, - std::string const& instanceName, - VirtualRobot::RobotNodeSetPtr const& rns, - VirtualRobot::RobotNodePtr const& tcp, - viz::Layer& layer, - grasping::GraspCandidateSeq& candidatesOut, - Armar6GraspProviderModule::ResultSeq& resultListOut); + + void calculateGraspCandidatesForObjectPose( + const objpose::ObjectPose& objectPose, + VirtualRobot::RobotNodeSetPtr const& rns, + VirtualRobot::RobotNodePtr const& tcp, + viz::Layer& layer, + grasping::GraspCandidateSeq& candidatesOut, + Armar6GraspProviderModule::ResultSeq& resultListOut); + + void calculateGraspCandidatesForWorkingMemoryInstance( + memoryx::ObjectInstanceWrapper const& instance, + VirtualRobot::RobotPtr const& robot, + VirtualRobot::RobotNodeSetPtr const& rns, + VirtualRobot::RobotNodePtr const& tcp, + viz::Layer& layer, + grasping::GraspCandidateSeq& candidatesOut, + Armar6GraspProviderModule::ResultSeq& resultListOut); + + void calculateGraspCandidatesForBB( + simox::OrientedBoxf const& bb, + Eigen::Matrix4f const& robotPose, + std::string const& className, + std::string const& instanceName, + VirtualRobot::RobotNodeSetPtr const& rns, + VirtualRobot::RobotNodePtr const& tcp, + viz::Layer& layer, + grasping::GraspCandidateSeq& candidatesOut, + Armar6GraspProviderModule::ResultSeq& resultListOut); private: @@ -287,7 +231,7 @@ namespace armarx std::string sourceFrameName; std::string providerName; - BoundingBox boundingBox; + simox::AxisAlignedBoundingBox boundingBox { -1e4, 1e4, -1e4, 1e4, -1e4, 1e4 }; bool flattenInZ = false; bool useObjectPoseObserver = false; bool useWorkingMemory = false; diff --git a/source/Armar6Skills/components/Armar6GraspProvider/CMakeLists.txt b/source/Armar6Skills/components/Armar6GraspProvider/CMakeLists.txt index 97c36a898941e85420e2ee5b09920bc37906b069..31fe5b94f783da1585cccfa0cec3c56c67716360 100644 --- a/source/Armar6Skills/components/Armar6GraspProvider/CMakeLists.txt +++ b/source/Armar6Skills/components/Armar6GraspProvider/CMakeLists.txt @@ -37,10 +37,14 @@ set(COMPONENT_LIBS set(SOURCES Armar6GraspProvider.cpp FitRectangle.cpp + + grasping_util.cpp ) set(HEADERS Armar6GraspProvider.h FitRectangle.h + + grasping_util.h ) armarx_add_component("${SOURCES}" "${HEADERS}") diff --git a/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.cpp b/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b4ad9f7962a310b877b8af755064f6c729c2439 --- /dev/null +++ b/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.cpp @@ -0,0 +1,86 @@ +#include "grasping_util.h" + +#include <VirtualRobot/math/Helpers.h> + +#include <ArmarXCore/core/exceptions/local/UnexpectedEnumValueException.h> + + +namespace armarx +{ + + std::string grasping::graspTypeToString(Armar6GraspProviderModule::GraspType graspType) + { + switch (graspType) + { + case Armar6GraspProviderModule::GraspType::Top: + return "Top"; + case Armar6GraspProviderModule::GraspType::Side: + return "Side"; + } + ARMARX_UNEXPECTED_ENUM_VALUE(Armar6GraspProviderModule::GraspType, graspType); + } + + + std::string grasping::preshapeTypeToString(Armar6GraspProviderModule::PreshapeType preshapeType) + { + switch (preshapeType) + { + case Armar6GraspProviderModule::PreshapeType::Open: + return "Open"; + case Armar6GraspProviderModule::PreshapeType::Preshaped: + return "Preshaped"; + } + ARMARX_UNEXPECTED_ENUM_VALUE(Armar6GraspProviderModule::PreshapeType, preshapeType); + } + + + + + void grasping::sortBoxExtendsForGraspCandidateGeneration( + Eigen::Vector3f& v1, Eigen::Vector3f& v2, Eigen::Vector3f& v3, + Eigen::Vector3f& robotExtend1, Eigen::Vector3f& robotExtend2, Eigen::Vector3f& robotExtend3) + { + // These have to be sorted in a specific way + // v3 should point in the direction of Z + // v1 should point along the longer remaining axis (after aligning v3) + Eigen::Vector3f z = Eigen::Vector3f::UnitZ(); + if (std::abs(v1.dot(z)) > 0.8f) + { + std::swap(v1, v3); + std::swap(robotExtend1, robotExtend3); + } + if (std::abs(v2.dot(z)) > 0.8f) + { + std::swap(v2, v3); + std::swap(robotExtend2, robotExtend3); + } + + if (v3.z() < 0.0f) + { + v3 = -v3; + robotExtend3 = -robotExtend3; + } + + if (robotExtend1.norm() < robotExtend2.norm()) + { + Eigen::Vector3f temp = v1; + v1 = v2; + v2 = -temp; + + temp = robotExtend1; + robotExtend1 = robotExtend2; + robotExtend2 = -temp; + } + } + + Armar6GraspProviderModule::GraspType grasping::determineGraspType(const math::Box3D & box) + { + float height = box.Size3(); + float width = box.Size1(); + return width > height ? Armar6GraspProviderModule::GraspType::Top + : Armar6GraspProviderModule::GraspType::Side; + } + + + +} diff --git a/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.h b/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.h new file mode 100644 index 0000000000000000000000000000000000000000..ac4cf8e0b2a63c9b0d7cfd79c30778789228cff8 --- /dev/null +++ b/source/Armar6Skills/components/Armar6GraspProvider/grasping_util.h @@ -0,0 +1,29 @@ +#pragma once + +#include <string> + +#include <Eigen/Core> + +#include <Armar6Skills/interface/Armar6GraspProviderInterface.h> + +#include "FitRectangle.h" + +namespace armarx::grasping +{ + + std::string graspTypeToString(Armar6GraspProviderModule::GraspType graspType); + std::string preshapeTypeToString(Armar6GraspProviderModule::PreshapeType preshapeType); + + + void sortBoxExtendsForGraspCandidateGeneration(Eigen::Vector3f& v1, + Eigen::Vector3f& v2, + Eigen::Vector3f& v3, + Eigen::Vector3f& robotExtend1, + Eigen::Vector3f& robotExtend2, + Eigen::Vector3f& robotExtend3); + + Armar6GraspProviderModule::GraspType determineGraspType(const math::Box3D & box); + + +} +