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

Implement service recording and display info about recorded services #1480

Merged

Conversation

Barry-Xu-2018
Copy link
Contributor

@Barry-Xu-2018 Barry-Xu-2018 commented Oct 13, 2023

Split #1414 to 2 PRs.
This is first PR. This PR implement service record and recorded service info display.

⚠️ This PR depended on ros2/rclcpp#2209

@Barry-Xu-2018 Barry-Xu-2018 requested a review from a team as a code owner October 13, 2023 00:55
@Barry-Xu-2018 Barry-Xu-2018 requested review from MichaelOrlov and james-rms and removed request for a team October 13, 2023 00:55
@Barry-Xu-2018
Copy link
Contributor Author

Barry-Xu-2018 commented Oct 13, 2023

The comments are from MichaelOrlov (#1414 (review))
Comments related to this PR (marked as ✅) will be handled in this PR.


I have made a first pass of the review and here is my major notes and proposals:


  1. It seems we don’t have tests for the rosbag2_cpp::Info::read_service_info(...) and Python wrapper for information about services. It would be nice to add at least one sanity check.


  2. I have a proposal about new parameters for topic/services exclusions:

    Keep the old parameter exclude but rename it to the exclude_regex. it will be applicable to both topics and services.
    Make exclude_topics and exclude_services as std::vectorstd::string i.e. space separated list of topics and services names for CLI arguments.
    IMO it will be more user-friendly. We have had recently an incoming issue from one of the users when it was expected that the exclude parameter is a list of topics. Like opposite to the topics parameter.
    It looks intuitively reasonable to expect it to be defined this way.

  3. Handle in Support service 2/2 --- rosbag2 service play #1481
    I would like to request to rename PlayerClient to the PlayerServiceClient and consider moving it to its own separate cpp and hpp files.
    The PlayerClient is pretty large and independent from its parent PlayerImpl class. We already have a lot of code inside the Player class and with this inner class inside it will become more cluttered and more difficult to navigate and support.

  4. Handle in Support service 2/2 --- rosbag2 service play #1481
    We are doing deserialization for the same service message twice. Once in the PlayerClient::is_include_request_message(..) and the second time in the PlayerClient::async_send_request(). This is an expensive procedure.
    I would like to request structural changes there.
    Could you please rework is_include_request_message(..) to the get_service_request_message(serialized_message) and return smart pointer to the deserialized message? If there are no valid request message it will return a pointer to null. Then rework async_send_request(deserialized_message) to accept those smart pointer to the already deserialized message.

  5. Handle in Support service 2/2 --- rosbag2 service play #1481
    I also have a concern about PlayerClient::async_send_request. We can’t really make it sending request asynchronously at least with the current design. Because we need to wait for future returning from client_->async_send_request(..). Since we can't delete ros_message until the future complete. Otherwise, it will be a dangling pointer to the request_addr and memory could be reused and we have a chance to use corrupted memory during the client_->async_send_request(..). Also according to the notes in the client_->async_send_request(..) API need to call client_->remove_pending_request(future) if we wait for future and timeout happened.
    As a first iteration, I would suggest to making sending client request synchronous with timeout. Then need to figure out how to design it to be asynchronous.
    I have idea to create some static worker thread and wait in it for static condition variable by timeout and check for future. If another request needs to be sent we can signal to condition variable to interrupt the wait earlier than timeout, remove_pending_request(future) and then try to send the new service request.

ros2bag/ros2bag/verb/record.py Outdated Show resolved Hide resolved
ros2bag/ros2bag/verb/record.py Outdated Show resolved Hide resolved
rosbag2_cpp/src/rosbag2_cpp/info.cpp Outdated Show resolved Hide resolved
rosbag2_cpp/src/rosbag2_cpp/info.cpp Outdated Show resolved Hide resolved
rosbag2_py/src/rosbag2_py/format_service_info.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/recorder.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
@Barry-Xu-2018
Copy link
Contributor Author

@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov

One case would like to discuss it with you.
While recording, user set --topics or --services and --regex at the same time.
Current process as below:

  1. Check if topic or service is in topic list or service list.
  2. Check if topic or service matches regular expression.

That is, the filtered topic or service must match 1 and 2 at the same time.
Whether is it better for user to change to match 1 or 2 ?

exclude parameter also has the same problem.

I'd like to hear your opinions.

@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 As regards

One case would like to discuss it with you.
While recording, user set --topics or --services and --regex at the same time.
Current process as below:

Check if topic or service is in topic list or service list.
Check if topic or service matches regular expression.
That is, the filtered topic or service must match 1 and 2 at the same time.
Whether is it better for user to change to match 1 or 2 ?

exclude parameter also has the same problem.

I'd like to hear your opinions.

I would expect if the user explicitly specifies --topics or --services and --regex at the same time then 1 or 2 logic should be applied as you mentioned above. Otherwise, it might be tedious for users to write a regex string which will satisfy both conditions.
Feel free to change the current logic for filtering in case if both topics or services and regex parameters are applied.

Copy link
Contributor

@MichaelOrlov MichaelOrlov left a comment

Choose a reason for hiding this comment

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

@Barry-Xu-2018 Thank you for addressing the review comments.
I've run one more round of review. I found a few minor things to change.
Also, I have a concern about the way the tests are written in the test_info.cpp.
On one hand, using the generated bag files in tests is a working approach, however on the other hand it will be difficult to support such test infrastructure in the future.
Sometimes we make changes in the bag format of metadata and have to regenerate all bags written for tests.
It would be better to write bags on the fly from each test to the temporary folder.
Could you please change tests this way?
You can find an example of how to write test bags on the fly in the other tests in the rosbag2_cpp package. For instance this one.

TEST_P(ParametrizedTemporaryDirectoryFixture, info_for_standalone_bagfile) {
  const auto storage_id = GetParam();
  const auto bag_path = rcpputils::fs::path(temporary_dir_path_) / "bag";
  {
    // Create an empty bag with default storage
    rosbag2_cpp::Writer writer;
    rosbag2_storage::StorageOptions storage_options;
    storage_options.storage_id = storage_id;
    storage_options.uri = bag_path.string();
    writer.open(storage_options);
    test_msgs::msg::BasicTypes msg;
    writer.write(msg, "testtopic", rclcpp::Time{});
  }

ros2bag/ros2bag/verb/record.py Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@MichaelOrlov MichaelOrlov left a comment

Choose a reason for hiding this comment

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

@Barry-Xu-2018 I made one more round of review.
We are certainly getting close to the finish, but tests still need some "love".
In the current state, almost all newly added tests tend to be flaky and written in non-deterministic way and rely on the ambient delays between critical operations.
I decided to speed up our review and development process and contribute to the tests stability.
I've made a PR Barry-Xu-2018#1 with base to this branch.
Please review my changes and if you don't have any concerns or requests for changes please feel free to merge on your branch.
cc: @fujitatomoya

@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov

We are certainly getting close to the finish, but tests still need some "love".
In the current state, almost all newly added tests tend to be flaky and written in non-deterministic way and rely on the ambient delays between critical operations.
I decided to speed up our review and development process and contribute to the tests stability.
I've made a PR Barry-Xu-2018#1 with base to this branch.
Please review my changes and if you don't have any concerns or requests for changes please feel free to merge on your branch.

Thank you for your assistance.

@Barry-Xu-2018 Barry-Xu-2018 force-pushed the review/rosbag2_service_record_and_show branch from ab62249 to 6a39627 Compare November 14, 2023 01:35
@Barry-Xu-2018
Copy link
Contributor Author

Do rebase since there are conflicts with rolling branch.

docs/message_definition_encoding.md Show resolved Hide resolved
ros2bag/ros2bag/verb/info.py Show resolved Hide resolved
ros2bag/ros2bag/verb/record.py Show resolved Hide resolved
Comment on lines +146 to +150
case service_msgs::msg::ServiceEventInfo::REQUEST_SENT:
case service_msgs::msg::ServiceEventInfo::REQUEST_RECEIVED:
service_process_info[bag_msg->topic_name]->request[msg.client_gid].emplace(
msg.sequence_number);
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

because of ros2/rmw#357, we cannot tell these messages at all, right? is this the current constraints or do we have work-around for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.
From the code perspective, we don't have a workaround.
We have to request that users do not enable service and client introspection simultaneously as a workaround.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Barry-Xu-2018 Wouldn't you mind creating a follow-up issue to not forget to change behavior when ros2/rmw#357 will be resolved?

rosbag2_cpp/src/rosbag2_cpp/service_utils.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/qos.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
rosbag2_transport/src/rosbag2_transport/topic_filter.cpp Outdated Show resolved Hide resolved
@fujitatomoya
Copy link
Contributor

@Barry-Xu-2018 i think we are getting closer on this, well tested i think. there are a few need-to-fix comments, please have a look at my comments.

@fujitatomoya
Copy link
Contributor

I will take a look at #1481 after this one has been merged. i think we need to rebase #1481 once this one is merged.

Copy link
Contributor

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

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

@Barry-Xu-2018 thanks for the comments. i do not have further comments, lgtm with green CI.
CC: @MichaelOrlov

@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 @fujitatomoya I need to recap what has been changed recently and what is yet unclear or unresolved from my questions.

Copy link
Contributor

@MichaelOrlov MichaelOrlov left a comment

Choose a reason for hiding this comment

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

@Barry-Xu-2018 I made one more round of review.
I have a few major concerns:

  1. As per my comment in the Implement service recording and display info about recorded services #1480 (comment) The service_in_list(..) function is redundant and introduces some confusion and potentially could be a source of errors in the future.
  2. As per my comment in the Implement service recording and display info about recorded services #1480 (comment) Relying on the assumption that embedded service dependencies will be always in the MSG files is totally wrong!
    This is a valid scenario when the service's type dependencies could be in IDL files. Need to properly handle this case and correctly detect and save in what encoding message definition is stored for further proper decoding on playback.
  3. There are some leftovers after rebase. Need to delete rosbag2_transport/qos.cpp. Since it was moved to the rosbag2_storage package and there are some delta from prior PRs. Delta from the rosbag2_transport/qos.cpp shall be disregarded as per our common agreement here Implement service recording and display info about recorded services #1480 (comment)

To avoid long ping-pong in review and speed up process I've made all fixes which I think shall be done for this PR in the separate branch and prepared a PR Barry-Xu-2018#2. Please review it. If you have no concerns or comments feel free to merge it on your branch or cherry-pick my commits.

@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov

Thank you for your comments.

As per my comment in the #1480 (comment) The service_in_list(..) function is redundant and introduces some confusion and potentially could be a source of errors in the future.

Okay. The comparison is actually based on the topic name.

As per my comment in the #1480 (comment) Relying on the assumption that embedded service dependencies will be always in the MSG files is totally wrong!
This is a valid scenario when the service's type dependencies could be in IDL files. Need to properly handle this case and correctly detect and save in what encoding message definition is stored for further proper decoding on playback.

Yes, I didn't consider this scenario in my implementation.
Thank you for helping to improve the code.

There are some leftovers after rebase. Need to delete rosbag2_transport/qos.cpp. Since it was moved to the rosbag2_storage package and there are some delta from prior PRs. Delta from the rosbag2_transport/qos.cpp shall be disregarded as per our common agreement here #1480 (comment)

Yes.

To avoid long ping-pong in review and speed up process I've made all fixes which I think shall be done for this PR in the separate branch and prepared a PR Barry-Xu-2018#2. Please review it. If you have no concerns or comments feel free to merge it on your branch or cherry-pick my commits.

After review, LGTM.
I merged it. Thank you.

Copy link
Contributor

@MichaelOrlov MichaelOrlov left a comment

Choose a reason for hiding this comment

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

@Barry-Xu-2018 Thank you, now LGTM with green CI.
Also please fix DCO. There is one missing signature for one commit.

@MichaelOrlov MichaelOrlov removed the request for review from james-rms December 14, 2023 06:35
@MichaelOrlov MichaelOrlov changed the title Support service 1/2 --- Implement service record and recorded service info display Implement service recording and display info about recorded services Dec 14, 2023
@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 Windows build fails with error message:

rosbag2_format_output.vcxproj -> C:\ci\ws\build\rosbag2_py\Release\rosbag2_format_output.dll

  Building Custom Rule C:/ci/ws/src/Barry-Xu-2018/rosbag2/rosbag2_py/CMakeLists.txt

  _info.cpp

LINK : fatal error LNK1181: cannot open input file 'Release\rosbag2_format_output.lib' [C:\ci\ws\build\rosbag2_py\_info.vcxproj]

Signed-off-by: Barry Xu <barry.xu@sony.com>
@Barry-Xu-2018 Barry-Xu-2018 force-pushed the review/rosbag2_service_record_and_show branch from 02494e9 to 25653d0 Compare December 15, 2023 02:17
@ros-discourse
Copy link

This pull request has been mentioned on ROS Discourse. There might be relevant details there:

https://discourse.ros.org/t/ros-2-tsc-meeting-minutes-for-2023-12-14/35153/1

Signed-off-by: Barry Xu <barry.xu@sony.com>
@MichaelOrlov
Copy link
Contributor

Re-run CI after an attempt to fix Windows build errors by adding visibility control to the new CPP library

BUILD args: --packages-above-and-dependencies ros2bag rosbag2_cpp rosbag2_py rosbag2_test_common rosbag2_test_msgdefs rosbag2_transport rosbag2_tests
TEST args: --packages-above ros2bag rosbag2_cpp rosbag2_py rosbag2_test_common rosbag2_test_msgdefs rosbag2_transport rosbag2_tests
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/13062

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

@fujitatomoya
Copy link
Contributor

@Barry-Xu-2018 @MichaelOrlov thank you very much! 🤞🤞🤞

@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 Sorry the Windows CI is still unhappy.
There are warnings which need to be addressed.

format_bag_metadata.cpp:229	[C4273]  'format_bag_meta_data': inconsistent dll linkage

and the same warning for the format_service_info

But before start fixing those warnings, I have a question. Why do you need those rosbag2_format_output library at all?
I would just use a regular includes in the _storage.cpp and _info.cpp since all of these references and dependencies are in the scope of the same package, creating a separate library looks like overengineering IMO.
Or maybe I am missing some valuable point?

- Also put `format_service_info(..)` and `format_bag_meta_data(..)`
under the rosbag2_py namespace

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 I've made a quick prototype and it seems the code compiles without errors and warnings without rosbag2_format_output library. All tests on my local setup are passing.
See my PR Barry-Xu-2018#4

Please note I've put newly exposed API under the rosbag2_py namespace. If you decided to go with option to keep rosbag2_format_output library will need to do the same and put header files under the separate include folder.

@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov MichaelOrlov

But before start fixing those warnings, I have a question. Why do you need those rosbag2_format_output library at all?
I would just use a regular includes in the _storage.cpp and _info.cpp since all of these references and dependencies are in the scope of the same package, creating a separate library looks like overengineering IMO.
Or maybe I am missing some valuable point?

As you changed, the same code format_bag_metadata.cpp are included in _storage and _info.

pybind11_add_module(_storage SHARED
  src/rosbag2_py/_storage.cpp
  src/rosbag2_py/format_bag_metadata.cpp
)
...
pybind11_add_module(_info SHARED
  src/rosbag2_py/_info.cpp
  src/rosbag2_py/format_bag_metadata.cpp
  src/rosbag2_py/format_service_info.cpp
)

I considered this approach at the beginning, which would be simpler. However, it would result in duplicate code being compiled into different libraries, which could raise questions during review. So, I decided to compile this part of the code into libraries.
Based on your suggested modifications, the simpler approach seems like the better choice. I agree with that.

@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov

I've made a quick prototype and it seems the code compiles without errors and warnings without rosbag2_format_output library. All tests on my local setup are passing.
See my PR Barry-Xu-2018#4

Thank you.
There are minor comments. Please look at Barry-Xu-2018#4

MichaelOrlov and others added 2 commits December 20, 2023 22:39
….hpp

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
…_service_recording

Replace rosbag2_format_output by direct source files linkage
@Barry-Xu-2018
Copy link
Contributor Author

@MichaelOrlov

Barry-Xu-2018#4 has been merged.
Could you run CI again ?

@MichaelOrlov
Copy link
Contributor

Re-run CI after removing rosbag2_format_output cpp library and deleting visibility_control.hpp file

BUILD args: --packages-above-and-dependencies ros2bag rosbag2_cpp rosbag2_py rosbag2_test_common rosbag2_test_msgdefs rosbag2_transport rosbag2_tests
TEST args: --packages-above ros2bag rosbag2_cpp rosbag2_py rosbag2_test_common rosbag2_test_msgdefs rosbag2_transport rosbag2_tests
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/13068

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

@MichaelOrlov MichaelOrlov merged commit 3286736 into ros2:rolling Dec 21, 2023
14 checks passed
@MichaelOrlov
Copy link
Contributor

@Barry-Xu-2018 @fujitatomoya Thank you for your initiative and for driving this large PR.
The PR has finally been merged. Yeah, we made it! 🎆
ROS 2 and rosbag2 became even better than they were before with this PR.
The ability to record service events for further service calls introspection will be a very valuable feature in the future for many developers.
We can count it as a good Christmas gift 🎁
Merry Christmas and Happy Holidays.

@Barry-Xu-2018
Copy link
Contributor Author

Barry-Xu-2018 commented Dec 22, 2023

@MichaelOrlov

Merry Christmas and Enjoy your holiday 🎄 🎇 !
I will start to rebase PR #1481.

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