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 cbor-raw compression support (ros2) #574

Merged
merged 9 commits into from
Aug 3, 2021

Conversation

jtbandes
Copy link
Member

@jtbandes jtbandes commented Jul 16, 2021

This PR is an adaptation of #452 for the ros2 branch.

After the initial cherry-pick, a new implementation of the /rosapi/get_topics_and_raw_types service was required for ROS 2, because the generated Python msg classes don't contain the original/combined message definition (see related rosbag2 discussion at ros2/rosbag2#782). To accomplish this, I added a stringify_field_types() which reconstitutes a plausible .msg definition (although without constants or default values) based on the _fields_and_field_types, in the ====-separated format seen in ROS 1 bags, which can be parsed by ROS 2 .msg parsers such as @foxglove/rosmsg.

I hope that stringify_field_types could be removed in the future if message generation is modified to output the original message definition text (ros2/ros2#1159) — I see it as a stopgap solution to get basic compatibility working.

I also modified get_publications_and_types to remove the extra /msg/ from the ROS 2 IDL names, so std_msgs/msg/String becomes std_msgs/String when the list of topics and datatypes are retrieved. This is more in line with what clients migrating from ROS 1 expect.

I had to make a few launch file / parameter changes to get the rosbridge_websocket_launch.xml to work. The test included with #452 is not enabled, because there seems to be no rostest replacement for ROS 2 and I wasn't sure how best to port the test. I noticed that some other tests are also disabled in this branch.

@mvollrath or @dirk-thomas, would you be able to help review this? I'd also be interested in pursuing including this package into Foxy/Galactic/Humble. It looks like it was released in Dashing but has been dropped recently (#536) and I'm not clear if that was intentional, or if it might just take a little shepherding to get it back into a release again.

(I'm also curious if you think there is any future where the ROS 1 and 2 versions of this package might be able to coexist, rather than living as two separate branches forever. It seems like there have already been several changes on develop that aren't in the ros2 branch...)

janpaul123 and others added 4 commits July 16, 2021 00:10
The CBOR compression is already a huge win over JSON or PNG encoding,
but it’s still suboptimal in some situations. This PR adds support for
getting messages in their raw binary (ROS-serialized) format. This has
benefits in the following cases:
- Your application already knows how to parse messages in bag files
  (e.g. using [rosbag.js](https://github.com/cruise-automation/rosbag.js),
  which means that now you can use consistent code paths for both bags
  and live messages.
- You want to parse messages as late as possible, or in parallel, e.g.
  only in the thread or WebWorker that cares about the message. Delaying
  the parsing of the message means that moving or copying the message to
  the thread is cheaper when its in binary form, since no serialization
  between threads is necessary.
- You only care about part of the message, and don't need to parse the
  rest of it.
- You really care about performance; no conversion between the ROS
  binary format and CBOR is done in the rosbridge_sever.
@dirk-thomas
Copy link
Contributor

Sorry, I am not involved in the project anymore.

@jtbandes
Copy link
Member Author

If you happen to know who is currently involved, I’d appreciate a pointer! Thanks

@mvollrath
Copy link
Contributor

(I'm also curious if you think there is any future where the ROS 1 and 2 versions of this package might be able to coexist, rather than living as two separate branches forever. It seems like there have already been several changes on develop that aren't in the ros2 branch...)

Major changes were made to ros1 develop after ros2 was branched, including fixes for backpressure and deadlock conditions. To summarize, in current ros2 websocket server outgoing messages are infinitely queued by Tornado after the implemented rosbridge_library queue/throttle features. This means a client can cause OOM on the server by subscribing to topics and not handling the messages fast enough.

The fix:

  • Outgoing message writes from rosbridge_library are blocked by the WebSocket server until its buffer is below some reasonable level. This newly-connected backpressure is managed by rosbridge_library queue/throttle features.
  • Under some conditions incoming messages can immediately produce outgoing messages, these conditions must be thread-decoupled to prevent deadlocking the WebSocket server while buffer is blocking.

@jtbandes
Copy link
Member Author

Do you see an easy path to backport (forward-port?) these changes to the ros2 branch?

Was there any particular reason the ros2 branch wasn't published in a release since Dashing? I'd love to get this feature in and get it published in some or all of Foxy/Galactic/Humble if possible.

@mvollrath
Copy link
Contributor

Do you see an easy path to backport (forward-port?) these changes to the ros2 branch?

Potentially just re-apply all the PRs, as long as there's E2E tests on the ros2 branch (like there are in ros1 develop) this should be low risk.

Was there any particular reason the ros2 branch wasn't published in a release since Dashing? I'd love to get this feature in and get it published in some or all of Foxy/Galactic/Humble if possible.

Not that I know of, just need somebody to push the button. I don't have any reason to take ownership of this atm.

@jtbandes
Copy link
Member Author

Yep, re-applying the PRs makes sense. Unfortunately it looks like the e2e tests were disabled in one of the initial commits porting to ROS 2. If someone (@dirk-thomas?) could point me at a suitable replacement for rostest, I could work on re-enabling the tests.

Part of my question was also: do you think it's possible to make ros1 and ros2 releases from the same branch of the same repo? That way we wouldn't continue having feature disparities between the two branches. Alternatively, would it make sense to make ros2 the default branch, and treat the ros1 develop branch as bugfix-only?

@mvollrath
Copy link
Contributor

Yep, re-applying the PRs makes sense. Unfortunately it looks like the e2e tests were disabled in one of the initial commits porting to ROS 2. If someone (@dirk-thomas?) could point me at a suitable replacement for rostest, I could work on re-enabling the tests.

I think launch_testing is current practice.

Part of my question was also: do you think it's possible to make ros1 and ros2 releases from the same branch of the same repo? That way we wouldn't continue having feature disparities between the two branches. Alternatively, would it make sense to make ros2 the default branch, and treat the ros1 develop branch as bugfix-only?

Don't think it's practical to use the same branch. Would make sense for ros2 to be default, hopefully everybody understands ROS1 branch is maintenance only since we're now in the final LTS distro.

@jtbandes
Copy link
Member Author

(or maybe rename develop to ros1, and ros2 to develop, or whatever is needed to bring this repo in line with standard branch naming for ROS projects?)

@jihoonl
Copy link
Member

jihoonl commented Jul 21, 2021

I have been in charge of the release process for ros1.

I don't think anyone is in charge of ros2 at the moment. If anyone with proper background steps up for ros2 release responsibility, I am happy to help you.

@jtbandes
Copy link
Member Author

@jihoonl Thanks for the reply. Foxglove would be happy to take responsibility for the ros2 release, but will definitely need your help 🙂 Happy to coordinate here or in our Slack or ROS Discord. I and/or some others from Foxglove will also be at the web tools working group meeting this week.

@jihoonl
Copy link
Member

jihoonl commented Jul 27, 2021

@jtbandes I don't think I am joining the next web tools group meeting. Would you send me an email with one or two github ids on it? I will invite them as maintainers for ros2 branch.

Don't think it's practical to use the same branch. Would make sense for ros2 to be default, hopefully everybody understands ROS1 branch is maintenance only since we're now in the final LTS distro.
(or maybe rename develop to ros1, and ros2 to develop, or whatever is needed to bring this repo in line with standard branch naming for ROS projects?)

I agree that we should set ros2 branch as default at some point. But, I am unsure whether it is the right time to do it.

@esthersweon
Copy link

esthersweon commented Jul 28, 2021

@jihoonl - Hi there, I'm another Foxglove team member. Just sent you an email with the info, as @jtbandes is out this week. Please let me know how I can help get this over the finish line.

@jtbandes jtbandes merged commit aabe697 into RobotWebTools:ros2 Aug 3, 2021
@jtbandes jtbandes deleted the ros2-cbor-raw branch August 3, 2021 21:09
jtbandes added a commit that referenced this pull request Aug 17, 2021
As discussed in #584, type names should look like `rcl_interfaces/msg/Log` rather than `rcl_interfaces/Log`.

I added this "sanitizing" code in #574, and intended to remove it in #584 but forgot.
jtbandes added a commit that referenced this pull request Aug 19, 2021
…uiltin_interfaces in combined definitions (#597)

In #574, I implemented get_topics_and_raw_types by reconstructing message definitions from generated Python code. It recently came to my attention [via ROS Answers](https://answers.ros.org/question/321062/python-rosmsgrospack-in-ros2/?answer=354166#post-id-354166) that `ros2 interface show` and similar tooling actually access the **original** `.msg` files using a function called `rosidl_runtime_py.get_interface_path`. This seems to work reliably enough, and produces better fidelity message definitions (comments, constants, and default values are preserved), so it can be used instead of reconstructing definitions from the generated code.

This PR also removes `/msg/` again from the "raw types" response. In #584 and #591 I made sure `/msg/` was included in datatype names and definitions because it seemed more correct in ROS 2. But while writing this PR, I realized that `.msg` definition files actually do not and **cannot** include `/msg/` in their references to other message types — it is rejected by the [rosidl adapter](https://github.com/ros2/rosidl/blob/36ed120f43daeaab31fd9ba2bf8dfb58db05091d/rosidl_adapter/rosidl_adapter/parser.py#L188-L190) at build time — so I think it should be excluded from the combined definition which is meant to stay as close as possible to the original .msg sources. Still, the **datatype names** do seem to include `/msg/`, so I'm keeping them there. Unfortunately this means that the top-level datatype names don't match the contents of the definitions, but this isn't a big deal since the definitions are all self-contained.

Finally, this PR removes logic that excluded `builtin_interfaces/Time` and `builtin_interfaces/Duration` from the combined message definitions. While these are "builtin" interfaces, they are technically still messages, so it seems more correct to include their contents in the combined definitions: https://groups.google.com/g/ros-sig-ng-ros/c/f7OcEJBj9tU
> Time and Duration are now messages and not built-in types. This is a good thing, because it makes our builtin types more portable. For example, you don’t need to depend on rostime (a C++ library) to use our generated message code.


See also: ros2/ros2#1159
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ros2 ros2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants