MoveIt Task Constructor
What is MoveIt Task Constructor?
 
MTC Stages
There are three possible stages relating to the result flow:
- Generators 
- Propagators 
- Connectors 
Generator Stage
 
CurrentState, which gets the current robot state as the starting point for a planning pipeline.GeneratePose. It usually monitors a CurrentState or ModifyPlanningScene stage. By monitoring the solutions of CurrentState, the GeneratePose stage can find the object or frame around which it should generate poses.Propagating Stage
 
Move Relative to a pose. This stage is commonly used to approach close to an object to pick.Connecting Stage
 
Wrapper
Compute IK for Generate Grasp Pose stage. A Generate Grasp Pose stage will produce cartesian pose solutions. By wrapping an Compute IK stage around Generate Pose stage, the cartesian pose solutions from Generate Pose stage can be used to produce IK solutions (i.e) produce joint state configuration of robot to reach the poses.MTC Containers
Currently available containers:
- Serial 
- Parallel 
Serial Container
Parallel Container
Parallel containers combine a set of stages to allow planning alternate solutions.
Initializing a MTC Task
The top-level planning problem is specified as a MTC Task and the subproblems which are specified by Stages are added to the MTC task object.
auto node = std::make_shared<rclcpp::Node>();
auto task = std::make_unique<moveit::task_constructor::Task>();
task->loadRobotModel(node);
// Set controllers used to execute robot motion. If not set, MoveIt has controller discovery logic.
task->setProperty("trajectory_execution_info", "joint_trajectory_controller gripper_controller");
Adding containers and stages to a MTC Task
Adding a stage to MTC task
auto current_state = std::make_unique<moveit::task_constructor::stages::CurrentState>("current_state");
task->add(std::move(current_state));
Containers derive from Stage and hence containers can be added to MTC task similarly
auto container = std::make_unique<moveit::task_constructor::SerialContainer>("Pick Object");
// TODO: Add stages to the container before adding the container to MTC task
task->add(std::move(container));
Setting planning solvers
Stages that do motion planning need solver information.
Solvers available in MTC
- PipelinePlanner- Uses MoveIt’s planning pipeline
- JointInterpolation- Interpolates between the start and goal joint states. It does not support complex motions.
- CartesianPath- Moves the end effector in a straight line in Cartesian space.
Code Example on how to initialize the solver
const auto mtc_pipeline_planner = std::make_shared<moveit::task_constructor::solvers::PipelinePlanner>(
    node, "ompl", "RRTConnectkConfigDefault");
const auto mtc_joint_interpolation_planner =
    std::make_shared<moveit::task_constructor::solvers::JointInterpolationPlanner>();
const auto mtc_cartesian_planner = std::make_shared<moveit::task_constructor::solvers::CartesianPath>();
These solvers will be passed into stages like MoveTo, MoveRelative, and Connect.
Setting Properties
void setProperty(const std::string& name, const boost::any& value);
Cost calculator for Stages
CostTerm is the basic interface to compute costs for solutions for MTC stages.
CostTerm implementations available in MTC
- Constant- Adds a constant cost to each solution
- PathLength- Cost depends on trajectory length with optional weight for different joints
- TrajectoryDuration- Cost depends on execution duration of the whole trajectory
- TrajectoryCostTerm- Cost terms that only work on SubTrajectory solutions
- LambdaCostTerm- Pass in a lambda expression to calculate cost
- DistanceToReference- Cost depends on weighted joint space distance to a reference point
- LinkMotion- Cost depends on length of Cartesian trajectory of a link
- Clearance- Cost is inverse of distance to collision
Example code on how to set CostTerm using LambdaCostTerm
stage->setCostTerm(moveit::task_constructor::LambdaCostTerm(
      [](const moveit::task_constructor::SubTrajectory& traj) { return 100 * traj.cost(); }));
All stages provided by MTC have default cost terms. Stages which produce trajectories as solutions usually use path length to calculate cost.
Planning and Executing a MTC Task
Planning an MTC task will return a MoveItErrorCode.
Refer here to identity the different error types.
If planning succeeds, you can expect the plan function to return moveit_msgs::msg::MoveItErrorCodes::SUCCESS.
auto error_code = task.plan()
After planning, extract the first successful solution and pass it to the execute function. This will create an execute_task_solution action client.
The action server resides in the execute_task_solution_capability plugin provided by MTC.
The plugin extends MoveGroupCapability. It constructs a MotionPlanRequest from the MTC solution and uses MoveIt’s PlanExecution to actuate the robot.
auto result = task.execute(*task.solutions().front());
Links to Additional Information
Here is a tutorial on how to create a Pick and Place pipeline using MTC.
The links listed below contain more information on stages and containers provided by MTC