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_image_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 <cv_bridge/cv_bridge.h>
00046 #include <sensor_msgs/image_encodings.h>
00047
00048 namespace jsk_rviz_plugins
00049 {
00050
00051 OverlayImageDisplay::OverlayImageDisplay()
00052 : Display(), width_(128), height_(128), left_(128), top_(128), alpha_(0.8),
00053 is_msg_available_(false), require_update_(false)
00054 {
00055
00056 update_topic_property_ = new rviz::RosTopicProperty(
00057 "Topic", "",
00058 ros::message_traits::datatype<sensor_msgs::Image>(),
00059 "sensor_msgs::Image topic to subscribe to.",
00060 this, SLOT( updateTopic() ));
00061 transport_hint_property_ = new ImageTransportHintsProperty("transport hint",
00062 "transport hint to subscribe topic",
00063 this, SLOT(updateTopic()));
00064 keep_aspect_ratio_property_ = new rviz::BoolProperty("keep aspect ratio", false,
00065 "keep aspect ratio of original image",
00066 this, SLOT(updateKeepAspectRatio()));
00067 width_property_ = new rviz::IntProperty("width", 128,
00068 "width of the image window",
00069 this, SLOT(updateWidth()));
00070 height_property_ = new rviz::IntProperty("height", 128,
00071 "height of the image window",
00072 this, SLOT(updateHeight()));
00073 left_property_ = new rviz::IntProperty("left", 128,
00074 "left of the image window",
00075 this, SLOT(updateLeft()));
00076 top_property_ = new rviz::IntProperty("top", 128,
00077 "top of the image window",
00078 this, SLOT(updateTop()));
00079 alpha_property_ = new rviz::FloatProperty("alpha", 0.8,
00080 "alpha belnding value",
00081 this, SLOT(updateAlpha()));
00082 }
00083
00084 OverlayImageDisplay::~OverlayImageDisplay()
00085 {
00086 delete update_topic_property_;
00087 delete transport_hint_property_;
00088 delete keep_aspect_ratio_property_;
00089 delete width_property_;
00090 delete height_property_;
00091 delete left_property_;
00092 delete top_property_;
00093 delete alpha_property_;
00094 }
00095
00096 void OverlayImageDisplay::onInitialize()
00097 {
00098 ros::NodeHandle nh;
00099 it_ = std::shared_ptr<image_transport::ImageTransport>(new image_transport::ImageTransport(nh));
00100
00101 updateWidth();
00102 updateHeight();
00103 updateKeepAspectRatio();
00104 updateTop();
00105 updateLeft();
00106 updateAlpha();
00107 updateTopic();
00108 }
00109
00110 void OverlayImageDisplay::onEnable()
00111 {
00112 if (overlay_) {
00113 overlay_->show();
00114 }
00115 subscribe();
00116 }
00117 void OverlayImageDisplay::onDisable()
00118 {
00119 if (overlay_) {
00120 overlay_->hide();
00121 }
00122 unsubscribe();
00123 }
00124
00125 void OverlayImageDisplay::unsubscribe()
00126 {
00127 sub_.shutdown();
00128
00129 }
00130
00131 void OverlayImageDisplay::subscribe()
00132 {
00133 if (isEnabled()) {
00134 std::string topic_name = update_topic_property_->getTopicStd();
00135
00136 if (topic_name.length() > 0 && topic_name != "/") {
00137 const image_transport::TransportHints transport_hint =
00138 transport_hint_property_->getTransportHints();
00139 sub_ = it_->subscribe(topic_name, 1, &OverlayImageDisplay::processMessage, this,
00140 transport_hint);
00141 }
00142 }
00143 }
00144
00145 void OverlayImageDisplay::processMessage(
00146 const sensor_msgs::Image::ConstPtr& msg)
00147 {
00148 boost::mutex::scoped_lock(mutex_);
00149 msg_ = msg;
00150 is_msg_available_ = true;
00151 require_update_ = true;
00152 if ((width_property_->getInt() < 0) || (height_property_->getInt() < 0) || keep_aspect_ratio_) {
00153
00154 updateWidth();
00155 updateHeight();
00156 }
00157 }
00158
00159
00160 void OverlayImageDisplay::update(float wall_dt, float ros_dt)
00161 {
00162 boost::mutex::scoped_lock(mutex_);
00163
00164 if (!isEnabled()) {
00165 return;
00166 }
00167
00168 if (require_update_ && is_msg_available_) {
00169 if (!overlay_) {
00170 static int count = 0;
00171 rviz::UniformStringStream ss;
00172 ss << "OverlayImageDisplayObject" << count++;
00173 overlay_.reset(new OverlayObject(ss.str()));
00174 overlay_->show();
00175 }
00176 overlay_->updateTextureSize(msg_->width, msg_->height);
00177
00178 height_property_->setHidden(keep_aspect_ratio_);
00179 setImageSize();
00180 redraw();
00181 require_update_ = false;
00182 }
00183 if (overlay_) {
00184 overlay_->setDimensions(width_, height_);
00185 overlay_->setPosition(left_, top_);
00186 }
00187 }
00188
00189 void OverlayImageDisplay::redraw()
00190 {
00191 try
00192 {
00193 if (msg_->width == 0 || msg_->height == 0) {
00194
00195
00196 return;
00197 }
00198 else {
00199 cv::Mat mat;
00200
00201 if (msg_->encoding == sensor_msgs::image_encodings::BGRA8 ||
00202 msg_->encoding == sensor_msgs::image_encodings::RGBA8) {
00203 const cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(
00204 msg_, sensor_msgs::image_encodings::BGRA8);
00205 cv_ptr->image.copyTo(mat);
00206 } else {
00207
00208 const cv_bridge::CvImagePtr cv_ptr =
00209 cv_bridge::toCvCopy(msg_, sensor_msgs::image_encodings::BGR8);
00210 const cv::Mat bgr_image = cv_ptr->image;
00211 std::vector<cv::Mat> channels;
00212
00213
00214 cv::split(bgr_image, channels);
00215
00216 const cv::Mat alpha(bgr_image.rows, bgr_image.cols, CV_8UC1,
00217 cv::Scalar(alpha_ * 255.0));
00218 channels.push_back(alpha);
00219 cv::merge(channels, mat);
00220 }
00221
00222 ScopedPixelBuffer buffer = overlay_->getBuffer();
00223 QImage Hud = buffer.getQImage(*overlay_);
00224
00225 memcpy(Hud.scanLine(0), mat.data, mat.cols * mat.rows * mat.elemSize());
00226 }
00227 }
00228 catch (cv_bridge::Exception& e)
00229 {
00230 ROS_ERROR("cv_bridge exception: %s", e.what());
00231 }
00232 }
00233
00234 void OverlayImageDisplay::updateTopic()
00235 {
00236 unsubscribe();
00237 subscribe();
00238 }
00239
00240 void OverlayImageDisplay::setImageSize()
00241 {
00242 if (width_ == -1) {
00243 if (is_msg_available_) {
00244 width_ = msg_->width;
00245 }
00246 else {
00247 width_ = 128;
00248 }
00249 }
00250
00251 if (height_ == -1) {
00252 if (is_msg_available_) {
00253 height_ = msg_->height;
00254 }
00255 else {
00256 height_ = 128;
00257 }
00258 }
00259
00260 if (keep_aspect_ratio_ && is_msg_available_) {
00261
00262 double aspect_ratio = msg_->height / (double)msg_->width;
00263 int height_from_width = std::ceil(width_ * aspect_ratio);
00264 height_ = height_from_width;
00265 }
00266
00267 }
00268
00269 void OverlayImageDisplay::updateWidth()
00270 {
00271 boost::mutex::scoped_lock lock(mutex_);
00272 width_ = width_property_->getInt();
00273 require_update_ = true;
00274 }
00275
00276 void OverlayImageDisplay::updateHeight()
00277 {
00278 boost::mutex::scoped_lock lock(mutex_);
00279 height_ = height_property_->getInt();
00280 require_update_ = true;
00281 }
00282
00283 void OverlayImageDisplay::updateTop()
00284 {
00285 boost::mutex::scoped_lock lock(mutex_);
00286 top_ = top_property_->getInt();
00287 }
00288
00289 void OverlayImageDisplay::updateLeft()
00290 {
00291 boost::mutex::scoped_lock lock(mutex_);
00292 left_ = left_property_->getInt();
00293 }
00294
00295 void OverlayImageDisplay::updateAlpha()
00296 {
00297 boost::mutex::scoped_lock lock(mutex_);
00298 alpha_ = alpha_property_->getFloat();
00299 }
00300
00301 void OverlayImageDisplay::updateKeepAspectRatio()
00302 {
00303 boost::mutex::scoped_lock lock(mutex_);
00304 keep_aspect_ratio_ = keep_aspect_ratio_property_->getBool();
00305 require_update_ = true;
00306 }
00307
00308 bool OverlayImageDisplay::isInRegion(int x, int y)
00309 {
00310 return (top_ < y && top_ + height_ > y &&
00311 left_ < x && left_ + width_ > x);
00312 }
00313
00314 void OverlayImageDisplay::movePosition(int x, int y)
00315 {
00316 top_ = y;
00317 left_ = x;
00318 }
00319
00320 void OverlayImageDisplay::setPosition(int x, int y)
00321 {
00322 top_property_->setValue(y);
00323 left_property_->setValue(x);
00324 }
00325
00326 }
00327
00328 #include <pluginlib/class_list_macros.h>
00329 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::OverlayImageDisplay, rviz::Display )