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/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
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
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
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
00180
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_) {
00235 if (height_property_->getInt() == -1) {
00236
00237 width_ = msg_->width;
00238 height_ = msg_->height;
00239 } else {
00240
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_) {
00258 if (width_property_->getInt() == -1) {
00259
00260 width_ = msg_->width;
00261 height_ = msg_->height;
00262 } else {
00263
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 )