diff --git a/rosbag2_cpp/src/rosbag2_cpp/readers/sequential_reader.cpp b/rosbag2_cpp/src/rosbag2_cpp/readers/sequential_reader.cpp index 8c8634bd62..301a4d2f06 100644 --- a/rosbag2_cpp/src/rosbag2_cpp/readers/sequential_reader.cpp +++ b/rosbag2_cpp/src/rosbag2_cpp/readers/sequential_reader.cpp @@ -87,6 +87,10 @@ void SequentialReader::open( const rosbag2_storage::StorageOptions & storage_options, const ConverterOptions & converter_options) { + if (storage_options.uri.empty()) { + throw std::runtime_error("Can't open rosbag2_cpp::SequentialReader. The input URI is empty"); + } + storage_options_ = storage_options; base_folder_ = storage_options.uri; @@ -108,7 +112,8 @@ void SequentialReader::open( } else { storage_ = storage_factory_->open_read_only(storage_options_); if (!storage_) { - throw std::runtime_error{"No storage could be initialized from the inputs."}; + throw std::runtime_error("No storage could be initialized for the input URI: " + + storage_options.uri); } if (!set_read_order(read_order_)) { ROSBAG2_CPP_LOG_WARN( diff --git a/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp b/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp index 2d38388564..ea6d2fa579 100644 --- a/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp +++ b/rosbag2_cpp/src/rosbag2_cpp/writers/sequential_writer.cpp @@ -103,6 +103,10 @@ void SequentialWriter::open( if (is_open_) { return; // The writer already opened } + if (storage_options.uri.empty()) { + throw std::runtime_error("Can't open rosbag2_cpp::SequentialWriter. The input URI is empty"); + } + base_folder_ = storage_options.uri; storage_options_ = storage_options; diff --git a/rosbag2_cpp/test/rosbag2_cpp/test_storage_without_metadata_file.cpp b/rosbag2_cpp/test/rosbag2_cpp/test_storage_without_metadata_file.cpp index 8b8ace9d3d..967b8a65fd 100644 --- a/rosbag2_cpp/test/rosbag2_cpp/test_storage_without_metadata_file.cpp +++ b/rosbag2_cpp/test/rosbag2_cpp/test_storage_without_metadata_file.cpp @@ -74,6 +74,7 @@ TEST_F(StorageWithoutMetadataFileTest, open_uses_storage_id_from_storage_options EXPECT_CALL(*metadata_io, metadata_file_exists).Times(1).WillOnce(Return(false)); rosbag2_storage::StorageOptions storage_options; + storage_options.uri = "foo.bar"; storage_options.storage_id = kStorageId; auto sequential_reader = std::make_unique( diff --git a/rosbag2_storage/src/rosbag2_storage/impl/storage_factory_impl.hpp b/rosbag2_storage/src/rosbag2_storage/impl/storage_factory_impl.hpp index 85c4694689..a73a24aabd 100644 --- a/rosbag2_storage/src/rosbag2_storage/impl/storage_factory_impl.hpp +++ b/rosbag2_storage/src/rosbag2_storage/impl/storage_factory_impl.hpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "pluginlib/class_loader.hpp" @@ -160,19 +162,38 @@ class StorageFactoryImpl virtual ~StorageFactoryImpl() = default; + std::unordered_set get_registered_plugin_names() + { + std::vector read_only_plugins = read_only_class_loader_->getDeclaredClasses(); + std::vector read_write_plugins = read_write_class_loader_->getDeclaredClasses(); + + // Merge read-only and read-write plugins + std::unordered_set combined_plugins( + read_only_plugins.begin(), read_only_plugins.end()); + combined_plugins.insert(read_write_plugins.begin(), read_write_plugins.end()); + return combined_plugins; + } + std::shared_ptr open_read_write(const StorageOptions & storage_options) { - auto instance = - get_interface_instance(read_write_class_loader_, storage_options); + auto instance = get_interface_instance(read_write_class_loader_, storage_options); if (instance == nullptr) { if (storage_options.storage_id.empty()) { ROSBAG2_STORAGE_LOG_ERROR_STREAM( - "No storage id specified, and no plugin found that could open URI"); + "No storage id specified, and no plugin found that could open URI: '" << + storage_options.uri << "'"); } else { ROSBAG2_STORAGE_LOG_ERROR_STREAM( "Could not load/open plugin with storage id '" << storage_options.storage_id << "'"); } + auto available_plugins = read_write_class_loader_->getDeclaredClasses(); + std::stringstream ss; + ss << "Available read-write storage plugins: "; + for (const auto & storage_plugin : available_plugins) { + ss << "'" << storage_plugin << "', "; + } + ROSBAG2_STORAGE_LOG_INFO("%s", ss.str().c_str()); } return instance; @@ -193,11 +214,19 @@ class StorageFactoryImpl if (instance == nullptr) { if (storage_options.storage_id.empty()) { ROSBAG2_STORAGE_LOG_ERROR_STREAM( - "No storage id specified, and no plugin found that could open URI"); + "No storage id specified, and no plugin found that could open URI: '" << + storage_options.uri << "'"); } else { ROSBAG2_STORAGE_LOG_ERROR_STREAM( - "Could not load/open plugin with storage id '" << storage_options.storage_id << "'"); + "Could not load/open plugin with storage id: '" << storage_options.storage_id << "'"); + } + auto available_plugins = get_registered_plugin_names(); + std::stringstream ss; + ss << "Available storage plugins: "; + for (const auto & storage_plugin : available_plugins) { + ss << "'" << storage_plugin << "', "; } + ROSBAG2_STORAGE_LOG_INFO("%s", ss.str().c_str()); } return instance;