Skip to content

Commit

Permalink
Add "--sort" CLI option to the "ros2 bag info" command (#1804)
Browse files Browse the repository at this point in the history
* sort info output by topic name

Signed-off-by: Soenke Prophet <[email protected]>

* add missing imports

Signed-off-by: Soenke Prophet <[email protected]>

* add sorting to service topics and remove sorting option by serialization format

Signed-off-by: Soenke Prophet <[email protected]>

* add CLI option for sorting output and move sorting methods to enum

Signed-off-by: Soenke Prophet <[email protected]>

* add sorting by name to topic only option of info output

Signed-off-by: Soenke Prophet <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* add test-cases for sorted info output

Signed-off-by: Soenke Prophet <[email protected]>

* Fix linker issues

- Add missing const qualifier for the generate_sorted_idx(..) version
with rosbag2_cpp::rosbag2_service_info_t
- Small cleanups

Signed-off-by: Michael Orlov <[email protected]>

* Regenerate pyi stub files

Signed-off-by: Michael Orlov <[email protected]>

* Small nitpick for using const reference in the for loop

Signed-off-by: Michael Orlov <[email protected]>

---------

Signed-off-by: Soenke Prophet <[email protected]>
Signed-off-by: Michael Orlov <[email protected]>
Co-authored-by: Soenke Prophet <[email protected]>
Co-authored-by: Michael Orlov <[email protected]>
(cherry picked from commit 25304dd)

# Conflicts:
#	ros2bag/ros2bag/verb/info.py
#	rosbag2_py/rosbag2_py/_info.pyi
#	rosbag2_py/src/rosbag2_py/_info.cpp
#	rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp
#	rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp
#	rosbag2_py/src/rosbag2_py/format_service_info.cpp
#	rosbag2_py/src/rosbag2_py/format_service_info.hpp
  • Loading branch information
Sanoronas authored and mergify[bot] committed Oct 17, 2024
1 parent 64717ee commit 4e5e021
Show file tree
Hide file tree
Showing 12 changed files with 507 additions and 30 deletions.
15 changes: 15 additions & 0 deletions ros2bag/ros2bag/verb/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 _is_service_event_topic(self, topic_name, topic_type) -> bool:

Expand All @@ -51,13 +56,23 @@ def main(self, *, args): # noqa: D102
print("Warning! You have set both the '-t' and '-v' parameters. The '-t' parameter "
'will be ignored.')
if args.verbose:
<<<<<<< HEAD
Info().read_metadata_and_output_service_verbose(args.bag_path, args.storage)
=======
Info().print_output_verbose(args.bag_path, m, args.sort)
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
else:
m = Info().read_metadata(args.bag_path, args.storage)
if args.topic_name:
<<<<<<< HEAD
for topic_info in m.topics_with_message_count:
if not self._is_service_event_topic(topic_info.topic_metadata.name,
topic_info.topic_metadata.type):
print(topic_info.topic_metadata.name)
else:
print(m)
=======
Info().print_output_topic_name_only(m, args.sort)
else:
Info().print_output(m, args.sort)
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
2 changes: 2 additions & 0 deletions rosbag2_py/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -86,6 +87,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
Expand Down
7 changes: 7 additions & 0 deletions rosbag2_py/rosbag2_py/_info.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@ import rosbag2_py._storage

class Info:
def __init__(self) -> None: ...
<<<<<<< HEAD
=======
def get_sorting_methods(self) -> Set[str]: ...
def print_output(self, arg0: rosbag2_py._storage.BagMetadata, arg1: str) -> None: ...
def print_output_topic_name_only(self, arg0: rosbag2_py._storage.BagMetadata, arg1: str) -> None: ...
def print_output_verbose(self, arg0: str, arg1: rosbag2_py._storage.BagMetadata, arg2: str) -> None: ...
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
def read_metadata(self, arg0: str, arg1: str) -> rosbag2_py._storage.BagMetadata: ...
def read_metadata_and_output_service_verbose(self, arg0: str, arg1: str) -> None: ...
71 changes: 71 additions & 0 deletions rosbag2_py/src/rosbag2_py/_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include <iostream>
#include <memory>
#include <string>
#include <algorithm>

#include "info_sorting_method.hpp"
#include "format_bag_metadata.hpp"
#include "format_service_info.hpp"
#include "rosbag2_cpp/info.hpp"
Expand All @@ -41,12 +43,47 @@ class Info
return info_->read_metadata(uri, storage_id);
}

<<<<<<< HEAD
void read_metadata_and_output_service_verbose(
const std::string & uri,
const std::string & storage_id)
{
auto metadata_info = read_metadata(uri, storage_id);

=======
void print_output(
const rosbag2_storage::BagMetadata & metadata_info, const std::string & 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, const std::string & sorting_method)
{
InfoSortingMethod sort_method = info_sorting_method_from_string(sorting_method);
std::vector<size_t> sorted_idx = generate_sorted_idx(
metadata_info.topics_with_message_count,
sort_method);

for (auto idx : sorted_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))
{
std::cout << topic_info.topic_metadata.name << std::endl;
}
}
}

void print_output_verbose(
const std::string & uri,
const rosbag2_storage::BagMetadata & metadata_info,
const std::string & sorting_method)
{
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
std::vector<std::shared_ptr<rosbag2_cpp::rosbag2_service_info_t>> all_services_info;
for (auto & file_info : metadata_info.files) {
auto services_info = info_->read_service_info(
Expand All @@ -60,9 +97,36 @@ class Info
}
}

<<<<<<< HEAD
// Output formatted metadata and service info
std::cout << format_bag_meta_data(metadata_info, true);
std::cout << format_service_info(all_services_info) << std::endl;
=======
std::unordered_map<std::string, uint64_t> messages_size = {};
for (const auto & file_info : metadata_info.files) {
auto messages_size_tmp = info_->compute_messages_size_contribution(
uri + "/" + file_info.path,
metadata_info.storage_identifier);
for (const auto & topic_size_tmp : messages_size_tmp) {
messages_size[topic_size_tmp.first] += topic_size_tmp.second;
}
}

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, sort_method) << std::endl;
}

std::unordered_set<std::string> get_sorting_methods()
{
std::unordered_set<std::string> sorting_methods;
for (const auto & sorting_method : rosbag2_py::sorting_method_map) {
sorting_methods.insert(sorting_method.first);
}
return sorting_methods;
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
}

protected:
Expand All @@ -77,7 +141,14 @@ PYBIND11_MODULE(_info, m) {
pybind11::class_<rosbag2_py::Info>(m, "Info")
.def(pybind11::init())
.def("read_metadata", &rosbag2_py::Info::read_metadata)
<<<<<<< HEAD
.def(
"read_metadata_and_output_service_verbose",
&rosbag2_py::Info::read_metadata_and_output_service_verbose);
=======
.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("get_sorting_methods", &rosbag2_py::Info::get_sorting_methods);
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
}
84 changes: 56 additions & 28 deletions rosbag2_py/src/rosbag2_py/format_bag_metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "rosbag2_storage/bag_metadata.hpp"

#include "format_bag_metadata.hpp"
#include "service_event_info.hpp"

namespace
{
Expand Down Expand Up @@ -113,7 +114,8 @@ void format_file_paths(
void format_topics_with_type(
const std::vector<rosbag2_storage::TopicInformation> & topics,
std::stringstream & info_stream,
int indentation_spaces)
int indentation_spaces,
const rosbag2_py::InfoSortingMethod sort_method = rosbag2_py::InfoSortingMethod::NAME)
{
if (topics.empty()) {
info_stream << std::endl;
Expand All @@ -129,13 +131,15 @@ void format_topics_with_type(
info_stream << std::endl;
};

std::vector<size_t> sorted_idx = rosbag2_py::generate_sorted_idx(topics, sort_method);

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++;
}
Expand All @@ -145,43 +149,31 @@ 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]]);
}
}

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<std::shared_ptr<ServiceInformation>> filter_service_event_topic(
std::vector<std::shared_ptr<rosbag2_py::ServiceEventInformation>> filter_service_event_topic(
const std::vector<rosbag2_storage::TopicInformation> & topics_with_message_count,
size_t & total_service_event_msg_count)
{
total_service_event_msg_count = 0;
std::vector<std::shared_ptr<ServiceInformation>> service_info_list;
std::vector<std::shared_ptr<rosbag2_py::ServiceEventInformation>> 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<ServiceInformation>();
auto service_info = std::make_shared<rosbag2_py::ServiceEventInformation>();
service_info->service_metadata.name =
rosbag2_cpp::service_event_topic_name_to_service_name(topic.topic_metadata.name);
service_info->service_metadata.type =
Expand All @@ -198,29 +190,43 @@ std::vector<std::shared_ptr<ServiceInformation>> filter_service_event_topic(
}

void format_service_with_type(
<<<<<<< HEAD
const std::vector<std::shared_ptr<ServiceInformation>> & services,
=======
const std::vector<std::shared_ptr<rosbag2_py::ServiceEventInformation>> & services,
const std::unordered_map<std::string, uint64_t> & messages_size,
bool verbose,
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
std::stringstream & info_stream,
int indentation_spaces)
int indentation_spaces,
const rosbag2_py::InfoSortingMethod sort_method = rosbag2_py::InfoSortingMethod::NAME)
{
if (services.empty()) {
info_stream << std::endl;
return;
}

auto print_service_info =
<<<<<<< HEAD
[&info_stream](const std::shared_ptr<ServiceInformation> & si) -> void {
=======
[&info_stream, &messages_size, verbose](
const std::shared_ptr<rosbag2_py::ServiceEventInformation> & si) -> void {
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
info_stream << "Service: " << si->service_metadata.name << " | ";
info_stream << "Type: " << si->service_metadata.type << " | ";
info_stream << "Event Count: " << si->event_message_count << " | ";
info_stream << "Serialization Format: " << si->service_metadata.serialization_format;
info_stream << std::endl;
};

print_service_info(services[0]);
std::vector<size_t> sorted_idx = rosbag2_py::generate_sorted_idx(services, sort_method);

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]]);
}
}

Expand All @@ -231,7 +237,14 @@ namespace rosbag2_py

std::string format_bag_meta_data(
const rosbag2_storage::BagMetadata & metadata,
<<<<<<< HEAD
bool only_topic)
=======
const std::unordered_map<std::string, uint64_t> & messages_size,
bool verbose,
bool only_topic,
const InfoSortingMethod sort_method)
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
{
auto start_time = metadata.starting_time.time_since_epoch();
auto end_time = start_time + metadata.duration;
Expand All @@ -243,10 +256,8 @@ std::string format_bag_meta_data(
}

size_t total_service_event_msg_count = 0;
std::vector<std::shared_ptr<ServiceInformation>> service_info_list;
service_info_list = filter_service_event_topic(
metadata.topics_with_message_count,
total_service_event_msg_count);
std::vector<std::shared_ptr<ServiceEventInformation>> service_info_list =
filter_service_event_topic(metadata.topics_with_message_count, total_service_event_msg_count);

info_stream << std::endl;
info_stream << "Files: ";
Expand All @@ -264,13 +275,30 @@ std::string format_bag_meta_data(
std::endl;
info_stream << "Topic information: ";
format_topics_with_type(
<<<<<<< HEAD
metadata.topics_with_message_count, info_stream, indentation_spaces);
=======
metadata.topics_with_message_count,
messages_size, verbose, info_stream,
indentation_spaces,
sort_method);
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))

if (!only_topic) {
info_stream << "Service: " << service_info_list.size() << std::endl;
info_stream << "Service information: ";
if (!service_info_list.empty()) {
<<<<<<< HEAD
format_service_with_type(service_info_list, info_stream, indentation_spaces + 2);
=======
format_service_with_type(
service_info_list,
messages_size,
verbose,
info_stream,
indentation_spaces + 2,
sort_method);
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))
}
}

Expand Down
9 changes: 9 additions & 0 deletions rosbag2_py/src/rosbag2_py/format_bag_metadata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@

#include <string>

#include "info_sorting_method.hpp"
#include "rosbag2_storage/bag_metadata.hpp"

namespace rosbag2_py
{

std::string format_bag_meta_data(
<<<<<<< HEAD
const rosbag2_storage::BagMetadata & metadata, bool only_topic = false);
=======
const rosbag2_storage::BagMetadata & metadata,
const std::unordered_map<std::string, uint64_t> & messages_size = {},
bool verbose = false,
bool only_topic = false,
InfoSortingMethod sort_method = InfoSortingMethod::NAME);
>>>>>>> 25304dd3 (Add "--sort" CLI option to the "ros2 bag info" command (#1804))

} // namespace rosbag2_py

Expand Down
Loading

0 comments on commit 4e5e021

Please sign in to comment.