multires_image_plugin.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <multires_image/multires_image_plugin.h>
00031 
00032 // C++ standard libraries
00033 #include <cstdio>
00034 
00035 // QT libraries
00036 #include <QFileDialog>
00037 #include <QGLWidget>
00038 #include <QPalette>
00039 
00040 // ROS libraries
00041 #include <ros/ros.h>
00042 #include <tf/transform_datatypes.h>
00043 
00044 // Declare plugin
00045 #include <pluginlib/class_list_macros.h>
00046 PLUGINLIB_DECLARE_CLASS(mapviz_plugins, multires_image, mapviz_plugins::MultiresImagePlugin, mapviz::MapvizPlugin)
00047 
00048 namespace mapviz_plugins
00049 {
00050   MultiresImagePlugin::MultiresImagePlugin() :
00051     loaded_(false),
00052     tile_set_(NULL),
00053     tile_view_(NULL),
00054     config_widget_(new QWidget()),
00055     transformed_(false)
00056   {
00057     ui_.setupUi(config_widget_);
00058 
00059     QPalette p(config_widget_->palette());
00060     p.setColor(QPalette::Background, Qt::white);
00061     config_widget_->setPalette(p);
00062 
00063     QPalette p2(ui_.status->palette());
00064     p2.setColor(QPalette::Text, Qt::red);
00065     ui_.status->setPalette(p2);
00066 
00067     QObject::connect(ui_.browse, SIGNAL(clicked()), this, SLOT(SelectFile()));
00068     QObject::connect(ui_.path, SIGNAL(editingFinished()), this, SLOT(AcceptConfiguration()));
00069 
00070     source_frame_ = "/";
00071   }
00072 
00073   MultiresImagePlugin::~MultiresImagePlugin()
00074   {
00075     delete tile_view_;
00076     delete tile_set_;
00077   }
00078 
00079   void MultiresImagePlugin::PrintError(const std::string& message)
00080   {
00081     if (message == ui_.status->text().toStdString())
00082       return;
00083 
00084     ROS_ERROR("Error: %s", message.c_str());
00085     QPalette p(ui_.status->palette());
00086     p.setColor(QPalette::Text, Qt::red);
00087     ui_.status->setPalette(p);
00088     ui_.status->setText(message.c_str());
00089   }
00090 
00091   void MultiresImagePlugin::PrintInfo(const std::string& message)
00092   {
00093     if (message == ui_.status->text().toStdString())
00094       return;
00095 
00096     ROS_INFO("%s", message.c_str());
00097     QPalette p(ui_.status->palette());
00098     p.setColor(QPalette::Text, Qt::green);
00099     ui_.status->setPalette(p);
00100     ui_.status->setText(message.c_str());
00101   }
00102 
00103   void MultiresImagePlugin::PrintWarning(const std::string& message)
00104   {
00105     if (message == ui_.status->text().toStdString())
00106       return;
00107 
00108     ROS_WARN("%s", message.c_str());
00109     QPalette p(ui_.status->palette());
00110     p.setColor(QPalette::Text, Qt::darkYellow);
00111     ui_.status->setPalette(p);
00112     ui_.status->setText(message.c_str());
00113   }
00114 
00115   void MultiresImagePlugin::AcceptConfiguration()
00116   {
00117     ROS_INFO("Accept multires image configuration.");
00118     if (tile_set_ != NULL && tile_set_->GeoReference().GeoPath() == ui_.path->text().toStdString())
00119     {
00120       // Nothing to do.
00121     }
00122     else
00123     {
00124       loaded_ = false;
00125       delete tile_set_;
00126       delete tile_view_;
00127       tile_set_ = new multires_image::TileSet(ui_.path->text().toStdString());
00128 
00129       if (tile_set_->Load())
00130       {
00131         loaded_ = true;
00132 
00133         source_frame_ = tile_set_->GeoReference().Projection();
00134         if (source_frame_.empty() || source_frame_[0] != '/')
00135         {
00136           source_frame_ = std::string("/") + source_frame_;
00137         }
00138 
00139         QPalette p(ui_.status->palette());
00140         p.setColor(QPalette::Text, Qt::green);
00141         ui_.status->setPalette(p);
00142         ui_.status->setText("OK");
00143 
00144         initialized_ = true;
00145 
00146         MultiresView* view = new MultiresView(tile_set_, canvas_);
00147         tile_view_ = view;
00148       }
00149       else
00150       {
00151         PrintError("Failed to load image.");
00152         delete tile_set_;
00153         tile_set_ = 0;
00154         tile_view_ = 0;
00155       }
00156     }
00157   }
00158 
00159   void MultiresImagePlugin::SelectFile()
00160   {
00161     QFileDialog dialog(config_widget_, "Select Multires Image");
00162     dialog.setFileMode(QFileDialog::ExistingFile);
00163     dialog.setNameFilter(tr("Geo Files (*.geo)"));
00164 
00165     dialog.exec();
00166 
00167     if (dialog.result() == QDialog::Accepted && dialog.selectedFiles().count() == 1)
00168     {
00169       ui_.path->setText(dialog.selectedFiles().first());
00170       AcceptConfiguration();
00171     }
00172   }
00173 
00174   QWidget* MultiresImagePlugin::GetConfigWidget(QWidget* parent)
00175   {
00176     config_widget_->setParent(parent);
00177 
00178     return config_widget_;
00179   }
00180 
00181   bool MultiresImagePlugin::Initialize(QGLWidget* canvas)
00182   {
00183     canvas_ = canvas;
00184 
00185     return true;
00186   }
00187 
00188   void MultiresImagePlugin::GetCenterPoint(double x, double y)
00189   {
00190       tf::Point point(x, y, 0);
00191       tf::Point center = inverse_transform_ * point;
00192       center_x_ = center.getX();
00193       center_y_ = center.getY();
00194   }
00195 
00196   void MultiresImagePlugin::Draw(double x, double y, double scale)
00197   {
00198     if (transformed_ && tile_set_ != NULL && tile_view_ != NULL)
00199     {
00200       GetCenterPoint(x, y);
00201       tile_view_->SetView(center_x_, center_y_, 1, scale);
00202 
00203       tile_view_->Draw();
00204 
00205       PrintInfo("OK");
00206     }
00207   }
00208 
00209   void MultiresImagePlugin::Transform()
00210   {
00211     transformed_ = false;
00212 
00213     if (!loaded_)
00214       return;
00215 
00216     if (!tf_manager_.GetTransform(target_frame_, source_frame_, transform_))
00217     {
00218       PrintError("Failed transform from " + source_frame_ + " to " + target_frame_);
00219       return;
00220     }
00221 
00222     if (!tf_manager_.GetTransform(source_frame_, target_frame_, inverse_transform_))
00223     {
00224       PrintError("Failed inverse transform from " + target_frame_ + " to " + source_frame_);
00225       return;
00226     }
00227 
00228     // Set relative positions of tile points based on tf transform
00229     for (int i = 0; i < tile_set_->LayerCount(); i++)
00230     {
00231       multires_image::TileSetLayer* layer = tile_set_->GetLayer(i);
00232       for (int r = 0; r < layer->RowCount(); r++)
00233       {
00234         for (int c = 0; c < layer->ColumnCount(); c++)
00235         {
00236           multires_image::Tile* tile = layer->GetTile(c, r);
00237 
00238           tile->Transform(transform_);
00239         }
00240       }
00241     }
00242 
00243     transformed_ = true;
00244   }
00245 
00246   boost::filesystem::path MultiresImagePlugin::MakePathRelative(boost::filesystem::path path, boost::filesystem::path base)
00247   {
00248     // Borrowed from: https://svn.boost.org/trac/boost/ticket/1976#comment:2
00249     if (path.has_root_path())
00250     {
00251       if (path.root_path() != base.root_path())
00252       {
00253         return path;
00254       }
00255       else
00256       {
00257         return MakePathRelative(path.relative_path(), base.relative_path());
00258       }
00259     }
00260     else
00261     {
00262       if (base.has_root_path())
00263       {
00264         ROS_WARN("Cannot uncomplete a path relative path from a rooted base.");
00265         return path;
00266       }
00267       else
00268       {
00269         typedef boost::filesystem::path::const_iterator path_iterator;
00270         path_iterator path_it = path.begin();
00271         path_iterator base_it = base.begin();
00272         while (path_it != path.end() && base_it != base.end())
00273         {
00274           if (*path_it != *base_it)
00275             break;
00276           ++path_it;
00277           ++base_it;
00278         }
00279         boost::filesystem::path result;
00280         for (; base_it != base.end(); ++base_it)
00281         {
00282           result /= "..";
00283         }
00284         for (; path_it != path.end(); ++path_it)
00285         {
00286           result /= *path_it;
00287         }
00288         return result;
00289       }
00290     }
00291   }
00292 
00293   void MultiresImagePlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00294   {
00295     if (node["path"])
00296     {
00297       std::string path_string;
00298       node["path"] >> path_string;
00299 
00300       boost::filesystem::path image_path(path_string);
00301       if (image_path.is_complete() == false)
00302       {
00303         boost::filesystem::path base_path(path);
00304         path_string =
00305           (path / image_path.relative_path()).normalize().string();
00306       }
00307 
00308       ui_.path->setText(path_string.c_str());
00309 
00310       AcceptConfiguration();
00311     }
00312   }
00313 
00314   void MultiresImagePlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00315   {
00316     boost::filesystem::path abs_path(ui_.path->text().toStdString());
00317     boost::filesystem::path base_path(path);
00318     boost::filesystem::path rel_path = MakePathRelative(abs_path, base_path);
00319 
00320     emitter << YAML::Key << "path" << YAML::Value << rel_path.string();
00321   }
00322 }
00323 


multires_image
Author(s): Marc Alban
autogenerated on Thu Aug 24 2017 02:46:18