Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions ros2bag/ros2bag/verb/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ def add_arguments(self, parser, cli_name): # noqa: D102
'is needed. A rule of thumb is to cache an order of magnitude corresponding to '
'about one second of total recorded data volume. '
'If the value specified is 0, then every message is directly written to disk.')
parser.add_argument(
'--disable-keyboard-controls', action='store_true', default=False,
help='disables keyboard controls for recorder')
parser.add_argument(
'--start-paused', action='store_true', default=False,
help='Start the recorder in a paused state.')
Expand Down Expand Up @@ -293,9 +296,12 @@ def main(self, *, args): # noqa: D102
)
record_options = RecordOptions()
record_options.all_topics = args.all_topics or args.all
record_options.all_services = args.all_services or args.all
record_options.is_discovery_disabled = args.no_discovery
record_options.topics = args.topics
record_options.topic_types = args.topic_types
# Convert service name to service event topic name
record_options.services = convert_service_to_service_event_topic(args.services)
record_options.exclude_topic_types = args.exclude_topic_types
record_options.rmw_serialization_format = args.serialization_format
record_options.topic_polling_interval = datetime.timedelta(
Expand All @@ -316,10 +322,7 @@ def main(self, *, args): # noqa: D102
record_options.start_paused = args.start_paused
record_options.ignore_leaf_topics = args.ignore_leaf_topics
record_options.use_sim_time = args.use_sim_time
record_options.all_services = args.all_services or args.all

# Convert service name to service event topic name
record_options.services = convert_service_to_service_event_topic(args.services)
record_options.disable_keyboard_controls = args.disable_keyboard_controls

recorder = Recorder()

Expand Down
1 change: 1 addition & 0 deletions rosbag2_py/rosbag2_py/_transport.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class RecordOptions:
compression_mode: str
compression_queue_size: int
compression_threads: int
disable_keyboard_controls: bool
exclude_regex: str
exclude_service_events: List[str]
exclude_topic_types: List[str]
Expand Down
28 changes: 26 additions & 2 deletions rosbag2_py/src/rosbag2_py/_transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,19 @@ class Player
install_signal_handlers();
try {
auto reader = rosbag2_transport::ReaderWriterFactory::make_reader(storage_options);
std::shared_ptr<KeyboardHandler> keyboard_handler;
if (!play_options.disable_keyboard_controls) {
#ifndef _WIN32
// Instantiate KeyboardHandler explicitly with disabled signal handler inside,
// since we have already installed our own signal handler
keyboard_handler = std::make_shared<KeyboardHandler>(false);
#else
// We don't have signal handler option in constructor for windows version
keyboard_handler = std::shared_ptr<KeyboardHandler>(new KeyboardHandler());
#endif
}
auto player = std::make_shared<rosbag2_transport::Player>(
std::move(reader), storage_options, play_options);
std::move(reader), std::move(keyboard_handler), storage_options, play_options);

rclcpp::executors::SingleThreadedExecutor exec;
exec.add_node(player);
Expand Down Expand Up @@ -304,8 +315,20 @@ class Recorder
}

auto writer = rosbag2_transport::ReaderWriterFactory::make_writer(record_options);
std::shared_ptr<KeyboardHandler> keyboard_handler;
if (!record_options.disable_keyboard_controls) {
#ifndef _WIN32
// Instantiate KeyboardHandler explicitly with disabled signal handler inside,
// since we have already installed our own signal handler
keyboard_handler = std::make_shared<KeyboardHandler>(false);
#else
// We don't have signal handler option in constructor for windows version
keyboard_handler = std::shared_ptr<KeyboardHandler>(new KeyboardHandler());
#endif
}

auto recorder = std::make_shared<rosbag2_transport::Recorder>(
std::move(writer), storage_options, record_options, node_name);
std::move(writer), std::move(keyboard_handler), storage_options, record_options, node_name);
recorder->record();

exec->add_node(recorder);
Expand Down Expand Up @@ -528,6 +551,7 @@ PYBIND11_MODULE(_transport, m) {
.def_readwrite("use_sim_time", &RecordOptions::use_sim_time)
.def_readwrite("services", &RecordOptions::services)
.def_readwrite("all_services", &RecordOptions::all_services)
.def_readwrite("disable_keyboard_controls", &RecordOptions::disable_keyboard_controls)
;

py::class_<rosbag2_py::Player>(m, "Player")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct RecordOptions
bool ignore_leaf_topics = false;
bool start_paused = false;
bool use_sim_time = false;
bool disable_keyboard_controls = false;
};

} // namespace rosbag2_transport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ RecordOptions get_record_options_from_node_params(rclcpp::Node & node)

record_options.start_paused = node.declare_parameter<bool>("record.start_paused", false);

record_options.disable_keyboard_controls =
node.declare_parameter<bool>("record.disable_keyboard_controls", false);

record_options.use_sim_time = node.get_parameter("use_sim_time").get_value<bool>();

if (record_options.use_sim_time && record_options.is_discovery_disabled) {
Expand Down
56 changes: 25 additions & 31 deletions rosbag2_transport/src/rosbag2_transport/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,10 @@ PlayerImpl::~PlayerImpl()

// remove callbacks on key_codes to prevent race conditions
// Note: keyboard_handler handles locks between removing & executing callbacks
for (auto cb_handle : keyboard_callbacks_) {
keyboard_handler_->delete_key_press_callback(cb_handle);
if (keyboard_handler_) {
for (auto cb_handle : keyboard_callbacks_) {
keyboard_handler_->delete_key_press_callback(cb_handle);
}
}
// closes reader
std::lock_guard<std::mutex> lk(reader_mutex_);
Expand Down Expand Up @@ -1319,22 +1321,22 @@ void PlayerImpl::add_key_callback(
const std::function<void()> & cb,
const std::string & op_name)
{
std::string key_str = enum_key_code_to_str(key);
if (key == KeyboardHandler::KeyCode::UNKNOWN) {
RCLCPP_ERROR_STREAM(
owner_->get_logger(),
"Invalid key binding " << key_str << " for " << op_name);
throw std::invalid_argument("Invalid key binding.");
if (keyboard_handler_) {
std::string key_str = enum_key_code_to_str(key);
if (key == KeyboardHandler::KeyCode::UNKNOWN) {
RCLCPP_ERROR_STREAM(
owner_->get_logger(),
"Invalid key binding " << key_str << " for " << op_name);
throw std::invalid_argument("Invalid key binding.");
}
keyboard_callbacks_.push_back(
keyboard_handler_->add_key_press_callback(
[cb](KeyboardHandler::KeyCode /*key_code*/,
KeyboardHandler::KeyModifiers /*key_modifiers*/) {cb();},
key));
// show instructions
RCLCPP_INFO_STREAM(owner_->get_logger(), "Press " << key_str << " for " << op_name);
}
keyboard_callbacks_.push_back(
keyboard_handler_->add_key_press_callback(
[cb](KeyboardHandler::KeyCode /*key_code*/,
KeyboardHandler::KeyModifiers /*key_modifiers*/) {cb();},
key));
// show instructions
RCLCPP_INFO_STREAM(
owner_->get_logger(),
"Press " << key_str << " for " << op_name);
}

void PlayerImpl::add_keyboard_callbacks()
Expand Down Expand Up @@ -1535,12 +1537,10 @@ Player::Player(const std::string & node_name, const rclcpp::NodeOptions & node_o
rosbag2_storage::StorageOptions storage_options = get_storage_options_from_node_params(*this);
PlayOptions play_options = get_play_options_from_node_params(*this);

#ifndef _WIN32
auto keyboard_handler = std::make_shared<KeyboardHandler>(false);
#else
// We don't have signal handler option in constructor for windows version
auto keyboard_handler = std::shared_ptr<KeyboardHandler>(new KeyboardHandler());
#endif
std::shared_ptr<KeyboardHandler> keyboard_handler;
if (!play_options.disable_keyboard_controls) {
keyboard_handler = std::make_shared<KeyboardHandler>();
}

auto reader = std::make_unique<rosbag2_cpp::Reader>();

Expand All @@ -1565,13 +1565,7 @@ Player::Player(
const std::string & node_name,
const rclcpp::NodeOptions & node_options)
: Player(std::move(reader),
// only call KeyboardHandler when using default keyboard handler implementation
#ifndef _WIN32
std::make_shared<KeyboardHandler>(false),
#else
// We don't have signal handler option in constructor for windows version
std::shared_ptr<KeyboardHandler>(new KeyboardHandler()),
#endif
play_options.disable_keyboard_controls ? nullptr : std::make_shared<KeyboardHandler>(),
storage_options, play_options, node_name, node_options)
{}

Expand All @@ -1586,7 +1580,7 @@ Player::Player(
node_name,
rclcpp::NodeOptions(node_options).arguments(play_options.topic_remapping_options)),
pimpl_(std::make_unique<PlayerImpl>(
this, std::move(reader), keyboard_handler,
this, std::move(reader), std::move(keyboard_handler),
storage_options, play_options))
{}

Expand Down
4 changes: 4 additions & 0 deletions rosbag2_transport/src/rosbag2_transport/record_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Node convert<rosbag2_transport::RecordOptions>::encode(
record_options.topic_qos_profile_overrides);
node["include_hidden_topics"] = record_options.include_hidden_topics;
node["include_unpublished_topics"] = record_options.include_unpublished_topics;
node["disable_keyboard_controls"] = record_options.disable_keyboard_controls;
return node;
}

Expand Down Expand Up @@ -97,6 +98,9 @@ bool convert<rosbag2_transport::RecordOptions>::decode(
optional_assign<bool>(
node, "include_unpublished_topics",
record_options.include_unpublished_topics);
optional_assign<bool>(
node, "disable_keyboard_controls",
record_options.disable_keyboard_controls);
return true;
}

Expand Down
48 changes: 23 additions & 25 deletions rosbag2_transport/src/rosbag2_transport/recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,19 @@ RecorderImpl::RecorderImpl(
"use_sim_time and is_discovery_disabled both set, but are incompatible settings. "
"The /clock topic needs to be discovered to record with sim time.");
}

std::string key_str = enum_key_code_to_str(Recorder::kPauseResumeToggleKey);
toggle_paused_key_callback_handle_ =
keyboard_handler_->add_key_press_callback(
[this](KeyboardHandler::KeyCode /*key_code*/,
KeyboardHandler::KeyModifiers /*key_modifiers*/) {this->toggle_paused();},
Recorder::kPauseResumeToggleKey);
if (!record_options.disable_keyboard_controls) {
std::string key_str = enum_key_code_to_str(Recorder::kPauseResumeToggleKey);
toggle_paused_key_callback_handle_ =
keyboard_handler_->add_key_press_callback(
[this](KeyboardHandler::KeyCode /*key_code*/,
KeyboardHandler::KeyModifiers /*key_modifiers*/) {this->toggle_paused();},
Recorder::kPauseResumeToggleKey);
// show instructions
RCLCPP_INFO_STREAM(
node->get_logger(),
"Press " << key_str << " for pausing/resuming");
}
topic_filter_ = std::make_unique<TopicFilter>(record_options, node->get_node_graph_interface());
// show instructions
RCLCPP_INFO_STREAM(
node->get_logger(),
"Press " << key_str << " for pausing/resuming");

for (auto & topic : record_options_.topics) {
topic = rclcpp::expand_topic_or_service_name(
Expand Down Expand Up @@ -217,7 +218,11 @@ RecorderImpl::RecorderImpl(

RecorderImpl::~RecorderImpl()
{
keyboard_handler_->delete_key_press_callback(toggle_paused_key_callback_handle_);
if (keyboard_handler_ &&
(toggle_paused_key_callback_handle_ != KeyboardHandler::invalid_handle))
{
keyboard_handler_->delete_key_press_callback(toggle_paused_key_callback_handle_);
}
stop();
}

Expand Down Expand Up @@ -745,12 +750,10 @@ Recorder::Recorder(

RecordOptions record_options = get_record_options_from_node_params(*this);

#ifndef _WIN32
auto keyboard_handler = std::make_shared<KeyboardHandler>(false);
#else
// We don't have signal handler option in constructor for windows version
auto keyboard_handler = std::shared_ptr<KeyboardHandler>(new KeyboardHandler());
#endif
std::shared_ptr<KeyboardHandler> keyboard_handler;
if (!record_options.disable_keyboard_controls) {
keyboard_handler = std::make_shared<KeyboardHandler>();
}

auto writer = std::make_unique<rosbag2_cpp::Writer>();

Expand All @@ -768,12 +771,7 @@ Recorder::Recorder(
const rclcpp::NodeOptions & node_options)
: Recorder(
std::move(writer),
#ifndef _WIN32
std::make_shared<KeyboardHandler>(false),
#else
// We don't have signal handler option in constructor for windows version
std::shared_ptr<KeyboardHandler>(new KeyboardHandler()),
#endif
record_options.disable_keyboard_controls ? nullptr : std::make_shared<KeyboardHandler>(),
storage_options,
record_options,
node_name,
Expand All @@ -791,7 +789,7 @@ Recorder::Recorder(
.start_parameter_event_publisher(false)
.append_parameter_override("use_sim_time", record_options.use_sim_time)),
pimpl_(std::make_unique<RecorderImpl>(
this, std::move(writer), keyboard_handler,
this, std::move(writer), std::move(keyboard_handler),
storage_options, record_options))
{}

Expand Down
1 change: 1 addition & 0 deletions rosbag2_transport/test/resources/recorder_node_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ recorder_params_node:
include_unpublished_topics: true
ignore_leaf_topics: false
start_paused: false
disable_keyboard_controls: true

storage:
uri: "path/to/some_bag"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ TEST_P(ComposablePlayerTests, player_can_parse_parameters_from_file) {
EXPECT_DOUBLE_EQ(play_options.playback_duration.seconds(), -1.0);
EXPECT_EQ(play_options.playback_until_timestamp, -2500000000LL);
EXPECT_EQ(play_options.start_offset, 999999999);
EXPECT_EQ(play_options.disable_keyboard_controls, true);
EXPECT_EQ(play_options.wait_acked_timeout, -999999999);
EXPECT_EQ(play_options.disable_loan_message, false);
EXPECT_EQ(play_options.publish_service_requests, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ TEST_P(ComposableRecorderTests, recorder_can_parse_parameters_from_file) {
EXPECT_EQ(record_options.include_unpublished_topics, true);
EXPECT_EQ(record_options.ignore_leaf_topics, false);
EXPECT_EQ(record_options.start_paused, false);
EXPECT_EQ(record_options.disable_keyboard_controls, true);
EXPECT_EQ(record_options.use_sim_time, false);

EXPECT_EQ(storage_options.uri, root_bag_path_.generic_string());
Expand Down