Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow an arbitrary topic to be recorded #26

Merged
merged 45 commits into from
Sep 4, 2018

Conversation

Martin-Idel-SI
Copy link
Contributor

@Martin-Idel-SI Martin-Idel-SI commented Aug 28, 2018

This is based on #24

This PR adds the ability to record an arbitrary topic of an arbitrary ROS 2 type. To do this, the following changes are made:

  • Extend the SQLite default storage plugin to contain a table of topics with type info
  • Subscribe to and publish raw messages of arbitrary known topics, where the type info is retrieved from the corresponding type-info package (using the ideas presented in loading ts from ament index #20)
  • To subscribe to messages without type info at compile time, we added a "GenericPublisher". Once this is possible with rclcpp this part can be deleted
  • The demo_record takes the name of the topic to be recorded as a parameter. If the topic does not exist, rosbag record exits early.
  • For now, the topic must be available at start up of rosbag_record. We have a small timeout to allow discovery of nodes and topics.

We make the following assumptions regarding types:

  • When calling node->get_topic_names_and_types() all ROS 2 topics will be of the form <package-name>/<message-type> (e.g. std_msgs/String), while neither the package name nor the message type contain any further slashes.
  • When a topic has multiple types, it is not a ROS 2 topic and won't be processed by rosbag

Known issues:

Copy link
Collaborator

@Karsten1987 Karsten1987 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will reiterate once you had a chance to rebase this PR, but I requested changes for the rosbag2Node class.

const std::string & topic_name, const std::shared_ptr<rclcpp::Node> & node)
{
// TODO(Martin-Idel-SI): This is a short sleep to allow the node some time to discover the topic
// This should be replaced by an auto-discovery system in the future
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe getting the topic type can eventually be excluded and done via the command line interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are my problems with this approach:

  • How do you plan to support subscribing to new topics which are not available at startup time? If I say rosbag2 record -all I would eventually expect also new topics that are created after startup to be recorded. In that case, this will have to be done in our C++ loops, so I don't think it's a good idea to do this in the python code.
  • I thought that the python code would really only be a python wrapper. But if you get topics and types in python, then you'd have further functionality there. I think it would be cleaner to have all functionality in C++

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point. I believe we could have an overload for record (for a later time):

  • record(const std::string & topic_name, ...)
  • record(const std::string & topic_name, const std::string & topic_type)

The reason I am bringing up the python interface is, because it's easier to load the type information from python directly.

The thing with recording new topics is tricky though. This has to be somehow specified how often we look for new topics then. I believe in the current ROS 1 implementation, only the topics available at startup time are recorded. Otherwise I would expect asking for all available topics after every spin.


if (type.empty()) {
RCUTILS_LOG_INFO_NAMED(ROS_PACKAGE_NAME, "Topic could not be found. Abort.");
return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it make sense to return an boolean here or throw? Somehow the calling user would not necessarily notice that the recording fails.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the throw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

rosbag2/src/rosbag2/rosbag2_node.cpp Show resolved Hide resolved
return;
}

auto subscription = node->create_generic_subscription(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generic subscription should be created directly through its constructor and a regular node can be given as a parameter. I believe this makes things easier later on when the generic sub/pub are in ros2 and thus keeps changes to a minimum.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's just for keeping changes to a minimum, I'm not really sure this is true: Now, we can just delete the node class (including its test), adapt the node type in rosbag2 and maybe slightly adapt the method calls in rosbag2. In the other case, we have to rewrite all publishing and subscribing code in rosbag2 so I think it's more a matter of taste.

namespace test_helpers
{

std::shared_ptr<rmw_serialized_message_t> serialize_string_message(std::string message)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not const std::string & message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME,
"Requested storage id %s does not exist", storage_id.c_str());
// This prevents unnecessary error messages when loading a ReadWrite storage as ReadOnly storage
if (last_attempt) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the exact purpose of this? When is decided that this is a last attempt? Can you elaborate on this?

Copy link
Contributor Author

@Martin-Idel-SI Martin-Idel-SI Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure: Before this change, whenever you used rosbag_play, you'd get an error message "Requested storage id sqlite3 does not exist" because there is no ReadOnlyStorage sqlite3 from pluginlib's perspective. Obviously, since there is a ReadWriteStorage sqlite3, we still open the storage and everything works correctly, but the error message is highly irritating.

I deleted the "last_attempt" workaround and just print a debug message at that point, printing an overall failure message when no loading succeeded.

@@ -32,13 +33,15 @@ class TestPlugin : public rosbag2_storage::storage_interfaces::ReadWriteInterfac

rosbag2_storage::BagInfo info() override;

bool has_next() const override;
void create_topic(const std::string & name, const std::string & type_id) override;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

topic_id here is the topic type? Or which id is meant here? If so, I would recommend having it renamed to type_type in order to keep the vocabulary in sync with upstream

Copy link
Contributor Author

@Martin-Idel-SI Martin-Idel-SI Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to name and type

@@ -40,39 +44,14 @@ SqliteWrapper::~SqliteWrapper()
sqlite3_close(db_ptr);
}

void SqliteWrapper::execute_query(const std::string & query)
SqliteStatement SqliteWrapper::prepare_statement(std::string query)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the change from const std::string & ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change, this is just git messing up. But changed to const ref.


#include "rcutils/types.h"

#include "../../../src/rosbag2_storage_default_plugins/sqlite/sqlite_wrapper.hpp"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's a test, but given that long include path, is there any use to having this wrapper file public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be made public in #31, because at that point we need it in other tests as well. But until then, I think it's cleaner to do it like this.

anhosi and others added 26 commits September 4, 2018 09:27
- Two table db layout (messages and topics)
- Messages table references topics table but without foreign key for
  improved write performance
- Create_topic must be called for every topic prior to storing a
  message of this topic.
- Sqlite_storage caches all known topics
- At least for now the type information is stored as a simple string.
@@ -20,13 +20,22 @@ find_package(rclcpp REQUIRED)
find_package(rcutils REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rosbag2_storage REQUIRED)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Alphabetical order

auto initial_capacity = 8u + static_cast<size_t>(test_message->data.size());
auto msg = new rmw_serialized_message_t;
*msg = rcutils_get_zero_initialized_char_array();
auto ret = rcutils_char_array_init(msg, initial_capacity, &rcutils_allocator);
Copy link
Collaborator

@Karsten1987 Karsten1987 Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the allocator pointer will dangle here when the rcutils_allocator goes out of scope.

@Karsten1987 Karsten1987 merged commit bdd7fd1 into ros2:master Sep 4, 2018
@anhosi anhosi deleted the feature/extend_db_schema branch September 5, 2018 06:57
anhosi added a commit to bosch-io/rosbag2 that referenced this pull request Sep 5, 2018
Karsten1987 pushed a commit that referenced this pull request Sep 5, 2018
* GH-61 Read topic directly from message when playing and allow to play multiple topics

* GH-61 Add test for SqliteStorage and update old ones

* GH-62 Extend function to poll for any number of specified topics

* GH-62 Allow subscription to several topics

* GH-61 Obtain the topic name directly from the database

- Uses a JOIN instead of mapping the topic_id to the name in code

* GH-61 Cache read row in result iterator

This allows repeated dereferencing on same row without quering the
database again.

* GH-62 Change demo-record to allow specifying multiple topics

* GH-62 Add test to write non-string topic + refactoring

* GH-62 Add test for subscription to multiple topics

* GH-62 Cleanup

* GH-62 Simplify test setup

* GH-61 Cleanup

* GH-61 consolidate storage integration test

* GH-62 Consolidate write integration tests

* GH-61 enhance read integration test to check multiple topics

* GH-62 Improve rosbag integration test

* GH-62: Polish rosbag2_rosbag_node_test

* GH-62 Fix cpplint

* GH-62 Fix memory leak in rosbag helper

* GH-62 Cleanup of subscriptions

* GH-62 do not use flaky timers in rosbag2_write_integration_test

* GH-62 Use rmw_serialize_message_t consistently in test helper classes

* GH-73 Use test_msgs in read_integration_test

* GH-26 Cleanup: fix alphabetic orderung
james-rms pushed a commit to james-rms/rosbag2 that referenced this pull request Nov 17, 2022
Addressing feedback from ros/rosdistro#32534 (comment)

Make mcap available as a shared library in the mcap_vendor package. It does not depend on lz4/zstd shared libraries but pulls them in directly using FetchContent.

mcap itself is also fetched directly from git instead of using conan to pull in the dependency.

Closes ros2#26, closes ros2#27

Signed-off-by: Jacob Bandes-Storch <jacob@foxglove.dev>
james-rms pushed a commit to james-rms/rosbag2 that referenced this pull request Nov 17, 2022
Addressing feedback from ros/rosdistro#32534 (comment)

Make mcap available as a shared library in the mcap_vendor package. It does not depend on lz4/zstd shared libraries but pulls them in directly using FetchContent.

mcap itself is also fetched directly from git instead of using conan to pull in the dependency.

Closes ros2#26, closes ros2#27

Signed-off-by: Jacob Bandes-Storch <jacob@foxglove.dev>
Signed-off-by: James Smith <james@foxglove.dev>
james-rms pushed a commit to james-rms/rosbag2 that referenced this pull request Nov 18, 2022
…ooling/rosbag_storage_mcap#28)

Addressing feedback from ros/rosdistro#32534 (comment)

Make mcap available as a shared library in the mcap_vendor package. It does not depend on lz4/zstd shared libraries but pulls them in directly using FetchContent.

mcap itself is also fetched directly from git instead of using conan to pull in the dependency.

Closes ros2#26, closes ros2#27

Signed-off-by: Jacob Bandes-Storch <jacob@foxglove.dev>
Signed-off-by: James Smith <james@foxglove.dev>
james-rms pushed a commit to james-rms/rosbag2 that referenced this pull request Nov 18, 2022
…ooling/rosbag2_storage_mcap#28)

Addressing feedback from ros/rosdistro#32534 (comment)

Make mcap available as a shared library in the mcap_vendor package. It does not depend on lz4/zstd shared libraries but pulls them in directly using FetchContent.

mcap itself is also fetched directly from git instead of using conan to pull in the dependency.

Closes ros2#26, closes ros2#27

Signed-off-by: Jacob Bandes-Storch <jacob@foxglove.dev>
Signed-off-by: James Smith <james@foxglove.dev>
emersonknapp added a commit that referenced this pull request Jun 10, 2024
…topic across splits in the bag recorder (#26)

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants