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 "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
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
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
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
00227
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
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
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
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
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
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 )