Warn for possible topic mismatch (#935)

FIXES=#929
master
gaschler 2018-07-12 12:18:00 +02:00 committed by Wally B. Feed
parent fb5b16d6d3
commit 54e8aa4f6d
6 changed files with 68 additions and 1 deletions

View File

@ -357,6 +357,9 @@ int Node::AddTrajectory(const TrajectoryOptions& options,
AddExtrapolator(trajectory_id, options); AddExtrapolator(trajectory_id, options);
AddSensorSamplers(trajectory_id, options); AddSensorSamplers(trajectory_id, options);
LaunchSubscribers(options, topics, trajectory_id); LaunchSubscribers(options, topics, trajectory_id);
wall_timers_.push_back(node_handle_.createWallTimer(
::ros::WallDuration(kTopicMismatchCheckDelaySec),
&Node::MaybeWarnAboutTopicMismatch, this, /*oneshot=*/true));
for (const auto& sensor_id : expected_sensor_ids) { for (const auto& sensor_id : expected_sensor_ids) {
subscribed_topics_.insert(sensor_id.id); subscribed_topics_.insert(sensor_id.id);
} }
@ -790,4 +793,35 @@ void Node::LoadState(const std::string& state_filename,
map_builder_bridge_.LoadState(state_filename, load_frozen_state); map_builder_bridge_.LoadState(state_filename, load_frozen_state);
} }
void Node::MaybeWarnAboutTopicMismatch(
const ::ros::WallTimerEvent& unused_timer_event) {
::ros::master::V_TopicInfo ros_topics;
::ros::master::getTopics(ros_topics);
std::set<std::string> published_topics;
std::stringstream published_topics_string;
for (const auto& it : ros_topics) {
std::string resolved_topic = node_handle_.resolveName(it.name, false);
published_topics.insert(resolved_topic);
published_topics_string << resolved_topic << ",";
}
bool print_topics = false;
for (const auto& entry : subscribers_) {
int trajectory_id = entry.first;
for (const auto& subscriber : entry.second) {
std::string resolved_topic = node_handle_.resolveName(subscriber.topic);
if (published_topics.count(resolved_topic) == 0) {
LOG(WARNING) << "Expected topic \"" << subscriber.topic
<< "\" (trajectory " << trajectory_id << ")"
<< " (resolved topic \"" << resolved_topic << "\")"
<< " but no publisher is currently active.";
print_topics = true;
}
}
}
if (print_topics) {
LOG(WARNING) << "Currently available topics are: "
<< published_topics_string.str();
}
}
} // namespace cartographer_ros } // namespace cartographer_ros

View File

@ -171,6 +171,7 @@ class Node {
const TrajectoryOptions& options); const TrajectoryOptions& options);
cartographer_ros_msgs::StatusResponse FinishTrajectoryUnderLock( cartographer_ros_msgs::StatusResponse FinishTrajectoryUnderLock(
int trajectory_id) REQUIRES(mutex_); int trajectory_id) REQUIRES(mutex_);
void MaybeWarnAboutTopicMismatch(const ::ros::WallTimerEvent&);
const NodeOptions node_options_; const NodeOptions node_options_;

View File

@ -43,6 +43,7 @@ constexpr char kTrajectoryNodeListTopic[] = "trajectory_node_list";
constexpr char kLandmarkPosesListTopic[] = "landmark_poses_list"; constexpr char kLandmarkPosesListTopic[] = "landmark_poses_list";
constexpr char kConstraintListTopic[] = "constraint_list"; constexpr char kConstraintListTopic[] = "constraint_list";
constexpr double kConstraintPublishPeriodSec = 0.5; constexpr double kConstraintPublishPeriodSec = 0.5;
constexpr double kTopicMismatchCheckDelaySec = 3.0;
constexpr int kInfiniteSubscriberQueueSize = 0; constexpr int kInfiniteSubscriberQueueSize = 0;
constexpr int kLatestOnlyPublisherQueueSize = 1; constexpr int kLatestOnlyPublisherQueueSize = 1;

View File

@ -238,7 +238,27 @@ void RunOfflineNode(const MapBuilderFactory& map_builder_factory) {
})); }));
} }
// TODO(gaschler): Warn if resolved topics are not in bags. std::set<std::string> bag_topics;
std::stringstream bag_topics_string;
for (const auto& topic : playable_bag_multiplexer.topics()) {
std::string resolved_topic = node.node_handle()->resolveName(topic, false);
bag_topics.insert(resolved_topic);
bag_topics_string << resolved_topic << ",";
}
bool print_topics = false;
for (const auto& entry : bag_topic_to_sensor_id) {
const std::string& resolved_topic = entry.first.second;
if (bag_topics.count(resolved_topic) == 0) {
LOG(WARNING) << "Expected resolved topic \"" << resolved_topic
<< "\" not found in bag file(s).";
print_topics = true;
}
}
if (print_topics) {
LOG(WARNING) << "Available topics in bag file(s) are "
<< bag_topics_string.str();
}
std::unordered_map<int, int> bag_index_to_trajectory_id; std::unordered_map<int, int> bag_index_to_trajectory_id;
const ros::Time begin_time = const ros::Time begin_time =
// If no bags were loaded, we cannot peek the time of first message. // If no bags were loaded, we cannot peek the time of first message.

View File

@ -43,6 +43,9 @@ PlayableBag::PlayableBag(
filtering_early_message_handler_( filtering_early_message_handler_(
std::move(filtering_early_message_handler)) { std::move(filtering_early_message_handler)) {
AdvanceUntilMessageAvailable(); AdvanceUntilMessageAvailable();
for (const auto* connection_info : view_->getConnections()) {
topics_.insert(connection_info->topic);
}
} }
ros::Time PlayableBag::PeekMessageTime() const { ros::Time PlayableBag::PeekMessageTime() const {
@ -99,6 +102,9 @@ void PlayableBag::AdvanceUntilMessageAvailable() {
} }
void PlayableBagMultiplexer::AddPlayableBag(PlayableBag playable_bag) { void PlayableBagMultiplexer::AddPlayableBag(PlayableBag playable_bag) {
for (const auto& topic : playable_bag.topics()) {
topics_.insert(topic);
}
playable_bags_.push_back(std::move(playable_bag)); playable_bags_.push_back(std::move(playable_bag));
CHECK(playable_bags_.back().IsMessageAvailable()); CHECK(playable_bags_.back().IsMessageAvailable());
next_message_queue_.emplace( next_message_queue_.emplace(

View File

@ -43,6 +43,7 @@ class PlayableBag {
std::tuple<ros::Time, ros::Time> GetBeginEndTime() const; std::tuple<ros::Time, ros::Time> GetBeginEndTime() const;
int bag_id() const; int bag_id() const;
std::set<std::string> topics() const { return topics_; }
private: private:
void AdvanceOneMessage(); void AdvanceOneMessage();
@ -59,6 +60,7 @@ class PlayableBag {
std::deque<rosbag::MessageInstance> buffered_messages_; std::deque<rosbag::MessageInstance> buffered_messages_;
const ::ros::Duration buffer_delay_; const ::ros::Duration buffer_delay_;
FilteringEarlyMessageHandler filtering_early_message_handler_; FilteringEarlyMessageHandler filtering_early_message_handler_;
std::set<std::string> topics_;
}; };
class PlayableBagMultiplexer { class PlayableBagMultiplexer {
@ -75,6 +77,8 @@ class PlayableBagMultiplexer {
bool IsMessageAvailable() const; bool IsMessageAvailable() const;
ros::Time PeekMessageTime() const; ros::Time PeekMessageTime() const;
std::set<std::string> topics() const { return topics_; }
private: private:
struct BagMessageItem { struct BagMessageItem {
ros::Time message_timestamp; ros::Time message_timestamp;
@ -90,6 +94,7 @@ class PlayableBagMultiplexer {
std::priority_queue<BagMessageItem, std::vector<BagMessageItem>, std::priority_queue<BagMessageItem, std::vector<BagMessageItem>,
BagMessageItem::TimestampIsGreater> BagMessageItem::TimestampIsGreater>
next_message_queue_; next_message_queue_;
std::set<std::string> topics_;
}; };
} // namespace cartographer_ros } // namespace cartographer_ros