-
Notifications
You must be signed in to change notification settings - Fork 253
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 support for replaying multiple bags #1848
Conversation
8315454
to
a7d712b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @christophebedard, Thank you for your contribution.
After thoroughly reviewing and considering the newly added class MetaPriorityQueue
.
I think it will not be much more efficient than std::priority_queue
protected with mutex from the STL.
For a few reasons:
- The MetaPriorityQueue push(message) and pop() became blocking calls and also had to be protected by a mutex.
- We impose a constraint on the
MetaPriorityQueue
that items queued into the same queue shall be in order of priority. That might not be true if we need to switch playback to usesend_timestamp
. - If considering performance, the
std::priority_queue
has log(n) runtime complexity for insertion and extraction operations and constant for peaking maximum element. While we are trying to achieve a constant time performance when using lock-free queues for relatively small numbers, the log(n) overhead is going to be very insignificant. For instance, we currently use 1000 elements for the queue by default. If we try to read out from 5 files and increase the maximum queue size by a factor of 5, i.e., to be 5000 elements, the log(5000) = 8.5. In the worst-case scenario, we will require 8.5 pointers swaps or iterations in the array. In comparison to the current design withMetaPriorityQueue
, we will have at least 5 iterations over 5 queues trying to find and update the current minimum index, and also, the overall underlying implementation of the lock-free queue, is not free and has some extra operations inside. The difference is going to be in the numbers of the 5-8 iterations over the array or swaps. Which is IMO negligible in this case.
I would prefer to have a more cleaner and straightforward impelmentation based on thestd::priority_queue
.
4ddc5fb
to
0ec79d3
Compare
0ec79d3
to
46e7c7f
Compare
46e7c7f
to
06ad64c
Compare
Changed to |
rosbag2_transport/src/rosbag2_transport/locked_priority_queue.hpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christophebedard Thanks for the updates and one more iteration.
Overall seems logically correct. See my comments and requests for changes inline.
rosbag2_transport/src/rosbag2_transport/locked_priority_queue.hpp
Outdated
Show resolved
Hide resolved
rosbag2_transport/src/rosbag2_transport/locked_priority_queue.hpp
Outdated
Show resolved
Hide resolved
rosbag2_transport/src/rosbag2_transport/locked_priority_queue.hpp
Outdated
Show resolved
Hide resolved
I'll rebase and fix the DCO & merge conflicts once the new changes look good. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christophebedard Thank you for the next round of changes and improvements.
I started liking the way how it is implemented.
I've made one more round of review. Mostly in the rosbag2_transport player classes. See my comments inline.
I also noticed that if we will not change get_storage_options()
API in the player.hpp file, this PR will likely become API/ABI compatible, and we will be able to backport it to Jazzy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christophebedard I've verified previous changes and made one more round of full review.
I have some suggestions for improvements but they are not require changes in the logic.
One of the generic suggestions is to rename local variables and constructor parameters input_bags
as well as private class member variable input_bags_
to the readers_with_options
.
IMO it is more clear what it is from the name. It will be helpful for future code supportability. at least for the local member variables and ctor parameters.
Another comment is to create a separate add_standard_multi_reader_args(parser: ArgumentParser)
function.
The rationale for that request is a difference in behavior. i.e., We deprecate --storage and provide --input parameters only for the ros2 bag play verb. The logic in the combined function became overcomplicated and not clear what is applied and when.
Also, see my other comments inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christophebedard Thank you for addressing all comments.
Now looks good to me.
Please rebase and fix DCO.
a1ad63d
to
a82f259
Compare
Signed-off-by: Christophe Bedard <[email protected]>
a82f259
to
eeca3aa
Compare
I just squashed to fix the DCO and rebased. I also fixed a linter issue: https://github.com/ros2/rosbag2/compare/a82f2597188a67cb11752815481d130fec18a9bb..eeca3aad929d4b5d7c6882d47ddc128af4a09181 |
@christophebedard It seems we've got a regression in rosbag2_transport tests on RPR job: https://build.ros2.org/job/Rpr__rosbag2__ubuntu_noble_amd64/448/testReport/ |
@ros-pull-request-builder retest this please |
It seems it was a false alarm. The RPR job passed green from the second start. I also was not able to reproduce any failures on my local setup. Running full CI then. |
Pulls: #1848 |
Two warnings on the Windows build are in the StaticSingleThreaded executor
and unrelated to the changes from this PR. Merging then to the Rolling. cc: @christophebedard I changed a bit PR description and title to be more descriptive for others. |
I ran the |
Thanks for the review, @MichaelOrlov |
https://github.com/Mergifyio backport jazzy |
✅ Backports have been created
|
Signed-off-by: Christophe Bedard <[email protected]> (cherry picked from commit 125db50) # Conflicts: # shared_queues_vendor/CHANGELOG.rst # shared_queues_vendor/package.xml
* Support replaying multiple bags (#1848) Signed-off-by: Christophe Bedard <[email protected]> (cherry picked from commit 125db50) # Conflicts: # shared_queues_vendor/CHANGELOG.rst # shared_queues_vendor/package.xml * Revert shared_queue_vendor package deletion Signed-off-by: Michael Orlov <[email protected]> --------- Signed-off-by: Michael Orlov <[email protected]> Co-authored-by: Christophe Bedard <[email protected]> Co-authored-by: Michael Orlov <[email protected]>
@MichaelOrlov should I proceed with marking some of the old APIs (i.e., single input bag) as deprecated? In Rolling only, of course. |
@christophebedard Yes please. I would appreciate a follow-up PR. |
This PR adds support for replaying multiple bags with
ros2 bag play
and the underlying classes (rosbag2_transport::Player
/rosbag2_py::Player
).To replay multiple bags, use the new
-i,--input
CLI option.Like with the
ros2 bag convert
option, the-i,--input
option takes an URI to the bag folder or dedicated bag file and an optional explicit storage ID. This option can be used multiple times to be able to specify multiple bags. We keep thebag_path
positional argument for backward compatibility and simplicity of usage in cases where users need to play just one bag file. However, the standalone--storage
CLI option has been deprecated. In the future, users will need to use-i bag [storage_id]
if they need to specify the storage ID explicitly.The
rosbag2_transport::Player
now uses astd::priority_queue
, which required changing the logic and interaction betweenPlayerImpl::play_messages_from_queue()
andPlayerImpl::play_next()
. In short, message publication is now all handled byPlayerImpl::play_messages_from_queue()
.PlayerImpl::play_next()
simply tells it to play the next message and then waits for the result. While the queue is not lock-free anymore, this change does simplify the interaction betweenPlayerImpl::play_messages_from_queue()
andPlayerImpl::play_next()
a bit. Note: the priority queue depth is defined by the--read-ahead-queue-size
CLI option, which is set to 1000 elements by default.Messages are played in order, based on their
recv_timestamp
(recorder reception timestamp). However, with the priority queue, this could eventually be changed (e.g., throughPlayOptions
) to thesend_timestamp
(original publication timestamp).Other notes for reviewers:
ros2 bag convert
, I added the-i, --input
option that takes a bag URI and an optional explicit storage ID. This option can be used multiple times for multiple bags.bag_path
positional argument (but made it optional) because it is quite nice to be able to just doros2 bag play my-bag
. However, I deprecated the storage ID option (--storage
); users will have to use-i, --input
to specify an explicit storage ID for an input bag.jazzy
branch. Some APIs needed to be added (mainly constructors) to support N input bags.