Skip to content

Add named frames to CollisionObjects#1060

Closed
felixvd wants to merge 12 commits intomoveit:kinetic-develfrom
felixvd:extend-planning-scene
Closed

Add named frames to CollisionObjects#1060
felixvd wants to merge 12 commits intomoveit:kinetic-develfrom
felixvd:extend-planning-scene

Conversation

@felixvd
Copy link
Copy Markdown
Contributor

@felixvd felixvd commented Sep 11, 2018

Description

This PR implements #1041. It adds named frames to collision objects so that they can be used for planning, both as targets in the planning scene, as well as end effector links when the objects are attached to the robot. This allows writing commands like "Move the tip of the screwdriver to the head of the screw" or "Move the spout of the teapot to the top of the mug". It also opens up avenues for using in-hand pose estimation to update the pose of an object in the gripper (e.g. grasp a tool, confirm the object pose with a camera, then use the updated tool tip pose on the object).

Currently, the named frames are displayed in Rviz in the Scene Objects tab and as red dots on the AttachedBodies. I also made a header file that converts URDF files to collision_object messages in C++, but it's not part of this PR. I didn't test it a lot yet, so there are surely some bugs, but it should be good enough to try out.

Here is a gist that you can use to create the following example images. These run for a UR5, but you have to adjust everything to your system and fill in some variables. I didn't have time to prepare a whole test package.

2018-9-11-ps-extension

The result of "Move the cylinder tip to the bottom of the box":

2018-09-11-ps-extension-2

Open ToDos:

  • Test the path and trajectory constraints (I only checked that it works on goal constraints)
  • Integrate the frames' visualization into Rviz (should they be published to TF? Should there be a checkbox?)
  • Implement MOVE for CollisionObjects and AttachedBodies (would be great for updating the object pose in the gripper)
  • Check effect on performance

Checklist

  • Required by CI: Code is auto formatted using clang-format
  • Extended the tutorials / documentation, if necessary reference
  • Include a screenshot if changing a GUI
  • Created tests, which fail without this PR reference
  • Decide if this should be cherry-picked to other current ROS branches
  • While waiting for someone to review your request, please consider reviewing another open pull request to support the maintainers

This changes the processAttachedCollisionObject function somewhat. Comments added to make it easier to follow.
If a motion plan request is sent through the move group interface, and its end_effector_link is a named frame on an AttachedBody instance, the function added in this commit makes the motion plan request valid by transforming the eef_link to a robot link. It uses a MoveGroupCapability because the MoveGroupInterface only tracks the robot joints, not the attached bodies. Doing it via a request to the PlanningScene would be possible as well, but this is the first prototype.

"validateConstraints" is not a good name for a function that forces the constraints to become valid, but I couldn't come up with anything better on the spot.
They appear in the scene as red dots and in the Scene Objects tab.
@v4hn
Copy link
Copy Markdown
Contributor

v4hn commented Sep 11, 2018

Wow, this is quite a lot of work 🥇
This takes some time to review & refine and I will sadly not be able to do this in the next month.

We shortly talked about this before and, unless I'm mistaken now,
we also talked about the alternative to add relative transforms to collision-objects, essentially allowing to add empty collision objects for relative frames, too, in a style similar to scene graphs.
Could you say a few words about why you chose child links instead?

Afaics now this will leave us with two somewhat redundant mechanisms if we should ever get around to implement scene graph support (which has been requested before).

@v4hn
Copy link
Copy Markdown
Contributor

v4hn commented Sep 11, 2018

Oh, one more important point.
This change requires message changes, so sadly we cannot merge it into the kinetic-devel branch anymore!

Personally I believe melodic-devel is still quite fine, but others might disagree.

@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Sep 12, 2018

I agree that a full scene graph would be good. The main reason I went this way is that I wasn't sure how much effort that would be, and this seemed like a less intrusive change. It also solves most of my application's pain points with a conceptually simple change, which was an argument in favor.

With the child objects/scene graph structure we discussed, I worried about additional pitfalls (recursive transforms and message processing). I think I might be able to tackle it now that I know a bit more, but I didn't want to bite off more than I could chew. And I am still not sure if I really know how the world object and AttachedBody data are communicated to different parts of the system.

While the child link structure may be redundant in some ways in the future, it is readable: One physical object is contained in a single CollisionObject message, and the intention of a named frame is clear. If scene graph support is added in the way you envision and all child frames are collision objects, an object with child frames would be spread over multiple CollisionObject messages, which seems less convenient and harder to read. That said, I'm totally open to doing and arranging things differently.

Lastly, this change doesn't get in the way of future work, and could coexist with a scene graph, as you said. The meat of commit defbd63 does not depend on the child links either and its extension to a scene-graph-like structure is straight forward.

If this can't be merged into kinetic-devel, let me know how to proceed. I suppose the missing messages are the reason the checks are failing.

@davetcoleman
Copy link
Copy Markdown
Member

Really great work! More thoughts, beyond those in the related issue #1041 you created:

Here is a gist that you can use to create the following example images.

This needs to be updated in the tutorial, either a new one or add to an existing one

I didn't have time to prepare a whole test package.

This has some big changes to MoveIt!, adding a few tests would make it much easier to get in

Copy link
Copy Markdown
Member

@davetcoleman davetcoleman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job with this!

@@ -160,7 +160,7 @@ static QString decideStatusText(const collision_detection::CollisionWorld::Objec
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think changes to Rviz should be a follow-up PR to keep the size of this one manageable. feel free to create it now, though

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure? It would make testing this PR less convenient, and I hope the Rviz changes will stay pretty limited.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not a hard rule, just a would be nice. your argument is fine

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1122 and the ToDo in the code make a good case for rethinking the Rviz changes and how to visualize these frames. Red dots are obviously not ideal. I will keep this in for testing and remove it before the merge.

@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Sep 13, 2018

Thanks for the review. It looks like clang introduced a number of unnecessary changes. clang-format -version returns clang-format version 3.8.0-2ubuntu4 (tags/RELEASE_380/final) though, which I assume is ok. I'll have a look at this next week. Any ideas on which settings might have caused this? I used the VSCode editor plugin, but I think it just calls clang-format on the file.

In the meantime, I actually made the planning scene monitor in our system publish the named frames to TF for convenience. I'm not sure about that choice, and why the objects weren't in TF before that. I'll bring this up in the issue about the planning scene/collision world you asked me to make.

@davetcoleman
Copy link
Copy Markdown
Member

The recommended command line command for using the correct clang format is here:
http://moveit.ros.org/documentation/contributing/code/

@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Sep 29, 2018

Thanks, that helps. I'm in a crunchtime I had to skip ROSCon and IROS for, but I'll get back to this at the latest after 20 October and before MoveIt Day.

As a quick note to myself, this is not compatible with planCartesianPath yet.

const Eigen::Affine3d& getTransform(const std::string& id) const;

/** \brief Get the object id that owns the named frame with name id*/
std::string getParent(const std::string& id) const;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id should be given a more descriptive name. Maybe something like object_id. From this comment it is unclear to me if this is solely for getting the parent_object_id for a child_frame or if it can also be used more generally. For instance, I might think that getParrent("wrist_2_link") would return wrist_1_link

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to keep the "id" convention, but I will have another look if there are functions that only take named frames' names.

bool moveObject(const std::string& id, const Eigen::Affine3d& transform);

/** \brief Replaces all shapes in an existing object.
* If the object already exists, this call will add the shape to the object
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name indicates that this would remove all shapes in an object and replace them with this new one. Please either rename the function or update the comment to match functionality.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the implementation, I found that the documentation here is wrong, but the function name matches implementation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I changed the documentation.

return true;
else // Then objects' named frames
{
for (auto o : objects_)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I tend to shy away from auto unless the object that is being iterated is defined nearby. If a reader has to open up another file to find out what type of object this will be then it is probably a bad idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agreed with what you wrote, but the rest of the file seems to follow the same convention. I only changed from auto to auto const& for now, under the assumption that it's faster.

@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Oct 12, 2018

As discussed with Dave on Wednesday, I had to freeze this until the week of the MoveIt Day because I am completely occupied with this. I think I can get it done and tested on Melodic by WMD though.

Copy link
Copy Markdown
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about how to store the attached frames, locally per-object (as currently) or in a global map.
A global map, would better reflect the global name space.

I will have another look, if commits are cleaned up.

objects_.clear();
}

bool World::setNamedFramesOfObject(const std::string& id, const std::map<std::string, Eigen::Affine3d>& named_frames)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about methods to add/remove/access individual frames of an object?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can imagine some use cases, but I don't think it's required for a first version. Do you have anything specific in mind?

This reverts commit 5487c35.
This reverts commit a7ca039.
According to the contribution guidelines
Includes changes: 
- from .count() to .find()
- _NAMED logging
- Use for-range loops
- Clean comments
- Restore knowsObject function
@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Oct 27, 2018

A quick update before I get on my plane. I have been on the road constantly and work from my laptop's VM is slow, but I added most of the comments during WMD. The conversations related to those are marked as resolved. The last commit changes a lot of lines, but (hopefully) very little functionally.

There are some decisions to take that affect the work left to do on this PR:

  1. Does the constraint validation have to be in a planning request adapter, or do we accept it as is for now? I am a bit worried that moving the validation to an adapter might take a while because I have never touched that part of the pipeline, but maybe it is easier than I think. At the same time, this could be changed later rather than now.
  2. Should the list of named frames be global for the scene, or held by each object? I would be in favor of the latter, because it is already implemented and it will allow multiple objects with same-name frames after we decide how to namespace them.

Known limitations:

  • The current version of planCartesianPath is not supported because it does not work the same way as the other planning requests.
  • There is no visualization of the frames in Rviz because they are not published to TF (the temporary visualization I added should be taken out before the merge)

Open small ToDos:

  • A getFrameInfo() method as suggested by Robert
  • Combining the constraint validation methods
  • Rebase the branch and resolve the conflicts

Another note: I will be in Europe for 3 weeks. That's another reason I am reluctant to introduce bigger changes now. I hope I can finish the small stuff very shortly, though. Will update after my flight!

@rhaschke rhaschke added the more work needed Everyone is invited to contribute label Dec 9, 2018
@felixvd
Copy link
Copy Markdown
Contributor Author

felixvd commented Apr 17, 2019

Closing because it is superceded by #1439.

@felixvd felixvd closed this Apr 17, 2019
@felixvd felixvd deleted the extend-planning-scene branch April 27, 2020 16:23
JafarAbdi pushed a commit to JafarAbdi/moveit that referenced this pull request Mar 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

more work needed Everyone is invited to contribute

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants