Skip to content

Grasp pose orientation issue - Moveit Task Constructor #743

Description

@RyanTrudeau

Hello. I am following along with the pick place demo: https://moveit.picknik.ai/main/doc/tutorials/pick_and_place_with_moveit_task_constructor/pick_and_place_with_moveit_task_constructor.html only i am using my custom robot. I plan to make my robot execute similar steps to that of the panda robot in the mtc pick place demo. Though I am having issues with the ik planning.

In my mtc script, i have the stages from the current robot position, to the gripper closing onto the object. Here I am using a flat object (which would represent a piece of paper in real life). What i get errors, is from the grasp pose ik stage. When i see the failed solutions in the stage in rviz, my end effector group, which is the gripper aligns with the object, but is 180 rotated in the z axis from this image:

Image

So obviously, the ik will fail since that orientation of the gripper is impossible. I have been experimenting with the approach and grasps stage in the script but it doesnt fix the orientation issue of the gripper. What can i fix within the script? Do i have to adjust my urdf?

Here is the mtc script i am using:
#include <rclcpp/rclcpp.hpp>
#include <moveit/planning_scene/planning_scene.hpp>
#include <moveit/planning_scene_interface/planning_scene_interface.hpp>
#include <moveit/task_constructor/task.h>
#include <moveit/task_constructor/solvers.h>
#include <moveit/task_constructor/stages.h>
#if __has_include(<tf2_geometry_msgs/tf2_geometry_msgs.hpp>)
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
#else
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#endif
#if __has_include(<tf2_eigen/tf2_eigen.hpp>)
#include <tf2_eigen/tf2_eigen.hpp>
#else
#include <tf2_eigen/tf2_eigen.h>
#endif

static const rclcpp::Logger LOGGER = rclcpp::get_logger("folding_demo");
namespace mtc = moveit::task_constructor;

class MTCTaskNode
{
public:
MTCTaskNode(const rclcpp::NodeOptions& options);

rclcpp::node_interfaces::NodeBaseInterface::SharedPtr getNodeBaseInterface();

void doTask();

void setupPlanningScene();

private:
// Compose an MTC task from a series of stages.
mtc::Task createTask();
mtc::Task task_;
rclcpp::Node::SharedPtr node_;
};

MTCTaskNode::MTCTaskNode(const rclcpp::NodeOptions& options)
: node_{ std::make_sharedrclcpp::Node("folding_node", options) }
{
}

rclcpp::node_interfaces::NodeBaseInterface::SharedPtr MTCTaskNode::getNodeBaseInterface()
{
return node_->get_node_base_interface();
}

void MTCTaskNode::setupPlanningScene()
{
moveit_msgs::msg::CollisionObject object;
object.id = "object";
object.header.frame_id = "world";
object.primitives.resize(1);
object.primitives[0].type = shape_msgs::msg::SolidPrimitive::BOX;
object.primitives[0].dimensions = { 0.095, 0.095, 0.0001 };

geometry_msgs::msg::Pose pose;
pose.position.x = -0.2;
pose.position.y = 0.05;
pose.position.z = 0.2;
pose.orientation.w = 1.0;
object.pose = pose;

moveit::planning_interface::PlanningSceneInterface psi;
psi.applyCollisionObject(object);
}

void MTCTaskNode::doTask()
{
task_ = createTask();

try
{
task_.init();
}
catch (mtc::InitStageException& e)
{
RCLCPP_ERROR_STREAM(LOGGER, e);
return;
}

if (!task_.plan(5))
{
RCLCPP_ERROR_STREAM(LOGGER, "Task planning failed");
return;
}
task_.introspection().publishSolution(*task_.solutions().front());

auto result = task_.execute(*task_.solutions().front());
if (result.val != moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
{
RCLCPP_ERROR_STREAM(LOGGER, "Task execution failed");
return;
}

return;
}

mtc::Task MTCTaskNode::createTask()
{
mtc::Task task;
task.stages()->setName("demo task");
task.loadRobotModel(node_);

const auto& arm_group_name = "arm";
const auto& hand_group_name = "gripper";
const auto& hand_frame = "link6";

// Set task properties
task.setProperty("group", arm_group_name);
task.setProperty("eef", hand_group_name);
task.setProperty("ik_frame", hand_frame);

// Disable warnings for this line, as it's a variable that's set but not used in this example
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
mtc::Stage* current_state_ptr = nullptr; // Forward current_state on to grasp pose generator
#pragma GCC diagnostic pop

auto stage_state_current = std::make_uniquemtc::stages::CurrentState("current"); // Current or home frame
current_state_ptr = stage_state_current.get(); // Use a pointer to lend to IK
task.add(std::move(stage_state_current));

auto sampling_planner = std::make_sharedmtc::solvers::PipelinePlanner(node_); // most complex for curves
auto interpolation_planner = std::make_sharedmtc::solvers::JointInterpolationPlanner(); // Use for gripper

auto cartesian_planner = std::make_sharedmtc::solvers::CartesianPath(); // Moves in a straight line
cartesian_planner->setMaxVelocityScalingFactor(1.0);
cartesian_planner->setMaxAccelerationScalingFactor(1.0);
cartesian_planner->setStepSize(.01);

auto stage_open_hand =
std::make_uniquemtc::stages::MoveTo("open hand", interpolation_planner);
stage_open_hand->setGroup(hand_group_name);
stage_open_hand->setGoal("open"); // Make sure there is open position pose in gripper already predefined
task.add(std::move(stage_open_hand));

// will have to integrate object track here at some point
auto stage_pick_paper = std::make_uniquemtc::stages::Connect(
"pick_paper", mtc::stages::Connect::GroupPlannerVector{{arm_group_name, sampling_planner}});
stage_pick_paper->setTimeout(5.0);
stage_pick_paper->properties().configureInitFrom(mtc::Stage::PARENT);
task.add(std::move(stage_pick_paper));

mtc::Stage* attach_object_stage = nullptr; // creates pointer towards stage object

{
auto grasp = std::make_uniquemtc::SerialContainer("pick paper");
task.properties().exposeTo(grasp->properties(), { "eef", "group", "ik_frame" });
grasp->properties().configureInitFrom(mtc::Stage::PARENT,
{ "eef", "group", "ik_frame" });
{
// Approach pose
auto stage = std::make_uniquemtc::stages::MoveRelative("approach paper", cartesian_planner);
stage->properties().set("marker_ns", "approach_object");
stage->properties().set("link", hand_frame);
stage->properties().configureInitFrom(mtc::Stage::PARENT, { "group" });
stage->setMinMaxDistance(0.1, 0.15);

  // Set hand forward direction
  geometry_msgs::msg::Vector3Stamped vec;
  vec.header.frame_id = hand_frame;
  vec.vector.z = 1.0;
  stage->setDirection(vec);
  grasp->insert(std::move(stage));
}

{
  // Sample grasp pose
  auto stage = std::make_unique<mtc::stages::GenerateGraspPose>("generate grasp pose");
  stage->properties().configureInitFrom(mtc::Stage::PARENT);
  stage->properties().set("marker_ns", "grasp_pose");
  stage->setPreGraspPose("open");
  stage->setObject("object");
  stage->setAngleDelta(M_PI/12);
  stage->setMonitoredStage(current_state_ptr);  // Hook into current state

  Eigen::Isometry3d grasp_frame_transform;
  Eigen::Quaterniond q = Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d::UnitX()) *
                 Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d::UnitY()) *
                 Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d::UnitZ());
  grasp_frame_transform.linear() = q.matrix();
  grasp_frame_transform.translation().z() = 0.1;


  //Eigen::Isometry3d grasp_frame_transform = Eigen::Isometry3d::Identity();
  //grasp_frame_transform.translation().z() = 0.1;


  // Compute IK
  auto wrapper =
    std::make_unique<mtc::stages::ComputeIK>("grasp pose IK", std::move(stage));
  wrapper->setMaxIKSolutions(8);
  wrapper->setMinSolutionDistance(1.0);
  wrapper->setIKFrame(grasp_frame_transform, hand_frame);
  wrapper->properties().configureInitFrom(mtc::Stage::PARENT, { "eef", "group" });
  wrapper->properties().configureInitFrom(mtc::Stage::INTERFACE, { "target_pose" });
  grasp->insert(std::move(wrapper));

}

{
  // Enable collision on the object
  auto stage =
  std::make_unique<mtc::stages::ModifyPlanningScene>("allow collision (hand,object)");
  stage->allowCollisions("object",
                    task.getRobotModel()
                        ->getJointModelGroup(hand_group_name)
                        ->getLinkModelNamesWithCollisionGeometry(),
                    true);
  grasp->insert(std::move(stage));
}

{ 
  // Closes hand on object
  auto stage = std::make_unique<mtc::stages::MoveTo>("close hand", interpolation_planner);
  stage->setGroup(hand_group_name);
  stage->setGoal("close");
  grasp->insert(std::move(stage));
}

{
  // Attaches object
  auto stage = std::make_unique<mtc::stages::ModifyPlanningScene>("attach object");
  stage->attachObject("object", hand_frame);
  attach_object_stage = stage.get();
  grasp->insert(std::move(stage));
}

task.add(std::move(grasp));

}
return task;
}

int main(int argc, char** argv)
{
rclcpp::init(argc, argv);

rclcpp::NodeOptions options;
options.automatically_declare_parameters_from_overrides(true);

auto mtc_task_node = std::make_shared(options);
rclcpp::executors::MultiThreadedExecutor executor;

auto spin_thread = std::make_uniquestd::thread(&executor, &mtc_task_node {
executor.add_node(mtc_task_node->getNodeBaseInterface());
executor.spin();
executor.remove_node(mtc_task_node->getNodeBaseInterface());
});

mtc_task_node->setupPlanningScene();
mtc_task_node->doTask();

spin_thread->join();
rclcpp::shutdown();
return 0;
}

And here is the terminal output as well:

Image

If there is another issue you see, please let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions