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

Add Python examples for tf2_ros #161

Merged
merged 14 commits into from
Nov 19, 2019
Merged

Add Python examples for tf2_ros #161

merged 14 commits into from
Nov 19, 2019

Conversation

sloretz
Copy link
Contributor

@sloretz sloretz commented Aug 31, 2019

Requires #99 ✔️
Requires #160 ✔️
Requires ros2/rclpy#412 ✔️

This adds a package with examples on how to use the tf2 Python API.

@sloretz sloretz added the in review Waiting for review (Kanban column) label Aug 31, 2019
@sloretz sloretz self-assigned this Aug 31, 2019
@sloretz sloretz added in progress Actively being worked on (Kanban column) and removed in review Waiting for review (Kanban column) labels Aug 31, 2019
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
@sloretz sloretz added in review Waiting for review (Kanban column) and removed in progress Actively being worked on (Kanban column) labels Nov 12, 2019
@sloretz
Copy link
Contributor Author

sloretz commented Nov 12, 2019

Looks like the examples work with the latest eloquent debs. This PR is ready for review.

Copy link
Contributor

@clalancette clalancette left a comment

Choose a reason for hiding this comment

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

I've got a few easy things to fix, and a few questions.

examples_tf2_py/README.md Outdated Show resolved Hide resolved
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we typically eschew the shebang nowadays, correct? In that case, please remove it. (the same comment applies several other times below)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Replaced shebang with copyright comment in 48ca46e

@@ -0,0 +1,64 @@
#!/usr/bin/env python3

import math
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't seem like we are actually using the math library here. Please remove.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added linter tests in e0479dc and fixed linter errors in 48ca46e

except KeyboardInterrupt:
pass
rclpy.shutdown()

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: trailing whitespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added linter tests in e0479dc and fixed linter errors in 48ca46e

examples_tf2_py/examples_tf2_py/dynamic_broadcaster.py Outdated Show resolved Hide resolved
examples_tf2_py/examples_tf2_py/static_broadcaster.py Outdated Show resolved Hide resolved
try:
# Block until the transform is available
when = rclpy.time.Time()
self._tf_buffer.lookup_transform(
Copy link
Contributor

Choose a reason for hiding this comment

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

When not using coroutines, what's our recommendations for doing lookups like this? Is it really to block in the callback? Obviously this works with a MultiThreadedExecutor, but it seems like blocking up any of the executor threads is problematic. I'm just wondering whether we should have this example at all, or if we should suggest something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When not using coroutines, what's our recommendations for doing lookups like this? Is it really to block in the callback?

I think so. Maybe someone could start a dedicated thread to poll for the transform? It would be nice if there was an api that called a callback when a transform became ready.

I'm just wondering whether we should have this example at all, or if we should suggest something else?

The API exists and this calls out in docstrings and comments that the blocking behavior is a problem. However, I would always use coroutines instead of the blocking API. I think the example should exist since the comments could steer someone to use the coroutine API instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so. Maybe someone could start a dedicated thread to poll for the transform? It would be nice if there was an api that called a callback when a transform became ready.

Oh yeah, good call.

So I'm OK with adding this example, as this is something people will want to do. But I'll request two things here:

  1. Open an issue to have a callback-based reply to lookup_transform.
  2. Update the comment right above this call, or in the class header (your choice) to be a little more strong and suggest to always use the coroutine way instead.

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 looks like it should be possible to avoid blocking without coroutines, but I encountered an issues ros2/rclpy#460, but that should be fixed by ros2/rclpy#461. I added a second example in 9c74ebc, but it could be made simpler if the result included the transform, so I opened #194 too.

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
@sloretz
Copy link
Contributor Author

sloretz commented Nov 15, 2019

Ready for 2nd round of review

Copy link
Contributor

@clalancette clalancette left a comment

Choose a reason for hiding this comment

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

One more request, then this is ready to go from my perspective.

try:
# Block until the transform is available
when = rclpy.time.Time()
self._tf_buffer.lookup_transform(
Copy link
Contributor

Choose a reason for hiding this comment

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

I think so. Maybe someone could start a dedicated thread to poll for the transform? It would be nice if there was an api that called a callback when a transform became ready.

Oh yeah, good call.

So I'm OK with adding this example, as this is something people will want to do. But I'll request two things here:

  1. Open an issue to have a callback-based reply to lookup_transform.
  2. Update the comment right above this call, or in the class header (your choice) to be a little more strong and suggest to always use the coroutine way instead.

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Comment on lines +42 to +46
self._lock = threading.Lock()
self._tf_future = None
self._from_frame = None
self._to_frame = None
self._when = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, I think there's a race condition here at startup time. I think it could be the case that on_timer fires before we initialize the lock and set these variables to None, in which case bad things may happen. I'll suggest moving this initialization near the top of the constructor.

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 think it's ok. The timer callback can't be called until the node is added to an executor, and that can't happen until after __init__() is finished.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, you are totally right. Sorry about that, will approve.

@sloretz
Copy link
Contributor Author

sloretz commented Nov 19, 2019

CI (only testing examples_tf2_py)

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

@sloretz sloretz merged commit 93ad54a into ros2 Nov 19, 2019
@wuffle-ros wuffle-ros bot removed the in review Waiting for review (Kanban column) label Nov 19, 2019
@delete-merged-branch delete-merged-branch bot deleted the examples_tf2_py branch November 19, 2019 18:22
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.

4 participants