Skip to content

Convert API to use std::shared_ptr#215

Merged
davetcoleman merged 12 commits intomoveit:kinetic-develfrom
fizyr-forks:std-shared-ptr-api
Sep 27, 2016
Merged

Convert API to use std::shared_ptr#215
davetcoleman merged 12 commits intomoveit:kinetic-develfrom
fizyr-forks:std-shared-ptr-api

Conversation

@de-vri-es
Copy link
Copy Markdown
Contributor

This PR updates the API to use std::shared_ptr for moveit types instead of boost::shared_ptr.

I'm not sure what the opinions are on this topic, but this PR at the least provides a place to discuss this specific API change. But do note that other libraries are doing the same thing right about now (like fcl and urdfdom).

Technically, switching from boost::enable_shared_from_this to std::enable_shared_from_this is not 100% API compatible, since weak_from_this is only added in C++17. This is very unlikely to cause problems though.

One more point: pluginlib still returns boost::shared_ptr and using createUnmanagedInstance is discouraged. Instead I opted to convert the pointers to std:: instead. That method is not 100% safe when weak_ptr are involved in the general case, but it is in this case because nobody else has a copy to the original boost::shared_ptr.

Because the conversion isn't safe in general I didn't want to put it in a header (the header would have to be exported or duplicated across 5 packages). Instead I opted now to duplicate the function in an anonymous namespace in 5 source files. I've also got a PR open with class_loader to add support for std:: smart pointers (unique and shared), so when that lands it makes sense to adapt to that interface. In the mean time I didn't know a nicer solution than the current in this PR.

@de-vri-es de-vri-es force-pushed the std-shared-ptr-api branch 2 times, most recently from a2a8c00 to d71592e Compare September 12, 2016 20:30
MOVEIT_CLASS_FORWARD(Shape);
class Shape;
typedef boost::shared_ptr<Shape> ShapePtr;
typedef boost::shared_ptr<const Shape> ShapeConstPtr;
Copy link
Copy Markdown
Member

@davetcoleman davetcoleman Sep 12, 2016

Choose a reason for hiding this comment

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

Just to make sure I understand the logic here - we don't want to use std::shared_ptr for Shape because its part of geometric_shapes, which is part of desktop-full, which is not suppose to have std in its public headers yet, correct?

https://github.com/ros-planning/geometric_shapes/blob/kinetic-devel/include/geometric_shapes/shapes.h#L273

We did already break this rule for that package because it was required for FCL/octomap, but I guess in this case we don't have a good reason to continue to break that rule. But another (cleaner) possibility would be to make the C++11 switch there, as well, correct?

Copy link
Copy Markdown
Contributor Author

@de-vri-es de-vri-es Sep 12, 2016

Choose a reason for hiding this comment

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

I agree, it would be nice to have std::shared_ptr there. The previous deviation from REP-003 was out of necessity though. On the other hand, urdfdom also switched. And while it may not be a real ROS package that is more or less a technicality.

But yeah, as long as the geometric_shape API uses boost::shared_ptr we can't switch them here.

/edit: Apparently urdfdom is packaged as ROS package too. It's been a while since I've used the official Ubuntu distribution ^^

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.

How about a comment for ROS-L saying we'll switch to C++11 then?

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.

I agree, please add a comment here that explains why this code still uses boost::shared_ptr and that it should be changed for lunar.

@davetcoleman
Copy link
Copy Markdown
Member

+1 but other maintainers should get a chance to review and discuss this big change
@v4hn @rhaschke @mikeferguson

@davetcoleman
Copy link
Copy Markdown
Member

I would like to merge this asap so we have momentum for the kinetic release

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.

+1.


/* used to unregister the notifier */
boost::weak_ptr<World> world_;
std::weak_ptr<World> world_;
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 a WeakPtr definition in MOVEIT_CLASS_FORWARD?

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.

We had a short discussion at #206. Nobody seemed very interested (including me), but if you think that is the right approach you can reopen the PR.

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.

-1 to that macro

changes_ = other.changes_;

boost::weak_ptr<World>(world).swap(world_);
std::weak_ptr<World>(world).swap(world_);
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.

see above (WeakPtr forward declaration)

#include <moveit_msgs/PlanningSceneComponents.h>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
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.

Is this still necessary?

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.

Yeah, line 96 and 887 still use it for non-moveit types.

Copy link
Copy Markdown
Contributor

@v4hn v4hn Sep 24, 2016

Choose a reason for hiding this comment

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

yes, but now thant you use the Ptr typedef they don't mention the symbol anymore. So this can be removed imo
The same is probably true for a number of other files..

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.

Good point, will check.

Copy link
Copy Markdown
Contributor

@v4hn v4hn left a comment

Choose a reason for hiding this comment

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

some minor refinements requested.
but overall this looks good to me.

MOVEIT_CLASS_FORWARD(Shape);
class Shape;
typedef boost::shared_ptr<Shape> ShapePtr;
typedef boost::shared_ptr<const Shape> ShapeConstPtr;
Copy link
Copy Markdown
Contributor

@v4hn v4hn Sep 22, 2016

Choose a reason for hiding this comment

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

same as above.


#include <moveit/collision_detection/world.h>
#include <moveit/macros/class_forward.h>
#include <boost/weak_ptr.hpp>
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.

this is missing a <memory> include, isn't it?

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.

Well, you can't make weak_ptrs without shared_ptrs. Since we have std::shared_ptr typedefs available from a macro in #include <moveit/macros/declare_ptr.h>, that will have pulled in #include <memory>.

But I am a fan of the rule "if you use a symbol from a header, include it", so I'll add it.

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.

#include <memory> added

MOVEIT_CLASS_FORWARD(Shape);
class Shape;
typedef boost::shared_ptr<Shape> ShapePtr;
typedef boost::shared_ptr<const Shape> ShapeConstPtr;
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.

gosh, how many of these cases are there? Why is this not centralized?

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 was a bit hesitant to add a macro for declaring boost::shared_ptr if they're going to turn in to std::shared_ptrs in the not-too-far future. Having macros like that lying around could be seen as an invitation to use them.

How about adding these typedefs in geometric_shapes (and possibly a new header geometric_shapes/forward.h to avoid including complex header), and until those are available keeping them explicit like this?

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.

+1, though I think you could make the switch now since kinetic is not released yet and Travis builds geometric_shapes from source for this PR

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.

Ah, these forward delarations where added by @rhaschke in 13d2e62 to reduce includes of geometric_shapes.
I don't like the idea to introduce a header there that only forward declares all the types.
@rhaschke is this change really worth the overhead to maintain the boost-shared_ptrs here?

On the other hand I agree with @davetcoleman. I don't think it's any good to have boost- and std- shared_ptr around in geometric_shapes in kinetic. So I would actually propose to fully move to std::shared_ptr there. This would also simplify the forward declarations here.

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 like the idea of that. I think I'll have some questions but I'll open a PR there for those (or an issue if the questions are blocking).

Copy link
Copy Markdown
Contributor

@v4hn v4hn Sep 22, 2016

Choose a reason for hiding this comment

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

I didn't think of it as a "solution to this problem". More as "this problem arises because the previous change that made geometric_shapes use c++11 shared_ptr was inconsistent."
And if we want to switch MoveIt! to std::shared_ptr (which is what this request is about), this should imho include geometric_shapes. Incidentally, I assumed all shared_ptr references where switched to c++11 when we discussed the issue with FCL and octomap.

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.

Nevertheless, moveit/geometric_shapes#57 and using MOVEIT_CLASS_FORWARD here again will also solve the practical issue.

That would basically mean dropping one commit from this PR:

  • Don't use MOVEIT_CLASS_FORWARD for non-moveit classes.

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 didn't seem your last comment when replying. But fair enough, it does make sense to switch geometric_shapes and moveit at the same time. It could get very confusing otherwise.

And in that light it may be acceptable to use MOVEIT_CLASS_FORWARD for geometric_shapes types. It feels a bit weird to define typedefs using a moveit convention in the namespace of another library, but I suppose geometric_shapes and moveit are related enough.

Shall I just drop the relevant commit then, and revert to using MOVEIT_CLASS_FORWARD?

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.

let's see what comes out of your new request for geometric_shapes.

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 was assuming we were not switching these because it would violate the ROS policy of no std::shared_ptrs in the public headers of packages in ros-desktop-full. But then again, we already had to break that rule for FCL and Octomap, so it doesn't make a difference going all the way now.

#include <moveit/collision_distance_field/collision_world_distance_field.h>
#include <moveit/collision_distance_field/collision_common_distance_field.h>
#include <moveit/distance_field/propagation_distance_field.h>
#include <boost/make_shared.hpp>
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.

this is missing <memory>

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.

Same as previous, so will also add.

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.

#include <memory> added

const std::vector<std::string> &resources)
{
return boost::make_shared<moveit_simple_controller_manager::FollowJointTrajectoryControllerHandle>(
return std::make_shared<moveit_simple_controller_manager::FollowJointTrajectoryControllerHandle>(
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.

<memory> is not included here, but <boost/shared_ptr.hpp> still is. Is the latter still required here?

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.

Good catch. Indeed, boost header removed, #include <memory> added

#include <moveit_msgs/PickupAction.h>
#include <moveit_msgs/PlaceAction.h>
#include <boost/noncopyable.hpp>
#include <boost/enable_shared_from_this.hpp>
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.

<memory> should be included for std::enable_shared_from_this

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.

#include <memory> added

MOVEIT_CLASS_FORWARD(Shape);
class Shape;
typedef boost::shared_ptr<Shape> ShapePtr;
typedef boost::shared_ptr<const Shape> ShapeConstPtr;
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.

and yet another case that should have a comment saying this should be changed in lunar.

@de-vri-es
Copy link
Copy Markdown
Contributor Author

hmm, seems something went wrong during a rebase

@de-vri-es
Copy link
Copy Markdown
Contributor Author

Ah, the new BenchmarkExecutor wasn't using the typedefs. Added a commit for that. Looks like that commit doesn't need to be cherry picked to Indigo and Jade either.

@davetcoleman
Copy link
Copy Markdown
Member

correct, BenchmarkExecutor only exists in Kinetic and will not be backported

@de-vri-es
Copy link
Copy Markdown
Contributor Author

de-vri-es commented Sep 22, 2016

Looks like the tests are build is failing because the version of pluginlib is too old. Probably needs to wait for a docker image rebuild?

Bit off-topic: apparently the version_gte tags in package.xml are just informative? Couldn't find any documentation on what they actually do, but it seems catkin and rosdep are ignoring them.

@gavanderhoorn
Copy link
Copy Markdown
Member

gavanderhoorn commented Sep 22, 2016

@de-vri-es wrote:

Bit off-topic: apparently the version_gte tags in package.xml are just informative? Couldn't find any documentation on what they actually do, but it seems catkin and rosdep are ignoring them.

This is documented in REP-140, but you're right that rosdep doesn't use that information. See also ros-infrastructure/rosdep#325 (specifically: ros-infrastructure/rosdep#325 (comment)).

Bloom translates those into the appropriate key:value pairs in Debian control and RPM spec files.

@davetcoleman
Copy link
Copy Markdown
Member

I'm looking into why the shadow-fixed CI is not building on Dockerhub

@davetcoleman
Copy link
Copy Markdown
Member

Docker error is described here: ros/ros_comm#904

@de-vri-es
Copy link
Copy Markdown
Contributor Author

@gavanderhoorn: Thanks for the information. Not sure how I missed that.

Update regarding this PR:

  • Dropped the commit that undid MOVEIT_CLASS_FORWARD(Shape).
  • Switched out a boost::dynamic_ptr_cast for the std equivalent.
  • Replaced boost::scoped_ptr with std::unique_ptr.

I think this addresses all the remaining review points, but correct me if I'm wrong.

Only the first change affects the MoveIt API. The other two are implementation changes. The last point wasn't technically needed, but I think it makes sense to remove all boost smart pointers in one go.

Locally this builds (with moveit/geometric_shapes#57), including the tests. I've never been able to run all tests successfully on my system though (probably due to python3 issues which I intend to investigate later). I don't expect any problems though, considering the interface and semantics of boost:: and std::shared_ptr are virtually identical (so the compiler should have caught any problems).

@de-vri-es
Copy link
Copy Markdown
Contributor Author

Actually, there are still boost::shared_ptrs left. It is possible that many of these can also be changed, but it needs to be verified that the library owning the type doesn't use boost::shared_ptr in their own API.

There are a number of cases in moveit_core and moveit_ros. Mostly these are shared_ptrs to tf, srdf, and urdf types. The real tricky bit here is knowing if it conflicts with other libraries besides the one owning the type. Many of these shared_ptrs might not even be part of the MoveIt API though, in which case it is safe. Should I look into these cases in more detail?

@v4hn
Copy link
Copy Markdown
Contributor

v4hn commented Sep 24, 2016

For tf I would stick with boost::shared_ptr for kinetic as there are interfaces in other packages that want to take ownership of a tf-listener and expect the boost ptr.

I'm unsure about the others. grep -r boost::shared_ptr --include *.h | grep -v tf::Transform basically lists moveit_experimental/collision_distance_field that still uses boost ptrs internally and a small number of diverse cases that need individual review.

But yes, I would welcome changing these cases (and also the non-API cases) too.

@de-vri-es
Copy link
Copy Markdown
Contributor Author

The last commit converts a number of internal shared_ptr to std::shared_ptr. I believe they were all safe to be converted.

Ignoring boost::shared_ptr<tf::...> and everything in moveit_experimental, chomp and sbpl, there is only one explicit boost::shared_ptr<urdf::Model> left in the setup assistant. But I think that is best left until ros/robot_model#153 is available.

@de-vri-es
Copy link
Copy Markdown
Contributor Author

Rebased on latest kinetic-devel again, now with collision_distance_field and chomp.

@davetcoleman
Copy link
Copy Markdown
Member

Need #250 to be merged before test build https://github.com/davetcoleman/moveit_kinetic_cpp11 passes, indicating this PR is good

@davetcoleman
Copy link
Copy Markdown
Member

@de-vri-es can you rebase this PR with the head of kinetic-devel? The build is failing because of the now fixed fcl dependency

@de-vri-es
Copy link
Copy Markdown
Contributor Author

Rebased. Note that there are two commits that we probably want to cherry-pick to I/J (using commit messages in case of future rebases):

  • Use srdf::ModelPtr typedefs.
  • Use shared_ptr typedefs in collision_distance_field and chomp.

@de-vri-es
Copy link
Copy Markdown
Contributor Author

The travis test passes \o/
https://travis-ci.org/davetcoleman/moveit_kinetic_cpp11

@davetcoleman
Copy link
Copy Markdown
Member

darn there is a merge conflict now, and i just merged moveit/geometric_shapes#57

can you fix asap?

@de-vri-es
Copy link
Copy Markdown
Contributor Author

On it, rebase worked automatically, but I'd like to compile before pushing to be sure (I find automatic merges scary). Should be about 5 to 10 minutes.

@de-vri-es
Copy link
Copy Markdown
Contributor Author

Compiled fine locally, pushed.

@davetcoleman davetcoleman merged commit 22c7aa6 into moveit:kinetic-devel Sep 27, 2016
@davetcoleman
Copy link
Copy Markdown
Member

👏 C++11!

@de-vri-es
Copy link
Copy Markdown
Contributor Author

\o/

@v4hn
Copy link
Copy Markdown
Contributor

v4hn commented Sep 29, 2016

I fully agree with this change, but want to point this out:

This change entails that all packages that compile with a moveit_core dependency in Xenial (the major ubuntu distribution supported by ROS kinetic) have to explicitly specify a standard >= c++11 in the build scripts to compile their packages. This is because Xenial ships gcc 5.3.1 which does not yet default to c++11.
At the moment this breaks our tutorials and packages in moveit_pr2 for kinetic (requests in progress).

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants