From 8645046115b937999d384164c98a60bd1b5a949d Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Wed, 11 Sep 2024 16:39:33 +0200 Subject: [PATCH 1/8] sort info output by topic name Signed-off-by: Soenke Prophet --- .../src/rosbag2_py/format_bag_metadata.cpp | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index 32883c736..b38eea765 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -115,7 +115,8 @@ void format_topics_with_type( const std::unordered_map & messages_size, bool verbose, std::stringstream & info_stream, - int indentation_spaces) + int indentation_spaces, + std::string sort_method = "name") { if (topics.empty()) { info_stream << std::endl; @@ -139,13 +140,37 @@ void format_topics_with_type( info_stream << std::endl; }; + std::vector sorted_idx(topics.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&topics, sort_method](size_t i1, size_t i2) { + if (sort_method == "type") + { + return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; + } + if (sort_method == "count") + { + return topics[i1].message_count < topics[i2].message_count; + } + if (sort_method == "serialization_format") + { + std::string format_1 = topics[i1].topic_metadata.serialization_format; + std::string format_2 = topics[i2].topic_metadata.serialization_format; + return format_1 < format_2; + } + return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; + } + ); + size_t number_of_topics = topics.size(); size_t i = 0; // Find first topic which isn't service event topic while (i < number_of_topics && rosbag2_cpp::is_service_event_topic( - topics[i].topic_metadata.name, - topics[i].topic_metadata.type)) + topics[sorted_idx[i]].topic_metadata.name, + topics[sorted_idx[i]].topic_metadata.type)) { i++; } @@ -155,15 +180,15 @@ void format_topics_with_type( return; } - print_topic_info(topics[i]); + print_topic_info(topics[sorted_idx[i]]); for (size_t j = ++i; j < number_of_topics; ++j) { if (rosbag2_cpp::is_service_event_topic( - topics[j].topic_metadata.name, topics[j].topic_metadata.type)) + topics[sorted_idx[j]].topic_metadata.name, topics[sorted_idx[j]].topic_metadata.type)) { continue; } indent(info_stream, indentation_spaces); - print_topic_info(topics[j]); + print_topic_info(topics[sorted_idx[j]]); } } From 5dd50099e87840577e926ccedac7d81bcec51f02 Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 13 Sep 2024 15:22:38 +0200 Subject: [PATCH 2/8] add missing imports Signed-off-by: Soenke Prophet --- rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index b38eea765..5586d0bee 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #ifdef _WIN32 #include From b6427eb565d452a11da513d9ef01198b69c21b73 Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 20 Sep 2024 11:13:37 +0200 Subject: [PATCH 3/8] add sorting to service topics and remove sorting option by serialization format Signed-off-by: Soenke Prophet --- .../src/rosbag2_py/format_bag_metadata.cpp | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index 5586d0bee..58ac318a4 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -148,20 +148,12 @@ void format_topics_with_type( sorted_idx.begin(), sorted_idx.end(), [&topics, sort_method](size_t i1, size_t i2) { - if (sort_method == "type") - { + if (sort_method == "type") { return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; } - if (sort_method == "count") - { + if (sort_method == "count") { return topics[i1].message_count < topics[i2].message_count; } - if (sort_method == "serialization_format") - { - std::string format_1 = topics[i1].topic_metadata.serialization_format; - std::string format_2 = topics[i2].topic_metadata.serialization_format; - return format_1 < format_2; - } return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; } ); @@ -239,7 +231,8 @@ void format_service_with_type( const std::unordered_map & messages_size, bool verbose, std::stringstream & info_stream, - int indentation_spaces) + int indentation_spaces, + std::string sort_method = "name") { if (services.empty()) { info_stream << std::endl; @@ -265,11 +258,27 @@ void format_service_with_type( info_stream << std::endl; }; - print_service_info(services[0]); + std::vector sorted_idx(services.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&services, sort_method](size_t i1, size_t i2) { + if (sort_method == "type") { + return services[i1]->service_metadata.type < services[i2]->service_metadata.type; + } + if (sort_method == "count") { + return services[i1]->event_message_count < services[i2]->event_message_count; + } + return services[i1]->service_metadata.name < services[i2]->service_metadata.name; + } + ); + + print_service_info(services[sorted_idx[0]]); auto number_of_services = services.size(); for (size_t j = 1; j < number_of_services; ++j) { indent(info_stream, indentation_spaces); - print_service_info(services[j]); + print_service_info(services[sorted_idx[j]]); } } From 60ea4c94ab226e550ead82d34a39470b5bcf98de Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 20 Sep 2024 14:32:48 +0200 Subject: [PATCH 4/8] add CLI option for sorting output and move sorting methods to enum Signed-off-by: Soenke Prophet --- ros2bag/ros2bag/verb/info.py | 9 ++++-- rosbag2_py/src/rosbag2_py/_info.cpp | 31 ++++++++++++++++--- .../src/rosbag2_py/format_bag_metadata.cpp | 27 ++++++++++------ .../src/rosbag2_py/format_bag_metadata.hpp | 13 +++++++- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/ros2bag/ros2bag/verb/info.py b/ros2bag/ros2bag/verb/info.py index 910cf6407..005c4b0ea 100644 --- a/ros2bag/ros2bag/verb/info.py +++ b/ros2bag/ros2bag/verb/info.py @@ -30,6 +30,11 @@ def add_arguments(self, parser, cli_name): # noqa: D102 '-v', '--verbose', action='store_true', help='Display request/response information for services' ) + available_sorting_methods = Info().get_sorting_methods() + parser.add_argument( + '--sort', default='name', choices=available_sorting_methods, + help='Configuration for sorting of output. ' + 'By default sorts by topic name - use this argument to override.') def main(self, *, args): # noqa: D102 if args.topic_name and args.verbose: @@ -37,9 +42,9 @@ def main(self, *, args): # noqa: D102 'will be ignored.') m = Info().read_metadata(args.bag_path, args.storage) if args.verbose: - Info().print_output_verbose(args.bag_path, m) + Info().print_output_verbose(args.bag_path, m, args.sort) else: if args.topic_name: Info().print_output_topic_name_only(m) else: - Info().print_output(m) + Info().print_output(m, args.sort) diff --git a/rosbag2_py/src/rosbag2_py/_info.cpp b/rosbag2_py/src/rosbag2_py/_info.cpp index cb3431f18..e93c92435 100644 --- a/rosbag2_py/src/rosbag2_py/_info.cpp +++ b/rosbag2_py/src/rosbag2_py/_info.cpp @@ -27,6 +27,12 @@ namespace rosbag2_py { + +std::unordered_map stringToSortingMethod = { + {"name", SortingMethod::NAME}, + {"type", SortingMethod::TYPE}, + {"count", SortingMethod::COUNT}}; + class Info { public: @@ -42,10 +48,12 @@ class Info return info_->read_metadata(uri, storage_id); } - void print_output(const rosbag2_storage::BagMetadata & metadata_info) + void print_output( + const rosbag2_storage::BagMetadata & metadata_info, std::string sorting_method) { + rosbag2_py::SortingMethod sort_method = rosbag2_py::stringToSortingMethod[sorting_method]; // Output formatted metadata - std::cout << format_bag_meta_data(metadata_info) << std::endl; + std::cout << format_bag_meta_data(metadata_info, {}, false, false, sort_method) << std::endl; } void print_output_topic_name_only(const rosbag2_storage::BagMetadata & metadata_info) @@ -61,7 +69,9 @@ class Info } void print_output_verbose( - const std::string & uri, const rosbag2_storage::BagMetadata & metadata_info) + const std::string & uri, + const rosbag2_storage::BagMetadata & metadata_info, + std::string sorting_method) { std::vector> all_services_info; for (auto & file_info : metadata_info.files) { @@ -86,11 +96,21 @@ class Info } } + rosbag2_py::SortingMethod sort_method = rosbag2_py::stringToSortingMethod[sorting_method]; // Output formatted metadata and service info - std::cout << format_bag_meta_data(metadata_info, messages_size, true, true); + std::cout << format_bag_meta_data(metadata_info, messages_size, true, true, sort_method); std::cout << format_service_info(all_services_info, messages_size, true) << std::endl; } + std::unordered_set get_sorting_methods() + { + std::unordered_set sorting_methods; + for (auto sorting_method : rosbag2_py::stringToSortingMethod) { + sorting_methods.insert(sorting_method.first); + } + return sorting_methods; + } + protected: std::unique_ptr info_; }; @@ -105,5 +125,6 @@ PYBIND11_MODULE(_info, m) { .def("read_metadata", &rosbag2_py::Info::read_metadata) .def("print_output", &rosbag2_py::Info::print_output) .def("print_output_topic_name_only", &rosbag2_py::Info::print_output_topic_name_only) - .def("print_output_verbose", &rosbag2_py::Info::print_output_verbose); + .def("print_output_verbose", &rosbag2_py::Info::print_output_verbose) + .def("get_sorting_methods", &rosbag2_py::Info::get_sorting_methods); } diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index 58ac318a4..0b1fa48bd 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -118,7 +118,7 @@ void format_topics_with_type( bool verbose, std::stringstream & info_stream, int indentation_spaces, - std::string sort_method = "name") + const rosbag2_py::SortingMethod sort_method = rosbag2_py::SortingMethod::NAME) { if (topics.empty()) { info_stream << std::endl; @@ -148,10 +148,10 @@ void format_topics_with_type( sorted_idx.begin(), sorted_idx.end(), [&topics, sort_method](size_t i1, size_t i2) { - if (sort_method == "type") { + if (sort_method == rosbag2_py::SortingMethod::TYPE) { return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; } - if (sort_method == "count") { + if (sort_method == rosbag2_py::SortingMethod::COUNT) { return topics[i1].message_count < topics[i2].message_count; } return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; @@ -232,7 +232,7 @@ void format_service_with_type( bool verbose, std::stringstream & info_stream, int indentation_spaces, - std::string sort_method = "name") + const rosbag2_py::SortingMethod sort_method = rosbag2_py::SortingMethod::NAME) { if (services.empty()) { info_stream << std::endl; @@ -264,10 +264,10 @@ void format_service_with_type( sorted_idx.begin(), sorted_idx.end(), [&services, sort_method](size_t i1, size_t i2) { - if (sort_method == "type") { + if (sort_method == rosbag2_py::SortingMethod::TYPE) { return services[i1]->service_metadata.type < services[i2]->service_metadata.type; } - if (sort_method == "count") { + if (sort_method == rosbag2_py::SortingMethod::COUNT) { return services[i1]->event_message_count < services[i2]->event_message_count; } return services[i1]->service_metadata.name < services[i2]->service_metadata.name; @@ -291,7 +291,8 @@ std::string format_bag_meta_data( const rosbag2_storage::BagMetadata & metadata, const std::unordered_map & messages_size, bool verbose, - bool only_topic) + bool only_topic, + const SortingMethod sort_method) { auto start_time = metadata.starting_time.time_since_epoch(); auto end_time = start_time + metadata.duration; @@ -324,14 +325,22 @@ std::string format_bag_meta_data( std::endl; info_stream << "Topic information: "; format_topics_with_type( - metadata.topics_with_message_count, messages_size, verbose, info_stream, indentation_spaces); + metadata.topics_with_message_count, + messages_size, verbose, info_stream, + indentation_spaces, + sort_method); if (!only_topic) { info_stream << "Service: " << service_info_list.size() << std::endl; info_stream << "Service information: "; if (!service_info_list.empty()) { format_service_with_type( - service_info_list, messages_size, verbose, info_stream, indentation_spaces + 2); + service_info_list, + messages_size, + verbose, + info_stream, + indentation_spaces + 2, + sort_method); } } diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp index 282b592d7..de8def134 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp @@ -23,11 +23,22 @@ namespace rosbag2_py { +/** + * \brief Available sorting methods for info output. + */ +enum class SortingMethod +{ + NAME, + TYPE, + COUNT, +}; + std::string format_bag_meta_data( const rosbag2_storage::BagMetadata & metadata, const std::unordered_map & messages_size = {}, bool verbose = false, - bool only_topic = false); + bool only_topic = false, + const SortingMethod sort_method = SortingMethod::NAME); } // namespace rosbag2_py From 2778bf7c8b33d07ff8714527c2b999e168b5aa5a Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 20 Sep 2024 14:47:52 +0200 Subject: [PATCH 5/8] add sorting by name to topic only option of info output Signed-off-by: Soenke Prophet --- rosbag2_py/src/rosbag2_py/_info.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/rosbag2_py/src/rosbag2_py/_info.cpp b/rosbag2_py/src/rosbag2_py/_info.cpp index e93c92435..8fd39d69b 100644 --- a/rosbag2_py/src/rosbag2_py/_info.cpp +++ b/rosbag2_py/src/rosbag2_py/_info.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "format_bag_metadata.hpp" #include "format_service_info.hpp" @@ -58,7 +60,19 @@ class Info void print_output_topic_name_only(const rosbag2_storage::BagMetadata & metadata_info) { - for (const auto & topic_info : metadata_info.topics_with_message_count) { + std::vector sorted_idx(metadata_info.topics_with_message_count.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&metadata_info](size_t i1, size_t i2) { + std::string topic_name_1 = metadata_info.topics_with_message_count[i1].topic_metadata.name; + std::string topic_name_2 = metadata_info.topics_with_message_count[i2].topic_metadata.name; + return topic_name_1 < topic_name_2; + } + ); + for (auto idx : sorted_idx) { + auto topic_info = metadata_info.topics_with_message_count[idx]; if (!rosbag2_cpp::is_service_event_topic( topic_info.topic_metadata.name, topic_info.topic_metadata.type)) From 56038707472f9f8af64a177347ce2dac7f4da51b Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 27 Sep 2024 15:14:59 +0200 Subject: [PATCH 6/8] move InfoSortingMethod and generate sorted idx functions to seprate files; move ServiceInformation and ServiceMetadata struct to storage package for clear include structure Signed-off-by: Soenke Prophet --- ros2bag/ros2bag/verb/info.py | 2 +- rosbag2_py/CMakeLists.txt | 1 + rosbag2_py/src/rosbag2_py/_info.cpp | 37 +++---- .../src/rosbag2_py/format_bag_metadata.cpp | 62 ++--------- .../src/rosbag2_py/format_bag_metadata.hpp | 13 +-- .../src/rosbag2_py/format_service_info.cpp | 9 +- .../src/rosbag2_py/format_service_info.hpp | 4 +- .../src/rosbag2_py/info_sorting_method.cpp | 103 ++++++++++++++++++ .../src/rosbag2_py/info_sorting_method.hpp | 63 +++++++++++ .../include/rosbag2_storage/bag_metadata.hpp | 13 +++ 10 files changed, 217 insertions(+), 90 deletions(-) create mode 100644 rosbag2_py/src/rosbag2_py/info_sorting_method.cpp create mode 100644 rosbag2_py/src/rosbag2_py/info_sorting_method.hpp diff --git a/ros2bag/ros2bag/verb/info.py b/ros2bag/ros2bag/verb/info.py index 005c4b0ea..d101c0c52 100644 --- a/ros2bag/ros2bag/verb/info.py +++ b/ros2bag/ros2bag/verb/info.py @@ -45,6 +45,6 @@ def main(self, *, args): # noqa: D102 Info().print_output_verbose(args.bag_path, m, args.sort) else: if args.topic_name: - Info().print_output_topic_name_only(m) + Info().print_output_topic_name_only(m, args.sort) else: Info().print_output(m, args.sort) diff --git a/rosbag2_py/CMakeLists.txt b/rosbag2_py/CMakeLists.txt index feb07925f..781fb3387 100644 --- a/rosbag2_py/CMakeLists.txt +++ b/rosbag2_py/CMakeLists.txt @@ -86,6 +86,7 @@ pybind11_add_module(_info SHARED src/rosbag2_py/_info.cpp src/rosbag2_py/format_bag_metadata.cpp src/rosbag2_py/format_service_info.cpp + src/rosbag2_py/info_sorting_method.cpp ) target_link_libraries(_info PUBLIC rosbag2_cpp::rosbag2_cpp diff --git a/rosbag2_py/src/rosbag2_py/_info.cpp b/rosbag2_py/src/rosbag2_py/_info.cpp index 8fd39d69b..7b5d0473d 100644 --- a/rosbag2_py/src/rosbag2_py/_info.cpp +++ b/rosbag2_py/src/rosbag2_py/_info.cpp @@ -18,6 +18,7 @@ #include #include +#include "info_sorting_method.hpp" #include "format_bag_metadata.hpp" #include "format_service_info.hpp" #include "rosbag2_cpp/info.hpp" @@ -30,11 +31,6 @@ namespace rosbag2_py { -std::unordered_map stringToSortingMethod = { - {"name", SortingMethod::NAME}, - {"type", SortingMethod::TYPE}, - {"count", SortingMethod::COUNT}}; - class Info { public: @@ -51,28 +47,23 @@ class Info } void print_output( - const rosbag2_storage::BagMetadata & metadata_info, std::string sorting_method) + const rosbag2_storage::BagMetadata & metadata_info, const std::string & sorting_method) { - rosbag2_py::SortingMethod sort_method = rosbag2_py::stringToSortingMethod[sorting_method]; + InfoSortingMethod sort_method = info_sorting_method_from_string(sorting_method); // Output formatted metadata std::cout << format_bag_meta_data(metadata_info, {}, false, false, sort_method) << std::endl; } - void print_output_topic_name_only(const rosbag2_storage::BagMetadata & metadata_info) + void print_output_topic_name_only( + const rosbag2_storage::BagMetadata & metadata_info, const std::string & sorting_method) { - std::vector sorted_idx(metadata_info.topics_with_message_count.size()); - std::iota(sorted_idx.begin(), sorted_idx.end(), 0); - std::sort( - sorted_idx.begin(), - sorted_idx.end(), - [&metadata_info](size_t i1, size_t i2) { - std::string topic_name_1 = metadata_info.topics_with_message_count[i1].topic_metadata.name; - std::string topic_name_2 = metadata_info.topics_with_message_count[i2].topic_metadata.name; - return topic_name_1 < topic_name_2; - } - ); + InfoSortingMethod sort_method = info_sorting_method_from_string(sorting_method); + std::vector sorted_idx = generate_sorted_idx( + metadata_info.topics_with_message_count, + sort_method); + for (auto idx : sorted_idx) { - auto topic_info = metadata_info.topics_with_message_count[idx]; + const auto & topic_info = metadata_info.topics_with_message_count[idx]; if (!rosbag2_cpp::is_service_event_topic( topic_info.topic_metadata.name, topic_info.topic_metadata.type)) @@ -85,7 +76,7 @@ class Info void print_output_verbose( const std::string & uri, const rosbag2_storage::BagMetadata & metadata_info, - std::string sorting_method) + const std::string & sorting_method) { std::vector> all_services_info; for (auto & file_info : metadata_info.files) { @@ -110,7 +101,7 @@ class Info } } - rosbag2_py::SortingMethod sort_method = rosbag2_py::stringToSortingMethod[sorting_method]; + rosbag2_py::InfoSortingMethod sort_method = info_sorting_method_from_string(sorting_method); // Output formatted metadata and service info std::cout << format_bag_meta_data(metadata_info, messages_size, true, true, sort_method); std::cout << format_service_info(all_services_info, messages_size, true) << std::endl; @@ -119,7 +110,7 @@ class Info std::unordered_set get_sorting_methods() { std::unordered_set sorting_methods; - for (auto sorting_method : rosbag2_py::stringToSortingMethod) { + for (auto sorting_method : rosbag2_py::sorting_method_map) { sorting_methods.insert(sorting_method.first); } return sorting_methods; diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index 0b1fa48bd..117d80793 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -118,7 +118,7 @@ void format_topics_with_type( bool verbose, std::stringstream & info_stream, int indentation_spaces, - const rosbag2_py::SortingMethod sort_method = rosbag2_py::SortingMethod::NAME) + const rosbag2_py::InfoSortingMethod sort_method = rosbag2_py::InfoSortingMethod::NAME) { if (topics.empty()) { info_stream << std::endl; @@ -142,21 +142,7 @@ void format_topics_with_type( info_stream << std::endl; }; - std::vector sorted_idx(topics.size()); - std::iota(sorted_idx.begin(), sorted_idx.end(), 0); - std::sort( - sorted_idx.begin(), - sorted_idx.end(), - [&topics, sort_method](size_t i1, size_t i2) { - if (sort_method == rosbag2_py::SortingMethod::TYPE) { - return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; - } - if (sort_method == rosbag2_py::SortingMethod::COUNT) { - return topics[i1].message_count < topics[i2].message_count; - } - return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; - } - ); + std::vector sorted_idx = rosbag2_py::generate_sorted_idx(topics, sort_method); size_t number_of_topics = topics.size(); size_t i = 0; @@ -186,31 +172,19 @@ void format_topics_with_type( } } -struct ServiceMetadata -{ - std::string name; - std::string type; - std::string serialization_format; -}; -struct ServiceInformation -{ - ServiceMetadata service_metadata; - size_t event_message_count = 0; -}; - -std::vector> filter_service_event_topic( +std::vector> filter_service_event_topic( const std::vector & topics_with_message_count, size_t & total_service_event_msg_count) { total_service_event_msg_count = 0; - std::vector> service_info_list; + std::vector> service_info_list; for (auto & topic : topics_with_message_count) { if (rosbag2_cpp::is_service_event_topic( topic.topic_metadata.name, topic.topic_metadata.type)) { - auto service_info = std::make_shared(); + auto service_info = std::make_shared(); service_info->service_metadata.name = rosbag2_cpp::service_event_topic_name_to_service_name(topic.topic_metadata.name); service_info->service_metadata.type = @@ -227,12 +201,12 @@ std::vector> filter_service_event_topic( } void format_service_with_type( - const std::vector> & services, + const std::vector> & services, const std::unordered_map & messages_size, bool verbose, std::stringstream & info_stream, int indentation_spaces, - const rosbag2_py::SortingMethod sort_method = rosbag2_py::SortingMethod::NAME) + const rosbag2_py::InfoSortingMethod sort_method = rosbag2_py::InfoSortingMethod::NAME) { if (services.empty()) { info_stream << std::endl; @@ -241,7 +215,7 @@ void format_service_with_type( auto print_service_info = [&info_stream, &messages_size, verbose]( - const std::shared_ptr & si) -> void { + const std::shared_ptr & si) -> void { info_stream << "Service: " << si->service_metadata.name << " | "; info_stream << "Type: " << si->service_metadata.type << " | "; info_stream << "Event Count: " << si->event_message_count << " | "; @@ -258,21 +232,7 @@ void format_service_with_type( info_stream << std::endl; }; - std::vector sorted_idx(services.size()); - std::iota(sorted_idx.begin(), sorted_idx.end(), 0); - std::sort( - sorted_idx.begin(), - sorted_idx.end(), - [&services, sort_method](size_t i1, size_t i2) { - if (sort_method == rosbag2_py::SortingMethod::TYPE) { - return services[i1]->service_metadata.type < services[i2]->service_metadata.type; - } - if (sort_method == rosbag2_py::SortingMethod::COUNT) { - return services[i1]->event_message_count < services[i2]->event_message_count; - } - return services[i1]->service_metadata.name < services[i2]->service_metadata.name; - } - ); + std::vector sorted_idx = rosbag2_py::generate_sorted_idx(services, sort_method); print_service_info(services[sorted_idx[0]]); auto number_of_services = services.size(); @@ -292,7 +252,7 @@ std::string format_bag_meta_data( const std::unordered_map & messages_size, bool verbose, bool only_topic, - const SortingMethod sort_method) + const InfoSortingMethod sort_method) { auto start_time = metadata.starting_time.time_since_epoch(); auto end_time = start_time + metadata.duration; @@ -304,7 +264,7 @@ std::string format_bag_meta_data( } size_t total_service_event_msg_count = 0; - std::vector> service_info_list; + std::vector> service_info_list; service_info_list = filter_service_event_topic( metadata.topics_with_message_count, total_service_event_msg_count); diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp index de8def134..88343006a 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp @@ -18,27 +18,18 @@ #include #include +#include "info_sorting_method.hpp" #include "rosbag2_storage/bag_metadata.hpp" namespace rosbag2_py { -/** - * \brief Available sorting methods for info output. - */ -enum class SortingMethod -{ - NAME, - TYPE, - COUNT, -}; - std::string format_bag_meta_data( const rosbag2_storage::BagMetadata & metadata, const std::unordered_map & messages_size = {}, bool verbose = false, bool only_topic = false, - const SortingMethod sort_method = SortingMethod::NAME); + const InfoSortingMethod sort_method = InfoSortingMethod::NAME); } // namespace rosbag2_py diff --git a/rosbag2_py/src/rosbag2_py/format_service_info.cpp b/rosbag2_py/src/rosbag2_py/format_service_info.cpp index 379425915..4b4f3d121 100644 --- a/rosbag2_py/src/rosbag2_py/format_service_info.cpp +++ b/rosbag2_py/src/rosbag2_py/format_service_info.cpp @@ -46,7 +46,8 @@ std::string format_service_info( std::vector> & service_info_list, const std::unordered_map & messages_size, - bool verbose) + bool verbose, + const InfoSortingMethod sort_method) { std::stringstream info_stream; const std::string service_info_string = "Service information: "; @@ -78,11 +79,13 @@ format_service_info( info_stream << std::endl; }; - print_service_info(service_info_list[0]); + std::vector sorted_idx = rosbag2_py::generate_sorted_idx(service_info_list, sort_method); + + print_service_info(service_info_list[sorted_idx[0]]); auto number_of_services = service_info_list.size(); for (size_t j = 1; j < number_of_services; ++j) { info_stream << std::string(indentation_spaces, ' '); - print_service_info(service_info_list[j]); + print_service_info(service_info_list[sorted_idx[j]]); } return info_stream.str(); diff --git a/rosbag2_py/src/rosbag2_py/format_service_info.hpp b/rosbag2_py/src/rosbag2_py/format_service_info.hpp index 2feb1432c..58b696e08 100644 --- a/rosbag2_py/src/rosbag2_py/format_service_info.hpp +++ b/rosbag2_py/src/rosbag2_py/format_service_info.hpp @@ -20,6 +20,7 @@ #include #include +#include "info_sorting_method.hpp" #include "rosbag2_cpp/info.hpp" namespace rosbag2_py @@ -28,7 +29,8 @@ namespace rosbag2_py std::string format_service_info( std::vector> & service_info, const std::unordered_map & messages_size = {}, - bool verbose = false); + bool verbose = false, + const InfoSortingMethod sort_method = InfoSortingMethod::NAME); } // namespace rosbag2_py diff --git a/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp b/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp new file mode 100644 index 000000000..cc07725e4 --- /dev/null +++ b/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp @@ -0,0 +1,103 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rosbag2_storage/bag_metadata.hpp" + +#include "info_sorting_method.hpp" + + +namespace rosbag2_py +{ + +InfoSortingMethod info_sorting_method_from_string(std::string str) +{ + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + auto find_result = sorting_method_map.find("str"); + if (find_result == sorting_method_map.end()) { + throw std::runtime_error("Enum value match for \"" + str + "\" string is not found."); + } + return find_result->second; +} + +std::vector generate_sorted_idx( + const std::vector & topics, + const InfoSortingMethod sort_method) +{ + std::vector sorted_idx(topics.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&topics, sort_method](size_t i1, size_t i2) { + if (sort_method == InfoSortingMethod::TYPE) { + return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; + } + if (sort_method == InfoSortingMethod::COUNT) { + return topics[i1].message_count < topics[i2].message_count; + } + return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; + } + ); + return sorted_idx; +} + + +std::vector generate_sorted_idx( + std::vector> & services, + const InfoSortingMethod sort_method) +{ + std::vector sorted_idx(services.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&services, sort_method](size_t i1, size_t i2) { + if (sort_method == InfoSortingMethod::TYPE) { + return services[i1]->type < services[i2]->type; + } + if (sort_method == InfoSortingMethod::COUNT) { + const auto & count_1 = services[i1]->request_count + services[i1]->response_count; + const auto & count_2 = services[i2]->request_count + services[i2]->response_count; + return count_1 < count_2; + } + return services[i1]->name < services[i2]->name; + } + ); + return sorted_idx; +} + + +std::vector generate_sorted_idx( + const std::vector> & services, + const InfoSortingMethod sort_method) +{ + std::vector sorted_idx(services.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&services, sort_method](size_t i1, size_t i2) { + if (sort_method == InfoSortingMethod::TYPE) { + return services[i1]->service_metadata.type < services[i2]->service_metadata.type; + } + if (sort_method == InfoSortingMethod::COUNT) { + return services[i1]->event_message_count < services[i2]->event_message_count; + } + return services[i1]->service_metadata.name < services[i2]->service_metadata.name; + } + ); + return sorted_idx; +} + +} // namespace rosbag2_py diff --git a/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp b/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp new file mode 100644 index 000000000..807e0116d --- /dev/null +++ b/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp @@ -0,0 +1,63 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef ROSBAG2_PY__INFO_SORTING_METHOD_HPP_ +#define ROSBAG2_PY__INFO_SORTING_METHOD_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "rosbag2_storage/topic_metadata.hpp" +#include "rosbag2_storage/bag_metadata.hpp" +#include "rosbag2_cpp/info.hpp" + +namespace rosbag2_py +{ + +/// \brief Available sorting methods for info output. +enum class InfoSortingMethod +{ + NAME, + TYPE, + COUNT, +}; + +const std::unordered_map sorting_method_map = { + {"name", InfoSortingMethod::NAME}, + {"type", InfoSortingMethod::TYPE}, + {"count", InfoSortingMethod::COUNT}}; + +InfoSortingMethod info_sorting_method_from_string(std::string str); + +std::vector generate_sorted_idx( + const std::vector & topics, + const InfoSortingMethod sort_method = InfoSortingMethod::NAME); + +std::vector generate_sorted_idx( + const std::vector> & services, + const InfoSortingMethod sort_method = InfoSortingMethod::NAME); + +std::vector generate_sorted_idx( + const std::vector> & services, + const InfoSortingMethod sort_method = InfoSortingMethod::NAME); + +} // namespace rosbag2_py + +#endif // ROSBAG2_PY__INFO_SORTING_METHOD_HPP_ diff --git a/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp b/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp index 4bbc1cda9..865772ddb 100644 --- a/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp +++ b/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp @@ -32,6 +32,19 @@ struct TopicInformation size_t message_count; }; +struct ServiceMetadata +{ + std::string name; + std::string type; + std::string serialization_format; +}; + +struct ServiceInformation +{ + ServiceMetadata service_metadata; + size_t event_message_count = 0; +}; + struct FileInformation { std::string path; From abd69469d618504c6bf5a89f7849ac102a245e5a Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 4 Oct 2024 12:06:03 +0200 Subject: [PATCH 7/8] move ServiceInformation struct to its own header file and rename to ServiceEventInformation; replace if-else by switch-case for differantiating between sorting methods; bugfix sorting method from string resolution and service info verbose not being sorted Signed-off-by: Soenke Prophet --- rosbag2_py/CMakeLists.txt | 1 + rosbag2_py/src/rosbag2_py/_info.cpp | 3 +- .../src/rosbag2_py/format_bag_metadata.cpp | 12 ++-- .../src/rosbag2_py/format_bag_metadata.hpp | 1 + .../src/rosbag2_py/format_service_info.cpp | 31 +++++++- .../src/rosbag2_py/info_sorting_method.cpp | 70 +++++++++++++------ .../src/rosbag2_py/info_sorting_method.hpp | 3 +- .../src/rosbag2_py/service_event_info.hpp | 39 +++++++++++ .../include/rosbag2_storage/bag_metadata.hpp | 13 ---- 9 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 rosbag2_py/src/rosbag2_py/service_event_info.hpp diff --git a/rosbag2_py/CMakeLists.txt b/rosbag2_py/CMakeLists.txt index 781fb3387..a4364cc94 100644 --- a/rosbag2_py/CMakeLists.txt +++ b/rosbag2_py/CMakeLists.txt @@ -67,6 +67,7 @@ target_link_libraries(_reader PUBLIC pybind11_add_module(_storage SHARED src/rosbag2_py/_storage.cpp src/rosbag2_py/format_bag_metadata.cpp + src/rosbag2_py/info_sorting_method.cpp ) target_link_libraries(_storage PUBLIC rosbag2_cpp::rosbag2_cpp diff --git a/rosbag2_py/src/rosbag2_py/_info.cpp b/rosbag2_py/src/rosbag2_py/_info.cpp index 7b5d0473d..93fccfe62 100644 --- a/rosbag2_py/src/rosbag2_py/_info.cpp +++ b/rosbag2_py/src/rosbag2_py/_info.cpp @@ -104,7 +104,8 @@ class Info rosbag2_py::InfoSortingMethod sort_method = info_sorting_method_from_string(sorting_method); // Output formatted metadata and service info std::cout << format_bag_meta_data(metadata_info, messages_size, true, true, sort_method); - std::cout << format_service_info(all_services_info, messages_size, true) << std::endl; + std::cout << + format_service_info(all_services_info, messages_size, true, sort_method) << std::endl; } std::unordered_set get_sorting_methods() diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp index 117d80793..71e7141ea 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp @@ -173,18 +173,18 @@ void format_topics_with_type( } -std::vector> filter_service_event_topic( +std::vector> filter_service_event_topic( const std::vector & topics_with_message_count, size_t & total_service_event_msg_count) { total_service_event_msg_count = 0; - std::vector> service_info_list; + std::vector> service_info_list; for (auto & topic : topics_with_message_count) { if (rosbag2_cpp::is_service_event_topic( topic.topic_metadata.name, topic.topic_metadata.type)) { - auto service_info = std::make_shared(); + auto service_info = std::make_shared(); service_info->service_metadata.name = rosbag2_cpp::service_event_topic_name_to_service_name(topic.topic_metadata.name); service_info->service_metadata.type = @@ -201,7 +201,7 @@ std::vector> filter_service } void format_service_with_type( - const std::vector> & services, + const std::vector> & services, const std::unordered_map & messages_size, bool verbose, std::stringstream & info_stream, @@ -215,7 +215,7 @@ void format_service_with_type( auto print_service_info = [&info_stream, &messages_size, verbose]( - const std::shared_ptr & si) -> void { + const std::shared_ptr & si) -> void { info_stream << "Service: " << si->service_metadata.name << " | "; info_stream << "Type: " << si->service_metadata.type << " | "; info_stream << "Event Count: " << si->event_message_count << " | "; @@ -264,7 +264,7 @@ std::string format_bag_meta_data( } size_t total_service_event_msg_count = 0; - std::vector> service_info_list; + std::vector> service_info_list; service_info_list = filter_service_event_topic( metadata.topics_with_message_count, total_service_event_msg_count); diff --git a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp index 88343006a..e511753aa 100644 --- a/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp +++ b/rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp @@ -19,6 +19,7 @@ #include #include "info_sorting_method.hpp" +#include "service_event_info.hpp" #include "rosbag2_storage/bag_metadata.hpp" namespace rosbag2_py diff --git a/rosbag2_py/src/rosbag2_py/format_service_info.cpp b/rosbag2_py/src/rosbag2_py/format_service_info.cpp index 4b4f3d121..64559539f 100644 --- a/rosbag2_py/src/rosbag2_py/format_service_info.cpp +++ b/rosbag2_py/src/rosbag2_py/format_service_info.cpp @@ -79,7 +79,36 @@ format_service_info( info_stream << std::endl; }; - std::vector sorted_idx = rosbag2_py::generate_sorted_idx(service_info_list, sort_method); + // std::vector sorted_idx = generate_sorted_idx(service_info_list, sort_method); + std::vector sorted_idx(service_info_list.size()); + std::iota(sorted_idx.begin(), sorted_idx.end(), 0); + std::sort( + sorted_idx.begin(), + sorted_idx.end(), + [&service_info_list, sort_method](size_t i1, size_t i2) { + bool is_greater = false; + switch (sort_method) { + case InfoSortingMethod::NAME: + is_greater = service_info_list[i1]->name < service_info_list[i2]->name; + break; + case InfoSortingMethod::TYPE: + is_greater = service_info_list[i1]->type < service_info_list[i2]->type; + break; + case InfoSortingMethod::COUNT: + { + const auto & count_1 = ( + service_info_list[i1]->request_count + service_info_list[i1]->response_count); + const auto & count_2 = ( + service_info_list[i2]->request_count + service_info_list[i2]->response_count); + is_greater = count_1 < count_2; + break; + } + default: + throw std::runtime_error("switch is not exhaustive"); + } + return is_greater; + } + ); print_service_info(service_info_list[sorted_idx[0]]); auto number_of_services = service_info_list.size(); diff --git a/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp b/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp index cc07725e4..3635c5629 100644 --- a/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp +++ b/rosbag2_py/src/rosbag2_py/info_sorting_method.cpp @@ -23,7 +23,7 @@ namespace rosbag2_py InfoSortingMethod info_sorting_method_from_string(std::string str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); - auto find_result = sorting_method_map.find("str"); + auto find_result = sorting_method_map.find(str); if (find_result == sorting_method_map.end()) { throw std::runtime_error("Enum value match for \"" + str + "\" string is not found."); } @@ -40,13 +40,21 @@ std::vector generate_sorted_idx( sorted_idx.begin(), sorted_idx.end(), [&topics, sort_method](size_t i1, size_t i2) { - if (sort_method == InfoSortingMethod::TYPE) { - return topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; + bool is_greater = false; + switch (sort_method) { + case InfoSortingMethod::NAME: + is_greater = topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; + break; + case InfoSortingMethod::TYPE: + is_greater = topics[i1].topic_metadata.type < topics[i2].topic_metadata.type; + break; + case InfoSortingMethod::COUNT: + is_greater = topics[i1].message_count < topics[i2].message_count; + break; + default: + throw std::runtime_error("switch is not exhaustive"); } - if (sort_method == InfoSortingMethod::COUNT) { - return topics[i1].message_count < topics[i2].message_count; - } - return topics[i1].topic_metadata.name < topics[i2].topic_metadata.name; + return is_greater; } ); return sorted_idx; @@ -63,15 +71,25 @@ std::vector generate_sorted_idx( sorted_idx.begin(), sorted_idx.end(), [&services, sort_method](size_t i1, size_t i2) { - if (sort_method == InfoSortingMethod::TYPE) { - return services[i1]->type < services[i2]->type; - } - if (sort_method == InfoSortingMethod::COUNT) { - const auto & count_1 = services[i1]->request_count + services[i1]->response_count; - const auto & count_2 = services[i2]->request_count + services[i2]->response_count; - return count_1 < count_2; + bool is_greater = false; + switch (sort_method) { + case InfoSortingMethod::NAME: + is_greater = services[i1]->name < services[i2]->name; + break; + case InfoSortingMethod::TYPE: + is_greater = services[i1]->type < services[i2]->type; + break; + case InfoSortingMethod::COUNT: + { + const auto & count_1 = services[i1]->request_count + services[i1]->response_count; + const auto & count_2 = services[i2]->request_count + services[i2]->response_count; + is_greater = count_1 < count_2; + break; + } + default: + throw std::runtime_error("switch is not exhaustive"); } - return services[i1]->name < services[i2]->name; + return is_greater; } ); return sorted_idx; @@ -79,7 +97,7 @@ std::vector generate_sorted_idx( std::vector generate_sorted_idx( - const std::vector> & services, + const std::vector> & services, const InfoSortingMethod sort_method) { std::vector sorted_idx(services.size()); @@ -88,13 +106,21 @@ std::vector generate_sorted_idx( sorted_idx.begin(), sorted_idx.end(), [&services, sort_method](size_t i1, size_t i2) { - if (sort_method == InfoSortingMethod::TYPE) { - return services[i1]->service_metadata.type < services[i2]->service_metadata.type; - } - if (sort_method == InfoSortingMethod::COUNT) { - return services[i1]->event_message_count < services[i2]->event_message_count; + bool is_greater = false; + switch (sort_method) { + case InfoSortingMethod::NAME: + is_greater = services[i1]->service_metadata.name < services[i2]->service_metadata.name; + break; + case InfoSortingMethod::TYPE: + is_greater = services[i1]->service_metadata.type < services[i2]->service_metadata.type; + break; + case InfoSortingMethod::COUNT: + is_greater = services[i1]->event_message_count < services[i2]->event_message_count; + break; + default: + throw std::runtime_error("switch is not exhaustive"); } - return services[i1]->service_metadata.name < services[i2]->service_metadata.name; + return is_greater; } ); return sorted_idx; diff --git a/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp b/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp index 807e0116d..a60faaf0d 100644 --- a/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp +++ b/rosbag2_py/src/rosbag2_py/info_sorting_method.hpp @@ -27,6 +27,7 @@ #include "rosbag2_storage/topic_metadata.hpp" #include "rosbag2_storage/bag_metadata.hpp" #include "rosbag2_cpp/info.hpp" +#include "service_event_info.hpp" namespace rosbag2_py { @@ -55,7 +56,7 @@ std::vector generate_sorted_idx( const InfoSortingMethod sort_method = InfoSortingMethod::NAME); std::vector generate_sorted_idx( - const std::vector> & services, + const std::vector> & services, const InfoSortingMethod sort_method = InfoSortingMethod::NAME); } // namespace rosbag2_py diff --git a/rosbag2_py/src/rosbag2_py/service_event_info.hpp b/rosbag2_py/src/rosbag2_py/service_event_info.hpp new file mode 100644 index 000000000..2c5746a40 --- /dev/null +++ b/rosbag2_py/src/rosbag2_py/service_event_info.hpp @@ -0,0 +1,39 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef ROSBAG2_PY__SERVICE_EVENT_INFO_HPP_ +#define ROSBAG2_PY__SERVICE_EVENT_INFO_HPP_ + +#include + +namespace rosbag2_py +{ + +struct ServiceMetadata +{ + std::string name; + std::string type; + std::string serialization_format; +}; + +struct ServiceEventInformation +{ + ServiceMetadata service_metadata; + size_t event_message_count = 0; +}; + +} // namespace rosbag2_py + +#endif // ROSBAG2_PY__SERVICE_EVENT_INFO_HPP_ diff --git a/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp b/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp index 865772ddb..4bbc1cda9 100644 --- a/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp +++ b/rosbag2_storage/include/rosbag2_storage/bag_metadata.hpp @@ -32,19 +32,6 @@ struct TopicInformation size_t message_count; }; -struct ServiceMetadata -{ - std::string name; - std::string type; - std::string serialization_format; -}; - -struct ServiceInformation -{ - ServiceMetadata service_metadata; - size_t event_message_count = 0; -}; - struct FileInformation { std::string path; From 043a6bf57afc5ba5cad9f7e54ea802fd7d3ab9bb Mon Sep 17 00:00:00 2001 From: Soenke Prophet Date: Fri, 4 Oct 2024 12:24:24 +0200 Subject: [PATCH 8/8] add test-cases for sorted info output Signed-off-by: Soenke Prophet --- .../test_rosbag2_info_end_to_end.cpp | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/rosbag2_tests/test/rosbag2_tests/test_rosbag2_info_end_to_end.cpp b/rosbag2_tests/test/rosbag2_tests/test_rosbag2_info_end_to_end.cpp index 61808d1c9..92e1a59ef 100644 --- a/rosbag2_tests/test/rosbag2_tests/test_rosbag2_info_end_to_end.cpp +++ b/rosbag2_tests/test/rosbag2_tests/test_rosbag2_info_end_to_end.cpp @@ -185,6 +185,102 @@ TEST_P(InfoEndToEndTestFixture, info_basic_types_and_arrays_with_verbose_option_ "Size Contribution: 2.7 KiB | Serialization Format: cdr")); } +TEST_P(InfoEndToEndTestFixture, info_output_default_sorted_by_name_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion("ros2 bag info cdr_test", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "Topic: /array_topic | Type: test_msgs/msg/Arrays | Count: 4 | " + "Serialization Format: cdr\n" + " Topic: /test_topic | Type: test_msgs/msg/BasicTypes | Count: 3 | " + "Serialization Format: cdr")); +} + +TEST_P(InfoEndToEndTestFixture, info_output_sorted_by_name_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info cdr_test --sort name", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "Topic: /array_topic | Type: test_msgs/msg/Arrays | Count: 4 | " + "Serialization Format: cdr\n" + " Topic: /test_topic | Type: test_msgs/msg/BasicTypes | Count: 3 | " + "Serialization Format: cdr")); +} + +TEST_P(InfoEndToEndTestFixture, info_output_sorted_by_type_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info cdr_test --sort type", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "Topic: /array_topic | Type: test_msgs/msg/Arrays | Count: 4 | " + "Serialization Format: cdr\n" + " Topic: /test_topic | Type: test_msgs/msg/BasicTypes | Count: 3 | " + "Serialization Format: cdr")); +} + +TEST_P(InfoEndToEndTestFixture, info_output_sorted_by_count_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info cdr_test --sort count", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "Topic: /test_topic | Type: test_msgs/msg/BasicTypes | Count: 3 | " + "Serialization Format: cdr\n" + " Topic: /array_topic | Type: test_msgs/msg/Arrays | Count: 4 | " + "Serialization Format: cdr")); +} + +TEST_P(InfoEndToEndTestFixture, info_output_topics_only_sorted_by_count_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info -t cdr_test --sort count", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "/test_topic\n" + "/array_topic")); +} + +TEST_P(InfoEndToEndTestFixture, info_output_topics_only_default_sorted_by_name_test) { + internal::CaptureStdout(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info -t cdr_test", bags_path_); + std::string output = internal::GetCapturedStdout(); + + EXPECT_THAT(exit_code, Eq(EXIT_SUCCESS)); + EXPECT_THAT( + output, HasSubstr( + "/array_topic\n" + "/test_topic")); +} + +TEST_P(InfoEndToEndTestFixture, info_fails_gracefully_sort_method_does_not_exist_test) { + internal::CaptureStderr(); + auto exit_code = execute_and_wait_until_completion( + "ros2 bag info cdr_test --sort non_existent", bags_path_); + auto error_output = internal::GetCapturedStderr(); + + EXPECT_THAT(exit_code, Ne(EXIT_SUCCESS)); + EXPECT_THAT( + error_output, HasSubstr("--sort: invalid choice: 'non_existent'")); +} + // TODO(Martin-Idel-SI): Revisit exit code non-zero here, gracefully should be exit code zero TEST_P(InfoEndToEndTestFixture, info_fails_gracefully_if_bag_does_not_exist) { internal::CaptureStderr();