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

Porting rosbridge library (capabilities and internal) to ROS2. #419

Merged

Conversation

jubeira
Copy link

@jubeira jubeira commented Jul 16, 2019

See ros2#3.

With this patch, all the code from the entrypoint (Websocket server) up to the internal libraries should be ROS2-compatible, and no references to rclpy or ROS1 code should remain.

Details
  • All the ROS1 code that involves publishers, subscribers and services now need a rclpy.node.Node handle to work.
  • RosbridgeWebsocketNode in rosbridge_websocket module was converted to a ROS2 node because it's near the entry point of the application. A reference to it shall be used to generate publishers, subscribers and service clients where necessary.
  • Besides routing the node handle to all the points of the program where it was required (the deepest point from the entrypoint is the internal package), there were a few features from ROS1 that changed a bit, so workarounds had to be found:
    • In publishers module inside internal, a ROS1 SubscriberListener was used to prevent late-joining subscribers from missing messages. This is now achieved using transient local QoS with a lifespan.
    • At the same time, there was support for latched topics. This now applies for publishers and subscribers, so transient local is the QoS of choice for subscribers as well.
    • In subscribers module, additional subscriber callbacks were used to send latched messages to new (web) subscribers using only one ROS subscriber. Since this is not available in ROS2 (at least not that I know of), a workaround was implemented and tested in a minimal example.
  • In message_conversion, the parameters don't seem to be used in the original code. For a first iteration, using defaults should work.

@jubeira jubeira self-assigned this Jul 16, 2019
@jubeira
Copy link
Author

jubeira commented Jul 16, 2019

@ivanpauno I can't add you as a reviewer, but would you please take an initial look?

/cc @dirk-thomas

Copy link

@ivanpauno ivanpauno left a comment

Choose a reason for hiding this comment

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

I left a bunch of comments. It's looking good.

""" Register a publisher on the specified topic.

Keyword arguments:
topic -- the name of the topic to register the publisher to
node_handle -- Handle to a rclpy node to create the publisher.
msg_type -- (optional) the type to register the publisher as. If not
provided, an attempt will be made to infer the topic type
latch -- (optional) if a client requested this publisher to be latched,

Choose a reason for hiding this comment

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

latch is not actually the keyword name. queue_size is undocumented.
That patch could be send to master.

rosbridge_server/scripts/rosbridge_websocket.py Outdated Show resolved Hide resolved
rosbridge_server/scripts/rosbridge_websocket.py Outdated Show resolved Hide resolved
rosbridge_server/scripts/rosbridge_websocket.py Outdated Show resolved Hide resolved
rosbridge_server/scripts/rosbridge_websocket.py Outdated Show resolved Hide resolved
for element in params_glob[1:-1].split(',')
if len(element.strip().strip("'")) > 0]

if "--port" in sys.argv:

Choose a reason for hiding this comment

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

I would consider start using argparse.

Choose a reason for hiding this comment

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

Maybe, that can be done in the original code too.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this seems to be like a manually implemented argparse. I'd say it's out of scope of this PR.

@wjwwood wjwwood mentioned this pull request Jul 23, 2019
34 tasks
@jubeira jubeira changed the base branch from ros2_ament_cmake to ros2 August 22, 2019 18:41
- Connecting to main entrypoint where necessary to get node handles.
- Updating to Dashing API.
- Initial E2E tests passing for topics, services and parameters.

Signed-off-by: Juan Ignacio Ubeira <jubeira@ekumenlabs.com>
@jubeira jubeira force-pushed the ros2_port/rosbridge_library_package branch from 9161521 to 184b462 Compare August 24, 2019 22:44
@jubeira
Copy link
Author

jubeira commented Aug 24, 2019

This was rebased against develop; the latest changes were ported to ROS2 as well.

Initial E2E tests are passing for topics, services and parameters using standard roslibjs. This is ready for another review.

Copy link

@ivanpauno ivanpauno left a comment

Choose a reason for hiding this comment

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

I left some comments and questions, otherwise LGTM.

How will this be tested? Will this repo be added to ros2 build farm or will it be tested in another place?

@@ -1,3 +1,2 @@
string node_name
string name
---

Choose a reason for hiding this comment

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

Unrelated, but add new line before EOF (develop should be corrected too).

@@ -1,3 +1,2 @@
string node_name
---
string[] names

Choose a reason for hiding this comment

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

same

@@ -1,4 +1,3 @@
string node_name
string name
---
bool exists

Choose a reason for hiding this comment

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

same

@@ -1,4 +1,3 @@
string node_name
string name
string value
---

Choose a reason for hiding this comment

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

same

self.globs = self.get_globs()
self.register_services()

# Initialises the ROS node
def register_services(self):
proxy.init(self)
params.init()
params.init(self.NAME)

Choose a reason for hiding this comment

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

Node name could have been remapped, use self.get_name, probably combined with self.get_namespace for getting the full name (get_fully_qualified_name method should be added to rclpy Node).

Choose a reason for hiding this comment

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

rclcpp Node class has a get_fully_qualified_name method

Copy link
Author

Choose a reason for hiding this comment

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

+1.
The code in the node already needs that internally:
https://github.com/ros2/rclpy/blob/0.7.5/rclpy/rclpy/node.py#L682-L686; a helper method could be a good idea.

@@ -51,7 +51,7 @@
"int": ["int8", "byte", "uint8", "char",
"int16", "uint16", "int32", "uint32",
"int64", "uint64", "float32", "float64"],
"float": ["float32", "float64"],
"float": ["float32", "float64", "double"],

Choose a reason for hiding this comment

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

Why has double been added?

Copy link
Author

Choose a reason for hiding this comment

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

That's the type you get in a ROS2 message when analyzing slots and types.
E.g. for a geometry_msgs/Vector3:

    __slots__ = [
        '_x',
        '_y',
        '_z',
    ]

    _fields_and_field_types = {
        'x': 'double',
        'y': 'double',
        'z': 'double',
    }

@@ -165,7 +198,7 @@ def _from_list_inst(inst, rostype):
return []

# Remove the list indicators from the rostype
rostype = list_braces.sub("", rostype)
rostype = re.search(list_tokens, rostype).group(1)

# Shortcut for primitives
if rostype in ros_primitive_types and not rostype in ["float32", "float64"]:

Choose a reason for hiding this comment

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

double?

@@ -199,6 +199,8 @@ def _splittype(typestring):
splits = [x for x in typestring.split("/") if x]
if len(splits) == 2:
return splits
elif len(splits) == 3:
return (splits[0], splits[2])

Choose a reason for hiding this comment

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

return [splits[0], splits[2]
for consistency, always return a list.

<buildtool_depend>rosidl_default_generators</buildtool_depend>

<exec_depend>rclpy</exec_depend>
<exec_depend>rcl_interfaces</exec_depend>

Choose a reason for hiding this comment

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

I think there is a build_depend on builtin_interfaces and there is no dependency on rcl_interfaces, right?

from rosbridge_msgs.msg import ConnectedClient, ConnectedClients
from std_msgs.msg import Int32


class ClientManager:
def __init__(self):
def __init__(self, node_handle):
qos = QoSProfile(depth=10,

Choose a reason for hiding this comment

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

Consider depth=1. I think that in ROS 1 with a latched topic and depth=10, you only got the last message in a late subscriber.
But in ROS 2 transient local durability with depth=10 will result in late subscribers receiving the last 10 messages.

Signed-off-by: Juan Ignacio Ubeira <jubeira@ekumenlabs.com>
@jubeira
Copy link
Author

jubeira commented Sep 2, 2019

@gonzodepedro would you please take one more look? Thanks!

Copy link

@gonzodepedro gonzodepedro left a comment

Choose a reason for hiding this comment

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

LGTM

@jubeira jubeira merged commit 8dea92f into RobotWebTools:ros2 Sep 9, 2019
@jubeira jubeira deleted the ros2_port/rosbridge_library_package branch September 9, 2019 17:06
@jubeira
Copy link
Author

jubeira commented Sep 9, 2019

Thanks @gonzodepedro !

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