attitude_indicator_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 #include <mapviz_plugins/attitude_indicator_plugin.h>
00030 
00031 // C++ standard libraries
00032 #include <algorithm>
00033 #include <cstdio>
00034 #include <vector>
00035 
00036 // QT libraries
00037 #include <QDebug>
00038 #include <QDialog>
00039 #include <QGLWidget>
00040 
00041 // ROS libraries
00042 #include <ros/master.h>
00043 
00044 #include <mapviz/select_topic_dialog.h>
00045 #include <mapviz/select_frame_dialog.h>
00046 
00047 // Declare plugin
00048 #include <pluginlib/class_list_macros.h>
00049 
00050 PLUGINLIB_DECLARE_CLASS(
00051     mapviz_plugins,
00052     attitude_indicator,
00053     mapviz_plugins::AttitudeIndicatorPlugin,
00054     mapviz::MapvizPlugin)
00055 
00056 namespace mapviz_plugins
00057 {
00058 #define IS_INSTANCE(msg, type) \
00059   (msg->getDataType() == ros::message_traits::datatype<type>())
00060 
00061   AttitudeIndicatorPlugin::AttitudeIndicatorPlugin() :
00062       config_widget_(new QWidget())
00063   {
00064     ui_.setupUi(config_widget_);
00065 
00066     // Set background white
00067     QPalette p(config_widget_->palette());
00068     p.setColor(QPalette::Background, Qt::white);
00069     config_widget_->setPalette(p);
00070     roll_ = pitch_ = yaw_ = 0;
00071     topics_.push_back("nav_msgs/Odometry");
00072     topics_.push_back("geometry_msgs/Pose");
00073     topics_.push_back("sensor_msgs/Imu");
00074     // Set status text red
00075     QPalette p3(ui_.status->palette());
00076     p3.setColor(QPalette::Text, Qt::red);
00077     ui_.status->setPalette(p3);
00078 
00079     placer_.setRect(QRect(0, 0, 100, 100));
00080     QObject::connect(this, SIGNAL(VisibleChanged(bool)),
00081                      &placer_, SLOT(setVisible(bool)));
00082 
00083     QObject::connect(ui_.selecttopic, SIGNAL(clicked()), this, SLOT(SelectTopic()));
00084     QObject::connect(ui_.topic, SIGNAL(editingFinished()), this, SLOT(TopicEdited()));
00085   }
00086 
00087   AttitudeIndicatorPlugin::~AttitudeIndicatorPlugin()
00088   {
00089   }
00090 
00091   void AttitudeIndicatorPlugin::SelectTopic()
00092   {
00093     ros::master::TopicInfo topic = mapviz::SelectTopicDialog::selectTopic(
00094         topics_);
00095     if (topic.name.empty())
00096     {
00097       return;
00098     }
00099 
00100     ui_.topic->setText(QString::fromStdString(topic.name));
00101     TopicEdited();
00102   }
00103 
00104   void AttitudeIndicatorPlugin::TopicEdited()
00105   {
00106     std::string topic = ui_.topic->text().trimmed().toStdString();
00107     if (topic != topic_)
00108     {
00109       initialized_ = true;
00110       PrintWarning("No messages received.");
00111 
00112        odometry_sub_.shutdown();
00113        topic_ = topic;
00114        if (!topic_.empty())
00115        {
00116          odometry_sub_ = node_.subscribe<topic_tools::ShapeShifter>(
00117              topic_, 100, &AttitudeIndicatorPlugin::handleMessage, this);
00118 
00119         ROS_INFO("Subscribing to %s", topic_.c_str());
00120       }
00121     }
00122   }
00123 
00124   void AttitudeIndicatorPlugin::handleMessage(const topic_tools::ShapeShifter::ConstPtr& msg)
00125   {
00126     if (IS_INSTANCE(msg, nav_msgs::Odometry))
00127     {
00128       AttitudeCallbackOdom(msg->instantiate<nav_msgs::Odometry>());
00129     }
00130     else if (IS_INSTANCE(msg, sensor_msgs::Imu))
00131     {
00132       AttitudeCallbackImu(msg->instantiate<sensor_msgs::Imu>());
00133     }
00134     else if (IS_INSTANCE(msg, geometry_msgs::Pose))
00135     {
00136       AttitudeCallbackPose(msg->instantiate<geometry_msgs::Pose>());
00137     }
00138     else
00139     {
00140       PrintError("Unknown message type: " + msg->getDataType());
00141     }
00142   }
00143 
00144   void AttitudeIndicatorPlugin::AttitudeCallbackOdom(const nav_msgs::OdometryConstPtr& odometry)
00145   {
00146     attitude_orientation_ = tf::Quaternion(
00147         odometry->pose.pose.orientation.x,
00148         odometry->pose.pose.orientation.y,
00149         odometry->pose.pose.orientation.z,
00150         odometry->pose.pose.orientation.w);
00151 
00152     tf::Matrix3x3 m(attitude_orientation_);
00153     m.getRPY(roll_, pitch_, yaw_);
00154     roll_ = roll_ * (180.0 / M_PI);
00155     pitch_ = pitch_ * (180.0 / M_PI);
00156     yaw_ = yaw_ * (180.0 / M_PI);
00157 
00158     ROS_INFO("roll %f,pitch %f, yaw %f", roll_, pitch_, yaw_);
00159     canvas_->update();
00160   }
00161 
00162   void AttitudeIndicatorPlugin::AttitudeCallbackImu(const sensor_msgs::ImuConstPtr& imu)
00163   {
00164     attitude_orientation_ = tf::Quaternion(
00165         imu->orientation.x,
00166         imu->orientation.y,
00167         imu->orientation.z,
00168         imu->orientation.w);
00169 
00170     tf::Matrix3x3 m(attitude_orientation_);
00171     m.getRPY(roll_, pitch_, yaw_);
00172     roll_ = roll_ * (180.0 / M_PI);
00173     pitch_ = pitch_ * (180.0 / M_PI);
00174     yaw_ = yaw_ * (180.0 / M_PI);
00175     ROS_INFO("roll %f,pitch %f, yaw %f", roll_, pitch_, yaw_);
00176 
00177     canvas_->update();
00178   }
00179 
00180   void AttitudeIndicatorPlugin::AttitudeCallbackPose(const geometry_msgs::PoseConstPtr& pose)
00181   {
00182     attitude_orientation_ = tf::Quaternion(
00183         pose->orientation.x,
00184         pose->orientation.y,
00185         pose->orientation.z,
00186         pose->orientation.w);
00187 
00188     tf::Matrix3x3 m(attitude_orientation_);
00189     m.getRPY(roll_, pitch_, yaw_);
00190     roll_ = roll_ * (180.0 / M_PI);
00191     pitch_ = pitch_ * (180.0 / M_PI);
00192     yaw_ = yaw_ * (180.0 / M_PI);
00193 
00194     ROS_INFO("roll %f,pitch %f, yaw %f", roll_, pitch_, yaw_);
00195     canvas_->update();
00196   }
00197 
00198   void AttitudeIndicatorPlugin::PrintError(const std::string& message)
00199   {
00200     if (message == ui_.status->text().toStdString())
00201     {
00202       return;
00203     }
00204 
00205     ROS_ERROR("Error: %s", message.c_str());
00206     QPalette p(ui_.status->palette());
00207     p.setColor(QPalette::Text, Qt::red);
00208     ui_.status->setPalette(p);
00209     ui_.status->setText(message.c_str());
00210   }
00211 
00212   void AttitudeIndicatorPlugin::PrintInfo(const std::string& message)
00213   {
00214     if (message == ui_.status->text().toStdString())
00215     {
00216       return;
00217     }
00218 
00219     ROS_INFO("%s", message.c_str());
00220     QPalette p(ui_.status->palette());
00221     p.setColor(QPalette::Text, Qt::green);
00222     ui_.status->setPalette(p);
00223     ui_.status->setText(message.c_str());
00224   }
00225 
00226   void AttitudeIndicatorPlugin::PrintWarning(const std::string& message)
00227   {
00228     if (message == ui_.status->text().toStdString())
00229     {
00230       return;
00231     }
00232 
00233     ROS_WARN("%s", message.c_str());
00234     QPalette p(ui_.status->palette());
00235     p.setColor(QPalette::Text, Qt::darkYellow);
00236     ui_.status->setPalette(p);
00237     ui_.status->setText(message.c_str());
00238   }
00239 
00240   QWidget* AttitudeIndicatorPlugin::GetConfigWidget(QWidget* parent)
00241   {
00242     config_widget_->setParent(parent);
00243     return config_widget_;
00244   }
00245 
00246   bool AttitudeIndicatorPlugin::Initialize(QGLWidget* canvas)
00247   {
00248     initialized_ = true;
00249     canvas_ = canvas;
00250     placer_.setContainer(canvas_);
00251     startTimer(50);
00252     return true;
00253   }
00254 
00255   void AttitudeIndicatorPlugin::Shutdown()
00256   {
00257     placer_.setContainer(NULL);
00258   }
00259 
00260   void AttitudeIndicatorPlugin::timerEvent(QTimerEvent*)
00261   {
00262     canvas_->update();
00263   }
00264 
00265   void AttitudeIndicatorPlugin::drawBall()
00266   {
00267     GLdouble eqn[4] = {0.0, 0.0, 1.0, 0.0};
00268     GLdouble eqn2[4] = {0.0, 0.0, -1.0, 0.0};
00269     GLdouble eqn4[4] = {0.0, 0.0, 1.0, 0.05};
00270     GLdouble eqn3[4] = {0.0, 0.0, -1.0, 0.05};
00271 
00272     glEnable(GL_DEPTH_TEST);
00273     glDepthFunc(GL_LESS);
00274 
00275     glPushMatrix();
00276 
00277     glColor3f(0.392156863f, 0.584313725f, 0.929411765f);
00278     glRotated(90.0 + pitch_, 1.0, 0.0, 0.0);
00279 
00280     glRotated(roll_, 0.0, 1.0, 0.0);
00281     glRotated(yaw_, 0.0, 0.0, 1.0);
00282     glClipPlane(GL_CLIP_PLANE1, eqn2);
00283     glEnable(GL_CLIP_PLANE1);
00284     glutSolidSphere(.8, 20, 16);
00285     glDisable(GL_CLIP_PLANE1);
00286     glPopMatrix();
00287 
00288     glPushMatrix();
00289 
00290     glLineWidth(2);
00291     glColor3f(1.0f, 1.0f, 1.0f);
00292     glRotated(90.0 + pitch_, 1.0, 0.0, 0.0);
00293     glRotated(roll_, 0.0, 1.0, 0.0);
00294     glRotated(yaw_, 0.0, 0.0, 1.0);
00295     glClipPlane(GL_CLIP_PLANE3, eqn4);
00296     glClipPlane(GL_CLIP_PLANE2, eqn3);
00297     glEnable(GL_CLIP_PLANE2);
00298     glEnable(GL_CLIP_PLANE3);
00299     glutWireSphere(.801, 10, 16);
00300     glDisable(GL_CLIP_PLANE2);
00301     glDisable(GL_CLIP_PLANE3);
00302     glPopMatrix();
00303 
00304     glPushMatrix();
00305     glColor3f(0.62745098f, 0.321568627f, 0.176470588f);
00306     glRotated(90.0 + pitch_, 1.0, 0.0, 0.0);//x
00307     glRotated(roll_, 0.0, 1.0, 0.0);//y
00308     glRotated(yaw_, 0.0, 0.0, 1.0);//z
00309     glClipPlane(GL_CLIP_PLANE0, eqn);
00310     glEnable(GL_CLIP_PLANE0);
00311     glutSolidSphere(.8, 20, 16);
00312     glDisable(GL_CLIP_PLANE0);
00313     glPopMatrix();
00314     glDisable(GL_DEPTH_TEST);
00315   }
00316 
00317   void AttitudeIndicatorPlugin::Draw(double x, double y, double scale)
00318   {
00319     glPushAttrib(GL_ALL_ATTRIB_BITS);
00320     glMatrixMode(GL_PROJECTION);
00321     glPushMatrix();
00322     glLoadIdentity();
00323     glOrtho(0, canvas_->width(), canvas_->height(), 0, -1.0f, 1.0f);
00324     glMatrixMode(GL_MODELVIEW);
00325     glPushMatrix();
00326     glLoadIdentity();
00327     // Setup coordinate system so that we have a [-1,1]x[1,1] cube on
00328     // the screen.
00329     QRect rect = placer_.rect();
00330     double s_x = rect.width() / 2.0;
00331     double s_y = -rect.height() / 2.0;
00332     double t_x = rect.right() - s_x;
00333     double t_y = rect.top() - s_y;
00334 
00335     double m[16] = {
00336         s_x, 0, 0, 0,
00337         0, s_y, 0, 0,
00338         0, 0, 1.0, 0,
00339         t_x, t_y, 0, 1.0};
00340     glMultMatrixd(m);
00341 
00342     // Placed in a separate function so that we don't forget to pop the
00343     // GL state back.
00344 
00345     drawBackground();
00346     drawBall();
00347 
00348     drawPanel();
00349 
00350     glPopMatrix();
00351     glMatrixMode(GL_PROJECTION);
00352     glPopMatrix();
00353     glMatrixMode(GL_MODELVIEW);
00354     glPopAttrib();
00355     PrintInfo("OK!");
00356   }
00357 
00358   void AttitudeIndicatorPlugin::drawBackground()
00359   {
00360     glBegin(GL_TRIANGLES);
00361     glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
00362 
00363     glVertex2d(-1.0, -1.0);
00364     glVertex2d(-1.0, 1.0);
00365     glVertex2d(1.0, 1.0);
00366 
00367     glVertex2d(-1.0, -1.0);
00368     glVertex2d(1.0, 1.0);
00369     glVertex2d(1.0, -1.0);
00370 
00371     glEnd();
00372   }
00373 
00374   void AttitudeIndicatorPlugin::drawPanel()
00375   {
00376     glLineWidth(2);
00377 
00378     glBegin(GL_LINE_STRIP);
00379     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00380 
00381     glVertex2d(-0.9, 0.0);
00382     glVertex2d(-0.2, 0.0);
00383 
00384     int divisions = 20;
00385     for (int i = 1; i < divisions; i++)
00386     {
00387       glVertex2d(-0.2 * std::cos(M_PI * i / divisions),
00388                  -0.2 * std::sin(M_PI * i / divisions));
00389     }
00390 
00391     glVertex2f(0.2, 0.0);
00392     glVertex2f(0.9, 0.0);
00393     glEnd();
00394 
00395     glBegin(GL_LINES);
00396     glVertex2f(0.0, -0.2f);
00397     glVertex2f(0.0, -0.9f);
00398     glEnd();
00399   }
00400 
00401   void AttitudeIndicatorPlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00402   {
00403     if (node["topic"])
00404     {
00405       std::string topic;
00406       node["topic"] >> topic;
00407       ui_.topic->setText(topic.c_str());
00408     }
00409 
00410     QRect current = placer_.rect();
00411     int x = current.x();
00412     int y = current.y();
00413     int width = current.width();
00414     int height = current.height();
00415 
00416     if (swri_yaml_util::FindValue(node, "x"))
00417     {
00418       node["x"] >> x;
00419     }
00420 
00421     if (swri_yaml_util::FindValue(node, "y"))
00422     {
00423       node["y"] >> y;
00424     }
00425 
00426     if (swri_yaml_util::FindValue(node, "width"))
00427     {
00428       node["width"] >> width;
00429     }
00430 
00431     if (swri_yaml_util::FindValue(node, "height"))
00432     {
00433       node["height"] >> height;
00434     }
00435 
00436     QRect position(x, y, width, height);
00437     placer_.setRect(position);
00438 
00439     TopicEdited();
00440   }
00441 
00442   void AttitudeIndicatorPlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00443   {
00444     emitter << YAML::Key << "topic" << YAML::Value << ui_.topic->text().toStdString();
00445 
00446     QRect position = placer_.rect();
00447 
00448     emitter << YAML::Key << "x" << YAML::Value << position.x();
00449     emitter << YAML::Key << "y" << YAML::Value << position.y();
00450     emitter << YAML::Key << "width" << YAML::Value << position.width();
00451     emitter << YAML::Key << "height" << YAML::Value << position.height();
00452   }
00453 }


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