submaps_display.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2016 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_rviz/submaps_display.h"
00018 
00019 #include "OgreResourceGroupManager.h"
00020 #include "absl/memory/memory.h"
00021 #include "absl/synchronization/mutex.h"
00022 #include "cartographer/mapping/id.h"
00023 #include "cartographer_ros_msgs/SubmapList.h"
00024 #include "cartographer_ros_msgs/SubmapQuery.h"
00025 #include "geometry_msgs/TransformStamped.h"
00026 #include "pluginlib/class_list_macros.h"
00027 #include "ros/package.h"
00028 #include "ros/ros.h"
00029 #include "rviz/display_context.h"
00030 #include "rviz/frame_manager.h"
00031 #include "rviz/properties/bool_property.h"
00032 #include "rviz/properties/string_property.h"
00033 
00034 namespace cartographer_rviz {
00035 
00036 namespace {
00037 
00038 constexpr int kMaxOnGoingRequestsPerTrajectory = 6;
00039 constexpr char kMaterialsDirectory[] = "/ogre_media/materials";
00040 constexpr char kGlsl120Directory[] = "/glsl120";
00041 constexpr char kScriptsDirectory[] = "/scripts";
00042 constexpr char kDefaultTrackingFrame[] = "base_link";
00043 constexpr char kDefaultSubmapQueryServiceName[] = "/submap_query";
00044 
00045 }  // namespace
00046 
00047 SubmapsDisplay::SubmapsDisplay() : tf_listener_(tf_buffer_) {
00048   submap_query_service_property_ = new ::rviz::StringProperty(
00049       "Submap query service", kDefaultSubmapQueryServiceName,
00050       "Submap query service to connect to.", this, SLOT(Reset()));
00051   tracking_frame_property_ = new ::rviz::StringProperty(
00052       "Tracking frame", kDefaultTrackingFrame,
00053       "Tracking frame, used for fading out submaps.", this);
00054   slice_high_resolution_enabled_ = new ::rviz::BoolProperty(
00055       "High Resolution", true, "Display high resolution slices.", this,
00056       SLOT(ResolutionToggled()), this);
00057   slice_low_resolution_enabled_ = new ::rviz::BoolProperty(
00058       "Low Resolution", false, "Display low resolution slices.", this,
00059       SLOT(ResolutionToggled()), this);
00060   client_ = update_nh_.serviceClient<::cartographer_ros_msgs::SubmapQuery>("");
00061   trajectories_category_ = new ::rviz::Property(
00062       "Submaps", QVariant(), "List of all submaps, organized by trajectories.",
00063       this);
00064   visibility_all_enabled_ = new ::rviz::BoolProperty(
00065       "All", true,
00066       "Whether submaps from all trajectories should be displayed or not.",
00067       trajectories_category_, SLOT(AllEnabledToggled()), this);
00068   pose_markers_all_enabled_ = new ::rviz::BoolProperty(
00069       "All Submap Pose Markers", true,
00070       "Whether submap pose markers should be displayed or not.",
00071       trajectories_category_, SLOT(PoseMarkersEnabledToggled()), this);
00072   fade_out_start_distance_in_meters_ =
00073       new ::rviz::FloatProperty("Fade-out distance", 1.f,
00074                                 "Distance in meters in z-direction beyond "
00075                                 "which submaps will start to fade out.",
00076                                 this);
00077   const std::string package_path = ::ros::package::getPath(ROS_PACKAGE_NAME);
00078   Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
00079       package_path + kMaterialsDirectory, "FileSystem", ROS_PACKAGE_NAME);
00080   Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
00081       package_path + kMaterialsDirectory + kGlsl120Directory, "FileSystem",
00082       ROS_PACKAGE_NAME);
00083   Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
00084       package_path + kMaterialsDirectory + kScriptsDirectory, "FileSystem",
00085       ROS_PACKAGE_NAME);
00086   Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
00087 }
00088 
00089 SubmapsDisplay::~SubmapsDisplay() {
00090   client_.shutdown();
00091   trajectories_.clear();
00092   scene_manager_->destroySceneNode(map_node_);
00093 }
00094 
00095 void SubmapsDisplay::Reset() { reset(); }
00096 
00097 void SubmapsDisplay::CreateClient() {
00098   client_ = update_nh_.serviceClient<::cartographer_ros_msgs::SubmapQuery>(
00099       submap_query_service_property_->getStdString());
00100 }
00101 
00102 void SubmapsDisplay::onInitialize() {
00103   MFDClass::onInitialize();
00104   map_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00105   CreateClient();
00106 }
00107 
00108 void SubmapsDisplay::reset() {
00109   MFDClass::reset();
00110   absl::MutexLock locker(&mutex_);
00111   client_.shutdown();
00112   trajectories_.clear();
00113   CreateClient();
00114 }
00115 
00116 void SubmapsDisplay::processMessage(
00117     const ::cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
00118   absl::MutexLock locker(&mutex_);
00119   map_frame_ = absl::make_unique<std::string>(msg->header.frame_id);
00120   // In case Cartographer node is relaunched, destroy trajectories from the
00121   // previous instance.
00122   for (const ::cartographer_ros_msgs::SubmapEntry& submap_entry : msg->submap) {
00123     const size_t trajectory_id = submap_entry.trajectory_id;
00124     if (trajectories_.count(trajectory_id) == 0) {
00125       continue;
00126     }
00127     const auto& trajectory_submaps = trajectories_[trajectory_id]->submaps;
00128     const auto it = trajectory_submaps.find(submap_entry.submap_index);
00129     if (it != trajectory_submaps.end() &&
00130         it->second->version() > submap_entry.submap_version) {
00131       // Versions should only increase unless Cartographer restarted.
00132       trajectories_.clear();
00133       break;
00134     }
00135   }
00136   using ::cartographer::mapping::SubmapId;
00137   std::set<SubmapId> listed_submaps;
00138   std::set<int> listed_trajectories;
00139   for (const ::cartographer_ros_msgs::SubmapEntry& submap_entry : msg->submap) {
00140     const SubmapId id{submap_entry.trajectory_id, submap_entry.submap_index};
00141     listed_submaps.insert(id);
00142     listed_trajectories.insert(submap_entry.trajectory_id);
00143     if (trajectories_.count(id.trajectory_id) == 0) {
00144       trajectories_.insert(std::make_pair(
00145           id.trajectory_id,
00146           absl::make_unique<Trajectory>(
00147               absl::make_unique<::rviz::BoolProperty>(
00148                   QString("Trajectory %1").arg(id.trajectory_id),
00149                   visibility_all_enabled_->getBool(),
00150                   QString(
00151                       "List of all submaps in Trajectory %1. The checkbox "
00152                       "controls whether all submaps in this trajectory should "
00153                       "be displayed or not.")
00154                       .arg(id.trajectory_id),
00155                   trajectories_category_),
00156               pose_markers_all_enabled_->getBool())));
00157     }
00158     auto& trajectory_visibility = trajectories_[id.trajectory_id]->visibility;
00159     auto& trajectory_submaps = trajectories_[id.trajectory_id]->submaps;
00160     auto& pose_markers_visibility =
00161         trajectories_[id.trajectory_id]->pose_markers_visibility;
00162     if (trajectory_submaps.count(id.submap_index) == 0) {
00163       // TODO(ojura): Add RViz properties for adjusting submap pose axes
00164       constexpr float kSubmapPoseAxesLength = 0.3f;
00165       constexpr float kSubmapPoseAxesRadius = 0.06f;
00166       trajectory_submaps.emplace(
00167           id.submap_index,
00168           absl::make_unique<DrawableSubmap>(
00169               id, context_, map_node_, trajectory_visibility.get(),
00170               trajectory_visibility->getBool(),
00171               pose_markers_visibility->getBool(), kSubmapPoseAxesLength,
00172               kSubmapPoseAxesRadius));
00173       trajectory_submaps.at(id.submap_index)
00174           ->SetSliceVisibility(0, slice_high_resolution_enabled_->getBool());
00175       trajectory_submaps.at(id.submap_index)
00176           ->SetSliceVisibility(1, slice_low_resolution_enabled_->getBool());
00177     }
00178     trajectory_submaps.at(id.submap_index)->Update(msg->header, submap_entry);
00179   }
00180   // Remove all deleted trajectories not mentioned in the SubmapList.
00181   for (auto it = trajectories_.begin(); it != trajectories_.end();) {
00182     if (listed_trajectories.count(it->first) == 0) {
00183       it = trajectories_.erase(it);
00184     } else {
00185       ++it;
00186     }
00187   }
00188   // Remove all submaps not mentioned in the SubmapList.
00189   for (const auto& trajectory_by_id : trajectories_) {
00190     const int trajectory_id = trajectory_by_id.first;
00191     auto& trajectory_submaps = trajectory_by_id.second->submaps;
00192     for (auto it = trajectory_submaps.begin();
00193          it != trajectory_submaps.end();) {
00194       if (listed_submaps.count(
00195               SubmapId{static_cast<int>(trajectory_id), it->first}) == 0) {
00196         it = trajectory_submaps.erase(it);
00197       } else {
00198         ++it;
00199       }
00200     }
00201   }
00202 }
00203 
00204 void SubmapsDisplay::update(const float wall_dt, const float ros_dt) {
00205   absl::MutexLock locker(&mutex_);
00206   // Schedule fetching of new submap textures.
00207   for (const auto& trajectory_by_id : trajectories_) {
00208     int num_ongoing_requests = 0;
00209     for (const auto& submap_entry : trajectory_by_id.second->submaps) {
00210       if (submap_entry.second->QueryInProgress()) {
00211         ++num_ongoing_requests;
00212       }
00213     }
00214     for (auto it = trajectory_by_id.second->submaps.rbegin();
00215          it != trajectory_by_id.second->submaps.rend() &&
00216          num_ongoing_requests < kMaxOnGoingRequestsPerTrajectory;
00217          ++it) {
00218       if (it->second->MaybeFetchTexture(&client_)) {
00219         ++num_ongoing_requests;
00220       }
00221     }
00222   }
00223   if (map_frame_ == nullptr) {
00224     return;
00225   }
00226   // Update the fading by z distance.
00227   const ros::Time kLatest(0);
00228   try {
00229     const ::geometry_msgs::TransformStamped transform_stamped =
00230         tf_buffer_.lookupTransform(
00231             *map_frame_, tracking_frame_property_->getStdString(), kLatest);
00232     for (auto& trajectory_by_id : trajectories_) {
00233       for (auto& submap_entry : trajectory_by_id.second->submaps) {
00234         submap_entry.second->SetAlpha(
00235             transform_stamped.transform.translation.z,
00236             fade_out_start_distance_in_meters_->getFloat());
00237       }
00238     }
00239   } catch (const tf2::TransformException& ex) {
00240     ROS_WARN_THROTTLE(1., "Could not compute submap fading: %s", ex.what());
00241   }
00242   // Update the map frame to fixed frame transform.
00243   Ogre::Vector3 position;
00244   Ogre::Quaternion orientation;
00245   if (context_->getFrameManager()->getTransform(*map_frame_, kLatest, position,
00246                                                 orientation)) {
00247     map_node_->setPosition(position);
00248     map_node_->setOrientation(orientation);
00249     context_->queueRender();
00250   }
00251 }
00252 
00253 void SubmapsDisplay::AllEnabledToggled() {
00254   absl::MutexLock locker(&mutex_);
00255   const bool visible = visibility_all_enabled_->getBool();
00256   for (auto& trajectory_by_id : trajectories_) {
00257     trajectory_by_id.second->visibility->setBool(visible);
00258   }
00259 }
00260 
00261 void SubmapsDisplay::PoseMarkersEnabledToggled() {
00262   absl::MutexLock locker(&mutex_);
00263   const bool visible = pose_markers_all_enabled_->getBool();
00264   for (auto& trajectory_by_id : trajectories_) {
00265     trajectory_by_id.second->pose_markers_visibility->setBool(visible);
00266   }
00267 }
00268 
00269 void SubmapsDisplay::ResolutionToggled() {
00270   absl::MutexLock locker(&mutex_);
00271   for (auto& trajectory_by_id : trajectories_) {
00272     for (auto& submap_entry : trajectory_by_id.second->submaps) {
00273       submap_entry.second->SetSliceVisibility(
00274           0, slice_high_resolution_enabled_->getBool());
00275       submap_entry.second->SetSliceVisibility(
00276           1, slice_low_resolution_enabled_->getBool());
00277     }
00278   }
00279 }
00280 
00281 void Trajectory::AllEnabledToggled() {
00282   const bool visible = visibility->getBool();
00283   for (auto& submap_entry : submaps) {
00284     submap_entry.second->set_visibility(visible);
00285   }
00286 }
00287 
00288 void Trajectory::PoseMarkersEnabledToggled() {
00289   const bool visible = pose_markers_visibility->getBool();
00290   for (auto& submap_entry : submaps) {
00291     submap_entry.second->set_pose_markers_visibility(visible);
00292   }
00293 }
00294 
00295 Trajectory::Trajectory(std::unique_ptr<::rviz::BoolProperty> property,
00296                        const bool pose_markers_enabled)
00297     : visibility(std::move(property)) {
00298   ::QObject::connect(visibility.get(), SIGNAL(changed()), this,
00299                      SLOT(AllEnabledToggled()));
00300   // Add toggle for submap pose markers as the first entry of the visibility
00301   // property list of this trajectory.
00302   pose_markers_visibility = absl::make_unique<::rviz::BoolProperty>(
00303       QString("Submap Pose Markers"), pose_markers_enabled,
00304       QString("Toggles the submap pose markers of this trajectory."),
00305       visibility.get());
00306   ::QObject::connect(pose_markers_visibility.get(), SIGNAL(changed()), this,
00307                      SLOT(PoseMarkersEnabledToggled()));
00308 }
00309 
00310 }  // namespace cartographer_rviz
00311 
00312 PLUGINLIB_EXPORT_CLASS(cartographer_rviz::SubmapsDisplay, ::rviz::Display)


cartographer_rviz
Author(s): The Cartographer Authors
autogenerated on Wed Jul 10 2019 04:10:34