overlay_image_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 JSK Lab 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 "overlay_image_display.h"
00037 
00038 #include <OGRE/OgreOverlayManager.h>
00039 #include <OGRE/OgreMaterialManager.h>
00040 #include <OGRE/OgreTextureManager.h>
00041 #include <OGRE/OgreTexture.h>
00042 #include <OGRE/OgreHardwarePixelBuffer.h>
00043 #include <OGRE/OgreTechnique.h>
00044 
00045 #include <rviz/uniform_string_stream.h>
00046 #include <cv_bridge/cv_bridge.h>
00047 #include <sensor_msgs/image_encodings.h>
00048 
00049 namespace jsk_rviz_plugins
00050 {
00051 
00052   OverlayImageDisplay::OverlayImageDisplay()
00053     : Display(), width_(128), height_(128), left_(128), top_(128), alpha_(0.8),
00054       is_msg_available_(false), require_update_(false)
00055   {
00056     // setup properties
00057     update_topic_property_ = new rviz::RosTopicProperty(
00058       "Topic", "",
00059       ros::message_traits::datatype<sensor_msgs::Image>(),
00060       "sensor_msgs::Image topic to subscribe to.",
00061       this, SLOT( updateTopic() ));
00062     width_property_ = new rviz::IntProperty("width", 128,
00063                                             "width of the image window",
00064                                             this, SLOT(updateWidth()));
00065     height_property_ = new rviz::IntProperty("height", 128,
00066                                              "height of the image window",
00067                                              this, SLOT(updateHeight()));
00068     left_property_ = new rviz::IntProperty("left", 128,
00069                                            "left of the image window",
00070                                            this, SLOT(updateLeft()));
00071     top_property_ = new rviz::IntProperty("top", 128,
00072                                           "top of the image window",
00073                                           this, SLOT(updateTop()));
00074     alpha_property_ = new rviz::FloatProperty("alpha", 0.8,
00075                                               "alpha belnding value",
00076                                               this, SLOT(updateAlpha()));
00077   }
00078 
00079   OverlayImageDisplay::~OverlayImageDisplay()
00080   {
00081     delete update_topic_property_;
00082     delete width_property_;
00083     delete height_property_;
00084     delete left_property_;
00085     delete top_property_;
00086     delete alpha_property_;
00087   }
00088   
00089   void OverlayImageDisplay::onInitialize()
00090   {
00091     ros::NodeHandle nh;
00092     it_ = boost::shared_ptr<image_transport::ImageTransport>(new image_transport::ImageTransport(nh));
00093     
00094     updateWidth();
00095     updateHeight();
00096     updateTop();
00097     updateLeft();
00098     updateAlpha();
00099     updateTopic();
00100   }
00101   
00102   void OverlayImageDisplay::onEnable()
00103   {
00104     if (overlay_) {
00105       overlay_->show();
00106     }
00107     subscribe();
00108   }
00109   void OverlayImageDisplay::onDisable()
00110   {
00111     if (overlay_) {
00112       overlay_->hide();
00113     }
00114     unsubscribe();
00115   }
00116 
00117   void OverlayImageDisplay::unsubscribe()
00118   {
00119     sub_.shutdown();
00120     // clear clear clear...
00121   }
00122 
00123   void OverlayImageDisplay::subscribe()
00124   {
00125     std::string topic_name = update_topic_property_->getTopicStd();
00126     
00127     if (topic_name.length() > 0 && topic_name != "/") {
00128       sub_ = it_->subscribe(topic_name, 1, &OverlayImageDisplay::processMessage, this);
00129     }
00130   }
00131 
00132   void OverlayImageDisplay::processMessage(
00133     const sensor_msgs::Image::ConstPtr& msg)
00134   {
00135     boost::mutex::scoped_lock(mutex_);
00136     msg_ = msg;
00137     is_msg_available_ = true;
00138     require_update_ = true;
00139     if ((width_property_->getInt() < 0) || (height_property_->getInt() < 0)) {
00140       // automatically setup display size
00141       updateWidth();
00142       updateHeight();
00143     }
00144   }
00145   
00146 
00147   void OverlayImageDisplay::update(float wall_dt, float ros_dt)
00148   {
00149     boost::mutex::scoped_lock(mutex_);
00150 
00151     if (!isEnabled()) {
00152       return;
00153     }
00154     
00155     if (require_update_) {
00156       if (!overlay_) {
00157         static int count = 0;
00158         rviz::UniformStringStream ss;
00159         ss << "OverlayImageDisplayObject" << count++;
00160         overlay_.reset(new OverlayObject(ss.str()));
00161         overlay_->show();
00162       }
00163       overlay_->updateTextureSize(msg_->width, msg_->height);
00164       redraw();
00165       require_update_ = false;
00166     }
00167     if (overlay_) {
00168       overlay_->setDimensions(width_, height_);
00169       overlay_->setPosition(left_, top_);
00170     }
00171   }
00172 
00173   void OverlayImageDisplay::redraw()
00174   {
00175     cv_bridge::CvImagePtr cv_ptr;
00176     try
00177     {
00178       if (msg_->width == 0 || msg_->height == 0) {
00179         // image width/height and texture width/height should be same
00180         // but they are not when input image width/height is 0
00181         return;
00182       }
00183       else if (msg_->encoding == sensor_msgs::image_encodings::RGBA8 ||
00184           msg_->encoding == sensor_msgs::image_encodings::BGRA8) {
00185         cv_ptr = cv_bridge::toCvCopy(msg_, sensor_msgs::image_encodings::RGBA8);
00186         cv::Mat mat = cv_ptr->image;
00187         ScopedPixelBuffer buffer = overlay_->getBuffer();
00188         QImage Hud = buffer.getQImage(*overlay_);
00189         for (int i = 0; i < overlay_->getTextureWidth(); i++) {
00190           for (int j = 0; j < overlay_->getTextureHeight(); j++) {
00191             QColor color(mat.data[j * mat.step + i * mat.elemSize() + 0],
00192                          mat.data[j * mat.step + i * mat.elemSize() + 1],
00193                          mat.data[j * mat.step + i * mat.elemSize() + 2],
00194                          mat.data[j * mat.step + i * mat.elemSize() + 3]);
00195             Hud.setPixel(i, j, color.rgba());
00196           }
00197         }
00198       }
00199       else {
00200         cv_ptr = cv_bridge::toCvCopy(msg_, sensor_msgs::image_encodings::RGB8);
00201         cv::Mat mat = cv_ptr->image;
00202         ScopedPixelBuffer buffer = overlay_->getBuffer();
00203         QImage Hud = buffer.getQImage(*overlay_);
00204         for (int i = 0; i < overlay_->getTextureWidth(); i++) {
00205           for (int j = 0; j < overlay_->getTextureHeight(); j++) {
00206             QColor color(mat.data[j * mat.step + i * mat.elemSize() + 0],
00207                          mat.data[j * mat.step + i * mat.elemSize() + 1],
00208                          mat.data[j * mat.step + i * mat.elemSize() + 2],
00209                          alpha_ * 255.0);
00210             Hud.setPixel(i, j, color.rgba());
00211           }
00212         }
00213       }
00214     }
00215     catch (cv_bridge::Exception& e)
00216     {
00217       ROS_ERROR("cv_bridge exception: %s", e.what());
00218     }
00219   }
00220 
00221   void OverlayImageDisplay::updateTopic()
00222   {
00223     unsubscribe();
00224     subscribe();
00225   }
00226   
00227   void OverlayImageDisplay::updateWidth()
00228   {
00229     boost::mutex::scoped_lock lock(mutex_);
00230     int input_value = width_property_->getInt();
00231     if (input_value >= 0) {
00232       width_ = input_value;
00233     } else {
00234       if (is_msg_available_) {  // will automatically set width
00235         if (height_property_->getInt() == -1) {
00236           // same size as input image
00237           width_ = msg_->width;
00238           height_ = msg_->height;
00239         } else {
00240           // same scale as height
00241           float scale = (float)height_ / msg_->height;
00242           width_ = (int)(scale * msg_->width);
00243         }
00244       } else {
00245         width_ = 128;
00246       }
00247     }
00248   }
00249   
00250   void OverlayImageDisplay::updateHeight()
00251   {
00252     boost::mutex::scoped_lock lock(mutex_);
00253     int input_value = height_property_->getInt();
00254     if (input_value >= 0) {
00255       height_ = input_value;
00256     } else {
00257       if (is_msg_available_) {  // will automatically set height
00258         if (width_property_->getInt() == -1) {
00259           // same size as input image
00260           width_ = msg_->width;
00261           height_ = msg_->height;
00262         } else {
00263           // same scale as width
00264           float scale = (float)width_ / msg_->width;
00265           height_ = (int)(scale * msg_->height);
00266         }
00267       } else {
00268         height_ = 128;
00269       }
00270     }
00271   }
00272 
00273   void OverlayImageDisplay::updateTop()
00274   {
00275     boost::mutex::scoped_lock lock(mutex_);
00276     top_ = top_property_->getInt();
00277   }
00278 
00279   void OverlayImageDisplay::updateLeft()
00280   {
00281     boost::mutex::scoped_lock lock(mutex_);
00282     left_ = left_property_->getInt();
00283   }
00284   
00285   void OverlayImageDisplay::updateAlpha()
00286   {
00287     boost::mutex::scoped_lock lock(mutex_);
00288     alpha_ = alpha_property_->getFloat();
00289   }
00290   
00291 }
00292 
00293 #include <pluginlib/class_list_macros.h>
00294 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::OverlayImageDisplay, rviz::Display )


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Sun Sep 13 2015 22:29:03