rosbag_publisher_main.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
20 #include "gflags/gflags.h"
21 #include "nav_msgs/Odometry.h"
22 #include "ros/ros.h"
23 #include "ros/time.h"
24 #include "rosbag/bag.h"
25 #include "rosbag/view.h"
26 #include "sensor_msgs/Imu.h"
27 #include "sensor_msgs/LaserScan.h"
28 #include "sensor_msgs/MultiEchoLaserScan.h"
29 #include "sensor_msgs/PointCloud2.h"
30 #include "tf2_msgs/TFMessage.h"
31 
32 DEFINE_string(bag_filename, "", "Bag to publish.");
33 
34 const int kQueueSize = 1;
35 
36 template <typename MessagePtrType>
37 void PublishWithModifiedTimestamp(MessagePtrType message,
38  const ros::Publisher& publisher,
39  ros::Duration bag_to_current) {
40  ros::Time& stamp = message->header.stamp;
41  stamp += bag_to_current;
42  publisher.publish(message);
43 }
44 
45 template <>
46 void PublishWithModifiedTimestamp<tf2_msgs::TFMessage::Ptr>(
47  tf2_msgs::TFMessage::Ptr message, const ros::Publisher& publisher,
48  ros::Duration bag_to_current) {
49  for (const auto& transform : message->transforms) {
50  ros::Time& stamp = const_cast<ros::Time&>(transform.header.stamp);
51  stamp += bag_to_current;
52  }
53  publisher.publish(message);
54 }
55 
56 int main(int argc, char** argv) {
57  google::InitGoogleLogging(argv[0]);
58  google::SetUsageMessage(
59  "\n\n"
60  "This replays and publishes messages from a given bag file, modifying "
61  "their header timestamps to match current ROS time.\n\n"
62  "Messages are published in the same sequence and with the same delay "
63  "they were recorded."
64  "Contrary to rosbag play, it does not publish a clock, so time is"
65  "hopefully smoother and it should be possible to reproduce timing"
66  "issues.\n"
67  "It only plays message types related to Cartographer.\n");
68  google::ParseCommandLineFlags(&argc, &argv, true);
69  CHECK(!FLAGS_bag_filename.empty()) << "-bag_filename is missing.";
70 
71  ros::init(argc, argv, "rosbag_publisher");
72  ros::start();
73 
75 
76  rosbag::Bag bag;
77  bag.open(FLAGS_bag_filename, rosbag::bagmode::Read);
78  rosbag::View view(bag);
79  ros::NodeHandle node_handle;
80  bool use_sim_time;
81  node_handle.getParam("/use_sim_time", use_sim_time);
82  if (use_sim_time) {
83  LOG(ERROR) << "use_sim_time is true but not supported. Expect conflicting "
84  "ros::Time and message header times or weird behavior.";
85  }
86  std::map<std::string, ros::Publisher> topic_to_publisher;
87  for (const rosbag::ConnectionInfo* c : view.getConnections()) {
88  const std::string& topic = c->topic;
89  if (topic_to_publisher.count(topic) == 0) {
90  ros::AdvertiseOptions options(c->topic, kQueueSize, c->md5sum,
91  c->datatype, c->msg_def);
92  topic_to_publisher[topic] = node_handle.advertise(options);
93  }
94  }
95  ros::Duration(1).sleep();
96  CHECK(ros::ok());
97 
98  ros::Time current_start = ros::Time::now();
99  ros::Time bag_start = view.getBeginTime();
100  ros::Duration bag_to_current = current_start - bag_start;
101  for (const rosbag::MessageInstance& message : view) {
102  ros::Duration after_bag_start = message.getTime() - bag_start;
103  if (!::ros::ok()) {
104  break;
105  }
106  ros::Time planned_publish_time = current_start + after_bag_start;
107  ros::Time::sleepUntil(planned_publish_time);
108 
109  ros::Publisher& publisher = topic_to_publisher.at(message.getTopic());
110  if (message.isType<sensor_msgs::PointCloud2>()) {
112  message.instantiate<sensor_msgs::PointCloud2>(), publisher,
113  bag_to_current);
114  } else if (message.isType<sensor_msgs::MultiEchoLaserScan>()) {
116  message.instantiate<sensor_msgs::MultiEchoLaserScan>(), publisher,
117  bag_to_current);
118  } else if (message.isType<sensor_msgs::LaserScan>()) {
120  message.instantiate<sensor_msgs::LaserScan>(), publisher,
121  bag_to_current);
122  } else if (message.isType<sensor_msgs::Imu>()) {
123  PublishWithModifiedTimestamp(message.instantiate<sensor_msgs::Imu>(),
124  publisher, bag_to_current);
125  } else if (message.isType<nav_msgs::Odometry>()) {
126  PublishWithModifiedTimestamp(message.instantiate<nav_msgs::Odometry>(),
127  publisher, bag_to_current);
128  } else if (message.isType<tf2_msgs::TFMessage>()) {
129  PublishWithModifiedTimestamp(message.instantiate<tf2_msgs::TFMessage>(),
130  publisher, bag_to_current);
131  } else {
132  LOG(WARNING) << "Skipping message with type " << message.getDataType();
133  }
134 
135  ros::Time current_time = ros::Time::now();
136  double simulation_delay = cartographer::common::ToSeconds(
137  cartographer_ros::FromRos(current_time) -
138  cartographer_ros::FromRos(planned_publish_time));
139  if (std::abs(simulation_delay) > 0.001) {
140  LOG(WARNING) << "Playback delayed by " << simulation_delay
141  << " s. planned_publish_time: " << planned_publish_time
142  << " current_time: " << current_time;
143  }
144  }
145  bag.close();
146 
147  ros::shutdown();
148 }
ROSCPP_DECL void start()
std::vector< const ConnectionInfo *> getConnections()
void open(std::string const &filename, uint32_t mode=bagmode::Read)
static bool sleepUntil(const Time &end)
DEFINE_string(bag_filename, "", "Bag to publish.")
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void close()
void publish(const boost::shared_ptr< M > &message) const
ros::Time getBeginTime()
void PublishWithModifiedTimestamp(MessagePtrType message, const ros::Publisher &publisher, ros::Duration bag_to_current)
options
bool getParam(const std::string &key, std::string &s) const
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double ToSeconds(const Duration duration)
::cartographer::common::Time FromRos(const ::ros::Time &time)
std::string topic
static Time now()
ROSCPP_DECL void shutdown()
int main(int argc, char **argv)
const int kQueueSize
bool sleep() const


cartographer_ros
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:06:05