Adds a rosbag_validate binary. (#536)

So far it creates statistics over timing information of the sensor data that Cartographer cares about. It also reports if time jumps backwards for a sensor.
Also updates the GitHub issue template to ask users to run this binary when reporting issues.

I verified that this tool is sufficient to analyze all the timing related issues mentioned in #529.
master
Holger Rapp 2017-10-13 17:26:50 +02:00 committed by GitHub
parent b9877fed12
commit 5b06f03558
3 changed files with 158 additions and 8 deletions

View File

@ -1,13 +1,25 @@
Thank you for filing an issue! Thank you for filing an issue!
It would help us tremendously if you provide the following so that we can easily It would help us tremendously if you run through the following checklist. This
reproduce your issue: ensures that we have the most information to quickly understand, analyze,
reproduce and eventually resolve your issue.
1. A link to a Git repository containing a branch of `cartographer_ros` Please
containing all the configuration, launch, and URDF files required to
reproduce your issue.
2. A link to a bag file we can use to reproduce your issue.
We will likely be unable to help you without both. 1. run `rosbag_validate` which does some checks on your sensor data. This
tool often finds issues that can explain poor performance and must be fixed
at recording time. Please post the full output of the tool into a
GitHub Gist at https://gist.github.com/, then link it in the issue even if
it does not report anything. You can run the tool like this:
Please remove this boilerplate text before submitting your issue. rosrun cartographer_ros cartographer_rosbag_validate -bag_filename <bag filename>
2. post a link to a Git repository containing a branch of
`cartographer_ros` containing all the configuration, launch, and URDF files
required to reproduce your issue.
3. post a link to a bag file we can use to reproduce your issue. Put it on
Google Drive, Dropbox, any webserver or wherever it is publicly
downloadable.
4. remove this boilerplate text before submitting your issue.
We will likely be unable to help you without all of these points addressed.

View File

@ -66,3 +66,14 @@ install(TARGETS cartographer_occupancy_grid_node
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
) )
google_binary(cartographer_rosbag_validate
SRCS
rosbag_validate_main.cc
)
install(TARGETS cartographer_rosbag_validate
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

View File

@ -0,0 +1,127 @@
/*
* Copyright 2017 The Cartographer Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <map>
#include <string>
#include "cartographer/common/histogram.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "nav_msgs/Odometry.h"
#include "ros/ros.h"
#include "ros/time.h"
#include "rosbag/bag.h"
#include "rosbag/view.h"
#include "sensor_msgs/Imu.h"
#include "sensor_msgs/LaserScan.h"
#include "sensor_msgs/MultiEchoLaserScan.h"
#include "sensor_msgs/PointCloud2.h"
#include "tf2_eigen/tf2_eigen.h"
#include "tf2_msgs/TFMessage.h"
#include "tf2_ros/buffer.h"
#include "urdf/model.h"
DEFINE_string(bag_filename, "", "Bag to process.");
namespace cartographer_ros {
namespace {
struct TimestampData {
ros::Time last_timestamp;
string topic;
::cartographer::common::Histogram histogram;
};
void Run(const string& bag_filename) {
rosbag::Bag bag;
bag.open(bag_filename, rosbag::bagmode::Read);
rosbag::View view(bag);
const ::ros::Time begin_time = view.getBeginTime();
std::map<string, TimestampData> timestamp_data;
for (const rosbag::MessageInstance& message : view) {
string frame_id;
ros::Time time;
if (message.isType<sensor_msgs::PointCloud2>()) {
auto msg = message.instantiate<sensor_msgs::PointCloud2>();
time = msg->header.stamp;
frame_id = msg->header.frame_id;
} else if (message.isType<sensor_msgs::MultiEchoLaserScan>()) {
auto msg = message.instantiate<sensor_msgs::MultiEchoLaserScan>();
time = msg->header.stamp;
frame_id = msg->header.frame_id;
} else if (message.isType<sensor_msgs::LaserScan>()) {
auto msg = message.instantiate<sensor_msgs::LaserScan>();
time = msg->header.stamp;
frame_id = msg->header.frame_id;
} else if (message.isType<sensor_msgs::Imu>()) {
auto msg = message.instantiate<sensor_msgs::Imu>();
time = msg->header.stamp;
frame_id = msg->header.frame_id;
} else if (message.isType<nav_msgs::Odometry>()) {
auto msg = message.instantiate<nav_msgs::Odometry>();
time = msg->header.stamp;
frame_id = msg->header.frame_id;
} else {
continue;
}
if (!timestamp_data.count(frame_id)) {
timestamp_data.emplace(
frame_id, TimestampData{time, message.getTopic(),
::cartographer::common::Histogram()});
} else {
auto& entry = timestamp_data.at(frame_id);
if (entry.topic != message.getTopic()) {
LOG(ERROR) << "frame_id \"" << frame_id
<< "\" is send on multiple topics. It was seen at least on "
<< entry.topic << " and " << message.getTopic();
}
const double delta_t_sec = (time - entry.last_timestamp).toSec();
if (delta_t_sec < 0) {
LOG(ERROR) << "Sensor with frame_id \"" << frame_id
<< "\" jumps backwards in time. Make sure that the bag "
"contains the data for each frame_id sorted by "
"header.stamp, i.e. the order in which they were "
"acquired from the sensor.";
}
entry.histogram.Add(delta_t_sec);
entry.last_timestamp = time;
}
}
bag.close();
constexpr int kNumBucketsForHistogram = 10;
for (const auto& entry_pair : timestamp_data) {
LOG(INFO) << "Time delta histogram for consecutive messages on topic \""
<< entry_pair.second.topic << "\" (frame_id: \""
<< entry_pair.first << "\"):\n"
<< entry_pair.second.histogram.ToString(kNumBucketsForHistogram);
}
}
} // namespace
} // namespace cartographer_ros
int main(int argc, char** argv) {
FLAGS_alsologtostderr = true;
google::InitGoogleLogging(argv[0]);
google::ParseCommandLineFlags(&argc, &argv, true);
CHECK(!FLAGS_bag_filename.empty()) << "-bag_filename is missing.";
::cartographer_ros::Run(FLAGS_bag_filename);
}