Skip to content

Commit 616df0d

Browse files
committed
Start adding progress-bar for ros2 bag play
Signed-off-by: Nicola Loi <[email protected]>
1 parent 9774138 commit 616df0d

File tree

6 files changed

+126
-0
lines changed

6 files changed

+126
-0
lines changed

ros2bag/ros2bag/verb/play.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ def add_arguments(self, parser, cli_name): # noqa: D102
168168
'--log-level', type=str, default='info',
169169
choices=['debug', 'info', 'warn', 'error', 'fatal'],
170170
help='Logging level.')
171+
parser.add_argument(
172+
'--progress-bar', action='store_true', default=False,
173+
help='Print a progress bar of the playback player.')
171174

172175
def get_playback_until_from_arg_group(self, playback_until_sec, playback_until_nsec) -> int:
173176
nano_scale = 1000 * 1000 * 1000
@@ -243,6 +246,7 @@ def main(self, *, args): # noqa: D102
243246
play_options.service_requests_source = ServiceRequestsSource.SERVICE_INTROSPECTION
244247
else:
245248
play_options.service_requests_source = ServiceRequestsSource.CLIENT_INTROSPECTION
249+
play_options.disable_progress_bar = not args.progress_bar
246250

247251
player = Player(args.log_level)
248252
try:

rosbag2_py/rosbag2_py/_transport.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class PlayOptions:
1010
delay: float
1111
disable_keyboard_controls: bool
1212
disable_loan_message: bool
13+
disable_progress_bar: bool
1314
exclude_regex_to_filter: str
1415
exclude_service_events_to_filter: List[str]
1516
exclude_topics_to_filter: List[str]

rosbag2_py/src/rosbag2_py/_transport.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ PYBIND11_MODULE(_transport, m) {
544544
"playback_until_timestamp",
545545
&PlayOptions::getPlaybackUntilTimestamp,
546546
&PlayOptions::setPlaybackUntilTimestamp)
547+
.def_readwrite(
548+
"disable_progress_bar", &PlayOptions::disable_progress_bar)
547549
.def_readwrite("wait_acked_timeout", &PlayOptions::wait_acked_timeout)
548550
.def_readwrite("disable_loan_message", &PlayOptions::disable_loan_message)
549551
.def_readwrite("publish_service_requests", &PlayOptions::publish_service_requests)

rosbag2_transport/include/rosbag2_transport/play_options.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ struct PlayOptions
123123

124124
// The source of the service request
125125
ServiceRequestsSource service_requests_source = ServiceRequestsSource::SERVICE_INTROSPECTION;
126+
127+
// Disable to print a progress bar of the playback player
128+
bool disable_progress_bar = true;
126129
};
127130

128131
} // namespace rosbag2_transport
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright 2024 Nicola Loi.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef ROSBAG2_TRANSPORT__PLAYER_PROGRESS_BAR_HPP_
16+
#define ROSBAG2_TRANSPORT__PLAYER_PROGRESS_BAR_HPP_
17+
18+
#include <mutex>
19+
#include <utility>
20+
#include <string>
21+
22+
#include "rcl/types.h"
23+
#include "rclcpp/rclcpp.hpp"
24+
25+
namespace rosbag2_transport
26+
{
27+
28+
class PlayerProgressBar final
29+
{
30+
public:
31+
explicit PlayerProgressBar(
32+
bool disable_progress_bar,
33+
rcutils_time_point_value_t bag_starting_time,
34+
rcutils_duration_value_t bag_duration)
35+
: disable_progress_bar_(disable_progress_bar),
36+
bag_starting_time_secs_(RCUTILS_NS_TO_S(static_cast<double>(bag_starting_time))),
37+
bag_duration_secs_(RCUTILS_NS_TO_S(static_cast<double>(bag_duration)))
38+
{
39+
}
40+
~PlayerProgressBar()
41+
{
42+
if (!disable_progress_bar_) {
43+
printf("\n");
44+
fflush(stdout);
45+
}
46+
}
47+
inline void print_running_status(const rcutils_time_point_value_t current_time) const
48+
{
49+
if (!disable_progress_bar_) {
50+
print_status(current_time, 'R');
51+
}
52+
}
53+
inline void print_paused_status(const rcutils_time_point_value_t current_time) const
54+
{
55+
if (!disable_progress_bar_) {
56+
print_status(current_time, 'P');
57+
}
58+
}
59+
inline void print_delayed_status(const rcutils_time_point_value_t current_time) const
60+
{
61+
if (!disable_progress_bar_) {
62+
print_status(current_time, 'D');
63+
}
64+
}
65+
std::string get_help_str() const
66+
{
67+
if (!disable_progress_bar_) {
68+
return "Bag Time and Duration [?]: ? = R running, P paused, D delayed";
69+
} else {
70+
return "Bag Time and Duration progress bar disabled.";
71+
}
72+
}
73+
74+
private:
75+
inline void print_status(const rcutils_time_point_value_t current_time, const char status) const
76+
{
77+
double current_time_secs = RCUTILS_NS_TO_S(static_cast<double>(current_time));
78+
double bag_progress_secs = current_time_secs - bag_starting_time_secs_;
79+
printf(" Bag Time %13.6f Duration %.6f/%.6f [%c] \r",
80+
current_time_secs, bag_progress_secs, bag_duration_secs_, status);
81+
fflush(stdout);
82+
}
83+
bool disable_progress_bar_;
84+
const double bag_starting_time_secs_;
85+
const double bag_duration_secs_;
86+
};
87+
88+
} // namespace rosbag2_transport
89+
90+
#endif // ROSBAG2_TRANSPORT__PLAYER_PROGRESS_BAR_HPP_

rosbag2_transport/src/rosbag2_transport/player.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "rosbag2_transport/config_options_from_node_params.hpp"
4242
#include "rosbag2_transport/player_service_client.hpp"
4343
#include "rosbag2_transport/reader_writer_factory.hpp"
44+
#include "rosbag2_transport/player_progress_bar.hpp"
4445

4546
#include "logging.hpp"
4647

@@ -349,6 +350,9 @@ class PlayerImpl
349350
std::vector<KeyboardHandler::callback_handle_t> keyboard_callbacks_;
350351

351352
std::shared_ptr<PlayerServiceClientManager> player_service_client_manager_;
353+
354+
// progress bar
355+
std::unique_ptr<PlayerProgressBar> progress_bar_;
352356
};
353357

354358
PlayerImpl::PlayerImpl(
@@ -393,6 +397,7 @@ PlayerImpl::PlayerImpl(
393397
// keep reader open until player is destroyed
394398
reader_->open(storage_options_, {"", rmw_get_serialization_format()});
395399
auto metadata = reader_->get_metadata();
400+
rcutils_duration_value_t bag_duration = metadata.duration.count();
396401
starting_time_ = std::chrono::duration_cast<std::chrono::nanoseconds>(
397402
metadata.starting_time.time_since_epoch()).count();
398403
// If a non-default (positive) starting time offset is provided in PlayOptions,
@@ -405,17 +410,21 @@ PlayerImpl::PlayerImpl(
405410
". Negative start offset ignored.");
406411
} else {
407412
starting_time_ += play_options_.start_offset;
413+
bag_duration -= play_options_.start_offset;
408414
}
409415
clock_ = std::make_unique<rosbag2_cpp::TimeControllerClock>(
410416
starting_time_, std::chrono::steady_clock::now,
411417
std::chrono::milliseconds{100}, play_options_.start_paused);
418+
progress_bar_ = std::make_unique<PlayerProgressBar>(play_options_.disable_progress_bar,
419+
starting_time_, bag_duration);
412420
set_rate(play_options_.rate);
413421
topic_qos_profile_overrides_ = play_options_.topic_qos_profile_overrides;
414422
prepare_publishers();
415423
configure_play_until_timestamp();
416424
}
417425
create_control_services();
418426
add_keyboard_callbacks();
427+
RCLCPP_INFO_STREAM(owner_->get_logger(), progress_bar_->get_help_str());
419428
}
420429

421430
PlayerImpl::~PlayerImpl()
@@ -486,6 +495,7 @@ bool PlayerImpl::play()
486495
do {
487496
if (delay > rclcpp::Duration(0, 0)) {
488497
RCLCPP_INFO_STREAM(owner_->get_logger(), "Sleep " << delay.nanoseconds() << " ns");
498+
progress_bar_->print_delayed_status(clock_->now());
489499
std::chrono::nanoseconds delay_duration(delay.nanoseconds());
490500
std::this_thread::sleep_for(delay_duration);
491501
}
@@ -602,18 +612,25 @@ void PlayerImpl::stop()
602612
playback_thread_.join();
603613
}
604614
}
615+
if (clock_->is_paused()) {
616+
progress_bar_->print_paused_status(clock_->now());
617+
} else {
618+
progress_bar_->print_running_status(clock_->now());
619+
}
605620
}
606621

607622
void PlayerImpl::pause()
608623
{
609624
clock_->pause();
610625
RCLCPP_INFO_STREAM(owner_->get_logger(), "Pausing play.");
626+
progress_bar_->print_paused_status(clock_->now());
611627
}
612628

613629
void PlayerImpl::resume()
614630
{
615631
clock_->resume();
616632
RCLCPP_INFO_STREAM(owner_->get_logger(), "Resuming play.");
633+
progress_bar_->print_running_status(clock_->now());
617634
}
618635

619636
void PlayerImpl::toggle_paused()
@@ -640,6 +657,11 @@ bool PlayerImpl::set_rate(double rate)
640657
} else {
641658
RCLCPP_WARN_STREAM(owner_->get_logger(), "Failed to set rate to invalid value " << rate);
642659
}
660+
if (clock_->is_paused()) {
661+
progress_bar_->print_paused_status(clock_->now());
662+
} else {
663+
progress_bar_->print_running_status(clock_->now());
664+
}
643665
return ok;
644666
}
645667

@@ -707,6 +729,7 @@ bool PlayerImpl::play_next()
707729
next_message_published = publish_message(message_ptr);
708730
clock_->jump(message_ptr->recv_timestamp);
709731

732+
progress_bar_->print_paused_status(clock_->now());
710733
message_queue_.pop();
711734
message_ptr = peek_next_message_from_queue();
712735
}
@@ -717,6 +740,7 @@ size_t PlayerImpl::burst(const size_t num_messages)
717740
{
718741
if (!clock_->is_paused()) {
719742
RCLCPP_WARN_STREAM(owner_->get_logger(), "Burst can only be used when in the paused state.");
743+
progress_bar_->print_running_status(clock_->now());
720744
return 0;
721745
}
722746

@@ -731,6 +755,7 @@ size_t PlayerImpl::burst(const size_t num_messages)
731755
}
732756

733757
RCLCPP_INFO_STREAM(owner_->get_logger(), "Burst " << messages_played << " messages.");
758+
progress_bar_->print_running_status(clock_->now());
734759
return messages_played;
735760
}
736761

@@ -956,6 +981,7 @@ void PlayerImpl::play_messages_from_queue()
956981
continue;
957982
}
958983
publish_message(message_ptr);
984+
progress_bar_->print_running_status(clock_->now());
959985
}
960986
message_queue_.pop();
961987
message_ptr = peek_next_message_from_queue();

0 commit comments

Comments
 (0)