Skip to content

Instantly share code, notes, and snippets.

@EduPonz
Created March 3, 2021 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EduPonz/bea0edf3e1ac366560eff62cceb5ddf9 to your computer and use it in GitHub Desktop.
Save EduPonz/bea0edf3e1ac366560eff62cceb5ddf9 to your computer and use it in GitHub Desktop.
Use rosbag2 to record and replay Fast DDS data

Use rosbag2 to record and replay Fast DDS data

It is possible to use rosbag2 to record and replay traffic generated by a Fast DDS application. In order to do so, the next steps need to be taken:

  1. Generate a message type using ROS 2 format (.msg)
  2. Generate a ROS 2 compatible IDL from the ROS 2 .msg using Fast DDS-gen
  3. Name the topic following ROS 2 topic naming conventions.

Demonstration

This example constitutes a step-by-step guide on how to use rosbag2 to record and replay Fast DDS data. It will modify Fast DDS' HelloWorld example to publish a ROS 2 compatible type that will be recorded and replayed using rosbag2. It assumes that there is a functional ROS 2 Foxy installation containing rosbag2, that is possible to build Fast DDS from sources, and that there is a functional Fast DDS-gen installation.

  1. Generate IDL from msg
  2. Generate ROS 2 compatible type support using Fast DDS-gen
  3. Patch example to include use the String type
  4. Record data from HelloWorld example
  5. Replay the recorded data

IMPORTANT: This demo has been tested using Fast DDS' commit fddbe1168ad980e39969a643f49638bbe10ea460. Using a different commit may require modification on the patch applied to the HelloWorld example.

Generate IDL from msg

For this example, the ROS 2 standard String.msg message has been used.

source <path_to_ros2_installation>/setup.bash
ros2 run rosidl_adapter msg2idl.py <path_to_msg>/String.msg

This will output a String.idl file. This file will then be used to generate the appropriate type support for the HelloWorld example.

Generate ROS 2 compatible type support using Fast DDS-gen

This step assumes that Fast DDS is built from sources.

cp String.idl <path_to_fastdds_repository>/examples/C++/DDS/HelloWorldExample/
cd <path_to_fastdds_repository>/examples/C++/DDS/HelloWorldExample/
fastddsgen String.idl -typeros2

This will generate the following type support files:

  • String.cxx
  • String.h
  • StringPubSubTypes.cxx
  • StringPubSubTypes.h

Patch example to include use the String type

rosbag2.patch modifies the example to use the ROS 2 compatible String type. It is important to note that the topic name has been modified to rt/HelloWorldTopic following ROS 2 topic naming mangling conventions.

cd <path_to_fastdds_repository>
git apply rosbag2.patch

After this step, Fast DDS needs to be rebuilt with flags -DCOMPILE_EXAMPLES=ON -DINSTALL_EXAMPLES=ON

Record data from HelloWorld example

For this step, two terminals are needed:

Terminal 1 - Fast DDS publisher

Start a publisher that publishes 100 messages on the topic

<path_to_fastdds_installation>/examples/C++/DDS/HelloWorldExample/bin/DDSHelloWorldExample publisher 100

Terminal 2 - rosbag2

Start a recording of /HelloWorldTopic topic

source <path_to_ros2_installation>/setup.bash
ros2 bag record /HelloWorldTopic -o rosbag_demo

Once the publisher has finished, stop the recording with CTRL-C. This generates a rosbag_demo directory that contains a sqlite3 database rosbag_demo_0.db3 with the data.

Replay the recorded data

Finally, you can replay the rosbag2 data and subscribe to it using the HelloWorld example.

Terminal 1 - Fast DDS subscriber

Start a subscriber that will receive the date replayed by rosbag2

<path_to_fastdds_installation>/examples/C++/DDS/HelloWorldExample/bin/DDSHelloWorldExample subscriber

Once the rosbag2 replay is finished, you can stop the subscriber pressing enter.

Terminal 2 - rosbag2

Start a recording of /HelloWorldTopic topic

source <path_to_ros2_installation>/setup.bash
ros2 bag play rosbag_demo/rosbag_demo_0.db3
diff --git a/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.cpp b/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.cpp
index c35d9e5b2..5036b5fea 100644
--- a/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.cpp
+++ b/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.cpp
@@ -35,14 +35,13 @@ HelloWorldPublisher::HelloWorldPublisher()
, publisher_(nullptr)
, topic_(nullptr)
, writer_(nullptr)
- , type_(new HelloWorldPubSubType())
+ , type_(new std_msgs::msg::StringPubSubType())
+ , msg_count_(0)
{
}
bool HelloWorldPublisher::init()
{
- hello_.index(0);
- hello_.message("HelloWorld");
DomainParticipantQos pqos;
pqos.name("Participant_pub");
participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);
@@ -63,7 +62,7 @@ bool HelloWorldPublisher::init()
return false;
}
- topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
+ topic_ = participant_->create_topic("rt/HelloWorldTopic", type_->getName(), TOPIC_QOS_DEFAULT);
if (topic_ == nullptr)
{
@@ -129,8 +128,7 @@ void HelloWorldPublisher::runThread(
{
if (publish(false))
{
- std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
- << " SENT" << std::endl;
+ std::cout << "Message: " << hello_.data() << " SENT" << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}
@@ -145,8 +143,7 @@ void HelloWorldPublisher::runThread(
}
else
{
- std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
- << " SENT" << std::endl;
+ std::cout << "Message: " << hello_.data() << " SENT" << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}
@@ -177,7 +174,9 @@ bool HelloWorldPublisher::publish(
{
if (listener_.firstConnected_ || !waitForListener || listener_.matched_ > 0)
{
- hello_.index(hello_.index() + 1);
+ std::stringstream message;
+ message << "ros2bag test: " << ++msg_count_;
+ hello_.data(message.str());
writer_->write(&hello_);
return true;
}
diff --git a/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.h b/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.h
index e1fced5ed..dfa731ffd 100644
--- a/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.h
+++ b/examples/C++/DDS/HelloWorldExample/HelloWorldPublisher.h
@@ -20,7 +20,8 @@
#ifndef HELLOWORLDPUBLISHER_H_
#define HELLOWORLDPUBLISHER_H_
-#include "HelloWorldPubSubTypes.h"
+// #include "HelloWorldPubSubTypes.h"
+#include "StringPubSubTypes.h"
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
@@ -48,7 +49,7 @@ public:
private:
- HelloWorld hello_;
+ std_msgs::msg::String hello_;
eprosima::fastdds::dds::DomainParticipant* participant_;
@@ -88,6 +89,7 @@ public:
uint32_t sleep);
eprosima::fastdds::dds::TypeSupport type_;
+ uint32_t msg_count_;
};
diff --git a/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.cpp b/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.cpp
index bc899fe29..b5625c2b9 100644
--- a/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.cpp
+++ b/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.cpp
@@ -33,7 +33,7 @@ HelloWorldSubscriber::HelloWorldSubscriber()
, subscriber_(nullptr)
, topic_(nullptr)
, reader_(nullptr)
- , type_(new HelloWorldPubSubType())
+ , type_(new std_msgs::msg::StringPubSubType())
{
}
@@ -61,8 +61,8 @@ bool HelloWorldSubscriber::init()
//CREATE THE TOPIC
topic_ = participant_->create_topic(
- "HelloWorldTopic",
- "HelloWorld",
+ "rt/HelloWorldTopic",
+ type_->getName(),
TOPIC_QOS_DEFAULT);
if (topic_ == nullptr)
@@ -131,7 +131,7 @@ void HelloWorldSubscriber::SubListener::on_data_available(
{
samples_++;
// Print your structure data here.
- std::cout << "Message " << hello_.message() << " " << hello_.index() << " RECEIVED" << std::endl;
+ std::cout << "Message " << hello_.data() << " RECEIVED" << std::endl;
}
}
}
diff --git a/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.h b/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.h
index c2cd03b7e..445299ac9 100644
--- a/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.h
+++ b/examples/C++/DDS/HelloWorldExample/HelloWorldSubscriber.h
@@ -20,7 +20,8 @@
#ifndef HELLOWORLDSUBSCRIBER_H_
#define HELLOWORLDSUBSCRIBER_H_
-#include "HelloWorldPubSubTypes.h"
+// #include "HelloWorldPubSubTypes.h"
+#include "StringPubSubTypes.h"
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
@@ -78,7 +79,7 @@ private:
eprosima::fastdds::dds::DataReader* reader,
const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override;
- HelloWorld hello_;
+ std_msgs::msg::String hello_;
int matched_;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment