rosbag_publisher_main.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2018 The Cartographer Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "cartographer/common/time.h"
00018 #include "cartographer_ros/ros_log_sink.h"
00019 #include "cartographer_ros/time_conversion.h"
00020 #include "gflags/gflags.h"
00021 #include "nav_msgs/Odometry.h"
00022 #include "ros/ros.h"
00023 #include "ros/time.h"
00024 #include "rosbag/bag.h"
00025 #include "rosbag/view.h"
00026 #include "sensor_msgs/Imu.h"
00027 #include "sensor_msgs/LaserScan.h"
00028 #include "sensor_msgs/MultiEchoLaserScan.h"
00029 #include "sensor_msgs/PointCloud2.h"
00030 #include "tf2_msgs/TFMessage.h"
00031 
00032 DEFINE_string(bag_filename, "", "Bag to publish.");
00033 
00034 const int kQueueSize = 1;
00035 
00036 template <typename MessagePtrType>
00037 void PublishWithModifiedTimestamp(MessagePtrType message,
00038                                   const ros::Publisher& publisher,
00039                                   ros::Duration bag_to_current) {
00040   ros::Time& stamp = message->header.stamp;
00041   stamp += bag_to_current;
00042   publisher.publish(message);
00043 }
00044 
00045 template <>
00046 void PublishWithModifiedTimestamp<tf2_msgs::TFMessage::Ptr>(
00047     tf2_msgs::TFMessage::Ptr message, const ros::Publisher& publisher,
00048     ros::Duration bag_to_current) {
00049   for (const auto& transform : message->transforms) {
00050     ros::Time& stamp = const_cast<ros::Time&>(transform.header.stamp);
00051     stamp += bag_to_current;
00052   }
00053   publisher.publish(message);
00054 }
00055 
00056 int main(int argc, char** argv) {
00057   google::InitGoogleLogging(argv[0]);
00058   google::SetUsageMessage(
00059       "\n\n"
00060       "This replays and publishes messages from a given bag file, modifying "
00061       "their header timestamps to match current ROS time.\n\n"
00062       "Messages are published in the same sequence and with the same delay "
00063       "they were recorded."
00064       "Contrary to rosbag play, it does not publish a clock, so time is"
00065       "hopefully smoother and it should be possible to reproduce timing"
00066       "issues.\n"
00067       "It only plays message types related to Cartographer.\n");
00068   google::ParseCommandLineFlags(&argc, &argv, true);
00069   CHECK(!FLAGS_bag_filename.empty()) << "-bag_filename is missing.";
00070 
00071   ros::init(argc, argv, "rosbag_publisher");
00072   ros::start();
00073 
00074   cartographer_ros::ScopedRosLogSink ros_log_sink;
00075 
00076   rosbag::Bag bag;
00077   bag.open(FLAGS_bag_filename, rosbag::bagmode::Read);
00078   rosbag::View view(bag);
00079   ros::NodeHandle node_handle;
00080   bool use_sim_time;
00081   node_handle.getParam("/use_sim_time", use_sim_time);
00082   if (use_sim_time) {
00083     LOG(ERROR) << "use_sim_time is true but not supported. Expect conflicting "
00084                   "ros::Time and message header times or weird behavior.";
00085   }
00086   std::map<std::string, ros::Publisher> topic_to_publisher;
00087   for (const rosbag::ConnectionInfo* c : view.getConnections()) {
00088     const std::string& topic = c->topic;
00089     if (topic_to_publisher.count(topic) == 0) {
00090       ros::AdvertiseOptions options(c->topic, kQueueSize, c->md5sum,
00091                                     c->datatype, c->msg_def);
00092       topic_to_publisher[topic] = node_handle.advertise(options);
00093     }
00094   }
00095   ros::Duration(1).sleep();
00096   CHECK(ros::ok());
00097 
00098   ros::Time current_start = ros::Time::now();
00099   ros::Time bag_start = view.getBeginTime();
00100   ros::Duration bag_to_current = current_start - bag_start;
00101   for (const rosbag::MessageInstance& message : view) {
00102     ros::Duration after_bag_start = message.getTime() - bag_start;
00103     if (!::ros::ok()) {
00104       break;
00105     }
00106     ros::Time planned_publish_time = current_start + after_bag_start;
00107     ros::Time::sleepUntil(planned_publish_time);
00108 
00109     ros::Publisher& publisher = topic_to_publisher.at(message.getTopic());
00110     if (message.isType<sensor_msgs::PointCloud2>()) {
00111       PublishWithModifiedTimestamp(
00112           message.instantiate<sensor_msgs::PointCloud2>(), publisher,
00113           bag_to_current);
00114     } else if (message.isType<sensor_msgs::MultiEchoLaserScan>()) {
00115       PublishWithModifiedTimestamp(
00116           message.instantiate<sensor_msgs::MultiEchoLaserScan>(), publisher,
00117           bag_to_current);
00118     } else if (message.isType<sensor_msgs::LaserScan>()) {
00119       PublishWithModifiedTimestamp(
00120           message.instantiate<sensor_msgs::LaserScan>(), publisher,
00121           bag_to_current);
00122     } else if (message.isType<sensor_msgs::Imu>()) {
00123       PublishWithModifiedTimestamp(message.instantiate<sensor_msgs::Imu>(),
00124                                    publisher, bag_to_current);
00125     } else if (message.isType<nav_msgs::Odometry>()) {
00126       PublishWithModifiedTimestamp(message.instantiate<nav_msgs::Odometry>(),
00127                                    publisher, bag_to_current);
00128     } else if (message.isType<tf2_msgs::TFMessage>()) {
00129       PublishWithModifiedTimestamp(message.instantiate<tf2_msgs::TFMessage>(),
00130                                    publisher, bag_to_current);
00131     } else {
00132       LOG(WARNING) << "Skipping message with type " << message.getDataType();
00133     }
00134 
00135     ros::Time current_time = ros::Time::now();
00136     double simulation_delay = cartographer::common::ToSeconds(
00137         cartographer_ros::FromRos(current_time) -
00138         cartographer_ros::FromRos(planned_publish_time));
00139     if (std::abs(simulation_delay) > 0.001) {
00140       LOG(WARNING) << "Playback delayed by " << simulation_delay
00141                    << " s. planned_publish_time: " << planned_publish_time
00142                    << " current_time: " << current_time;
00143     }
00144   }
00145   bag.close();
00146 
00147   ros::shutdown();
00148 }


cartographer_ros
Author(s): The Cartographer Authors
autogenerated on Wed Jul 10 2019 04:10:28