$search
00001 /* 00002 * Copyright (c) 2009, Willow Garage, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of the Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include "image_display.h" 00031 #include "rviz/visualization_manager.h" 00032 #include "rviz/render_panel.h" 00033 #include "rviz/properties/property.h" 00034 #include "rviz/properties/property_manager.h" 00035 #include "rviz/window_manager_interface.h" 00036 #include "rviz/frame_manager.h" 00037 #include "rviz/validate_floats.h" 00038 00039 #include <tf/transform_listener.h> 00040 00041 #include <boost/bind.hpp> 00042 00043 #include <ogre_tools/axes.h> 00044 00045 #include <OGRE/OgreSceneNode.h> 00046 #include <OGRE/OgreSceneManager.h> 00047 #include <OGRE/OgreRectangle2D.h> 00048 #include <OGRE/OgreMaterialManager.h> 00049 #include <OGRE/OgreTextureManager.h> 00050 #include <OGRE/OgreViewport.h> 00051 #include <OGRE/OgreRenderWindow.h> 00052 #include <OGRE/OgreManualObject.h> 00053 #include <OGRE/OgreRoot.h> 00054 #include <OGRE/OgreRenderSystem.h> 00055 00056 #include <wx/frame.h> 00057 00058 namespace rviz 00059 { 00060 00061 ImageDisplay::ImageDisplay( const std::string& name, VisualizationManager* manager ) 00062 : Display( name, manager ) 00063 , transport_("raw") 00064 , texture_(update_nh_) 00065 , frame_(0) 00066 { 00067 { 00068 static uint32_t count = 0; 00069 std::stringstream ss; 00070 ss << "ImageDisplay" << count++; 00071 scene_manager_ = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, ss.str()); 00072 } 00073 00074 scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode(); 00075 00076 { 00077 static int count = 0; 00078 std::stringstream ss; 00079 ss << "ImageDisplayObject" << count++; 00080 00081 screen_rect_ = new Ogre::Rectangle2D(true); 00082 screen_rect_->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1); 00083 screen_rect_->setCorners(-1.0f, 1.0f, 1.0f, -1.0f); 00084 00085 ss << "Material"; 00086 material_ = Ogre::MaterialManager::getSingleton().create( ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); 00087 material_->setSceneBlending( Ogre::SBT_REPLACE ); 00088 material_->setDepthWriteEnabled(false); 00089 material_->setReceiveShadows(false); 00090 material_->setDepthCheckEnabled(false); 00091 00092 material_->getTechnique(0)->setLightingEnabled(false); 00093 Ogre::TextureUnitState* tu = material_->getTechnique(0)->getPass(0)->createTextureUnitState(); 00094 tu->setTextureName(texture_.getTexture()->getName()); 00095 tu->setTextureFiltering( Ogre::TFO_NONE ); 00096 00097 material_->setCullingMode(Ogre::CULL_NONE); 00098 Ogre::AxisAlignedBox aabInf; 00099 aabInf.setInfinite(); 00100 screen_rect_->setBoundingBox(aabInf); 00101 screen_rect_->setMaterial(material_->getName()); 00102 scene_node_->attachObject(screen_rect_); 00103 00104 } 00105 00106 wxWindow* parent = 0; 00107 00108 WindowManagerInterface* wm = vis_manager_->getWindowManager(); 00109 if (wm) 00110 { 00111 parent = wm->getParentWindow(); 00112 } 00113 else 00114 { 00115 frame_ = new wxFrame(0, wxID_ANY, wxString::FromAscii(name.c_str()), wxDefaultPosition, wxDefaultSize, wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxCAPTION | wxCLIP_CHILDREN); 00116 parent = frame_; 00117 } 00118 00119 render_panel_ = new RenderPanel(parent, false, this); 00120 render_panel_->SetSize(wxSize(640, 480)); 00121 if (wm) 00122 { 00123 wm->addPane(name, render_panel_); 00124 } 00125 00126 render_panel_->createRenderWindow(); 00127 00128 render_panel_->initialize(scene_manager_, vis_manager_); 00129 00130 render_panel_->setAutoRender(false); 00131 render_panel_->getViewport()->setOverlaysEnabled(false); 00132 render_panel_->getViewport()->setClearEveryFrame(true); 00133 render_panel_->getRenderWindow()->setActive(false); 00134 render_panel_->getRenderWindow()->setAutoUpdated(false); 00135 render_panel_->getCamera()->setNearClipDistance( 0.01f ); 00136 } 00137 00138 ImageDisplay::~ImageDisplay() 00139 { 00140 unsubscribe(); 00141 00142 if (frame_) 00143 { 00144 frame_->Destroy(); 00145 } 00146 else 00147 { 00148 WindowManagerInterface* wm = vis_manager_->getWindowManager(); 00149 wm->removePane(render_panel_); 00150 render_panel_->Destroy(); 00151 } 00152 00153 delete screen_rect_; 00154 00155 scene_node_->getParentSceneNode()->removeAndDestroyChild(scene_node_->getName()); 00156 } 00157 00158 void ImageDisplay::onEnable() 00159 { 00160 subscribe(); 00161 00162 if (frame_) 00163 { 00164 frame_->Show(true); 00165 } 00166 else 00167 { 00168 WindowManagerInterface* wm = vis_manager_->getWindowManager(); 00169 wm->showPane(render_panel_); 00170 } 00171 00172 render_panel_->getRenderWindow()->setActive(true); 00173 } 00174 00175 void ImageDisplay::onDisable() 00176 { 00177 render_panel_->getRenderWindow()->setActive(false); 00178 00179 if (frame_) 00180 { 00181 frame_->Show(false); 00182 } 00183 else 00184 { 00185 WindowManagerInterface* wm = vis_manager_->getWindowManager(); 00186 wm->closePane(render_panel_); 00187 } 00188 00189 unsubscribe(); 00190 00191 clear(); 00192 } 00193 00194 void ImageDisplay::subscribe() 00195 { 00196 if ( !isEnabled() ) 00197 { 00198 return; 00199 } 00200 00201 texture_.setTopic(topic_); 00202 } 00203 00204 void ImageDisplay::unsubscribe() 00205 { 00206 texture_.setTopic(""); 00207 } 00208 00209 void ImageDisplay::setTopic( const std::string& topic ) 00210 { 00211 unsubscribe(); 00212 00213 topic_ = topic; 00214 clear(); 00215 00216 subscribe(); 00217 00218 propertyChanged(topic_property_); 00219 } 00220 00221 void ImageDisplay::setTransport(const std::string& transport) 00222 { 00223 transport_ = transport; 00224 00225 texture_.setTransportType(transport); 00226 00227 propertyChanged(transport_property_); 00228 } 00229 00230 void ImageDisplay::clear() 00231 { 00232 texture_.clear(); 00233 00234 setStatus(status_levels::Warn, "Image", "No Image received"); 00235 00236 render_panel_->getCamera()->setPosition(Ogre::Vector3(999999, 999999, 999999)); 00237 } 00238 00239 void ImageDisplay::updateStatus() 00240 { 00241 if (texture_.getImageCount() == 0) 00242 { 00243 setStatus(status_levels::Warn, "Image", "No image received"); 00244 } 00245 else 00246 { 00247 std::stringstream ss; 00248 ss << texture_.getImageCount() << " images received"; 00249 setStatus(status_levels::Ok, "Image", ss.str()); 00250 } 00251 } 00252 00253 void ImageDisplay::update(float wall_dt, float ros_dt) 00254 { 00255 updateStatus(); 00256 00257 try 00258 { 00259 texture_.update(); 00260 00261 //make sure the aspect ratio of the image is preserved 00262 float win_width = render_panel_->getViewport()->getActualWidth(); 00263 float win_height = render_panel_->getViewport()->getActualHeight(); 00264 00265 float img_width = texture_.getWidth(); 00266 float img_height = texture_.getHeight(); 00267 00268 if ( img_width != 0 && img_height != 0 && win_width !=0 && win_height != 0 ) 00269 { 00270 float img_aspect = img_width / img_height; 00271 float win_aspect = win_width / win_height; 00272 00273 if ( img_aspect > win_aspect ) 00274 { 00275 screen_rect_->setCorners(-1.0f, 1.0f * win_aspect/img_aspect, 1.0f, -1.0f * win_aspect/img_aspect, false); 00276 } 00277 else 00278 { 00279 screen_rect_->setCorners(-1.0f * img_aspect/win_aspect, 1.0f, 1.0f * img_aspect/win_aspect, -1.0f, false); 00280 } 00281 } 00282 00283 render_panel_->getRenderWindow()->update(); 00284 } 00285 catch (UnsupportedImageEncoding& e) 00286 { 00287 setStatus(status_levels::Error, "Image", e.what()); 00288 } 00289 } 00290 00291 void ImageDisplay::onTransportEnumOptions(V_string& choices) 00292 { 00293 texture_.getAvailableTransportTypes(choices); 00294 } 00295 00296 void ImageDisplay::createProperties() 00297 { 00298 topic_property_ = property_manager_->createProperty<ROSTopicStringProperty>( "Image Topic", property_prefix_, boost::bind( &ImageDisplay::getTopic, this ), 00299 boost::bind( &ImageDisplay::setTopic, this, _1 ), parent_category_, this ); 00300 setPropertyHelpText(topic_property_, "sensor_msgs::Image topic to subscribe to."); 00301 ROSTopicStringPropertyPtr topic_prop = topic_property_.lock(); 00302 topic_prop->setMessageType(ros::message_traits::datatype<sensor_msgs::Image>()); 00303 00304 transport_property_ = property_manager_->createProperty<EditEnumProperty>("Transport Hint", property_prefix_, boost::bind(&ImageDisplay::getTransport, this), 00305 boost::bind(&ImageDisplay::setTransport, this, _1), parent_category_, this); 00306 EditEnumPropertyPtr ee_prop = transport_property_.lock(); 00307 ee_prop->setOptionCallback(boost::bind(&ImageDisplay::onTransportEnumOptions, this, _1)); 00308 } 00309 00310 void ImageDisplay::fixedFrameChanged() 00311 { 00312 } 00313 00314 void ImageDisplay::targetFrameChanged() 00315 { 00316 00317 } 00318 00319 void ImageDisplay::reset() 00320 { 00321 Display::reset(); 00322 00323 clear(); 00324 } 00325 00326 } // namespace rviz