route_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 <mapviz_plugins/route_plugin.h>
00031 
00032 // C++ standard libraries
00033 #include <cstdio>
00034 #include <vector>
00035 
00036 // QT libraries
00037 #include <QDialog>
00038 #include <QGLWidget>
00039 #include <QPainter>
00040 #include <QPalette>
00041 
00042 #include <opencv2/core/core.hpp>
00043 
00044 // ROS libraries
00045 #include <ros/master.h>
00046 
00047 #include <swri_image_util/geometry_util.h>
00048 #include <swri_route_util/util.h>
00049 #include <swri_transform_util/transform_util.h>
00050 #include <mapviz/select_topic_dialog.h>
00051 
00052 #include <marti_nav_msgs/Route.h>
00053 
00054 // Declare plugin
00055 #include <pluginlib/class_list_macros.h>
00056 
00057 PLUGINLIB_DECLARE_CLASS(mapviz_plugins, route, mapviz_plugins::RoutePlugin,
00058                         mapviz::MapvizPlugin);
00059 
00060 namespace sru = swri_route_util;
00061 namespace stu = swri_transform_util;
00062 
00063 namespace mapviz_plugins
00064 {
00065   RoutePlugin::RoutePlugin() : config_widget_(new QWidget()), draw_style_(LINES)
00066   {
00067     ui_.setupUi(config_widget_);
00068 
00069     ui_.color->setColor(Qt::green);
00070     // Set background white
00071     QPalette p(config_widget_->palette());
00072     p.setColor(QPalette::Background, Qt::white);
00073     config_widget_->setPalette(p);
00074     // Set status text red
00075     QPalette p3(ui_.status->palette());
00076     p3.setColor(QPalette::Text, Qt::red);
00077     ui_.status->setPalette(p3);
00078     QObject::connect(ui_.selecttopic, SIGNAL(clicked()), this,
00079                      SLOT(SelectTopic()));
00080     QObject::connect(ui_.topic, SIGNAL(editingFinished()), this,
00081                      SLOT(TopicEdited()));
00082     QObject::connect(ui_.selectpositiontopic, SIGNAL(clicked()), this,
00083                      SLOT(SelectPositionTopic()));
00084     QObject::connect(ui_.positiontopic, SIGNAL(editingFinished()), this,
00085                      SLOT(PositionTopicEdited()));
00086     QObject::connect(ui_.drawstyle, SIGNAL(activated(QString)), this,
00087                      SLOT(SetDrawStyle(QString)));
00088     QObject::connect(ui_.color, SIGNAL(colorEdited(const QColor&)), this,
00089                      SLOT(DrawIcon()));
00090   }
00091 
00092   RoutePlugin::~RoutePlugin()
00093   {
00094   }
00095 
00096   void RoutePlugin::DrawIcon()
00097   {
00098     if (icon_)
00099     {
00100       QPixmap icon(16, 16);
00101       icon.fill(Qt::transparent);
00102 
00103       QPainter painter(&icon);
00104       painter.setRenderHint(QPainter::Antialiasing, true);
00105 
00106       QPen pen(ui_.color->color());
00107 
00108       if (draw_style_ == POINTS)
00109       {
00110         pen.setWidth(7);
00111         pen.setCapStyle(Qt::RoundCap);
00112         painter.setPen(pen);
00113         painter.drawPoint(8, 8);
00114       }
00115       else if (draw_style_ == LINES)
00116       {
00117         pen.setWidth(3);
00118         pen.setCapStyle(Qt::FlatCap);
00119         painter.setPen(pen);
00120         painter.drawLine(1, 14, 14, 1);
00121       }
00122 
00123       icon_->SetPixmap(icon);
00124     }
00125   }
00126 
00127   void RoutePlugin::SetDrawStyle(QString style)
00128   {
00129     if (style == "lines")
00130     {
00131       draw_style_ = LINES;
00132     }
00133     else if (style == "points")
00134     {
00135       draw_style_ = POINTS;
00136     }
00137     DrawIcon();
00138   }
00139 
00140   void RoutePlugin::SelectTopic()
00141   {
00142     ros::master::TopicInfo topic =
00143         mapviz::SelectTopicDialog::selectTopic("marti_nav_msgs/Route");
00144 
00145     if (topic.name.empty())
00146     {
00147       return;
00148     }
00149 
00150     ui_.topic->setText(QString::fromStdString(topic.name));
00151     TopicEdited();
00152   }
00153 
00154   void RoutePlugin::SelectPositionTopic()
00155   {
00156     ros::master::TopicInfo topic =
00157         mapviz::SelectTopicDialog::selectTopic("marti_nav_msgs/RoutePosition");
00158 
00159     if (topic.name.empty())
00160     {
00161       return;
00162     }
00163 
00164     ui_.positiontopic->setText(QString::fromStdString(topic.name));
00165     PositionTopicEdited();
00166   }
00167 
00168   void RoutePlugin::TopicEdited()
00169   {
00170     std::string topic = ui_.topic->text().trimmed().toStdString();
00171     if (topic != topic_)
00172     {
00173       src_route_ = sru::Route();
00174 
00175       route_sub_.shutdown();
00176 
00177       topic_ = topic;
00178       if (!topic.empty())
00179       {
00180         route_sub_ =
00181             node_.subscribe(topic_, 1, &RoutePlugin::RouteCallback, this);
00182 
00183         ROS_INFO("Subscribing to %s", topic_.c_str());
00184       }
00185     }
00186   }
00187 
00188   void RoutePlugin::PositionTopicEdited()
00189   {
00190     std::string topic = ui_.positiontopic->text().trimmed().toStdString();
00191     if (topic != position_topic_)
00192     {
00193       src_route_position_.reset();
00194       position_sub_.shutdown();
00195 
00196       if (!topic.empty())
00197       {
00198         position_topic_ = topic;
00199         position_sub_ = node_.subscribe(position_topic_, 1,
00200                                         &RoutePlugin::PositionCallback, this);
00201 
00202         ROS_INFO("Subscribing to %s", position_topic_.c_str());
00203       }
00204     }
00205   }
00206 
00207   void RoutePlugin::PositionCallback(
00208       const marti_nav_msgs::RoutePositionConstPtr& msg)
00209   {
00210     src_route_position_ = msg;
00211   }
00212 
00213   void RoutePlugin::RouteCallback(const marti_nav_msgs::RouteConstPtr& msg)
00214   {
00215     src_route_ = sru::Route(*msg);
00216   }
00217 
00218   void RoutePlugin::PrintError(const std::string& message)
00219   {
00220     if (message == ui_.status->text().toStdString())
00221     {
00222       return;
00223     }
00224 
00225     ROS_ERROR_THROTTLE(1.0, "Error: %s", message.c_str());
00226     QPalette p(ui_.status->palette());
00227     p.setColor(QPalette::Text, Qt::red);
00228     ui_.status->setPalette(p);
00229     ui_.status->setText(message.c_str());
00230   }
00231 
00232   void RoutePlugin::PrintInfo(const std::string& message)
00233   {
00234     if (message == ui_.status->text().toStdString())
00235     {
00236       return;
00237     }
00238 
00239     ROS_INFO_THROTTLE(1.0, "%s", message.c_str());
00240     QPalette p(ui_.status->palette());
00241     p.setColor(QPalette::Text, Qt::green);
00242     ui_.status->setPalette(p);
00243     ui_.status->setText(message.c_str());
00244   }
00245 
00246   void RoutePlugin::PrintWarning(const std::string& message)
00247   {
00248     if (message == ui_.status->text().toStdString())
00249     {
00250       return;
00251     }
00252 
00253     ROS_WARN_THROTTLE(1.0, "%s", message.c_str());
00254     QPalette p(ui_.status->palette());
00255     p.setColor(QPalette::Text, Qt::darkYellow);
00256     ui_.status->setPalette(p);
00257     ui_.status->setText(message.c_str());
00258   }
00259 
00260   QWidget* RoutePlugin::GetConfigWidget(QWidget* parent)
00261   {
00262     config_widget_->setParent(parent);
00263 
00264     return config_widget_;
00265   }
00266 
00267   bool RoutePlugin::Initialize(QGLWidget* canvas)
00268   {
00269     canvas_ = canvas;
00270 
00271     DrawIcon();
00272 
00273     initialized_ = true;
00274     return true;
00275   }
00276 
00277   void RoutePlugin::Draw(double x, double y, double scale)
00278   {
00279     if (!src_route_.valid())
00280     {
00281       PrintError("No valid route received.");
00282       return;
00283     }
00284 
00285     sru::Route route = src_route_;
00286     if (route.header.frame_id.empty())
00287     {
00288       route.header.frame_id = "/wgs84";
00289     }
00290 
00291     stu::Transform transform;
00292     if (!GetTransform(route.header.frame_id, ros::Time(), transform))
00293     {
00294       PrintError("Failed to transform route");
00295       return;
00296     }
00297 
00298     sru::transform(route, transform, target_frame_);
00299     sru::projectToXY(route);
00300     sru::fillOrientations(route);
00301 
00302     DrawRoute(route);
00303 
00304     bool ok = true;
00305     if (route.valid() && src_route_position_)
00306     {
00307       sru::RoutePoint point;
00308       if (sru::interpolateRoutePosition(point, route, *src_route_position_, true))
00309       {
00310         DrawRoutePoint(point);
00311       }
00312       else
00313       {
00314         PrintError("Failed to find route position in route.");
00315         ok = false;
00316       }
00317     }
00318 
00319     if (ok)
00320     {
00321       PrintInfo("OK");
00322     }
00323   }
00324 
00325   void RoutePlugin::DrawStopWaypoint(double x, double y)
00326   {
00327     const double a = 2;
00328     const double S = a * 2.414213562373095;
00329 
00330     glBegin(GL_POLYGON);
00331 
00332     glColor3f(1.0, 0.0, 0.0);
00333 
00334     glVertex2d(x + S / 2.0, y - a / 2.0);
00335     glVertex2d(x + S / 2.0, y + a / 2.0);
00336     glVertex2d(x + a / 2.0, y + S / 2.0);
00337     glVertex2d(x - a / 2.0, y + S / 2.0);
00338     glVertex2d(x - S / 2.0, y + a / 2.0);
00339     glVertex2d(x - S / 2.0, y - a / 2.0);
00340     glVertex2d(x - a / 2.0, y - S / 2.0);
00341     glVertex2d(x + a / 2.0, y - S / 2.0);
00342 
00343     glEnd();
00344   }
00345 
00346   void RoutePlugin::DrawRoute(const sru::Route& route)
00347   {
00348     const QColor color = ui_.color->color();
00349     glColor4d(color.redF(), color.greenF(), color.blueF(), 1.0);
00350 
00351     if (draw_style_ == LINES)
00352     {
00353       glLineWidth(3);
00354       glBegin(GL_LINE_STRIP);
00355     }
00356     else
00357     {
00358       glPointSize(2);
00359       glBegin(GL_POINTS);
00360     }
00361 
00362     for (size_t i = 0; i < route.points.size(); i++)
00363     {
00364       glVertex2d(route.points[i].position().x(),
00365                  route.points[i].position().y());
00366     }
00367     glEnd();
00368   }
00369 
00370   void RoutePlugin::DrawRoutePoint(const sru::RoutePoint& point)
00371   {
00372     const double arrow_size = ui_.iconsize->value();
00373 
00374     tf::Vector3 v1(arrow_size, 0.0, 0.0);
00375     tf::Vector3 v2(0.0, arrow_size / 2.0, 0.0);
00376     tf::Vector3 v3(0.0, -arrow_size / 2.0, 0.0);
00377 
00378     tf::Transform point_g(point.orientation(), point.position());
00379 
00380     v1 = point_g * v1;
00381     v2 = point_g * v2;
00382     v3 = point_g * v3;
00383 
00384     const QColor color = ui_.positioncolor->color();
00385     glLineWidth(3);
00386     glBegin(GL_POLYGON);
00387     glColor4d(color.redF(), color.greenF(), color.blueF(), 1.0);
00388     glVertex2d(v1.x(), v1.y());
00389     glVertex2d(v2.x(), v2.y());
00390     glVertex2d(v3.x(), v3.y());
00391     glEnd();
00392   }
00393 
00394   void RoutePlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00395   {
00396     if (node["topic"])
00397     {
00398       std::string route_topic;
00399       node["topic"] >> route_topic;
00400       ui_.topic->setText(route_topic.c_str());
00401     }
00402     if (node["color"])
00403     {
00404       std::string color;
00405       node["color"] >> color;
00406       ui_.color->setColor(QColor(color.c_str()));
00407     }
00408     if (node["postopic"])
00409     {
00410       std::string pos_topic;
00411       node["postopic"] >> pos_topic;
00412       ui_.positiontopic->setText(pos_topic.c_str());
00413     }
00414     if (node["poscolor"])
00415     {
00416       std::string poscolor;
00417       node["poscolor"] >> poscolor;
00418       ui_.positioncolor->setColor(QColor(poscolor.c_str()));
00419     }
00420 
00421     if (node["draw_style"])
00422     {
00423       std::string draw_style;
00424       node["draw_style"] >> draw_style;
00425 
00426       if (draw_style == "lines")
00427       {
00428         draw_style_ = LINES;
00429         ui_.drawstyle->setCurrentIndex(0);
00430       }
00431       else if (draw_style == "points")
00432       {
00433         draw_style_ = POINTS;
00434         ui_.drawstyle->setCurrentIndex(1);
00435       }
00436     }
00437 
00438     TopicEdited();
00439     PositionTopicEdited();
00440   }
00441 
00442   void RoutePlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00443   {
00444     std::string route_topic = ui_.topic->text().toStdString();
00445     emitter << YAML::Key << "topic" << YAML::Value << route_topic;
00446 
00447     std::string color = ui_.color->color().name().toStdString();
00448     emitter << YAML::Key << "color" << YAML::Value << color;
00449 
00450     std::string pos_topic = ui_.positiontopic->text().toStdString();
00451     emitter << YAML::Key << "postopic" << YAML::Value << pos_topic;
00452 
00453     std::string pos_color = ui_.positioncolor->color().name().toStdString();
00454     emitter << YAML::Key << "poscolor" << YAML::Value << pos_color;
00455 
00456     std::string draw_style = ui_.drawstyle->currentText().toStdString();
00457     emitter << YAML::Key << "draw_style" << YAML::Value << draw_style;
00458   }
00459 }


mapviz_plugins
Author(s): Marc Alban
autogenerated on Thu Aug 24 2017 02:46:09