ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to plan the Cartesian path with multiple waypoints with MoveItCpp API

asked 2022-06-13 02:26:42 -0500

Xinjue gravatar image

updated 2022-06-14 07:21:08 -0500

Hello,

I'm following the tutorial of MoveIt to learning the MoveItCpp API in ROS Melodic. Before switching to MoveItCpp API, I followed the demo of of Move Group C++ Interface and implemented the Cartesian path, now I want to make an analog Caresian path by MoveItCpp API.

But I can't find way to plan the path after the successfull return of "computeCartesianPath" which will plan the path simultaneously in Move Group C++ Interface. I tried to iteratively setGoal and plan on each result state returned from "computeCartesianPath", but this looks ungraceful and probably time-cosuming. Is there a way, analog to Move Group C++ interface, to plan such Cartesian path?

Here are my code sippets:

// plan05
// 
// restore the start state
planningComponents->setStartState(*robotStartState);
// set the state to the one which satisfies the constraints of Cartesian
auto startState05 = *(moveitCppPtr->getCurrentState());
geometry_msgs::Pose startPose05;
if (dof > 6)
{
    // DOF 7
    startPose05.orientation.w = 1.0;
}
else
{
    // DOF 6
    startPose05.orientation = robotStartPose.orientation;
}
startPose05.position.x = paramStartPose05[0];
startPose05.position.y = paramStartPose05[1];
startPose05.position.z = paramStartPose05[2];
if (startState05.setFromIK(jointModelGroupPtr, startPose05, paramIkTimeout05))
{
    planningComponents->setStartState(startState05);

    // organize waypoints
    EigenSTL::vector_Isometry3d waypoints;
    Eigen::Isometry3d eigenPose;
    tf::poseMsgToEigen(startPose05, eigenPose);
    waypoints.push_back(eigenPose);

    geometry_msgs::Pose wayPose = startPose05;
    // up and back
    for (std::size_t i = 0; i < paramPoseIndex01.size(); ++i)
    {
        if (paramPoseIndex01[i] == "x")
        {
            wayPose.position.x += paramPoseDelta01[i];
        }
        else if (paramPoseIndex01[i] == "y")
        {
            wayPose.position.y += paramPoseDelta01[i];
        }
        else
        {
            wayPose.position.z += paramPoseDelta01[i];
        }
    }
    tf::poseMsgToEigen(wayPose, eigenPose);
    waypoints.push_back(eigenPose);
    // left
    for (std::size_t i = 0; i < paramPoseIndex02.size(); ++i)
    {
        if (paramPoseIndex02[i] == "x")
        {
            wayPose.position.x += paramPoseDelta02[i];
        }
        else if (paramPoseIndex02[i] == "y")
        {
            wayPose.position.y += paramPoseDelta02[i];
        }
        else
        {
            wayPose.position.z += paramPoseDelta02[i];
        }
    }
    tf::poseMsgToEigen(wayPose, eigenPose);
    waypoints.push_back(eigenPose);
    // down and right
    for (std::size_t i = 0; i < paramPoseIndex03.size(); ++i)
    {
        if (paramPoseIndex03[i] == "x")
        {
            wayPose.position.x += paramPoseDelta03[i];
        }
        else if (paramPoseIndex03[i] == "y")
        {
            wayPose.position.y += paramPoseDelta03[i];
        }
        else
        {
            wayPose.position.z += paramPoseDelta03[i];
        }
    }
    tf::poseMsgToEigen(wayPose, eigenPose);
    waypoints.push_back(eigenPose);

    std::vector<moveit::core::RobotStatePtr> resTraj;
    double fraction = startState05.computeCartesianPath(jointModelGroupPtr, resTraj, jointModelGroupPtr->getLinkModel(paramVisualLink), waypoints,
        true, paramEndEffectorStep, paramJumpThreshold);
    ROS_INFO_NAMED("demo", "visualizing plan 05 (Cartesian path) (%.2f%% achieved)", fraction * 100.0);

    visualTools.publishText(textPose, "Cartesian path", rvt::WHITE, rvt::XLARGE);
    for (std::size_t i = 0; i < waypoints.size(); ++i)
    {
        visualTools.publishAxisLabeled(waypoints[i], "pt" + std::to_string(i), rvt::SMALL);
    }
    visualTools.trigger();

    for (auto it : resTraj)
    {
        planningComponents->setGoal(*it);
        auto planSolution05 = planningComponents->plan();
        // set the previous state to current
        planningComponents->setStartState(*it);

        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
}
else
{
    visualTools.publishText(textPose, "failed to get the IK from pre-set start state", rvt::WHITE, rvt::XLARGE);
    visualTools.publishAxisLabeled(startPose05, "target_pose");
    visualTools.trigger();
}

// start the next plan
visualTools.deleteAllMarkers();
visualTools.prompt("Press 'next' to continue with plan 06");

iteratively setGoal and plan behavior: image description

Thanks for your insights!

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2022-06-18 03:31:26 -0500

Xinjue gravatar image

updated 2022-06-18 03:33:07 -0500

Hello to myself and others

I find a feasible solution by digging into the "computeCartesianPath" of move_group. I finally understood that the plan is actually proceed after the return of "computeCartesianPath", and what I missed was to publish the planned trajectory.

so I added the trajectory publish as following code snippets, then I can visualize the animation of planned Cartesian path:

    std::vector<moveit::core::RobotStatePtr> resTraj;
    double fraction = startState05.computeCartesianPath(jointModelGroupPtr, resTraj, jointModelGroupPtr->getLinkModel(paramVisualLink), waypoints,
        true, paramEndEffectorStep, paramJumpThreshold);
    ROS_INFO_NAMED("demo", "visualizing plan 05 (Cartesian path) (%.2f%% achieved)", fraction * 100.0);

    /// to visualize the Cartesian path
    // get the robot_trajectory::RobotTrajectory from RobotStatePtr
    robot_trajectory::RobotTrajectory traj(robotModelPtr, paramPlanningGroup);
    for (const moveit::core::RobotStatePtr& trajState : resTraj)
    {
        traj.addSuffixWayPoint(trajState, 0.0);
    }
    // get the moveit_msgs::RobotTrajectory from robot_trajectory::RobotTrajectory
    moveit_msgs::RobotTrajectory msgTraj;
    traj.getRobotTrajectoryMsg(msgTraj);
    if (traj.getWayPointCount() > 0)
    {
        moveit_msgs::DisplayTrajectory dispTraj;
        dispTraj.model_id = robotModelPtr->getName();
        dispTraj.trajectory.resize(1, msgTraj);
        moveit::core::robotStateToRobotStateMsg(traj.getFirstWayPoint(), dispTraj.trajectory_start);
        auto displayPathPub = nodeHandle.advertise<moveit_msgs::DisplayTrajectory>(
            "/whi_moveit_cpp_demo/ompl/display_planned_path"/*planning_pipeline::PlanningPipeline::DISPLAY_PATH_TOPIC*/, 10, true);
        displayPathPub.publish(dispTraj);
    }

    visualTools.publishText(textPose, "Cartesian path", rvt::WHITE, rvt::XLARGE);
    for (std::size_t i = 0; i < waypoints.size(); ++i)
    {
        visualTools.publishAxisLabeled(waypoints[i], "pt" + std::to_string(i), rvt::SMALL);
    }
    // still have no idea how to leverage visualTools to publish the Cartesian path???
    //visualTools.publishTrajectoryLine(traj, jointModelGroupPtr);
    visualTools.trigger();

further more I think there would be other ways to do so, like leveraging MoveItVisualTools, but I don't get to it so far...

the published trajectory:image description(https://ibb.co/Q68PQsb)

here is the link of the completed code for such thread. After compilation, it can be launched with argument, for example with the panda arm:

roslaunch whi_moveit_cpp_demo moveit_cpp_demo.launch arm:=panda
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2022-06-13 02:26:42 -0500

Seen: 448 times

Last updated: Jun 18 '22