diff --git a/rosbag2_cpp/include/rosbag2_cpp/writer.hpp b/rosbag2_cpp/include/rosbag2_cpp/writer.hpp index b95bd29504..0c82439370 100644 --- a/rosbag2_cpp/include/rosbag2_cpp/writer.hpp +++ b/rosbag2_cpp/include/rosbag2_cpp/writer.hpp @@ -88,6 +88,7 @@ class ROSBAG2_CPP_PUBLIC Writer final const rosbag2_storage::StorageOptions & storage_options, const ConverterOptions & converter_options = ConverterOptions()); + void close(); /** * Create a new topic in the underlying storage. Needs to be called for every topic used within * a message which is passed to write(...). diff --git a/rosbag2_cpp/src/rosbag2_cpp/writer.cpp b/rosbag2_cpp/src/rosbag2_cpp/writer.cpp index 56267a94f1..fa9b41fb96 100644 --- a/rosbag2_cpp/src/rosbag2_cpp/writer.cpp +++ b/rosbag2_cpp/src/rosbag2_cpp/writer.cpp @@ -65,6 +65,10 @@ void Writer::open( writer_impl_->open(storage_options, converter_options); } +void Writer::close() +{ + writer_impl_->close(); +} void Writer::create_topic(const rosbag2_storage::TopicMetadata & topic_with_type) { std::lock_guard writer_lock(writer_mutex_); diff --git a/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp b/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp index 11e8b00ff0..f83b308ffa 100644 --- a/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp +++ b/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp @@ -165,6 +165,12 @@ void SequentialWriter::close() metadata_io_->write_metadata(base_folder_, metadata_); } + if (storage_) { + auto info = std::make_shared(); + info->closed_file = storage_->get_relative_file_path(); + callback_manager_.execute_callbacks(bag_events::BagEvent::WRITE_SPLIT, info); + } + storage_.reset(); // Necessary to ensure that the storage is destroyed before the factory storage_factory_.reset(); } diff --git a/rosbag2_py/src/rosbag2_py/_transport.cpp b/rosbag2_py/src/rosbag2_py/_transport.cpp index 1b51f30429..3613e2f7f0 100644 --- a/rosbag2_py/src/rosbag2_py/_transport.cpp +++ b/rosbag2_py/src/rosbag2_py/_transport.cpp @@ -190,7 +190,8 @@ class Player class Recorder { private: - std::unique_ptr exec_; + static std::unique_ptr exec_; + static std::shared_ptr recorder_; public: Recorder() @@ -199,7 +200,8 @@ class Recorder exec_ = std::make_unique(); std::signal( SIGTERM, [](int /* signal */) { - rclcpp::shutdown(); + if (exec_) {exec_->cancel();} + if (recorder_) {recorder_->stop();} }); } @@ -218,11 +220,11 @@ class Recorder } auto writer = rosbag2_transport::ReaderWriterFactory::make_writer(record_options); - auto recorder = std::make_shared( + recorder_ = std::make_shared( std::move(writer), storage_options, record_options, node_name); - recorder->record(); + recorder_->record(); - exec_->add_node(recorder); + exec_->add_node(recorder_); // Release the GIL for long-running record, so that calling Python code can use other threads { py::gil_scoped_release release; @@ -236,6 +238,9 @@ class Recorder } }; +std::unique_ptr Recorder::exec_; +std::shared_ptr Recorder::recorder_; + // Return a RecordOptions struct with defaults set for rewriting bags. rosbag2_transport::RecordOptions bag_rewrite_default_record_options() { diff --git a/rosbag2_transport/include/rosbag2_transport/recorder.hpp b/rosbag2_transport/include/rosbag2_transport/recorder.hpp index 4354aa8b16..30c2d30b31 100644 --- a/rosbag2_transport/include/rosbag2_transport/recorder.hpp +++ b/rosbag2_transport/include/rosbag2_transport/recorder.hpp @@ -102,6 +102,10 @@ class Recorder : public rclcpp::Node ROSBAG2_TRANSPORT_PUBLIC void pause(); + /// Stop the recording. + ROSBAG2_TRANSPORT_PUBLIC + void stop(); + /// Resume recording. ROSBAG2_TRANSPORT_PUBLIC void resume(); diff --git a/rosbag2_transport/src/rosbag2_transport/recorder.cpp b/rosbag2_transport/src/rosbag2_transport/recorder.cpp index 84ae46b481..d15309c490 100644 --- a/rosbag2_transport/src/rosbag2_transport/recorder.cpp +++ b/rosbag2_transport/src/rosbag2_transport/recorder.cpp @@ -108,12 +108,18 @@ Recorder::Recorder( Recorder::~Recorder() { keyboard_handler_->delete_key_press_callback(toggle_paused_key_callback_handle_); + stop(); +} + +void Recorder::stop() +{ stop_discovery_ = true; if (discovery_future_.valid()) { discovery_future_.wait(); } - + paused_ = true; subscriptions_.clear(); + writer_->close(); { std::lock_guard lock(event_publisher_thread_mutex_); @@ -127,6 +133,7 @@ Recorder::~Recorder() void Recorder::record() { + paused_ = record_options_.start_paused; topic_qos_profile_overrides_ = record_options_.topic_qos_profile_overrides; if (record_options_.rmw_serialization_format.empty()) { throw std::runtime_error("No serialization format specified!"); @@ -199,6 +206,7 @@ void Recorder::record() callbacks.write_split_callback = [this](rosbag2_cpp::bag_events::BagSplitInfo & info) { { + RCLCPP_INFO(get_logger(), "Event publisher thread: Trigger"); std::lock_guard lock(event_publisher_thread_mutex_); bag_split_info_ = info; write_split_has_occurred_ = true; @@ -235,6 +243,7 @@ void Recorder::event_publisher_thread_main() auto message = rosbag2_interfaces::msg::WriteSplitEvent(); message.closed_file = bag_split_info_.closed_file; message.opened_file = bag_split_info_.opened_file; + RCLCPP_INFO(get_logger(), "Event publisher thread: Publish"); split_event_pub_->publish(message); }