plotter_2d_display.cpp
Go to the documentation of this file.
00001 // -*- mode: c++; -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2014, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Willow Garage nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #include "plotter_2d_display.h"
00037 #include <OGRE/OgreHardwarePixelBuffer.h>
00038 #include <rviz/uniform_string_stream.h>
00039 #include <rviz/display_context.h>
00040 #include <QPainter>
00041 
00042 namespace jsk_rviz_plugin
00043 {
00044   Plotter2DDisplay::Plotter2DDisplay()
00045     : rviz::Display()
00046   {
00047     update_topic_property_ = new rviz::RosTopicProperty(
00048       "Topic", "",
00049       ros::message_traits::datatype<std_msgs::Float32>(),
00050       "std_msgs::Float32 topic to subscribe to.",
00051       this, SLOT( updateTopic() ));
00052     buffer_length_property_ = new rviz::IntProperty(
00053       "Buffer length", 100,
00054       ros::message_traits::datatype<std_msgs::Float32>(),
00055       this, SLOT(updateBufferSize()));
00056     width_property_ = new rviz::IntProperty("width", 128,
00057                                             "width of the plotter window",
00058                                             this, SLOT(updateWidth()));
00059     width_property_->setMin(1);
00060     width_property_->setMax(2000);
00061     height_property_ = new rviz::IntProperty("height", 128,
00062                                              "height of the plotter window",
00063                                              this, SLOT(updateHeight()));
00064     height_property_->setMin(1);
00065     height_property_->setMax(2000);
00066     left_property_ = new rviz::IntProperty("left", 128,
00067                                            "left of the plotter window",
00068                                            this, SLOT(updateLeft()));
00069     left_property_->setMin(0);
00070     top_property_ = new rviz::IntProperty("top", 128,
00071                                           "top of the plotter window",
00072                                           this, SLOT(updateTop()));
00073     top_property_->setMin(0);
00074     auto_scale_property_ = new rviz::BoolProperty("auto scale", true,
00075                                                   "enable auto scale",
00076                                                   this, SLOT(updateAutoScale()));
00077     max_value_property_ = new rviz::FloatProperty("max value", 1.0,
00078                                                   "max value, used only if auto scale is disabled",
00079                                                   this, SLOT(updateMaxValue()));
00080     min_value_property_ = new rviz::FloatProperty("min value", -1.0,
00081                                                   "min value, used only if auto scale is disabled",
00082                                                   this, SLOT(updateMinValue()));
00083     fg_color_property_ = new rviz::ColorProperty("foreground color", QColor(25, 255, 240),
00084                                                  "color to draw line",
00085                                                  this, SLOT(updateFGColor()));
00086     fg_alpha_property_ = new rviz::FloatProperty("foreground alpha", 0.7,
00087                                                  "alpha belnding value for foreground",
00088                                                  this, SLOT(updateFGAlpha()));
00089     fg_alpha_property_->setMin(0);
00090     fg_alpha_property_->setMax(1.0);
00091     bg_color_property_ = new rviz::ColorProperty("background color", QColor(0, 0, 0),
00092                                                  "background color",
00093                                                  this, SLOT(updateBGColor()));
00094     bg_alpha_property_ = new rviz::FloatProperty("backround alpha", 0.0,
00095                                                  "alpha belnding value for background",
00096                                                  this, SLOT(updateBGAlpha()));
00097     bg_alpha_property_->setMin(0);
00098     bg_alpha_property_->setMax(1.0);
00099     line_width_property_ = new rviz::IntProperty("linewidth", 1,
00100                                                  "linewidth of the plot",
00101                                                  this, SLOT(updateLineWidth()));
00102     line_width_property_->setMin(1);
00103     line_width_property_->setMax(1000);
00104     show_border_property_ = new rviz::BoolProperty("border", true,
00105                                                    "show border or not",
00106                                                    this, SLOT(updateShowBorder()));
00107     text_size_property_ = new rviz::IntProperty("text size", 12,
00108                                                 "text size of the caption",
00109                                                 this, SLOT(updateTextSize()));
00110     text_size_property_->setMin(1);
00111     text_size_property_->setMax(1000);
00112     show_caption_property_ = new rviz::BoolProperty("caption", true,
00113                                                     "show caption or not",
00114                                                     this, SLOT(updateShowCaption()));
00115     update_interval_property_ = new rviz::FloatProperty("update interval", 0.04,
00116                                                         "update interval of the plotter",
00117                                                         this, SLOT(updateUpdateInterval()));
00118     update_interval_property_->setMin(0.0);
00119     update_interval_property_->setMax(100);
00120     auto_color_change_property_
00121       = new rviz::BoolProperty("auto color change",
00122                                false,
00123                                "change the color automatically",
00124                                this, SLOT(updateAutoColorChange()));
00125     max_color_property_
00126       = new rviz::ColorProperty("max color",
00127                                 QColor(255, 0, 0),
00128                                 "only used if auto color change is set to True.",
00129                                 this, SLOT(updateMaxColor()));
00130   }
00131 
00132   Plotter2DDisplay::~Plotter2DDisplay()
00133   {
00134     onDisable();
00135     // delete update_topic_property_;
00136     // delete buffer_length_property_;
00137     // delete fg_color_property_;
00138     // delete bg_color_property_;
00139     // delete fg_alpha_property_;
00140     // delete bg_alpha_property_;
00141     // delete top_property_;
00142     // delete left_property_;
00143     // delete width_property_;
00144     // delete height_property_;
00145     // delete line_width_property_;
00146     // delete show_border_property_;
00147     // delete auto_color_change_property_;
00148     // delete max_color_property_;
00149     // delete update_interval_property_;
00150     // delete show_caption_property_;
00151     // delete text_size_property_;
00152     // delete min_value_property_;
00153     // delete max_value_property_;
00154     // delete auto_color_change_property_;
00155   }
00156 
00157   void Plotter2DDisplay::initializeBuffer()
00158   {
00159     buffer_.resize(buffer_length_);
00160     min_value_ = -1.0;
00161     max_value_ = 1.0;
00162     for (size_t i = 0; i < buffer_length_; i++) {
00163       buffer_[i] = 0.0;
00164     }
00165   }
00166 
00167   void Plotter2DDisplay::onInitialize()
00168   {
00169     static int count = 0;
00170     updateBufferSize();
00171     rviz::UniformStringStream ss;
00172     ss << "Plotter2DDisplayObject" << count++;
00173     overlay_.reset(new OverlayObject(ss.str()));
00174     onEnable();
00175     updateWidth();
00176     updateHeight();
00177     updateLeft();
00178     updateTop();
00179     updateFGColor();
00180     updateBGColor();
00181     updateFGAlpha();
00182     updateBGAlpha();
00183     updateLineWidth();
00184     updateUpdateInterval();
00185     updateShowBorder();
00186     updateAutoColorChange();
00187     updateMaxColor();
00188     updateShowCaption();
00189     updateTextSize();
00190     updateAutoScale();
00191     updateMinValue();
00192     updateMaxValue();
00193     overlay_->updateTextureSize(width_property_->getInt(),
00194                                 height_property_->getInt() + caption_offset_);
00195   }
00196 
00197   void Plotter2DDisplay::drawPlot()
00198   {
00199     QColor fg_color(fg_color_);
00200     QColor bg_color(bg_color_);
00201     
00202     fg_color.setAlpha(fg_alpha_);
00203     bg_color.setAlpha(bg_alpha_);
00204 
00205     if (auto_color_change_) {
00206       double r
00207         = std::min(std::max((buffer_[buffer_.size() - 1] - min_value_) / (max_value_ - min_value_),
00208                             0.0), 1.0);
00209       fg_color.setRed((max_color_.red() - fg_color_.red()) * r
00210                       + fg_color_.red());
00211       fg_color.setGreen((max_color_.green() - fg_color_.green()) * r
00212                       + fg_color_.green());
00213       fg_color.setBlue((max_color_.blue() - fg_color_.blue()) * r
00214                        + fg_color_.blue());
00215     }
00216     
00217     {
00218       ScopedPixelBuffer buffer = overlay_->getBuffer();
00219       QImage Hud = buffer.getQImage(*overlay_);
00220       // initilize by the background color
00221       for (int i = 0; i < overlay_->getTextureWidth(); i++) {
00222         for (int j = 0; j < overlay_->getTextureHeight(); j++) {
00223           Hud.setPixel(i, j, bg_color.rgba());
00224         }
00225       }
00226       // paste in HUD speedometer. I resize the image and offset it by 8 pixels from
00227       // the bottom left edge of the render window
00228       QPainter painter( &Hud );
00229       painter.setRenderHint(QPainter::Antialiasing, true);
00230       painter.setPen(QPen(fg_color, line_width_, Qt::SolidLine));
00231       
00232       uint16_t w = overlay_->getTextureWidth();
00233       uint16_t h = overlay_->getTextureHeight() - caption_offset_;
00234 
00235       double margined_max_value = max_value_ + (max_value_ - min_value_) / 2;
00236       double margined_min_value = min_value_ - (max_value_ - min_value_) / 2;
00237       
00238       for (size_t i = 1; i < buffer_length_; i++) {
00239         double v_prev = (margined_max_value - buffer_[i - 1]) / (margined_max_value - margined_min_value);
00240         double v = (margined_max_value - buffer_[i]) / (margined_max_value - margined_min_value);
00241         double u_prev = (i - 1) / (float)buffer_length_;
00242         double u = i / (float)buffer_length_;
00243 
00244         // chop within 0 ~ 1
00245         v_prev = std::max(std::min(v_prev, 1.0), 0.0);
00246         u_prev = std::max(std::min(u_prev, 1.0), 0.0);
00247         v = std::max(std::min(v, 1.0), 0.0);
00248         u = std::max(std::min(u, 1.0), 0.0);
00249         
00250         uint16_t x_prev = (int)(u_prev * w);
00251         uint16_t x = (int)(u * w);
00252         uint16_t y_prev = (int)(v_prev * h);
00253         uint16_t y = (int)(v * h);
00254         painter.drawLine(x_prev, y_prev, x, y);
00255       }
00256       // draw border
00257       if (show_border_) {
00258         painter.drawLine(0, 0, 0, h);
00259         painter.drawLine(0, h, w, h);
00260         painter.drawLine(w, h, w, 0);
00261         painter.drawLine(w, 0, 0, 0);
00262       }
00263       // draw caption
00264       if (show_caption_) {
00265         QFont font = painter.font();
00266         font.setPointSize(text_size_);
00267         font.setBold(true);
00268         painter.setFont(font);
00269         painter.drawText(0, h, w, caption_offset_,
00270                          Qt::AlignCenter | Qt::AlignVCenter,
00271                          getName());
00272 
00273       }
00274       
00275       // done
00276       painter.end();
00277     }
00278   }
00279   
00280   void Plotter2DDisplay::processMessage(const std_msgs::Float32::ConstPtr& msg)
00281   {
00282     boost::mutex::scoped_lock lock(mutex_);
00283 
00284     if (!isEnabled()) {
00285       return;
00286     }
00287     
00288     // add the message to the buffer
00289     double min_value = buffer_[0];
00290     double max_value = buffer_[0];
00291     for (size_t i = 0; i < buffer_length_ - 1; i++) {
00292       buffer_[i] = buffer_[i + 1];
00293       if (min_value > buffer_[i]) {
00294         min_value = buffer_[i];
00295       }
00296       if (max_value < buffer_[i]) {
00297         max_value = buffer_[i];
00298       }
00299     }
00300     buffer_[buffer_length_ - 1] = msg->data;
00301     if (min_value > msg->data) {
00302       min_value = msg->data;
00303     }
00304     if (max_value < msg->data) {
00305       max_value = msg->data;
00306     }
00307     if (auto_scale_) {
00308       min_value_ = min_value;
00309       max_value_ = max_value;
00310       if (min_value_ == max_value_) {
00311         min_value_ = min_value_ - 0.5;
00312         max_value_ = max_value_ + 0.5;
00313       }
00314     }
00315     if (!overlay_->isVisible()) {
00316       return;
00317     }
00318     
00319     overlay_->updateTextureSize(texture_width_,
00320                                 texture_height_ + caption_offset_);
00321     overlay_->setPosition(left_, top_);
00322     overlay_->setDimensions(overlay_->getTextureWidth(), overlay_->getTextureHeight());
00323     draw_required_ = true;
00324   }
00325 
00326   void Plotter2DDisplay::update(float wall_dt, float ros_dt)
00327   {
00328     if (draw_required_) {
00329       if (wall_dt + last_time_ > update_interval_) {
00330         last_time_ = 0;
00331         drawPlot();
00332         draw_required_ = false;
00333       }
00334       else {
00335         last_time_ = last_time_ + wall_dt;
00336       }
00337     }
00338   }
00339   
00340   void Plotter2DDisplay::subscribe()
00341   {
00342     initializeBuffer();
00343     std::string topic_name = update_topic_property_->getTopicStd();
00344     if (topic_name.length() > 0 && topic_name != "/") {
00345       ros::NodeHandle n;
00346       sub_ = n.subscribe(topic_name, 1, &Plotter2DDisplay::processMessage, this);
00347     }
00348   }
00349 
00350   void Plotter2DDisplay::unsubscribe()
00351   {
00352     sub_.shutdown();
00353   }
00354 
00355   void Plotter2DDisplay::onEnable()
00356   {
00357     last_time_ = 0;
00358     draw_required_ = false;
00359     subscribe();
00360     overlay_->show();
00361   }
00362 
00363   void Plotter2DDisplay::onDisable()
00364   {
00365     unsubscribe();
00366     overlay_->hide();
00367   }
00368 
00369   void Plotter2DDisplay::updateWidth()
00370   {
00371     boost::mutex::scoped_lock lock(mutex_);
00372     texture_width_ = width_property_->getInt();
00373   }
00374   
00375   void Plotter2DDisplay::updateHeight()
00376   {
00377     boost::mutex::scoped_lock lock(mutex_);
00378     texture_height_ = height_property_->getInt();
00379   }
00380   
00381   void Plotter2DDisplay::updateTop()
00382   {
00383     top_ = top_property_->getInt();
00384   }
00385   
00386   void Plotter2DDisplay::updateLeft()
00387   {
00388     left_ = left_property_->getInt();
00389   }
00390   
00391   void Plotter2DDisplay::updateBGColor()
00392   {
00393     bg_color_ = bg_color_property_->getColor();
00394   }
00395 
00396   void Plotter2DDisplay::updateFGColor()
00397   {
00398     fg_color_ = fg_color_property_->getColor();
00399   }
00400 
00401   void Plotter2DDisplay::updateFGAlpha()
00402   {
00403     fg_alpha_ = fg_alpha_property_->getFloat() * 255.0;
00404   }
00405 
00406   void Plotter2DDisplay::updateBGAlpha()
00407   {
00408     bg_alpha_ = bg_alpha_property_->getFloat() * 255.0;
00409   }
00410   
00411   void Plotter2DDisplay::updateTopic()
00412   {
00413     unsubscribe();
00414     subscribe();
00415   }
00416 
00417   void Plotter2DDisplay::updateShowBorder()
00418   {
00419     show_border_ = show_border_property_->getBool();
00420   }
00421   
00422   void Plotter2DDisplay::updateLineWidth()
00423   {
00424     line_width_ = line_width_property_->getInt();
00425   }
00426   
00427   void Plotter2DDisplay::updateBufferSize()
00428   {
00429     buffer_length_ = buffer_length_property_->getInt();
00430     initializeBuffer();
00431   }
00432 
00433   void Plotter2DDisplay::updateAutoColorChange()
00434   {
00435     auto_color_change_ = auto_color_change_property_->getBool();
00436   }
00437 
00438   void Plotter2DDisplay::updateMaxColor()
00439   {
00440     max_color_ = max_color_property_->getColor();
00441   }
00442   
00443   void Plotter2DDisplay::updateUpdateInterval()
00444   {
00445     update_interval_ = update_interval_property_->getFloat();
00446   }
00447 
00448   void Plotter2DDisplay::updateTextSize()
00449   {
00450     text_size_ = text_size_property_->getInt();
00451     QFont font;
00452     font.setPointSize(text_size_);
00453     caption_offset_ = QFontMetrics(font).height();
00454   }
00455   
00456   void Plotter2DDisplay::updateShowCaption()
00457   {
00458     show_caption_  = show_caption_property_->getBool();
00459   }
00460 
00461   void Plotter2DDisplay::updateMinValue()
00462   {
00463     if (!auto_scale_) {
00464       min_value_ = min_value_property_->getFloat();
00465     }
00466   }
00467 
00468   void Plotter2DDisplay::updateMaxValue()
00469   {
00470     if (!auto_scale_) {
00471       max_value_ = max_value_property_->getFloat();
00472     }
00473   }
00474 
00475   void Plotter2DDisplay::updateAutoScale()
00476   {
00477     auto_scale_ = auto_scale_property_->getBool();
00478     updateMinValue();
00479     updateMaxValue();
00480   }
00481   
00482 }
00483 
00484 #include <pluginlib/class_list_macros.h>
00485 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugin::Plotter2DDisplay, rviz::Display )


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Mon Oct 6 2014 01:18:44