00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <mapviz_plugins/attitude_indicator_plugin.h>
00030
00031
00032 #include <algorithm>
00033 #include <cstdio>
00034 #include <vector>
00035
00036
00037 #include <QDebug>
00038 #include <QDialog>
00039 #include <QGLWidget>
00040
00041
00042 #include <ros/master.h>
00043
00044 #include <mapviz/select_topic_dialog.h>
00045 #include <mapviz/select_frame_dialog.h>
00046
00047
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
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
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);
00307 glRotated(roll_, 0.0, 1.0, 0.0);
00308 glRotated(yaw_, 0.0, 0.0, 1.0);
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
00328
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
00343
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 }