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 
00030 
00031 
00032 
00033 
00034 
00035 
00036 #include "overlay_diagnostic_display.h"
00037 
00038 #include <OGRE/OgreMaterialManager.h>
00039 #include <OGRE/OgreTextureManager.h>
00040 #include <OGRE/OgreTexture.h>
00041 #include <OGRE/OgreHardwarePixelBuffer.h>
00042 #include <OGRE/OgreTechnique.h>
00043 
00044 #include <rviz/uniform_string_stream.h>
00045 #include <rviz/display_context.h>
00046 #include <rviz/view_manager.h>
00047 #include <rviz/render_panel.h>
00048 
00049 namespace jsk_rviz_plugins
00050 {
00051   const double overlay_diagnostic_animation_duration = 5.0;
00052   const double overlay_diagnostic_animation_transition_duration = 0.2;
00053   OverlayDiagnosticDisplay::OverlayDiagnosticDisplay()
00054     : previous_state_(STALL_STATE), Display()
00055   {
00056     ros_topic_property_ = new rviz::RosTopicProperty(
00057       "Topic", "/diagnostics_agg",
00058       ros::message_traits::datatype<diagnostic_msgs::DiagnosticArray>(),
00059       "diagnostic_msgs::DiagnosticArray topic to subscribe to.",
00060       this, SLOT( updateRosTopic() ));
00061     diagnostics_namespace_property_ = new rviz::EditableEnumProperty(
00062       "diagnostics namespace", "/",
00063       "diagnostics namespace to visualize diagnostics",
00064       this, SLOT(updateDiagnosticsNamespace()));
00065     type_property_ = new rviz::EnumProperty(
00066       "type", "SAC", "Type of visualization", this, SLOT(updateType()));
00067     type_property_->addOptionStd("SAC", 0);
00068     type_property_->addOptionStd("EVA", 1);
00069     top_property_ = new rviz::IntProperty(
00070       "top", 128,
00071       "top positoin",
00072       this, SLOT(updateTop()));
00073     left_property_ = new rviz::IntProperty(
00074       "left", 128,
00075       "left positoin",
00076       this, SLOT(updateLeft()));
00077     size_property_ = new rviz::IntProperty(
00078       "size", 128,
00079       "size of the widget",
00080       this, SLOT(updateSize()));
00081     size_property_->setMin(1);
00082     alpha_property_ = new rviz::FloatProperty(
00083       "alpha", 0.8,
00084       "alpha value",
00085       this, SLOT(updateAlpha()));
00086     alpha_property_->setMin(0.0);
00087     alpha_property_->setMax(1.0);
00088     stall_duration_property_ = new rviz::FloatProperty(
00089       "stall duration", 5.0,
00090       "seconds to be regarded as stalled",
00091       this, SLOT(updateStallDuration())
00092       );
00093     stall_duration_property_->setMin(0.0);
00094   }
00095 
00096   OverlayDiagnosticDisplay::~OverlayDiagnosticDisplay()
00097   {
00098     if (overlay_) {
00099       overlay_->hide();
00100     }
00101     
00102     
00103     delete ros_topic_property_;
00104     delete diagnostics_namespace_property_;
00105     delete top_property_;
00106     delete left_property_;
00107     delete alpha_property_;
00108     delete size_property_;
00109     delete type_property_;
00110   }
00111 
00112   void OverlayDiagnosticDisplay::processMessage(
00113     const diagnostic_msgs::DiagnosticArray::ConstPtr& msg)
00114   {
00115     boost::mutex::scoped_lock(mutex_);
00116     
00117     
00118     std::set<std::string> new_namespaces;
00119     for (size_t i = 0; i < msg->status.size(); i++) {
00120       new_namespaces.insert(msg->status[i].name);
00121     }
00122     
00123     std::set<std::string> difference_namespaces;
00124     std::set_difference(namespaces_.begin(), namespaces_.end(),
00125                         new_namespaces.begin(), new_namespaces.end(),
00126                         std::inserter(difference_namespaces,
00127                                       difference_namespaces.end()));
00128     if (difference_namespaces.size() != 0) {
00129       namespaces_ = new_namespaces;
00130       fillNamespaceList();
00131     }
00132     else {
00133       difference_namespaces.clear();
00134       std::set_difference(new_namespaces.begin(), new_namespaces.end(),
00135                           namespaces_.begin(), namespaces_.end(),
00136                           std::inserter(difference_namespaces,
00137                                         difference_namespaces.end()));
00138       if (difference_namespaces.size() != 0) {
00139         namespaces_ = new_namespaces;
00140         fillNamespaceList();
00141       }
00142     }
00143     
00144     if (diagnostics_namespace_.length() == 0) {
00145       return;
00146     }
00147 
00148     for (size_t i = 0; i < msg->status.size(); i++) {
00149       diagnostic_msgs::DiagnosticStatus status = msg->status[i];
00150       if (status.name == diagnostics_namespace_) {
00151         latest_status_
00152           = std::make_shared<diagnostic_msgs::DiagnosticStatus>(status);
00153         latest_message_time_ = ros::WallTime::now();
00154         break;
00155       }
00156     }
00157   }
00158 
00159   void OverlayDiagnosticDisplay::update(float wall_dt, float ros_dt)
00160   {
00161     boost::mutex::scoped_lock(mutex_);
00162     if (!isEnabled()) {
00163       return;
00164     }
00165     if (!overlay_) {
00166       static int count = 0;
00167       rviz::UniformStringStream ss;
00168       ss << "OverlayDiagnosticDisplayObject" << count++;
00169       overlay_.reset(new OverlayObject(ss.str()));
00170       overlay_->show();
00171       animation_start_time_ = ros::WallTime::now();
00172     }
00173     t_ += wall_dt;
00174 
00175     
00176     if (!is_animating_) {
00177       if (previous_state_ != getLatestState()) {
00178         is_animating_ = true;
00179         animation_start_time_ = ros::WallTime::now();
00180       }
00181     }
00182     else {
00183       if (!isAnimating()) {     
00184         is_animating_ = false;
00185         previous_state_ = getLatestState();
00186       }
00187     }
00188     
00189     overlay_->updateTextureSize(size_, size_);
00190     redraw();
00191     overlay_->setDimensions(overlay_->getTextureWidth(),
00192                             overlay_->getTextureHeight());
00193     overlay_->setPosition(left_, top_);
00194     t_ = fmod(t_, overlay_diagnostic_animation_duration);
00195   }
00196 
00197   bool OverlayDiagnosticDisplay::isAnimating()
00198   {
00199     return ((ros::WallTime::now() - animation_start_time_).toSec() < overlay_diagnostic_animation_transition_duration);
00200   }
00201   
00202   double OverlayDiagnosticDisplay::animationRate()
00203   {
00204     return ((ros::WallTime::now() - animation_start_time_).toSec() / overlay_diagnostic_animation_transition_duration);
00205   }
00206   
00207   void OverlayDiagnosticDisplay::onEnable()
00208   {
00209     t_ = 0.0;
00210     if (overlay_) {
00211       overlay_->show();
00212     }
00213     subscribe();
00214   }
00215 
00216   void OverlayDiagnosticDisplay::onDisable()
00217   {
00218     ROS_INFO("onDisable");
00219     if (overlay_) {
00220       overlay_->hide();
00221     }
00222     unsubscribe();
00223   }
00224 
00225   void OverlayDiagnosticDisplay::onInitialize()
00226   {
00227     
00228     ROS_DEBUG("onInitialize");
00229     updateType();
00230     updateDiagnosticsNamespace();
00231     updateSize();
00232     updateAlpha();
00233     updateLeft();
00234     updateTop();
00235     updateStallDuration();
00236     updateRosTopic();
00237   }
00238   
00239   void OverlayDiagnosticDisplay::unsubscribe()
00240   {
00241     sub_.shutdown();
00242   }
00243   
00244   void OverlayDiagnosticDisplay::subscribe()
00245   {
00246     ros::NodeHandle n;
00247     sub_ = n.subscribe(ros_topic_property_->getTopicStd(),
00248                        1,
00249                        &OverlayDiagnosticDisplay::processMessage,
00250                        this);
00251   }
00252 
00253   bool OverlayDiagnosticDisplay::isStalled()
00254   {
00255     if (latest_status_) {
00256       ros::WallDuration message_duration
00257         = ros::WallTime::now() - latest_message_time_;
00258       if (message_duration.toSec() < stall_duration_) {
00259         return false;
00260       }
00261       else {
00262         return true;
00263       }
00264     }
00265     else {
00266       return true;
00267     }
00268   }
00269   
00270   std::string OverlayDiagnosticDisplay::statusText()
00271   {
00272     if (latest_status_) {
00273       if (!isStalled()) {
00274         if (latest_status_->level == diagnostic_msgs::DiagnosticStatus::OK) {
00275           return "OK";
00276         }
00277         else if (latest_status_->level == diagnostic_msgs::DiagnosticStatus::WARN) {
00278           return "WARN";
00279         }
00280         else if (latest_status_->level == diagnostic_msgs::DiagnosticStatus::ERROR) {
00281           return "ERROR";
00282         }
00283         else {
00284           return "UNKNOWN";
00285         }
00286       }
00287       else {
00288         return "UNKNOWN";
00289       }
00290     }
00291     else {
00292       return "UNKNOWN";
00293     }
00294   }
00295   
00296   OverlayDiagnosticDisplay::State
00297   OverlayDiagnosticDisplay::getLatestState()
00298   {
00299     if (latest_status_) {
00300       if (!isStalled()) {
00301         if (latest_status_->level == diagnostic_msgs::DiagnosticStatus::OK) {
00302           return OK_STATE;
00303         }
00304         else if (latest_status_->level
00305                  == diagnostic_msgs::DiagnosticStatus::WARN) {
00306           return WARN_STATE;
00307         }
00308         else if (latest_status_->level
00309                  == diagnostic_msgs::DiagnosticStatus::ERROR) {
00310           return ERROR_STATE;
00311         }
00312         else {
00313           return STALL_STATE;
00314         }
00315       }
00316       else {
00317         return STALL_STATE;
00318       }
00319     }
00320     else {
00321       return STALL_STATE;
00322     } 
00323   }
00324 
00325   QColor OverlayDiagnosticDisplay::foregroundColor()
00326   {
00327     QColor ok_color(25, 255, 240, alpha_ * 255.0);
00328     QColor warn_color(240, 173, 78, alpha_ * 255.0);
00329     QColor error_color(217, 83, 79, alpha_ * 255.0);
00330     QColor stall_color(151, 151, 151, alpha_ * 255.0);
00331     
00332     State state = getLatestState();
00333     if (state == OK_STATE) {
00334       return ok_color;
00335     }
00336     else if (state == WARN_STATE) {
00337       return warn_color;
00338     }
00339     else if (state == ERROR_STATE) {
00340       return error_color;
00341     }
00342     else {
00343       return stall_color;
00344     }
00345   }
00346 
00347   QColor OverlayDiagnosticDisplay::textColor()
00348   {
00349     QColor ok_color(40, 40, 40,  alpha_ * 255.0);
00350     QColor warn_color(255, 255, 255, alpha_ * 255.0);
00351     QColor error_color(240, 173, 78, alpha_ * 255.0);
00352     QColor stall_color(240, 173, 78, alpha_ * 255.0);
00353     
00354     State state = getLatestState();
00355     if (state == OK_STATE) {
00356       return ok_color;
00357     }
00358     else if (state == WARN_STATE) {
00359       return warn_color;
00360     }
00361     else if (state == ERROR_STATE) {
00362       return error_color;
00363     }
00364     else {
00365       return stall_color;
00366     }
00367   }
00368 
00369 
00370   
00371   QColor OverlayDiagnosticDisplay::blendColor(QColor a, QColor b, double a_rate) {
00372     QColor ret (a.red() * a_rate + b.red() * (1 - a_rate),
00373                 a.green() * a_rate + b.green() * (1 - a_rate),
00374                 a.blue() * a_rate + b.blue() * (1 - a_rate),
00375                 a.alpha() * a_rate + b.alpha() * (1 - a_rate));
00376     return ret;
00377   }
00378 
00379   double OverlayDiagnosticDisplay::textWidth(QPainter& painter, double font_size, const std::string& text)
00380   {
00381     painter.save();
00382     const double r = size_ / 128.0;
00383     QFont font("Liberation Sans", font_size * r, font_size * r, QFont::Bold);
00384     QPen pen;
00385     QPainterPath path;
00386     pen.setWidth(1);
00387     painter.setFont(font);
00388     painter.setPen(pen);
00389     QFontMetrics metrics(font);
00390     const int text_width = metrics.width(text.c_str());
00391     const int text_height = metrics.height();
00392     painter.restore();
00393     return text_width;
00394   }
00395 
00396   double OverlayDiagnosticDisplay::textHeight(QPainter& painter, double font_size)
00397   {
00398     painter.save();
00399     const double r = size_ / 128.0;
00400     QFont font("Liberation Sans", font_size * r, font_size * r, QFont::Bold);
00401     QPen pen;
00402     QPainterPath path;
00403     pen.setWidth(1);
00404     painter.setFont(font);
00405     painter.setPen(pen);
00406     QFontMetrics metrics(font);
00407     const int text_height = metrics.height();
00408     painter.restore();
00409     return text_height;
00410   }
00411   
00412   
00413   double OverlayDiagnosticDisplay::drawAnimatingText(QPainter& painter,
00414                                                      QColor fg_color,
00415                                                      const double height,
00416                                                      const double font_size,
00417                                                      const std::string text)
00418   {
00419     const double r = size_ / 128.0;
00420     QFont font("Liberation Sans", font_size * r, font_size * r, false);
00421     QPen pen;
00422     QPainterPath path;
00423     pen.setWidth(1);
00424     pen.setColor(blendColor(fg_color, Qt::white, 0.5));
00425     painter.setFont(font);
00426     painter.setPen(pen);
00427     painter.setBrush(fg_color);
00428     QFontMetrics metrics(font);
00429     const int text_width = metrics.width(text.c_str());
00430     const int text_height = metrics.height();
00431     if (overlay_->getTextureWidth() > text_width) {
00432       path.addText((overlay_->getTextureWidth() - text_width) / 2.0,
00433                    height,
00434                    font, text.c_str());
00435     }
00436     else {
00437       double left = - fmod(t_, overlay_diagnostic_animation_duration) /
00438         overlay_diagnostic_animation_duration * text_width * 2 + text_width;
00439       path.addText(left, height, font, text.c_str());
00440     }
00441     painter.drawPath(path);
00442     return text_height;
00443   }
00444   
00445   void OverlayDiagnosticDisplay::drawText(QPainter& painter, QColor fg_color,
00446                                           const std::string& text)
00447   {
00448     double status_size = drawAnimatingText(painter, fg_color,
00449                                            overlay_->getTextureHeight() / 3.0,
00450                                            20, text);
00451     double namespace_size = drawAnimatingText(painter, fg_color,
00452                                               overlay_->getTextureHeight() / 3.0 + status_size,
00453                                               10, diagnostics_namespace_);
00454     std::string message;
00455     if (latest_status_) {
00456       if (!isStalled()) {
00457         message = latest_status_->message;
00458       }
00459       else {
00460         message = "stalled";
00461       }
00462     }
00463     else {
00464       message = "stalled";
00465     }
00466     drawAnimatingText(painter, fg_color,
00467                       overlay_->getTextureHeight() / 3.0
00468                       + status_size + namespace_size,
00469                       10, message);
00470   }
00471 
00472   void OverlayDiagnosticDisplay::drawSAC(QImage& Hud)
00473   {
00474     QColor fg_color = foregroundColor();
00475     
00476     
00477     QPainter painter( &Hud );
00478     const int line_width = 10;
00479     const int margin = 10;
00480     const int inner_line_width = 20;
00481     
00482     painter.setRenderHint(QPainter::Antialiasing, true);
00483     painter.setPen(QPen(fg_color, line_width, Qt::SolidLine));
00484     painter.drawEllipse(line_width / 2, line_width / 2,
00485                         overlay_->getTextureWidth() - line_width,
00486                         overlay_->getTextureHeight() - line_width);
00487     
00488     painter.setPen(QPen(fg_color, inner_line_width, Qt::SolidLine));    
00489     const double start_angle = fmod(t_, overlay_diagnostic_animation_duration) /
00490       overlay_diagnostic_animation_duration * 360;
00491     const double draw_angle = 250;
00492     const double inner_circle_start
00493       = line_width + margin + inner_line_width / 2.0;
00494     drawText(painter, fg_color, statusText());
00495   }
00496 
00497   void OverlayDiagnosticDisplay::drawEVAConnectedRectangle(QPainter& painter,
00498                                                            QColor color,
00499                                                            QColor small_color,
00500                                                            int width)
00501   {
00502     double S = size_;
00503     double A = S * 0.1;
00504     double B = 0.2 * S;
00505     double C = 0.2;
00506     painter.setPen(QPen(color, width, Qt::SolidLine));
00507     QPainterPath large_rectangle_path;
00508     large_rectangle_path.moveTo(A, S - B);
00509     large_rectangle_path.lineTo(A, S);
00510     large_rectangle_path.lineTo(S, B);
00511     large_rectangle_path.lineTo(S, 0);
00512     painter.setPen(Qt::NoPen);
00513     painter.fillPath(large_rectangle_path, QBrush(color));
00514     QPainterPath small_rectangle_path;
00515     small_rectangle_path.moveTo(A, S - B);
00516     small_rectangle_path.lineTo(A, S - B + C * B);
00517     small_rectangle_path.lineTo(A + (S - A) * C, S - B + C * B - (S - B) * C);
00518     small_rectangle_path.lineTo(A + (S - A) * C, S - B - (S - B) * C);
00519     painter.setPen(Qt::NoPen);
00520     painter.fillPath(small_rectangle_path, QBrush(small_color));
00521   }
00522 
00523   void OverlayDiagnosticDisplay::drawEVANonConnectedRectangle(QPainter& painter,
00524                                                               QColor color,
00525                                                               QColor small_color,
00526                                                               int width,
00527                                                               double D)
00528   {
00529     double S = size_;
00530     double A = S * 0.1;
00531     double B = 0.2 * S;
00532     double C = 0.2;
00533     
00534     painter.setPen(QPen(color, width, Qt::SolidLine));
00535     QPainterPath large_rectangle_path;
00536     large_rectangle_path.moveTo(A, S - B);
00537     large_rectangle_path.lineTo(A, S);
00538     double r0 = (S - A - D) / 2 / (S - A);
00539     large_rectangle_path.lineTo(A + (S - A - D) / 2, S - r0 * (S - B));
00540     large_rectangle_path.lineTo(A + (S - A - D) / 2, S - r0 * (S - B) - B);
00541     painter.setPen(Qt::NoPen);
00542     painter.fillPath(large_rectangle_path, QBrush(color));
00543 
00544     QPainterPath large_rectangle_path2;
00545     large_rectangle_path2.moveTo(S - (S - A - D) / 2, (S - B) * r0);
00546     large_rectangle_path2.lineTo(S - (S - A - D) / 2, (S - B) * r0 + B);
00547     large_rectangle_path2.lineTo(S, B);
00548     large_rectangle_path2.lineTo(S, 0);
00549     painter.setPen(Qt::NoPen);
00550     painter.fillPath(large_rectangle_path2, QBrush(color));
00551     
00552     QPainterPath small_rectangle_path;
00553     small_rectangle_path.moveTo(A, S - B);
00554     small_rectangle_path.lineTo(A, S - B + C * B);
00555     small_rectangle_path.lineTo(A + (S - A) * C, S - B + C * B - (S - B) * C);
00556     small_rectangle_path.lineTo(A + (S - A) * C, S - B - (S - B) * C);
00557     painter.setPen(Qt::NoPen);
00558     painter.fillPath(small_rectangle_path, QBrush(small_color));
00559   }
00560   
00561   void OverlayDiagnosticDisplay::drawEVA(QImage& Hud)
00562   {
00563     QColor line_color(240, 173, 78, alpha_ * 255.0);
00564     QColor rectangle_color = foregroundColor();
00565     QColor small_rectangle_color(line_color);
00566     QPainter painter(&Hud);
00567     State close_state = OK_STATE;
00568     int line_width = 2;
00569     double S = size_;
00570     double A = S * 0.1;
00571     double B = 0.2 * S;
00572     double C = 0.2;
00573     double max_gap = 0.05 * S;
00574     painter.setRenderHint(QPainter::Antialiasing, true);
00575     painter.setPen(QPen(line_color, line_width, Qt::SolidLine));
00576     painter.drawLine(QPoint(0, 0), QPoint(0, S));
00577     painter.drawLine(QPoint(0, S - B / 2), QPoint(A, S - B / 2));
00578     if (isAnimating()) {
00579       
00580       double r = animationRate();
00581       if (previous_state_ == close_state) { 
00582         drawEVANonConnectedRectangle(painter, rectangle_color, small_rectangle_color, line_width, max_gap * r);
00583       }
00584       else if (getLatestState() == close_state) { 
00585         drawEVANonConnectedRectangle(painter, rectangle_color, small_rectangle_color, line_width, max_gap * (1 - r));
00586       }
00587       else {                    
00588         drawEVANonConnectedRectangle(painter, rectangle_color, small_rectangle_color, line_width, max_gap);
00589       }
00590     }
00591     else {
00592       State state = getLatestState();
00593       if (state == close_state) {
00594         drawEVAConnectedRectangle(painter, rectangle_color, small_rectangle_color, line_width);
00595       }
00596       else {
00597         drawEVANonConnectedRectangle(painter, rectangle_color, small_rectangle_color, line_width, max_gap);
00598       }
00599     }
00600     painter.setPen(QPen(textColor(), 2 * line_width, Qt::SolidLine));
00601     painter.setFont(QFont("Liberation Sans", 12, QFont::Bold));
00602     double theta = atan2(S - B, S - A) / M_PI * 180;
00603     double text_box_height = cos(theta*M_PI/180) * B;
00604     double text_box_width = (S - A) / cos(theta*M_PI/180) - sin(theta*M_PI/180) * B * 2;
00605     double text_width = textWidth(painter, 12, diagnostics_namespace_);
00606     
00607     painter.translate(A, S - B);
00608     painter.rotate(-theta);
00609     if (text_width > text_box_width) {
00610       double text_left = - fmod(t_, overlay_diagnostic_animation_duration) /
00611         overlay_diagnostic_animation_duration * text_width;
00612       painter.drawText(QRectF(text_left, 0, text_width*2, text_box_height), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
00613                        diagnostics_namespace_.c_str());
00614     }
00615     else {
00616       painter.drawText(QRectF(0, 0, text_box_width, text_box_height), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
00617                        diagnostics_namespace_.c_str());
00618     }
00619   }
00620   
00621   void OverlayDiagnosticDisplay::redraw()
00622   {
00623     ScopedPixelBuffer buffer = overlay_->getBuffer();
00624     QColor transparent(0, 0, 0, 0.0);    
00625     QImage Hud = buffer.getQImage(*overlay_, transparent);
00626     if (type_ == 0) {
00627       drawSAC(Hud);
00628     }
00629     else if (type_ == 1) {
00630       drawEVA(Hud);
00631     }
00632   }
00633 
00634   void OverlayDiagnosticDisplay::fillNamespaceList()
00635   {
00636     
00637     diagnostics_namespace_property_->clearOptions();
00638     for (std::set<std::string>::iterator it = namespaces_.begin();
00639          it != namespaces_.end();
00640          it++) {
00641       diagnostics_namespace_property_->addOptionStd(*it);
00642     }
00643     diagnostics_namespace_property_->sortOptions();
00644   }
00645   
00646   void OverlayDiagnosticDisplay::updateRosTopic()
00647   {
00648     latest_status_.reset();
00649     unsubscribe();
00650     subscribe();
00651   }
00652 
00653   void OverlayDiagnosticDisplay::updateDiagnosticsNamespace()
00654   {
00655     latest_status_.reset();
00656     diagnostics_namespace_ = diagnostics_namespace_property_->getStdString();
00657   }
00658   
00659   void OverlayDiagnosticDisplay::updateSize()
00660   {
00661     size_ = size_property_->getInt();
00662   }
00663 
00664   void OverlayDiagnosticDisplay::updateAlpha()
00665   {
00666     alpha_ = alpha_property_->getFloat();
00667   }
00668 
00669   void OverlayDiagnosticDisplay::updateTop()
00670   {
00671     top_ = top_property_->getInt();
00672   }
00673   
00674   void OverlayDiagnosticDisplay::updateLeft()
00675   {
00676     left_ = left_property_->getInt();
00677   }
00678   
00679   void OverlayDiagnosticDisplay::updateStallDuration()
00680   {
00681     stall_duration_ = stall_duration_property_->getFloat();
00682   }
00683 
00684   bool OverlayDiagnosticDisplay::isInRegion(int x, int y)
00685   {
00686     return (top_ < y && top_ + size_ > y &&
00687             left_ < x && left_ + size_ > x);
00688   }
00689 
00690   void OverlayDiagnosticDisplay::movePosition(int x, int y)
00691   {
00692     top_ = y;
00693     left_ = x;
00694   }
00695 
00696   void OverlayDiagnosticDisplay::setPosition(int x, int y)
00697   {
00698     top_property_->setValue(y);
00699     left_property_->setValue(x);
00700   }
00701 
00702   void OverlayDiagnosticDisplay::updateType()
00703   {
00704     type_ = type_property_->getOptionInt();
00705   }
00706 }
00707 
00708 #include <pluginlib/class_list_macros.h>
00709 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::OverlayDiagnosticDisplay, rviz::Display)