From 6519206d6baf25151c83cdfcd3bb791a939a8eda Mon Sep 17 00:00:00 2001 From: Fabian Reister <fabian.reister@kit.edu> Date: Fri, 3 Mar 2023 20:32:59 +0100 Subject: [PATCH] reach pre grasp skill + minor cleanup --- .../Component.cpp | 50 ++- .../Component.cpp | 9 +- .../geometric_planning/ArVizDrawer.cpp | 39 +-- .../geometric_planning/CMakeLists.txt | 2 + .../manipulation/geometric_planning/util.cpp | 105 ++++++ .../manipulation/geometric_planning/util.h | 33 +- .../skills/ApproachHandleDirect.cpp | 272 ---------------- .../armarx/manipulation/skills/CMakeLists.txt | 5 +- .../armarx/manipulation/skills/ReachGrasp.cpp | 301 ++++++++++++++++++ .../{ApproachHandleDirect.h => ReachGrasp.h} | 27 +- .../skills/aron/ReachGraspParams.xml | 33 ++ source/armarx/manipulation/skills/constants.h | 3 +- 12 files changed, 499 insertions(+), 380 deletions(-) create mode 100644 source/armarx/manipulation/geometric_planning/util.cpp delete mode 100644 source/armarx/manipulation/skills/ApproachHandleDirect.cpp create mode 100644 source/armarx/manipulation/skills/ReachGrasp.cpp rename source/armarx/manipulation/skills/{ApproachHandleDirect.h => ReachGrasp.h} (78%) create mode 100644 source/armarx/manipulation/skills/aron/ReachGraspParams.xml diff --git a/source/armarx/manipulation/components/articulated_object_augmented_visualization/Component.cpp b/source/armarx/manipulation/components/articulated_object_augmented_visualization/Component.cpp index 965dd127..01af8f05 100644 --- a/source/armarx/manipulation/components/articulated_object_augmented_visualization/Component.cpp +++ b/source/armarx/manipulation/components/articulated_object_augmented_visualization/Component.cpp @@ -94,11 +94,11 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali const auto descriptions = virtualRobotReaderPlugin->get().queryDescriptions(Clock::Now()); - ARMARX_INFO << "Found the following robot descriptions: "; + ARMARX_VERBOSE << "Found the following robot descriptions: "; for (const auto& description : descriptions) { - ARMARX_INFO << "Loading robot `" << description.name << "` from " - << description.xml; + ARMARX_VERBOSE << "Loading robot `" << description.name << "` from " + << description.xml; const auto robot = VirtualRobot::RobotIO::loadRobot( description.xml.toSystemPath(), VirtualRobot::RobotIO::RobotDescription::eStructure); @@ -111,7 +111,7 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali } } - ARMARX_INFO << "Visualizing paths for nodes"; + ARMARX_VERBOSE << "Visualizing paths for nodes"; Metronome metronome(Frequency::Hertz(2)); while (true) { @@ -148,11 +148,11 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali // const auto descriptions = articulatedObjectReader.queryDescriptions(armem::Time::Now()); - // ARMARX_INFO << "Found " << descriptions.size() << " articulated object descriptions"; + // ARMARX_VERBOSE << "Found " << descriptions.size() << " articulated object descriptions"; // for (const auto& description : descriptions) // { - // ARMARX_INFO << "- " << description.name; + // ARMARX_VERBOSE << "- " << description.name; // } // std::vector<VirtualRobot::RobotPtr> articulatedObjects; @@ -181,10 +181,10 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali const auto objectPoses = ObjectPoseClientPluginUser::getObjectPoses(); const auto descriptions = articulatedObjectReader.queryDescriptions(armem::Time::Now()); - ARMARX_INFO << "Found " << descriptions.size() << " articulated object descriptions"; + ARMARX_VERBOSE << "Found " << descriptions.size() << " articulated object descriptions"; for (const auto& description : descriptions) { - ARMARX_INFO << "- " << description.name; + ARMARX_VERBOSE << "- " << description.name; } std::vector<armarx::objpose::ObjectPose> articulatedObjectPoses; @@ -205,12 +205,12 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali } - ARMARX_INFO << "Found " << articulatedObjectPoses.size() + ARMARX_VERBOSE << "Found " << articulatedObjectPoses.size() << " articulated objects in the scene"; for (const auto& objectPose : articulatedObjectPoses) { - ARMARX_INFO << "- " << objectPose.objectID; + ARMARX_VERBOSE << "- " << objectPose.objectID; } const auto now = Clock::Now(); @@ -299,12 +299,11 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali auto layer = arviz.layer("grasps " + articulatedObject->getType() + "/" + articulatedObject->getName()); - for (const auto& node : articulatedObject->getRobotNodes()) + for (const auto& [node, graspSets] : geometric_planning::allGraspSets(*articulatedObject)) { - const auto graspSets = node->getAllGraspSets(); if (not graspSets.empty()) { - ARMARX_IMPORTANT << "Found grasp sets attached to node " << node->getName(); + ARMARX_VERBOSE << "Found grasp sets attached to node " << node->getName(); for (const auto& graspSet : graspSets) { for (const auto& grasp : graspSet->getGrasps()) @@ -312,7 +311,7 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali const std::string side = graspSet->getName(); ARMARX_TRACE; - ARMARX_INFO << "- " << grasp->getName(); + ARMARX_VERBOSE << "- " << grasp->getName(); drawGrasp(side, grasp, core::Pose(node->getGlobalPose()), layer); } } @@ -320,7 +319,6 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali } ARMARX_TRACE; - ARMARX_INFO << VAROUT(layer.size()); arviz.commit(layer); } } @@ -350,16 +348,14 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali ARMARX_TRACE; - struct Foo + struct Info { Eigen::Isometry3f tcp_T_hand_root; std::map<std::string, float> jointValues; - }; - // FIXME for both left and right! - const Foo foo = [&] - (){ + const Info info = [&]() + { ARMARX_TRACE; const armarx::RobotNameHelper::Arm arm = robotNameHelper->getArm(side); @@ -372,16 +368,16 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali const auto eef = robot->getEndEffector(eefName); - ARMARX_INFO << "preshape: " << grasp->getPreshapeName(); + ARMARX_VERBOSE << "preshape: " << grasp->getPreshapeName(); const auto preshape = eef->getPreshape(grasp->getPreshapeName()); - Foo foo; + Info foo; if (preshape != nullptr) { foo.jointValues = preshape->getRobotNodeJointValueMap(); - ARMARX_INFO << "preshape with joint values " << foo.jointValues; + ARMARX_VERBOSE << "preshape with joint values " << foo.jointValues; } ARMARX_TRACE; @@ -394,10 +390,6 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali }(); ARMARX_TRACE; - // FIXME this does not work. weak_ptr exception - // const auto vizElement = viz::RobotHand(grasp->getName()) - // .fileBySide("Right", robotNameHelper) - // .tcpPose(global_T_tcp, robot); std::string modelFile = "armar6_rt/robotmodel/Armar6-SH/Armar6-" + side + "Hand-v3.xml"; @@ -406,8 +398,8 @@ namespace armarx::manipulation::components::articulated_object_augmented_visuali const auto vizElement = viz::Robot(side + "/" + grasp->getName()) .file("armar6_rt", modelFile) - .pose(Eigen::Matrix4f{(global_T_tcp * foo.tcp_T_hand_root).matrix()}) - .joints(foo.jointValues) + .pose(Eigen::Matrix4f{(global_T_tcp * info.tcp_T_hand_root).matrix()}) + .joints(info.jointValues) .overrideColor(simox::Color::azure()); ARMARX_TRACE; diff --git a/source/armarx/manipulation/components/articulated_objects_skill_provider/Component.cpp b/source/armarx/manipulation/components/articulated_objects_skill_provider/Component.cpp index 37db9d32..c75696b4 100644 --- a/source/armarx/manipulation/components/articulated_objects_skill_provider/Component.cpp +++ b/source/armarx/manipulation/components/articulated_objects_skill_provider/Component.cpp @@ -42,7 +42,7 @@ #include "armarx/manipulation/skills/meta/OpenFridge.h" #include <armarx/manipulation/core/aron/Hand.aron.generated.h> #include <armarx/manipulation/skills/ApproachHandle.h> -#include <armarx/manipulation/skills/ApproachHandleDirect.h> +#include <armarx/manipulation/skills/ReachGrasp.h> #include <armarx/manipulation/skills/SetJointValues.h> #include <armarx/manipulation/skills/meta/OpenDishwasherDoor.h> @@ -114,7 +114,7 @@ namespace armarx::manipulation::components::articulated_objects_skill_provider .articulatedObjectReader = articulatedObjectReaderPlugin->get(), .arviz = arviz})); - addSkill(std::make_unique<skills::ApproachHandleDirect>(skills::ApproachHandleDirect::Context{ + addSkill(std::make_unique<skills::ReachGrasp>(skills::ReachGrasp::Context{ .robot = *robot, .articulatedObjectReader = articulatedObjectReaderPlugin->get(), .arviz = arviz})); @@ -125,6 +125,11 @@ namespace armarx::manipulation::components::articulated_objects_skill_provider addSkill(std::make_unique<skills::ReleaseHandle>( skills::ReleaseHandle::Context{.robot = *robot, .arviz = arviz})); + addSkill(std::make_unique<skills::ReachGrasp>(skills::ReachGrasp::Context{ + .robot = *robot, + .articulatedObjectReader = articulatedObjectReaderPlugin->get(), + .arviz = arviz})); + // // Public skills // diff --git a/source/armarx/manipulation/geometric_planning/ArVizDrawer.cpp b/source/armarx/manipulation/geometric_planning/ArVizDrawer.cpp index 17a5899c..0e0591bb 100644 --- a/source/armarx/manipulation/geometric_planning/ArVizDrawer.cpp +++ b/source/armarx/manipulation/geometric_planning/ArVizDrawer.cpp @@ -48,21 +48,6 @@ namespace armarx::manipulation::geometric_planning arviz.commit(l); } - // void - // ArVizDrawer::draw(const std::vector<const geometric_planning::ParametricPath*>& paths) - // { - // auto l = arviz.layer("parametric_paths"); - - // std::for_each(paths.begin(), - // paths.end(), - // [&](const auto* path) - // { - // ARMARX_CHECK_NOT_NULL(path); - // draw(l, *path); - // }); - - // arviz.commit(l); - // } std::vector<Eigen::Vector3f> to3D(const std::vector<Eigen::Vector2f>& points2d) @@ -87,16 +72,12 @@ namespace armarx::manipulation::geometric_planning const core::Pose& frame, const std::string& name) { - const Eigen::Vector3f from = frame * line.getPosition(line.parameterRange().min); const Eigen::Vector3f to = frame * line.getPosition(line.parameterRange().max); layer.add(viz::Sphere(name + "_from").scale(2).color(viz::Color::red()).position(from)); layer.add(viz::Sphere(name + "_to").scale(2).color(viz::Color::green()).position(to)); - // Eigen::Vector3f normal = - // (core::Pose(virtualDishwasher->getGlobalPose()) * p.frame).translation(); - ARMARX_DEBUG << "from " << from; ARMARX_DEBUG << "to " << to; @@ -108,10 +89,6 @@ namespace armarx::manipulation::geometric_planning .color(armarx::viz::Color::fromRGBA(0, 128, 255, 128)); layer.add(arrow); - // layer.add(viz::Sphere("line_from").position(from).radius(50).color( - // viz::Color::fromRGBA(0, 255, 0, 50))); - // layer.add(viz::Sphere("line_to").position(to).radius(50).color( - // viz::Color::fromRGBA(255, 0, 0, 50))); } @@ -136,10 +113,6 @@ namespace armarx::manipulation::geometric_planning ARMARX_DEBUG << "Parameter range is " << circleSegment.parameterRange().min << ", " << circleSegment.parameterRange().max; - // auto polygon = viz::Arrow("path" + std::to_string(++ii)) - // .fromTo(from, to) - // .color(viz::Color::fromRGBA(0, 128, 255, 128)); - const float completion = (circleSegment.parameterRange().max - circleSegment.parameterRange().min) / (2 * M_PI); @@ -149,11 +122,6 @@ namespace armarx::manipulation::geometric_planning .completion(completion) .color(armarx::viz::Color::fromRGBA(0, 128, 255, 128)); - // layer.add(viz::Sphere("circle_from").position(from).radius(50).color( - // viz::Color::fromRGBA(0, 255, 0, 50))); - // layer.add( - // viz::Sphere("circle_to").position(to).radius(50).color(viz::Color::fromRGBA(255, 0, 0, 50))); - layer.add(arrow); } @@ -178,7 +146,7 @@ namespace armarx::manipulation::geometric_planning if (circleSegment != nullptr) { - ARMARX_INFO << "Circle"; + ARMARX_VERBOSE << "Circle"; draw(layer, *circleSegment, core::Pose(path.frame->getGlobalPose()), name); return; } @@ -186,10 +154,7 @@ namespace armarx::manipulation::geometric_planning const auto* line = dynamic_cast<simox::geometric_planning::Line*>(path.path.get()); if (line != nullptr) { - ARMARX_INFO << "Line"; - - // ARMARX_DEBUG << "global root pose" << path.global_T_root.matrix(); - // ARMARX_DEBUG << "frame" << path.root_T_frame.matrix(); + ARMARX_VERBOSE << "Line"; draw(layer, *line, core::Pose(path.frame->getGlobalPose()), name); return; } diff --git a/source/armarx/manipulation/geometric_planning/CMakeLists.txt b/source/armarx/manipulation/geometric_planning/CMakeLists.txt index f83ca7be..e646be65 100644 --- a/source/armarx/manipulation/geometric_planning/CMakeLists.txt +++ b/source/armarx/manipulation/geometric_planning/CMakeLists.txt @@ -23,8 +23,10 @@ armarx_add_library(geometric_planning ArmarXGuiComponentPlugins SOURCES ArVizDrawer.cpp + util.cpp HEADERS ArVizDrawer.h + util.h ) diff --git a/source/armarx/manipulation/geometric_planning/util.cpp b/source/armarx/manipulation/geometric_planning/util.cpp new file mode 100644 index 00000000..9757a035 --- /dev/null +++ b/source/armarx/manipulation/geometric_planning/util.cpp @@ -0,0 +1,105 @@ +/** + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @author Fabian Reister ( fabian dot reister at kit dot edu ) + * @date 2023 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#include "util.h" + +#include <algorithm> +#include <optional> +#include <tuple> +#include <vector> + +#include <SimoxUtility/algorithm/string/string_tools.h> +#include <VirtualRobot/Grasping/GraspSet.h> +#include <VirtualRobot/Robot.h> + +namespace armarx::manipulation::geometric_planning +{ + + + std::vector<std::string> + nodesMatching(const std::vector<std::string>& allNodeNames, const std::string& identifier) + { + + std::vector<std::string> handleNodeNames; + std::copy_if(allNodeNames.begin(), + allNodeNames.end(), + std::back_inserter(handleNodeNames), + [&identifier](const auto& nodeName) + { + // the second check is a bit hacky: we can define transformation nodes in URDF which might match, e.g. "parent->child" + return simox::alg::ends_with(nodeName, identifier) and + not simox::alg::contains(nodeName, '>'); + }); + + return handleNodeNames; + } + + std::optional<std::tuple<VirtualRobot::RobotNodePtr, VirtualRobot::GraspPtr>> + findGraspByName(const VirtualRobot::Robot& robot, + const std::string& graspSetName, + const std::string& graspName) + { + for (const auto& [node, graspSets] : allGraspSets(robot)) + { + if (not graspSets.empty()) + { + // ARMARX_VERBOSE << "Found grasp sets attached to node " << node->getName(); + for (const auto& graspSet : graspSets) + { + // check if grasp set name matches if provided + if (not graspSetName.empty() and graspSet->getName() != graspSetName) + { + continue; + } + + for (const auto& grasp : graspSet->getGrasps()) + { + if (graspName == grasp->getName()) + { + return std::make_tuple(node, grasp); + } + } + } + } + } + + return std::nullopt; + } + + + std::map<VirtualRobot::RobotNodePtr, std::vector<VirtualRobot::GraspSetPtr>> + allGraspSets(const VirtualRobot::Robot& robot) + { + std::map<VirtualRobot::RobotNodePtr, std::vector<VirtualRobot::GraspSetPtr>> nodeGraspSets; + + for (const auto& node : robot.getRobotNodes()) + { + const auto graspSets = node->getAllGraspSets(); + for (const auto& graspSet : graspSets) + { + nodeGraspSets[node].push_back(graspSet); + } + } + + return nodeGraspSets; + } + +} // namespace armarx::manipulation::geometric_planning diff --git a/source/armarx/manipulation/geometric_planning/util.h b/source/armarx/manipulation/geometric_planning/util.h index e33a179f..a0a9ce4f 100644 --- a/source/armarx/manipulation/geometric_planning/util.h +++ b/source/armarx/manipulation/geometric_planning/util.h @@ -21,30 +21,23 @@ #pragma once -#include <algorithm> -#include <vector> -#include <SimoxUtility/algorithm/string/string_tools.h> +#include <map> + +#include <VirtualRobot/VirtualRobot.h> namespace armarx::manipulation::geometric_planning { - inline std::vector<std::string> - nodesMatching(const std::vector<std::string>& allNodeNames, const std::string& identifier) - { - - std::vector<std::string> handleNodeNames; - std::copy_if(allNodeNames.begin(), - allNodeNames.end(), - std::back_inserter(handleNodeNames), - [&identifier](const auto& nodeName) - { - // the second check is a bit hacky: we can define transformation nodes in URDF which might match, e.g. "parent->child" - return simox::alg::ends_with(nodeName, identifier) and - not simox::alg::contains(nodeName, '>'); - }); - - return handleNodeNames; - } + std::vector<std::string> nodesMatching(const std::vector<std::string>& allNodeNames, + const std::string& identifier); + + std::optional<std::tuple<VirtualRobot::RobotNodePtr, VirtualRobot::GraspPtr>> + findGraspByName(const VirtualRobot::Robot& robot, + const std::string& graspSetName, + const std::string& graspName); + + std::map<VirtualRobot::RobotNodePtr, std::vector<VirtualRobot::GraspSetPtr>> + allGraspSets(const VirtualRobot::Robot& robot); } // namespace armarx::manipulation::geometric_planning diff --git a/source/armarx/manipulation/skills/ApproachHandleDirect.cpp b/source/armarx/manipulation/skills/ApproachHandleDirect.cpp deleted file mode 100644 index 37b05363..00000000 --- a/source/armarx/manipulation/skills/ApproachHandleDirect.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "ApproachHandleDirect.h" - -#include <memory> - -#include <Eigen/Core> -#include <Eigen/Geometry> - -#include <IceUtil/Time.h> -#include <SimoxUtility/color/Color.h> - -#include <ArmarXCore/observers/variant/DatafieldRef.h> -#include <ArmarXCore/util/CPPUtility/trace.h> - -#include "RobotAPI/components/ArViz/Client/Client.h" -#include "RobotAPI/libraries/ArmarXObjects/aron_conversions/armarx.h" -#include "RobotAPI/libraries/RobotStatechartHelpers/VelocityControllerHelper.h" -#include "RobotAPI/libraries/armem_objects/types.h" -#include "RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h" -#include <RobotAPI/components/ArViz/Client/Elements.h> -#include <RobotAPI/libraries/core/CartesianVelocityController.h> -#include <RobotAPI/libraries/core/CartesianWaypointController.h> -#include <RobotAPI/libraries/core/FramedPose.h> - -#include "armarx/manipulation/core/arm.h" -#include "armarx/manipulation/skills/constants.h" -#include <armarx/manipulation/core/aron_conversions.h> -#include <armarx/manipulation/core/types.h> - -namespace armarx::manipulation::skills -{ - ApproachHandleDirect::ApproachHandleDirect(const ApproachHandleDirect::Context& ctx) : - Base(DefaultSkillDescription(), armarx::Frequency(armarx::Duration::MilliSeconds(20))), - ctx(ctx) - { - } - - ApproachHandleDirect::~ApproachHandleDirect() = default; - - - armarx::skills::PeriodicSkill::StepResult - ApproachHandleDirect::step(const SpecializedMainInput& in) - { - ARMARX_CHECK(ctx.robot.synchronize(Clock::Now())); - - const Eigen::Vector3f robot_V_tcp_handle = approachDirection(in.params); - - Eigen::Vector6f velocity; - velocity << robot_V_tcp_handle.x(), robot_V_tcp_handle.y(), robot_V_tcp_handle.z(), 0, 0, 0; - - velocityController->setTargetVelocity(in.params.approachVelocity * velocity); - - draw(in.params); - - if (finished(in.params)) - { - return {.status = armarx::skills::ActiveOrTerminatedSkillStatus::Succeeded, .data = {}}; - } - - return {.status = armarx::skills::ActiveOrTerminatedSkillStatus::Running, .data = {}}; - } - - armarx::skills::Skill::ExitResult - ApproachHandleDirect::exit(const SpecializedExitInput& in) - { - stop(); - return {.status = armarx::skills::TerminatedSkillStatus::Succeeded}; - } - - armarx::skills::Skill::InitResult - ApproachHandleDirect::init(const SpecializedInitInput& in) - { - ARMARX_INFO << "ApproachHandleDirect::initialize"; - - ARMARX_CHECK(ctx.robot.synchronize(Clock::Now())); - - core::Hand hand{}; - fromAron(in.params.hand, hand); - - const core::Arm arm = core::getArm(hand); - - ARMARX_INFO << "Approaching handle with " << core::HandNames.to_name(hand) << " hand."; - ARMARX_INFO << "Arm is " << core::ArmNames.to_name(arm); - - const auto armRns = ctx.robot.arm(arm); - - ARMARX_INFO << "Arm RNS " << armRns->getName(); - - const std::string controllerName = "ApproachHandleDirectController" + armRns->getName(); - - velocityController = std::make_shared<armarx::VelocityControllerHelper>( - ctx.robot.robotUnit(), armRns->getName(), controllerName); - - - ARMARX_INFO << "Querying descriptions"; - const auto descriptions = ctx.articulatedObjectReader.queryDescriptions(Clock::Now()); - - ARMARX_INFO << "Available descriptions are:"; - for (const auto& description : descriptions) - { - ARMARX_INFO << description; - } - - ObjectID objectID; - fromAron(in.params.object, objectID); - - const std::string dishwasherName = objectID.dataset() + "/" + objectID.className(); - ARMARX_INFO << "Searching for object name `" << dishwasherName << "`"; - - const auto isMatchingDescription = [&objectID](const auto& description) -> bool - { return objectID.equalClass(ObjectID(description.name)); }; - - const auto descriptionIt = - std::find_if(descriptions.begin(), descriptions.end(), isMatchingDescription); - ARMARX_CHECK(descriptionIt != descriptions.end()) - << "Description " << objectID << " not available"; - - ARMARX_INFO << "getting object"; - std::optional<armarx::armem::articulated_object::ArticulatedObject> dishwasherOpt = - ctx.articulatedObjectReader.get(*descriptionIt, Clock::Now(), "0"); - ARMARX_CHECK(dishwasherOpt); - - armarx::armem::articulated_object::ArticulatedObject dishwasher = *dishwasherOpt; - dishwasher.instance = "0"; // first available dishwasher FIXME objectID available - - - const std::string xmlFilename = dishwasher.description.xml.toSystemPath(); - ARMARX_INFO << "Loading (virtual) robot '" << dishwasher.description.name - << "' from XML file '" << xmlFilename << "'"; - - object = VirtualRobot::RobotIO::loadRobot(xmlFilename); - ARMARX_CHECK_NOT_NULL(object); - - - simox::geometric_planning::ArticulatedObjectDoorHelper::Params doorHelperParams; - simox::geometric_planning::ArticulatedObjectDoorHelper doorHelper(object, doorHelperParams); - - interactionInfo = doorHelper.planInteractionExtended( - in.params.objectNodeSet, Pose(armRns->getTCP()->getGlobalPose())); - - draw(in.params); - - return {.status = armarx::skills::TerminatedSkillStatus::Succeeded}; - } - - void - ApproachHandleDirect::draw(const ApproachHandleDirect::ParamsT& params) - { - core::Hand hand{}; - fromAron(params.hand, hand); - - const core::Pose global_T_tcp_at_handle = - core::Pose(interactionInfo.rns.handleSurfaceProjection->getGlobalPose()) * - core::Pose(interactionInfo.handleSurfaceProjection_T_tcp_at_handle); - - const Eigen::Vector3f global_P_tcp_at_handle = global_T_tcp_at_handle.translation(); - const Eigen::Vector3f global_P_tcp = - ctx.robot.arm(core::getArm(hand))->getTCP()->getGlobalPosition(); - - auto layer = ctx.arviz.layer("skills.approach_handle"); - - layer.add(armarx::viz::Sphere("tcp") - .position(global_P_tcp) - .radius(parameters.sphereVisuRadius) - .color(simox::Color::red(parameters.visuAlpha))); - - layer.add(armarx::viz::Sphere("tcp_at_handle") - .position(global_P_tcp_at_handle) - .radius(parameters.sphereVisuRadius) - .color(simox::Color::green(parameters.visuAlpha))); - - layer.add(armarx::viz::Arrow("movement_direction") - .fromTo(global_P_tcp, global_P_tcp + approachVector(params)) - .width(parameters.arrowVisuWidth)); - - ctx.arviz.commit(layer); - } - - Eigen::Vector3f - ApproachHandleDirect::approachVector(const ApproachHandleDirect::ParamsT& params) - { - core::Hand hand{}; - fromAron(params.hand, hand); - - const Pose global_T_tcp_at_handle = - Pose(interactionInfo.rns.handleSurfaceProjection->getGlobalPose()) * - Pose(interactionInfo.handleSurfaceProjection_T_tcp_at_handle); - - // TODO apply offset in tcp_at_handle frame ... => y direction... - const Eigen::Vector3f global_P_tcp_at_handle = - global_T_tcp_at_handle.translation() + Eigen::Vector3f::UnitZ() * 100; - - const Eigen::Vector3f global_P_tcp = - ctx.robot.arm(getArm(hand))->getTCP()->getGlobalPosition(); - const Eigen::Vector3f global_V_tcp_handle = (global_P_tcp_at_handle - global_P_tcp); - - // -> tcp frame - armarx::FramedDirection framedDirection( - global_V_tcp_handle, armarx::GlobalFrame, ctx.robot.name()); - - Eigen::Vector3f robot_V_tcp_handle = - framedDirection.toRootFrame(ctx.robot.robot())->toEigen(); - - return robot_V_tcp_handle; - } - - Eigen::Vector3f - ApproachHandleDirect::approachDirection(const ApproachHandleDirect::ParamsT& params) - { - return approachVector(params).normalized(); - } - - bool - ApproachHandleDirect::stop() - { - ARMARX_INFO << "ApproachHandleDirect::initialize"; - - velocityController->cleanup(); - - return true; - } - - bool - ApproachHandleDirect::finished(const ApproachHandleDirect::ParamsT& params) - { - // Force limit - - core::Hand hand{}; - fromAron(params.hand, hand); - - const auto ft = ctx.robot.getForceTorqueInHand(hand); - ARMARX_CHECK(ft.has_value()) - << "No force/torque data available for hand " << core::HandNames.to_name(hand); - - const armarx::FramedDirection framedForce = ft->force; - - const Eigen::Vector3f global_V_force = framedForce.toGlobalEigen(ctx.robot.robot()); - const Eigen::Vector3f global_V_approach_dir = approachDirection(params); - - // define a frame where x is pointing into the movement direction - const Eigen::Matrix3f global_R_approach = - Eigen::Quaternionf::FromTwoVectors(Eigen::Vector3f::UnitX(), global_V_approach_dir) - .toRotationMatrix(); - - // Now the contact can be evaluated along the x-axis. Other forces should be minimal. - const Eigen::Vector3f approach_V_force = global_R_approach.inverse() * global_V_force; - - const float force = std::abs(approach_V_force.x()); // x - const float forcePerturbation = approach_V_force.tail<2>().norm(); // y and z - - ARMARX_DEBUG << VAROUT(force); - ARMARX_DEBUG << VAROUT(forcePerturbation); - - const bool forceLimitReached = force > params.contactForceThreshold; - - // TODO(fabian.reister): Evaluate position -> success / failure - const bool positionLimitReached = - approachVector(params).norm() < params.positionLimit; - - return forceLimitReached and positionLimitReached; - } - - - armarx::skills::SkillDescription - ApproachHandleDirect::DefaultSkillDescription() - { - return {constants::ApproachHandleDirect, - "", - {}, - armarx::core::time::Duration::MilliSeconds(999999), // ?? - ParamType::ToAronType()}; - } -} // namespace armarx::manipulation::skills diff --git a/source/armarx/manipulation/skills/CMakeLists.txt b/source/armarx/manipulation/skills/CMakeLists.txt index 6718f929..9d3e992f 100644 --- a/source/armarx/manipulation/skills/CMakeLists.txt +++ b/source/armarx/manipulation/skills/CMakeLists.txt @@ -2,6 +2,7 @@ armarx_add_aron_library(skills_aron ARON_FILES aron/Open.xml aron/GraspHandleParams.xml + aron/ReachGraspParams.xml aron/ParametricPathExecutorParams.xml aron/SetJointValuesParams.xml aron/ReleaseHandleParams.xml @@ -37,7 +38,7 @@ armarx_add_library(skills SOURCES GraspHandle.cpp ApproachHandle.cpp - ApproachHandleDirect.cpp + ReachGrasp.cpp ParametricPathExecutor.cpp EstablishDoorContact.cpp ShapeHand.cpp @@ -50,7 +51,7 @@ armarx_add_library(skills HEADERS ParametricPathExecutor.h ApproachHandle.h - ApproachHandleDirect.h + ReachGrasp.h EstablishDoorContact.h ShapeHand.h GraspHandle.h diff --git a/source/armarx/manipulation/skills/ReachGrasp.cpp b/source/armarx/manipulation/skills/ReachGrasp.cpp new file mode 100644 index 00000000..d8e1cada --- /dev/null +++ b/source/armarx/manipulation/skills/ReachGrasp.cpp @@ -0,0 +1,301 @@ +#include "ReachGrasp.h" + +#include <memory> + +#include <Eigen/Core> +#include <Eigen/Geometry> + +#include <IceUtil/Time.h> + +#include <SimoxUtility/color/Color.h> +#include <VirtualRobot/Grasping/Grasp.h> + +#include <ArmarXCore/observers/variant/DatafieldRef.h> +#include <ArmarXCore/util/CPPUtility/trace.h> + +#include "RobotAPI/components/ArViz/Client/Client.h" +#include "RobotAPI/libraries/ArmarXObjects/aron_conversions/armarx.h" +#include "RobotAPI/libraries/RobotStatechartHelpers/VelocityControllerHelper.h" +#include "RobotAPI/libraries/armem_objects/types.h" +#include "RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h" +#include <RobotAPI/components/ArViz/Client/Elements.h> +#include <RobotAPI/libraries/core/CartesianVelocityController.h> +#include <RobotAPI/libraries/core/CartesianWaypointController.h> +#include <RobotAPI/libraries/core/FramedPose.h> + +#include "armarx/manipulation/core/arm.h" +#include "armarx/manipulation/geometric_planning/util.h" +#include "armarx/manipulation/skills/constants.h" +#include <armarx/manipulation/core/aron_conversions.h> +#include <armarx/manipulation/core/types.h> + +namespace armarx::manipulation::skills +{ + ReachGrasp::ReachGrasp(const ReachGrasp::Context& ctx) : + Base(DefaultSkillDescription(), armarx::Frequency(armarx::Duration::MilliSeconds(20))), + ctx(ctx) + { + } + + ReachGrasp::~ReachGrasp() = default; + + + armarx::skills::PeriodicSkill::StepResult + ReachGrasp::step(const SpecializedMainInput& in) + { + ARMARX_CHECK(ctx.robot.synchronize(Clock::Now())); + + // const Eigen::Vector3f robot_V_tcp_handle = approachDirection(in.params); + + // Eigen::Vector6f velocity; + // velocity << robot_V_tcp_handle.x(), robot_V_tcp_handle.y(), robot_V_tcp_handle.z(), 0, 0, 0; + + // FIXME update target + // velocityController->setTargetVelocity(in.params.approachVelocity * velocity); + + draw(in.params); + + if (finished(in.params)) + { + return {.status = armarx::skills::ActiveOrTerminatedSkillStatus::Succeeded, .data = {}}; + } + + return {.status = armarx::skills::ActiveOrTerminatedSkillStatus::Running, .data = {}}; + } + + armarx::skills::Skill::ExitResult + ReachGrasp::exit(const SpecializedExitInput& in) + { + stop(); + return {.status = armarx::skills::TerminatedSkillStatus::Succeeded}; + } + + armarx::skills::Skill::InitResult + ReachGrasp::init(const SpecializedInitInput& in) + { + ARMARX_INFO << "ReachGrasp::initialize"; + + ARMARX_CHECK(ctx.robot.synchronize(Clock::Now())); + + core::Hand hand{}; + fromAron(in.params.hand, hand); + + const core::Arm arm = core::getArm(hand); + + ARMARX_INFO << "Approaching handle with " << core::HandNames.to_name(hand) << " hand."; + ARMARX_INFO << "Arm is " << core::ArmNames.to_name(arm); + + const auto armRns = ctx.robot.arm(arm); + + ARMARX_INFO << "Arm RNS " << armRns->getName(); + + const std::string controllerName = "ReachGraspController" + armRns->getName(); + + // velocityController = std::make_shared<armarx::VelocityControllerHelper>( + // ctx.robot.robotUnit(), armRns->getName(), controllerName); + + + ARMARX_INFO << "Querying descriptions"; + const auto descriptions = ctx.articulatedObjectReader.queryDescriptions(Clock::Now()); + + ARMARX_INFO << "Available descriptions are:"; + for (const auto& description : descriptions) + { + ARMARX_INFO << description; + } + + ObjectID objectID; + fromAron(in.params.object, objectID); + + const std::string objectName = objectID.dataset() + "/" + objectID.className(); + ARMARX_INFO << "Searching for object with name `" << objectName << "`"; + + const auto isMatchingDescription = [&objectID](const auto& description) -> bool + { return objectID.equalClass(ObjectID(description.name)); }; + + const auto descriptionIt = + std::find_if(descriptions.begin(), descriptions.end(), isMatchingDescription); + ARMARX_CHECK(descriptionIt != descriptions.end()) + << "Description " << objectID << " not available"; + + ARMARX_INFO << "getting object"; + std::optional<armarx::armem::articulated_object::ArticulatedObject> objectOpt = + ctx.articulatedObjectReader.get(*descriptionIt, Clock::Now(), objectID.instanceName()); + ARMARX_CHECK(objectOpt); + + armarx::armem::articulated_object::ArticulatedObject articulatedObject = *objectOpt; + articulatedObject.instance = + objectID.instanceName(); // first available dishwasher FIXME objectID available + + + const std::string xmlFilename = articulatedObject.description.xml.toSystemPath(); + ARMARX_INFO << "Loading (virtual) robot '" << articulatedObject.description.name + << "' from XML file '" << xmlFilename << "'"; + + object = VirtualRobot::RobotIO::loadRobot(xmlFilename); + ARMARX_CHECK_NOT_NULL(object); + + // TODO do this continuously + object->setJointValues(articulatedObject.config.jointMap); + object->setGlobalPose(articulatedObject.config.globalPose.matrix()); + object->setName(objectID.str()); // this is optional, name not used directly + object->applyJointValues(); + + const std::optional<std::tuple<VirtualRobot::RobotNodePtr, VirtualRobot::GraspPtr>> + graspInfo = geometric_planning::findGraspByName(*object, in.params.graspSetName, in.params.graspName); + ARMARX_CHECK(graspInfo.has_value()) << in.params.graspName << " not found"; + std::tie(graspNode, grasp) = graspInfo.value(); + + // simox::geometric_planning::ArticulatedObjectDoorHelper::Params doorHelperParams; + // simox::geometric_planning::ArticulatedObjectDoorHelper doorHelper(object, doorHelperParams); + + // interactionInfo = doorHelper.planInteractionExtended( + // in.params.objectNodeSet, Pose(armRns->getTCP()->getGlobalPose())); + + draw(in.params); + + return {.status = armarx::skills::TerminatedSkillStatus::Succeeded}; + } + + void + ReachGrasp::draw(const ReachGrasp::ParamsT& params) + { + core::Hand hand{}; + fromAron(params.hand, hand); + + auto layer = ctx.arviz.layer("skills.reach_grasp"); + + { + ARMARX_CHECK_NOT_NULL(grasp); + + ARMARX_TRACE; + const auto& robot = ctx.robot.robot(); + + const auto global_T_tcp = grasp->getTcpPoseGlobal(graspNode->getGlobalPose()); + + + + ARMARX_TRACE; + + struct Info + { + Eigen::Isometry3f tcp_T_hand_root; + std::map<std::string, float> jointValues; + }; + + const Info info = [&]() + { + ARMARX_TRACE; + const armarx::RobotNameHelper::Arm& arm = ctx.robot.armHelper(core::getArm(hand)); + + ARMARX_TRACE; + const armarx::RobotNameHelper::RobotArm& robotArm = ctx.robot.robotArmHelper(core::getArm(hand)); + + const auto eefName = arm.getEndEffector(); + const auto eef = robot->getEndEffector(eefName); + + ARMARX_VERBOSE << "preshape: " << grasp->getPreshapeName(); + const auto preshape = eef->getPreshape(grasp->getPreshapeName()); + + Info info; + + if (preshape != nullptr) + { + info.jointValues = preshape->getRobotNodeJointValueMap(); + ARMARX_VERBOSE << "preshape with joint values " << info.jointValues; + } + + ARMARX_TRACE; + const Eigen::Isometry3f tcp_T_hand_root( + robotArm.getTCP()->getPoseInRootFrame().inverse() * + robot->getRobotNode(arm.getHandRootNode())->getPoseInRootFrame()); + info.tcp_T_hand_root = tcp_T_hand_root; + + return info; + }(); + + ARMARX_TRACE; + + const armarx::RobotNameHelper::Arm& arm = ctx.robot.armHelper(core::getArm(hand)); + const std::string armName = core::getArmName(hand); + + ARMARX_TRACE; + const auto vizElement = + viz::Robot(armName + "/" + grasp->getName()) + .file(arm.getHandModelPackage(), arm.getHandModelPath()) + .pose(Eigen::Matrix4f{(global_T_tcp * info.tcp_T_hand_root).matrix()}) + .joints(info.jointValues) + .overrideColor(simox::Color::cyan()); + + ARMARX_TRACE; + layer.add(vizElement); + } + + ctx.arviz.commit(layer); + } + + + bool + ReachGrasp::stop() + { + ARMARX_INFO << "ReachGrasp::initialize"; + + // velocityController->cleanup(); + + return true; + } + + bool + ReachGrasp::finished(const ReachGrasp::ParamsT& params) + { + // Force limit + + // core::Hand hand{}; + // fromAron(params.hand, hand); + + // const auto ft = ctx.robot.getForceTorqueInHand(hand); + // ARMARX_CHECK(ft.has_value()) + // << "No force/torque data available for hand " << core::HandNames.to_name(hand); + + // const armarx::FramedDirection framedForce = ft->force; + + // const Eigen::Vector3f global_V_force = framedForce.toGlobalEigen(ctx.robot.robot()); + // const Eigen::Vector3f global_V_approach_dir = approachDirection(params); + + // // define a frame where x is pointing into the movement direction + // const Eigen::Matrix3f global_R_approach = + // Eigen::Quaternionf::FromTwoVectors(Eigen::Vector3f::UnitX(), global_V_approach_dir) + // .toRotationMatrix(); + + // // Now the contact can be evaluated along the x-axis. Other forces should be minimal. + // const Eigen::Vector3f approach_V_force = global_R_approach.inverse() * global_V_force; + + // const float force = std::abs(approach_V_force.x()); // x + // const float forcePerturbation = approach_V_force.tail<2>().norm(); // y and z + + // ARMARX_DEBUG << VAROUT(force); + // ARMARX_DEBUG << VAROUT(forcePerturbation); + + // const bool forceLimitReached = force > params.contactForceThreshold; + + // // TODO(fabian.reister): Evaluate position -> success / failure + // const bool positionLimitReached = + // approachVector(params).norm() < params.positionLimit; + + // return forceLimitReached and positionLimitReached; + + // FIXME implement pos limit + return false; + } + + + armarx::skills::SkillDescription + ReachGrasp::DefaultSkillDescription() + { + return {constants::ReachGrasp, + "", + {}, + armarx::core::time::Duration::MilliSeconds(999999), // ?? + ParamType::ToAronType()}; + } +} // namespace armarx::manipulation::skills diff --git a/source/armarx/manipulation/skills/ApproachHandleDirect.h b/source/armarx/manipulation/skills/ReachGrasp.h similarity index 78% rename from source/armarx/manipulation/skills/ApproachHandleDirect.h rename to source/armarx/manipulation/skills/ReachGrasp.h index ccd17567..b652e6fe 100644 --- a/source/armarx/manipulation/skills/ApproachHandleDirect.h +++ b/source/armarx/manipulation/skills/ReachGrasp.h @@ -28,7 +28,7 @@ #include <GeometricPlanning/ArticulatedObjectDoorHelper.h> #include <armarx/manipulation/core/Robot.h> -#include <armarx/manipulation/skills/aron/ApproachHandleParams.aron.generated.h> +#include <armarx/manipulation/skills/aron/ReachGraspParams.aron.generated.h> namespace armarx { @@ -44,12 +44,12 @@ namespace armarx::viz namespace armarx::manipulation::skills { - class ApproachHandleDirect : - virtual public armarx::skills::PeriodicSpecializedSkill<arondto::ApproachHandleParams> + class ReachGrasp : + virtual public armarx::skills::PeriodicSpecializedSkill<arondto::ReachGraspParams> { public: - using ParamsT = arondto::ApproachHandleParams; - using Base = armarx::skills::PeriodicSpecializedSkill<arondto::ApproachHandleParams>; + using ParamsT = arondto::ReachGraspParams; + using Base = armarx::skills::PeriodicSpecializedSkill<ParamsT>; struct Context { @@ -73,9 +73,9 @@ namespace armarx::manipulation::skills int visuAlpha = 128.F; }; - ApproachHandleDirect(const Context& ctx); + ReachGrasp(const Context& ctx); - ~ApproachHandleDirect() override; + ~ReachGrasp() override; private: @@ -95,21 +95,14 @@ namespace armarx::manipulation::skills bool finished(const ParamsT& params); - Eigen::Vector3f approachDirection(const ParamsT& params); - - Eigen::Vector3f approachVector(const ParamsT& params); - private: Context ctx; Parameters parameters; - // FIXME use impedance controller instead - armarx::VelocityControllerHelperPtr velocityController; - - simox::geometric_planning::ArticulatedObjectDoorHelper::DoorInteractionContextExtended - interactionInfo; - VirtualRobot::RobotPtr object; + + VirtualRobot::GraspPtr grasp; + VirtualRobot::RobotNodePtr graspNode; }; } // namespace armarx::manipulation::skills diff --git a/source/armarx/manipulation/skills/aron/ReachGraspParams.xml b/source/armarx/manipulation/skills/aron/ReachGraspParams.xml new file mode 100644 index 00000000..79a0de5a --- /dev/null +++ b/source/armarx/manipulation/skills/aron/ReachGraspParams.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<AronTypeDefinition> + <AronIncludes> + <PackagePath package="RobotAPI" path="libraries/ArmarXObjects/aron/ObjectID.xml" /> + <Include include="armarx/manipulation/core/aron/Hand.xml" /> + </AronIncludes> + + <GenerateTypes> + <Object name='armarx::manipulation::skills::arondto::ReachGraspParams'> + + <!-- <ObjectChild key='objectEntityId'> + <string /> + </ObjectChild> --> + + <ObjectChild key='hand'> + <armarx::manipulation::core::arondto::Hand /> + </ObjectChild> + + <ObjectChild key='object'> + <armarx::arondto::ObjectID /> + </ObjectChild> + + <ObjectChild key='graspSetName'> + <string /> + </ObjectChild> + + <ObjectChild key='graspName'> + <string /> + </ObjectChild> + + </Object> + </GenerateTypes> +</AronTypeDefinition> diff --git a/source/armarx/manipulation/skills/constants.h b/source/armarx/manipulation/skills/constants.h index ff09edb1..09756ca2 100644 --- a/source/armarx/manipulation/skills/constants.h +++ b/source/armarx/manipulation/skills/constants.h @@ -31,7 +31,8 @@ namespace armarx::manipulation::skills::constants inline const std::string OpenFridge = "OpenFridge"; inline const std::string ApproachHandle = "ApproachHandle"; - inline const std::string ApproachHandleDirect = "ApproachHandleDirect"; + // inline const std::string ApproachHandleDirect = "ApproachHandleDirect"; + inline const std::string ReachGrasp = "ReachGrasp"; inline const std::string EstablishDoorContact = "EstablishDoorContact"; inline const std::string GraspHandle = "GraspHandle"; inline const std::string MoveTCP = "MoveTCP"; -- GitLab