Skip to content
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

Refactor the ROS 2 code to be more modern #126

Merged
merged 21 commits into from
Jan 28, 2020
Merged

Refactor the ROS 2 code to be more modern #126

merged 21 commits into from
Jan 28, 2020

Conversation

clalancette
Copy link
Contributor

This is a major refactor of the robot_state_publisher code. There are a few goals here:

  1. Finish up the port, including adding support for most of the parameters that were hard-coded before.
  2. Heavily cleanup the code to make it easier to understand.
  3. Switch to have robot_description provided as a parameter instead of a command-line argument.
  4. Allow the robot_description to be updated on the fly (via doing a "set" on the parameter).
  5. Allow robot_state_publisher to be composed.
  6. Add additional documentation on how to launch it.

With all of the above, this is a large API and ABI break, so is only appropriate for Foxy and forwards. Once this is ready to go in, there will be another PR necessary to https://github.com/ros2/demos/blob/857c436e76bc6b40d32f096f6989bf51bb73f359/dummy_robot/dummy_robot_bringup/launch/dummy_robot_bringup.launch.py#L28 to make it use the new parameter.

Reviews and thoughts on this welcome!

Signed-off-by: Chris Lalancette <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
The new implementation will be dynamic, so downstream consumers
shouldn't need to subclass it.

Signed-off-by: Chris Lalancette <[email protected]>
We'll use this during the constructor and later on during
the parameter setup.

Signed-off-by: Chris Lalancette <[email protected]>
This includes some example launch files.

Signed-off-by: Chris Lalancette <[email protected]>
Copy link
Member

@mjcarroll mjcarroll left a comment

Choose a reason for hiding this comment

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

A few drive-by comments.

Signed-off-by: Chris Lalancette <[email protected]>
Copy link
Contributor

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

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

Generally looks good! Some questions and suggestions below.

output='screen',
)

urdf_file = os.path.join(os.path.dirname(__file__), 'two_links_moving_joint.urdf')
Copy link
Contributor

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but it looks like this is the only difference with the other launch_testing file. Can we consolidate and make the urdf file name a launch argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not a bad idea. I'll follow-up a little later on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I tried to do this, but I don't think it is possible (or at least, I don't know how to do it with the launch_testing API). The problem is that inside the launch file, I need to do something like:

urdf_path = os.path.join(os.path.dirname(__file__), LaunchConfiguration('urdf_file').expand())
with open(urdf_path) as infp:
    robot_desc = infp.read()
params = {'robot_description': robot_desc}

Unfortunately, the expand() method on LaunchConfiguration just doesn't exist. There is perform(), but that needs some sort of context that I don't know how to get. Without that, I can't read in the robot_description that I need. So I'm going to give up on this for now.

Any ideas on how to accomplish this are welcome!

Copy link
Contributor

Choose a reason for hiding this comment

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

I see the problem. Here's a similar question with not quite the answer we're looking for. I feel like it should be possible; e.g. wrap the LaunchConfiguration substitution in another Substitution that does the file read. I don't have bandwidth atm to look into, so I'm happy to move forward with this PR as-is and if we figure it out we can revisit it.

geometry_msgs::msg::TransformStamped tf_transform = kdlToTransform(seg.second.segment.pose(0));
rclcpp::Time now = this->now();
if (!use_tf_static_) {
now = now + rclcpp::Duration(std::chrono::milliseconds(500));
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we adding 500ms to the current time here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I honestly have no idea. This is ported directly from

tf_transform.header.stamp += ros::Duration(0.5);
; I'll have to look into it later.

Copy link
Contributor

Choose a reason for hiding this comment

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

👌

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did a bit of archaeology in it, and found #46 . In there, Jackie says that she considered this a hack, to be removed, but kept it for backwards-compatibility reasons. It looks like she thought that we should just always default to use_tf_static, and remove the ability to shut it off.

That being said, I know we've had some complaints about this in the past, as splitting the tf tree between tf and tf_static can make it more difficult to get a full view of the tf tree. So I'm on the fence about this. My inclination is to leave it as-is, but I'm definitely open to hearing other opinions about it.

Copy link
Contributor

@jacobperron jacobperron Jan 24, 2020

Choose a reason for hiding this comment

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

I tend to agree with removing the use_tf_static option and always publishing fixed frames as static (i.e. /tf_static), on the grounds that the split topics /tf and /tf_static are agreed on as a standard. IMO, tools that interact with the TF package (e.g. viewing the tree) should handle data coming from both channels.

Moving forward, I'd suggest deprecating the usage of use_tf_static; defaulting to true and warning the user if they set it to false.

My two cents.

Copy link
Contributor

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

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

LGTM with green CI

Signed-off-by: Chris Lalancette <[email protected]>
@clalancette
Copy link
Contributor Author

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@clalancette
Copy link
Contributor Author

After doing the changes to dummy_robot_bringup in ros2/demos#426 , there are 2 backwards compatibility concerns:

  1. The name of the standalone node switched from robot_state_publisher to robot_state_publisher_node.
  2. The URDF now has to be passed as a parameter, not a command-line argument, to the standalone node.

The first one is easy enough to fix, if we want to. For the second one, we could make it backwards compatible (with a warning) if I hand-wrote the standalone node and did argument processing in there. @jacobperron @sloretz thoughts on how important backwards compatibility is here?

Signed-off-by: Chris Lalancette <[email protected]>
@jacobperron
Copy link
Contributor

jacobperron commented Jan 27, 2020

If there's not a strong argument for renaming the node, I'd vote for changing it back to robot_state_publisher. This should make it more straight forward for people not only coming from Eloquent, but also ROS 1.

Regarding the second point. You don't necessarily have to write the standalone node by hand. I ran into a similar situation when refactoring the image_tools demos and we added this line so that non-ROS CLI args are passed to the node component (accessed with the NodeOptions arguments(), for example).

@mjcarroll
Copy link
Member

Regarding the second point. You don't necessarily have to write the standalone node by hand. I ran into a similar situation when refactoring the image_tools demos and we added this line so that non-ROS CLI args are passed to the node component (accessed with the NodeOptions arguments(), for example).

Can we get this in the component tutorials/documentation somewhere? I think this is a pattern that people would like to know about.

@jacobperron
Copy link
Contributor

Can we get this in the component tutorials/documentation somewhere? I think this is a pattern that people would like to know about.

Sure. At the time there was discussion as to whether we were actually abusing the NodeOptions API, which was originally intended for ROS-args. IMO, our usage is still a little awkward, since the rclcpp_components node is stripping out the ROS-args and only forwarding the non-ROS args. Maybe we should change the behaviour so that rclcpp_components doesn't strip away the ROS-args, or we can leave it as-is and document the special case for components. I can open a ticket to change the behaviour if I get a +1.

@clalancette
Copy link
Contributor Author

If there's not a strong argument for renaming the node, I'd vote for changing it back to robot_state_publisher. This should make it more straight forward for people not only coming from Eloquent, but also ROS 1.

Yeah, agreed. Will make that change.

Regarding the second point. You don't necessarily have to write the standalone node by hand. I ran into a similar situation when refactoring the image_tools demos and we added this line so that non-ROS CLI args are passed to the node component (accessed with the NodeOptions arguments(), for example).

Oh, nice. I'll play around with this, and make something that has backwards compatibility with the old stuff.

@clalancette
Copy link
Contributor Author

All right, backwards compatibility implemented. I'm pretty close here, there is one last thing not working. On Windows, the trick I'm using to pass the test executable name into the launch file doesn't work for some reason. I'm still debugging that.

@clalancette
Copy link
Contributor Author

And tests fixed on Windows. Here's another CI try:

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status
  • Windows Debug Build Status

@clalancette
Copy link
Contributor Author

All right, all CI is green except for Windows Debug. But the warning there already exists from the nightly: https://ci.ros2.org/view/nightly/job/nightly_win_deb/1509/

Unless there are further objections, I'm going to go ahead and merge this tomorrow morning. Thanks again to @jacobperron and @mjcarroll for reviews!

@clalancette
Copy link
Contributor Author

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status
  • Windows Debug Build Status

Copy link
Contributor

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

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

LGTM!

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.

3 participants