-
Notifications
You must be signed in to change notification settings - Fork 158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
documenting instructions for the pick-and-place task #238
Changes from 1 commit
2b18369
162f66c
f1d0f8b
aeb8aa4
2086b04
b093270
c83c99e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,20 +82,29 @@ void PickPlaceTask::loadParameters() { | |
rosparam_shortcuts::shutdownIfError(LOGNAME, errors); | ||
} | ||
|
||
// The required sequences for a successful pick-and-place task are defined below. The entire process is comprised of six | ||
// "high level" movements: Checking if the object to be picked is already attached to the robot arm, opening the robot's | ||
// hand, moving the robot to the pre-grasp position, grasping the object, moving the robot to a pre-place position, | ||
// placing the object, and finally, moving the robot to a standstill position. These six sequences are listed on the | ||
// least indented column of the "Motion Planning Tasks" widget in Rviz. These sequences are not planned or executed but | ||
// defined as part of moveit's task constructor object below. The stages are be described in more detail below. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd call it a |
||
|
||
void PickPlaceTask::init() { | ||
ROS_INFO_NAMED(LOGNAME, "Initializing task pipeline"); | ||
const std::string object = object_name_; | ||
|
||
// Reset ROS introspection before constructing the new object | ||
// TODO(henningkayser): verify this is a bug, fix if possible | ||
// The structure of the pick-and-place process is collected inside a moveit::task_constructor::Task. | ||
task_.reset(); | ||
task_.reset(new moveit::task_constructor::Task()); | ||
|
||
Task& t = *task_; | ||
t.stages()->setName(task_name_); | ||
t.loadRobotModel(); | ||
|
||
// Sampling planner | ||
//The robot movement is planned by different planners: a cartesian planner, a pipeline planner, or a joint | ||
//interpolation planner. | ||
auto sampling_planner = std::make_shared<solvers::PipelinePlanner>(); | ||
sampling_planner->setProperty("goal_joint_tolerance", 1e-5); | ||
|
||
|
@@ -117,6 +126,7 @@ void PickPlaceTask::init() { | |
* Current State * | ||
* * | ||
***************************************************/ | ||
// Before beginning with the operation, one needs to verify if the object is not already attached to the robot. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Stage* current_state_ptr = nullptr; // Forward current_state on to grasp pose generator | ||
{ | ||
auto current_state = std::make_unique<stages::CurrentState>("current state"); | ||
|
@@ -153,6 +163,9 @@ void PickPlaceTask::init() { | |
* Move to Pick * | ||
* * | ||
***************************************************/ | ||
// This is the second major phase of picking the object. This phase moves to the start of the picking location. The | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would keep it shorter here, too. E.g. "Moves to a pre-grasp pose from where the gripper approaches the object. Generated by a stage::Connect object which does not plan a movement, but connects two stages that do." Also, remove the comment in the next line |
||
// movement is generated by a stage::Connect object which itself does not declare any movements but acts as a bridge | ||
// between two stages that are precisely defined. | ||
{ // Move-to pre-grasp | ||
auto stage = std::make_unique<stages::Connect>( | ||
"move to pick", stages::Connect::GroupPlannerVector{ { arm_group_name_, sampling_planner } }); | ||
|
@@ -168,6 +181,10 @@ void PickPlaceTask::init() { | |
***************************************************/ | ||
Stage* attach_object_stage = nullptr; // Forward attach_object_stage to place pose generator | ||
{ | ||
// The third major stage of the pick-and-place sequence is defined: picking the object. The grasp is defined | ||
// inside a SerialContainer. A SerialContainer consists of a sequence of subordinate tasks. Stages other than | ||
// these subordinate tasks can communicate only with the entire SerialContainer and do not need to know each | ||
// subordinate task. | ||
auto grasp = std::make_unique<SerialContainer>("pick object"); | ||
t.properties().exposeTo(grasp->properties(), { "eef", "hand", "group", "ik_frame" }); | ||
grasp->properties().configureInitFrom(Stage::PARENT, { "eef", "hand", "group", "ik_frame" }); | ||
|
@@ -176,7 +193,11 @@ void PickPlaceTask::init() { | |
---- * Approach Object * | ||
***************************************************/ | ||
{ | ||
auto stage = std::make_unique<stages::MoveRelative>("approach object", cartesian_planner); | ||
// This movement approaches the object and stops right before it through a MoveRelative stage. The stage | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Misses a comment that this stage is inserted into the |
||
// resembles the Connect because it does not define an end or starting point but move across space as defined | ||
// as a geometryMsgs. In contrast to the Connect stage, however, the planner does not have any flexibility in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// the cartesian structure of the movement as this is precisely defined. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean by "cartesian structure of the movement" |
||
auto stage = std::make_unique<stages::MoveRelative>("approach object", cartesian_planner); | ||
stage->properties().set("marker_ns", "approach_object"); | ||
stage->properties().set("link", hand_frame_); | ||
stage->properties().configureInitFrom(Stage::PARENT, { "group" }); | ||
|
@@ -194,16 +215,24 @@ void PickPlaceTask::init() { | |
---- * Generate Grasp Pose * | ||
***************************************************/ | ||
{ | ||
// Sample grasp pose | ||
auto stage = std::make_unique<stages::GenerateGraspPose>("generate grasp pose"); | ||
stage->properties().configureInitFrom(Stage::PARENT); | ||
stage->properties().set("marker_ns", "grasp_pose"); | ||
stage->setPreGraspPose(hand_open_pose_); | ||
stage->setObject(object); | ||
stage->setAngleDelta(M_PI / 12); | ||
stage->setMonitoredStage(current_state_ptr); // Hook into current state | ||
|
||
// Compute IK | ||
// The object grasp is defined by combining two stages, a GenerateGraspPose and a ComputeIK pose. The | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "latches onto the object" implies a connection that I don't really see. "connects" seems to make more sense. "The generateGraspPose" should be "The generateGraspPose stage" or "...container". The phrase "a ComputeIK pose" seems to be used to mean "a ComputeIKpose stage". This is confusing.
|
||
// generateGraspPose latches several possible target poses onto the object to be grasped. The | ||
// GenerateGraspPose circles in AngleDelta increments along the object creating one target pose in each | ||
// instance. | ||
auto stage = std::make_unique<stages::GenerateGraspPose>("generate grasp pose"); | ||
stage->properties().configureInitFrom(Stage::PARENT); | ||
stage->properties().set("marker_ns", "grasp_pose"); | ||
stage->setPreGraspPose(hand_open_pose_); | ||
stage->setObject(object); | ||
stage->setAngleDelta(M_PI / 4); | ||
stage->setMonitoredStage(current_state_ptr); // Hook into current state | ||
|
||
// The ComputeIK stage defines the grasp pose for the end-effector. The ComputeIK stage attempts to compute | ||
// the appropriate joint parameters from two components: The target posed sampled from the GenerateGraspPose | ||
// stage and the user-defined grasp_frame_transform: The proposed solution is post-multiplied by the | ||
// inverse of the grasp_frame_transform to yield a target frame to be attained by the robot's end-effector. | ||
// If an IK solution is found, the end effectors frame times the rasp_frame_transform equals the frame | ||
// generated in the GenerateGraspPose stage and the object can be picked. | ||
auto wrapper = std::make_unique<stages::ComputeIK>("grasp pose IK", std::move(stage)); | ||
wrapper->setMaxIKSolutions(8); | ||
wrapper->setMinSolutionDistance(1.0); | ||
|
@@ -216,19 +245,25 @@ void PickPlaceTask::init() { | |
/**************************************************** | ||
---- * Allow Collision (hand object) * | ||
***************************************************/ | ||
{ | ||
auto stage = std::make_unique<stages::ModifyPlanningScene>("allow collision (hand,object)"); | ||
stage->allowCollisions( | ||
object, t.getRobotModel()->getJointModelGroup(hand_group_name_)->getLinkModelNamesWithCollisionGeometry(), | ||
true); | ||
grasp->insert(std::move(stage)); | ||
} | ||
{ | ||
// After the grasp frame has been determined, the next step is to pick up the object. At first, the planning | ||
// scene needs to be modified to allow the robot to pick up the object. This stage does not alter the | ||
// robot's position. | ||
auto stage = std::make_unique<stages::ModifyPlanningScene>("allow collision (hand,object)"); | ||
stage->allowCollisions( | ||
object, t.getRobotModel()->getJointModelGroup(hand_group_name_)->getLinkModelNamesWithCollisionGeometry(), | ||
true); | ||
grasp->insert(std::move(stage)); | ||
} | ||
|
||
/**************************************************** | ||
---- * Close Hand * | ||
***************************************************/ | ||
{ | ||
auto stage = std::make_unique<stages::MoveTo>("close hand", sampling_planner); | ||
// To close the hand, the robot moves from the position of an open hand to a position with a closed hand. | ||
// Similar to moving from the initial pose to the pose with `open hand` as done in the beginning, the MoveTo | ||
// stage is used. | ||
auto stage = std::make_unique<stages::MoveTo>("close hand", sampling_planner); | ||
stage->setGroup(hand_group_name_); | ||
stage->setGoal(hand_close_pose_); | ||
grasp->insert(std::move(stage)); | ||
|
@@ -237,6 +272,8 @@ void PickPlaceTask::init() { | |
/**************************************************** | ||
.... * Attach Object * | ||
***************************************************/ | ||
// The next four stages modify the planning scene again by attaching the object to the hand, and lifting the | ||
// object while guaranteeing that the cylinder does not touch the ground. | ||
{ | ||
auto stage = std::make_unique<stages::ModifyPlanningScene>("attach object"); | ||
stage->attachObject(object, hand_frame_); | ||
|
@@ -274,11 +311,11 @@ void PickPlaceTask::init() { | |
/**************************************************** | ||
.... * Forbid collision (object support) * | ||
***************************************************/ | ||
{ | ||
auto stage = std::make_unique<stages::ModifyPlanningScene>("forbid collision (object,surface)"); | ||
stage->allowCollisions({ object }, support_surfaces_, false); | ||
grasp->insert(std::move(stage)); | ||
} | ||
{ | ||
auto stage = std::make_unique<stages::ModifyPlanningScene>("forbid collision (object,surface)"); | ||
stage->allowCollisions({ object }, support_surfaces_, false); | ||
grasp->insert(std::move(stage)); | ||
} | ||
|
||
// Add grasp container to task | ||
t.add(std::move(grasp)); | ||
|
@@ -290,7 +327,10 @@ void PickPlaceTask::init() { | |
* * | ||
*****************************************************/ | ||
{ | ||
auto stage = std::make_unique<stages::Connect>( | ||
// Similar to the `move to pick` stage, the `move to place` stage is defined implicitly as a Connect stage: No | ||
// robot movement on its own is defined but the movement bridges the previous `pick object` and the following | ||
// `place object` serial containers. | ||
auto stage = std::make_unique<stages::Connect>( | ||
"move to place", stages::Connect::GroupPlannerVector{ { arm_group_name_, sampling_planner } }); | ||
stage->setTimeout(5.0); | ||
stage->properties().configureInitFrom(Stage::PARENT); | ||
|
@@ -302,7 +342,10 @@ void PickPlaceTask::init() { | |
* Place Object * | ||
* * | ||
*****************************************************/ | ||
{ | ||
// Placing the object constitutes again a sequence of operations that are combined into a SerialContainer so that | ||
// outside stages only need to communicate with the boundaries of the SerialContainer. The process is very similar | ||
// to the pick object process described above and thus not illustrated. | ||
{ | ||
auto place = std::make_unique<SerialContainer>("place object"); | ||
t.properties().exposeTo(place->properties(), { "eef", "hand", "group" }); | ||
place->properties().configureInitFrom(Stage::PARENT, { "eef", "hand", "group" }); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"least indented" --> "top-level", although since technically that's not true either I'd skip it altogether. "These sequences are shown in the widget..."