Commits

John Hsu  committed 80a25e7 Merge

merging from default

  • Participants
  • Parent commits ad69a08, ba1993e
  • Branches set_joint_position

Comments (0)

Files changed (88)

File CMakeLists.txt

 
 set (GAZEBO_VERSION_NAME "lithium")
 set (GAZEBO_MAJOR_VERSION 1)
-set (GAZEBO_MINOR_VERSION 3)
-set (GAZEBO_PATCH_VERSION 1)
+set (GAZEBO_MINOR_VERSION 4)
+set (GAZEBO_PATCH_VERSION 0)
 
 set (GAZEBO_VERSION ${GAZEBO_MAJOR_VERSION}.${GAZEBO_MINOR_VERSION})
 set (GAZEBO_VERSION_FULL ${GAZEBO_MAJOR_VERSION}.${GAZEBO_MINOR_VERSION}.${GAZEBO_PATCH_VERSION})
 #####################################
 # Build type link flags
 set (CMAKE_LINK_FLAGS_RELEASE " " CACHE INTERNAL "Link flags fro release" FORCE)
+set (CMAKE_LINK_FLAGS_RELWITHDEBINFO " " CACHE INTERNAL "Link flags for release with debug support" FORCE)
 set (CMAKE_LINK_FLAGS_DEBUG " " CACHE INTERNAL "Link flags for debug" FORCE)
 set (CMAKE_LINK_FLAGS_PROFILE " -pg" CACHE INTERNAL "Link flags for profile" FORCE)
 set (CMAKE_LINK_FLAGS_CHECK " --coverage" CACHE INTERNAL "Link flags for static code checking" FORCE)
   message(STATUS "\nSSE4 disabled.\n")
 endif()
 
-set (CMAKE_C_FLAGS_RELEASE " -s -O2 -DNDEBUG ${CMAKE_C_FLAGS_ALL}" CACHE INTERNAL "C Flags for release" FORCE)
+set (CMAKE_C_FLAGS_RELEASE " -s -O3 -DNDEBUG ${CMAKE_C_FLAGS_ALL}" CACHE INTERNAL "C Flags for release" FORCE)
 set (CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
 
+set (CMAKE_C_FLAGS_RELWITHDEBINFO " -g -O2 ${CMAKE_C_FLAGS_ALL}" CACHE INTERNAL "C Flags for release with debug support" FORCE)
+set (CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO})
+
 set (CMAKE_C_FLAGS_DEBUG " -ggdb3 ${CMAKE_C_FLAGS_ALL}" CACHE INTERNAL "C Flags for debug" FORCE)
 set (CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
 
 #####################################
 # Set the default build type
 if (NOT CMAKE_BUILD_TYPE)
-  set (CMAKE_BUILD_TYPE "RELEASE" CACHE STRING 
-    "Choose the type of build, options are: debug release profile check" FORCE)
+  set (CMAKE_BUILD_TYPE "RELWITHDEBINFO" CACHE STRING 
+    "Choose the type of build, options are: debug release relwithdebinfo profile check" FORCE)
 endif (NOT CMAKE_BUILD_TYPE)
 string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
 
   set (BUILD_TYPE_RELEASE FALSE)
 endif()
 
+if ( "${CMAKE_BUILD_TYPE}" STREQUAL "RELWITHDEBINFO")
+  set (BUILD_TYPE_RELWITHDEBINFO TRUE)
+else()
+  set (BUILD_TYPE_RELWITHDEBINFO FALSE)
+endif()
+
 if ( "${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
   set (BUILD_TYPE_DEBUG TRUE)
 else()

File gazebo/CMakeLists.txt

 )
 
 include_directories(
-  ${PROJECT_SOURCE_DIR}/gazebo 
-  ${PROJECT_BINARY_DIR}/gazebo 
+  ${PROJECT_SOURCE_DIR}/gazebo
+  ${PROJECT_BINARY_DIR}/gazebo
 )
 
-link_directories(  
+link_directories(
   ${ogre_library_dirs}
-  ${Boost_LIBRARY_DIRS} 
+  ${Boost_LIBRARY_DIRS}
 )
 
+if(HAVE_URDFDOM_HEADERS)
+  link_directories(
+    ${urdfdom_LIBRARY_DIRS}
+    ${urdfdom_headers_LIBRARY_DIRS})
+endif(HAVE_URDFDOM_HEADERS)
+
+if(HAVE_CONSOLE_BRIDGE)
+  link_directories(
+    ${console_bridge_LIBRARY_DIRS})
+endif(HAVE_CONSOLE_BRIDGE)
+
 add_subdirectory(msgs)
 add_subdirectory(math)
 add_subdirectory(sdf)

File gazebo/Master.cc

 }
 
 //////////////////////////////////////////////////
-void Master::OnAccept(const transport::ConnectionPtr &new_connection)
+void Master::OnAccept(const transport::ConnectionPtr &_newConnection)
 {
   // Send the gazebo version string
   msgs::GzString versionMsg;
   versionMsg.set_data(std::string("gazebo ") + GAZEBO_VERSION_FULL);
-  new_connection->EnqueueMsg(msgs::Package("version_init", versionMsg), true);
+  _newConnection->EnqueueMsg(msgs::Package("version_init", versionMsg), true);
 
   // Send all the current topic namespaces
   msgs::GzString_V namespacesMsg;
   {
     namespacesMsg.add_data(*iter);
   }
-  new_connection->EnqueueMsg(msgs::Package("topic_namepaces_init",
+  _newConnection->EnqueueMsg(msgs::Package("topic_namepaces_init",
                               namespacesMsg), true);
 
   // Send all the publishers
     msgs::Publish *pub = publishersMsg.add_publisher();
     pub->CopyFrom(pubiter->first);
   }
-  new_connection->EnqueueMsg(
+  _newConnection->EnqueueMsg(
       msgs::Package("publishers_init", publishersMsg), true);
 
 
     boost::recursive_mutex::scoped_lock lock(*this->connectionMutex);
     int index = this->connections.size();
 
-    this->connections[index] = new_connection;
+    this->connections[index] = _newConnection;
 
     // Start reading from the connection
-    new_connection->AsyncRead(
+    _newConnection->AsyncRead(
         boost::bind(&Master::OnRead, this, index, _1));
   }
 }

File gazebo/common/Image.cc

 {
   FIBITMAP *tmp = FreeImage_ConvertTo24Bits(this->bitmap);
   this->GetDataImpl(_data, _count, tmp);
+  FreeImage_Unload(tmp);
 }
 
 //////////////////////////////////////////////////
 /////////////////////////////////////////////////
 Image::PixelFormat Image::ConvertPixelFormat(const std::string &_format)
 {
+  // Handle old format strings
+  if (_format == "L8" || _format == "L_INT8")
+    return L_INT8;
+  else if (_format == "R8G8B8" || _format == "RGB_INT8")
+    return RGB_INT8;
+
   for (unsigned int i = 0; i < PIXEL_FORMAT_COUNT; ++i)
     if (PixelFormatNames[i] == _format)
       return static_cast<PixelFormat>(i);

File gazebo/gui/Actions.cc

 QAction *gazebo::gui::g_fpsAct = 0;
 QAction *gazebo::gui::g_orbitAct = 0;
 
+QAction *gazebo::gui::g_topicVisAct = 0;
+
 gazebo::gui::DeleteAction *gazebo::gui::g_deleteAct = 0;

File gazebo/gui/Actions.hh

     extern QAction *g_translateAct;
     extern QAction *g_rotateAct;
 
+    extern QAction *g_topicVisAct;
+
     /// \class DeleteAction Actions.hh gui/gui.hh
     /// \brief Custom delete action.
     class DeleteAction : public QAction

File gazebo/gui/CMakeLists.txt

   ${Boost_LIBRARY_DIRS} 
 )
 
-add_definitions( ${QT_DEFINITIONS} )
+add_definitions(${QT_DEFINITIONS})
 
 add_subdirectory(qtpropertybrowser)
 
   ModelRightMenu.cc
   JointControlWidget.cc
   ToolsWidget.cc
+  TopicSelector.cc
+  viewers/ImageView.cc
+  viewers/TopicView.cc
+  viewers/TextView.cc
+  viewers/ViewFactory.cc
 )
 
 set (qt_headers
   ModelRightMenu.hh
   JointControlWidget.hh
   ToolsWidget.hh
+  TopicSelector.hh
+  viewers/ImageView.hh
+  viewers/TextView.hh
+  viewers/TopicView.hh
 )
 
 set (headers
   GuiEvents.hh
   LightMaker.hh
   qt.h
+  viewers/ViewFactory.hh
   )
 
 set (resources resources.qrc)

File gazebo/gui/GLWidget.cc

     {
       math::Pose pose, camPose;
       camPose = this->userCamera->GetWorldPose();
-      pose.pos = this->scene->GetFirstContact(this->userCamera,
-                                              this->mouseEvent.pos);
-      this->userCamera->SetFocalPoint(pose.pos);
+      if (this->scene->GetFirstContact(this->userCamera,
+                                   this->mouseEvent.pos, pose.pos))
+      {
+        this->userCamera->SetFocalPoint(pose.pos);
 
-      math::Vector3 dir = pose.pos - camPose.pos;
-      pose.pos = camPose.pos + (dir * 0.8);
+        math::Vector3 dir = pose.pos - camPose.pos;
+        pose.pos = camPose.pos + (dir * 0.8);
 
-      pose.rot = this->userCamera->GetWorldRotation();
-      this->userCamera->MoveToPosition(pose, 0.5);
+        pose.rot = this->userCamera->GetWorldRotation();
+        this->userCamera->MoveToPosition(pose, 0.5);
+      }
     }
     else
     {
     event::Events::setSelectedEntity(this->mouseMoveVis->GetName(), "move");
     QApplication::setOverrideCursor(Qt::ClosedHandCursor);
   }
+  else
+    this->userCamera->HandleMouseEvent(this->mouseEvent);
 }
 
 /////////////////////////////////////////////////
       QApplication::setOverrideCursor(Qt::OpenHandCursor);
     else
       QApplication::setOverrideCursor(Qt::ArrowCursor);
+    this->userCamera->HandleMouseEvent(this->mouseEvent);
   }
 }
 
     this->SetSelectedVisual(rendering::VisualPtr());
     event::Events::setSelectedEntity("", "normal");
   }
+
+  this->userCamera->HandleMouseEvent(this->mouseEvent);
 }
 
 //////////////////////////////////////////////////
   gui::set_active_camera(this->userCamera);
   this->scene = _scene;
 
-  this->userCamera->SetWorldPose(math::Pose(5, -5, 2, 0,
-                                            GZ_DTOR(11.31), GZ_DTOR(135)));
+  math::Vector3 camPos(5, -5, 2);
+  math::Vector3 lookAt(0, 0, 0);
+  math::Vector3 delta = lookAt - camPos;
+
+  double yaw = atan2(delta.y, delta.x);
+
+  double pitch = atan2(-delta.z, sqrt(delta.x*delta.x + delta.y*delta.y));
+  this->userCamera->SetWorldPose(math::Pose(camPos,
+        math::Vector3(0, pitch, yaw)));
 
   if (this->windowId >= 0)
   {

File gazebo/gui/GuiTypes.hh

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef _GUITYPES_HH_
+#define _GUITYPES_HH_
+
+#include <boost/shared_ptr.hpp>
+
+/// \file
+/// \ingroup gazebo_gui
+/// \brief default namespace for gazebo
+namespace gazebo
+{
+  /// \brief GUI forward declarations and type defines
+  namespace gui
+  {
+    class TopicView;
+    class ImageView;
+    class TextView;
+
+    /// \def TopicViewPtr
+    /// \brief Boost shared pointer to a TopicView object
+    typedef boost::shared_ptr<TopicView> TopicViewPtr;
+
+    /// \def ImageViewPtr
+    /// \brief Boost shared pointer to a ImageView object
+    typedef boost::shared_ptr<ImageView> ImageViewPtr;
+
+    /// \def TextViewPtr
+    /// \brief Boost shared pointer to a TextView object
+    typedef boost::shared_ptr<TextView> TextViewPtr;
+  }
+}
+
+#endif

File gazebo/gui/MainWindow.cc

  *
  */
 
-#include "gazebo.hh"
-#include "common/Console.hh"
-#include "common/Exception.hh"
-#include "common/Events.hh"
+#include "gazebo/gui/TopicSelector.hh"
+#include "gazebo/gui/viewers/ViewFactory.hh"
+#include "gazebo/gui/viewers/TopicView.hh"
+#include "gazebo/gui/viewers/ImageView.hh"
 
-#include "transport/Node.hh"
-#include "transport/Transport.hh"
+#include "gazebo/gazebo.hh"
+#include "gazebo/common/Console.hh"
+#include "gazebo/common/Exception.hh"
+#include "gazebo/common/Events.hh"
 
-#include "rendering/UserCamera.hh"
-#include "rendering/RenderEvents.hh"
+#include "gazebo/transport/Node.hh"
+#include "gazebo/transport/Transport.hh"
 
-#include "gui/Actions.hh"
-#include "gui/Gui.hh"
-#include "gui/InsertModelWidget.hh"
-#include "gui/SkyWidget.hh"
-#include "gui/ModelListWidget.hh"
-#include "gui/RenderWidget.hh"
-#include "gui/ToolsWidget.hh"
-#include "gui/GLWidget.hh"
-#include "gui/MainWindow.hh"
-#include "gui/GuiEvents.hh"
+#include "gazebo/rendering/UserCamera.hh"
+#include "gazebo/rendering/RenderEvents.hh"
+
+#include "gazebo/gui/Actions.hh"
+#include "gazebo/gui/Gui.hh"
+#include "gazebo/gui/InsertModelWidget.hh"
+#include "gazebo/gui/ModelListWidget.hh"
+#include "gazebo/gui/RenderWidget.hh"
+#include "gazebo/gui/ToolsWidget.hh"
+#include "gazebo/gui/GLWidget.hh"
+#include "gazebo/gui/MainWindow.hh"
+#include "gazebo/gui/GuiEvents.hh"
 
 using namespace gazebo;
 using namespace gui;
   this->connections.push_back(
      event::Events::ConnectSetSelectedEntity(
        boost::bind(&MainWindow::OnSetSelectedEntity, this, _1, _2)));
+
+  gui::ViewFactory::RegisterAll();
 }
 
 /////////////////////////////////////////////////
 }
 
 /////////////////////////////////////////////////
+void MainWindow::SelectTopic()
+{
+  TopicSelector *selector = new TopicSelector();
+  selector->exec();
+  std::string topic = selector->GetTopic();
+  std::string msgType = selector->GetMsgType();
+  delete selector;
+
+  if (!topic.empty())
+  {
+    TopicView *view = ViewFactory::NewView(msgType, topic, this);
+    if (view)
+      view->show();
+    else
+      gzerr << "Unable to create viewer for message type[" << msgType << "]\n";
+  }
+}
+
+/////////////////////////////////////////////////
 void MainWindow::Open()
 {
   std::string filename = QFileDialog::getOpenFileName(this,
 void MainWindow::Reset()
 {
   rendering::UserCameraPtr cam = gui::get_active_camera();
-  cam->SetWorldPose(math::Pose(5, -5, 2, 0, GZ_DTOR(11.31), GZ_DTOR(135)));
+
+  math::Vector3 camPos(5, -5, 2);
+  math::Vector3 lookAt(0, 0, 0);
+  math::Vector3 delta = camPos - lookAt;
+
+  double yaw = atan2(delta.x, delta.y);
+  double pitch = atan2(delta.z, sqrt(delta.x*delta.x + delta.y*delta.y));
+  cam->SetWorldPose(math::Pose(camPos, math::Vector3(0, pitch, yaw)));
 }
 
 /////////////////////////////////////////////////
   connect(g_newAct, SIGNAL(triggered()), this, SLOT(New()));
   */
 
+  g_topicVisAct = new QAction(tr("Topic Visualization"), this);
+  g_topicVisAct->setShortcut(tr("Ctrl+T"));
+  g_topicVisAct->setStatusTip(tr("Select a topic to visualize"));
+  connect(g_topicVisAct, SIGNAL(triggered()), this, SLOT(SelectTopic()));
+
   g_openAct = new QAction(tr("&Open World"), this);
   g_openAct->setShortcut(tr("Ctrl+O"));
   g_openAct->setStatusTip(tr("Open an world file"));
 
   this->setMenuWidget(frame);
 
-  this->fileMenu = this->menuBar->addMenu(tr("&File"));
-  // this->fileMenu->addAction(g_openAct);
-  // this->fileMenu->addAction(g_importAct);
-  // this->fileMenu->addAction(g_newAct);
-  this->fileMenu->addAction(g_saveAct);
-  this->fileMenu->addAction(g_saveAsAct);
-  this->fileMenu->addSeparator();
-  this->fileMenu->addAction(g_quitAct);
+  QMenu *fileMenu = this->menuBar->addMenu(tr("&File"));
+  // fileMenu->addAction(g_openAct);
+  // fileMenu->addAction(g_importAct);
+  // fileMenu->addAction(g_newAct);
+  fileMenu->addAction(g_saveAct);
+  fileMenu->addAction(g_saveAsAct);
+  fileMenu->addSeparator();
+  fileMenu->addAction(g_quitAct);
 
-  this->editMenu = this->menuBar->addMenu(tr("&Edit"));
-  this->editMenu->addAction(g_resetModelsAct);
-  this->editMenu->addAction(g_resetWorldAct);
+  QMenu *editMenu = this->menuBar->addMenu(tr("&Edit"));
+  editMenu->addAction(g_resetModelsAct);
+  editMenu->addAction(g_resetWorldAct);
 
-  this->viewMenu = this->menuBar->addMenu(tr("&View"));
-  this->viewMenu->addAction(g_showGridAct);
-  this->viewMenu->addSeparator();
+  QMenu *viewMenu = this->menuBar->addMenu(tr("&View"));
+  viewMenu->addAction(g_showGridAct);
+  viewMenu->addSeparator();
 
-  this->viewMenu->addAction(g_transparentAct);
-  this->viewMenu->addAction(g_showCollisionsAct);
-  this->viewMenu->addAction(g_showJointsAct);
-  this->viewMenu->addAction(g_showCOMAct);
-  this->viewMenu->addAction(g_showContactsAct);
-  this->viewMenu->addSeparator();
+  viewMenu->addAction(g_transparentAct);
+  viewMenu->addAction(g_showCollisionsAct);
+  viewMenu->addAction(g_showJointsAct);
+  viewMenu->addAction(g_showCOMAct);
+  viewMenu->addAction(g_showContactsAct);
+  viewMenu->addSeparator();
 
-  this->viewMenu->addAction(g_resetAct);
-  this->viewMenu->addAction(g_fullScreenAct);
-  this->viewMenu->addSeparator();
-  // this->viewMenu->addAction(g_fpsAct);
-  this->viewMenu->addAction(g_orbitAct);
+  viewMenu->addAction(g_resetAct);
+  viewMenu->addAction(g_fullScreenAct);
+  viewMenu->addSeparator();
+  // viewMenu->addAction(g_fpsAct);
+  viewMenu->addAction(g_orbitAct);
+
+  QMenu *windowMenu = this->menuBar->addMenu(tr("&Window"));
+  windowMenu->addAction(g_topicVisAct);
 
   this->menuBar->addSeparator();
 
-  this->helpMenu = this->menuBar->addMenu(tr("&Help"));
-  this->helpMenu->addAction(g_aboutAct);
+  QMenu *helpMenu = this->menuBar->addMenu(tr("&Help"));
+  helpMenu->addAction(g_aboutAct);
 }
 
 /////////////////////////////////////////////////

File gazebo/gui/MainWindow.hh

 
       private: void OnGUI(ConstGUIPtr &_msg);
 
+
       private slots: void ItemSelected(QTreeWidgetItem *, int);
       private slots: void New();
       private slots: void Open();
       private slots: void OnResetWorld();
       private slots: void SetTransparent();
 
+      /// \brief Callback when topic selection action.
+      private slots: void SelectTopic();
+
       private: void OnFullScreen(bool _value);
       private: void OnMoveMode(bool _mode);
 
                                         const std::string &_mode);
       private: void OnStats(ConstWorldStatisticsPtr &_msg);
 
-      private: QMenu *fileMenu;
-      private: QMenu *editMenu;
-      private: QMenu *viewMenu;
-      private: QMenu *helpMenu;
       private: QToolBar *playToolbar;
 
       private: RenderWidget *renderWidget;

File gazebo/gui/SkyWidget.cc

-/*
- * Copyright 2012 Open Source Robotics Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-#include "common/SystemPaths.hh"
-
-#include "gui/Gui.hh"
-#include "gui/GuiEvents.hh"
-
-#include "transport/Node.hh"
-#include "transport/Publisher.hh"
-
-#include "gui/SkyWidget.hh"
-
-using namespace gazebo;
-using namespace gui;
-
-/////////////////////////////////////////////////
-SkyWidget::SkyWidget(QWidget *_parent)
-: QWidget(_parent)
-{
-  this->setObjectName("sky");
-
-  QLabel *label;
-  QVBoxLayout *mainLayout = new QVBoxLayout;
-
-  QFrame *frame = new QFrame;
-  QVBoxLayout *frameLayout = new QVBoxLayout;
-
-
-  QHBoxLayout *timeLayout = new QHBoxLayout;
-  this->timeLineEdit = new QDoubleSpinBox;
-  this->timeLineEdit->setRange(0, 24);
-  this->timeLineEdit->setSingleStep(0.1);
-  this->timeLineEdit->setDecimals(2);
-  this->timeLineEdit->setValue(10.0);
-  label = new QLabel(tr("Time:"));
-  timeLayout->addWidget(label);
-  timeLayout->addWidget(this->timeLineEdit);
-  timeLayout->insertStretch(1, 0);
-
-
-  QHBoxLayout *sunriseLayout = new QHBoxLayout;
-  this->sunriseLineEdit = new QDoubleSpinBox;
-  this->sunriseLineEdit->setRange(0, 24);
-  this->sunriseLineEdit->setSingleStep(0.1);
-  this->sunriseLineEdit->setDecimals(2);
-  this->sunriseLineEdit->setValue(10.0);
-  label = new QLabel(tr("Sunrise:"));
-  sunriseLayout->addWidget(label);
-  sunriseLayout->addWidget(this->sunriseLineEdit);
-  sunriseLayout->insertStretch(1, 0);
-
-
-  QHBoxLayout *sunsetLayout = new QHBoxLayout;
-  this->sunsetLineEdit = new QDoubleSpinBox;
-  this->sunsetLineEdit->setRange(0, 24);
-  this->sunsetLineEdit->setSingleStep(0.1);
-  this->sunsetLineEdit->setDecimals(2);
-  this->sunsetLineEdit->setValue(10.0);
-  label = new QLabel(tr("Sunset:"));
-  sunsetLayout->addWidget(label);
-  sunsetLayout->addWidget(this->sunsetLineEdit);
-  sunsetLayout->insertStretch(1, 0);
-
-
-  // Clouds
-  // Wind Speed
-  QHBoxLayout *windSpeedLayout = new QHBoxLayout;
-  this->windSpeedLineEdit = new QDoubleSpinBox;
-  this->windSpeedLineEdit->setRange(0, 10);
-  this->windSpeedLineEdit->setSingleStep(0.1);
-  this->windSpeedLineEdit->setDecimals(2);
-  this->windSpeedLineEdit->setValue(10.0);
-  label = new QLabel(tr("Wind Speed:"));
-  windSpeedLayout->addWidget(label);
-  windSpeedLayout->addWidget(this->windSpeedLineEdit);
-  windSpeedLayout->insertStretch(1, 0);
-
-
-  // Direction
-  QHBoxLayout *windDirectionLayout = new QHBoxLayout;
-  this->windDirectionLineEdit = new QDoubleSpinBox;
-  this->windDirectionLineEdit->setRange(0, M_PI*2.0);
-  this->windDirectionLineEdit->setSingleStep(0.1);
-  this->windDirectionLineEdit->setDecimals(2);
-  this->windDirectionLineEdit->setValue(10.0);
-  label = new QLabel(tr("Wind Direction:"));
-  windDirectionLayout->addWidget(label);
-  windDirectionLayout->addWidget(this->windDirectionLineEdit);
-  windDirectionLayout->insertStretch(1, 0);
-
-  QHBoxLayout *cloudAmbientColorLayout = new QHBoxLayout;
-  this->cloudAmbientColorButton = new QPushButton;
-  label = new QLabel(tr("Color:"));
-  cloudAmbientColorLayout->addWidget(label);
-  cloudAmbientColorLayout->addWidget(this->cloudAmbientColorButton);
-  cloudAmbientColorLayout->insertStretch(1, 0);
-
-  QHBoxLayout *humidityLayout = new QHBoxLayout;
-  this->humidityLineEdit = new QDoubleSpinBox;
-  this->humidityLineEdit->setRange(0, 1);
-  this->humidityLineEdit->setSingleStep(0.1);
-  this->humidityLineEdit->setDecimals(2);
-  this->humidityLineEdit->setValue(10.0);
-  label = new QLabel(tr("Humidity:"));
-  humidityLayout->addWidget(label);
-  humidityLayout->addWidget(this->humidityLineEdit);
-  humidityLayout->insertStretch(1, 0);
-
-  QHBoxLayout *avgCloudSizeLayout = new QHBoxLayout;
-  this->avgCloudSizeLineEdit = new QDoubleSpinBox;
-  this->avgCloudSizeLineEdit->setRange(0, 1);
-  this->avgCloudSizeLineEdit->setSingleStep(0.1);
-  this->avgCloudSizeLineEdit->setDecimals(2);
-  this->avgCloudSizeLineEdit->setValue(10.0);
-  label = new QLabel(tr("Mean Cloud Size:"));
-  avgCloudSizeLayout->addWidget(label);
-  avgCloudSizeLayout->addWidget(this->avgCloudSizeLineEdit);
-  avgCloudSizeLayout->insertStretch(1, 0);
-
-  frameLayout->addLayout(timeLayout);
-  frameLayout->addLayout(sunriseLayout);
-  frameLayout->addLayout(sunsetLayout);
-  frameLayout->addLayout(windSpeedLayout);
-  frameLayout->addLayout(windDirectionLayout);
-  frameLayout->addLayout(cloudAmbientColorLayout);
-  frameLayout->addLayout(humidityLayout);
-  frameLayout->addLayout(avgCloudSizeLayout);
-
-  frameLayout->setContentsMargins(0, 0, 0, 0);
-  frame->setLayout(frameLayout);
-
-  mainLayout->addWidget(frame);
-  this->setLayout(mainLayout);
-  this->layout()->setContentsMargins(0, 0, 0, 0);
-
-  connect(this->timeLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnTime(double)));
-  connect(this->sunriseLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnSunrise(double)));
-  connect(this->sunsetLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnSunset(double)));
-  connect(this->windSpeedLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnWindSpeed(double)));
-  connect(this->windDirectionLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnWindDirection(double)));
-  connect(this->humidityLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnHumidity(double)));
-  connect(this->avgCloudSizeLineEdit, SIGNAL(valueChanged(double)),
-          this, SLOT(OnAvgCloudSize(double)));
-
-
-  this->node = transport::NodePtr(new transport::Node());
-  this->node->Init();
-  this->pub = this->node->Advertise<msgs::Sky>("~/sky");
-}
-
-/////////////////////////////////////////////////
-SkyWidget::~SkyWidget()
-{
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnTime(double _v)
-{
-  msgs::Sky msg;
-  msg.set_time(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnSunrise(double _v)
-{
-  msgs::Sky msg;
-  msg.set_sunrise(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnSunset(double _v)
-{
-  msgs::Sky msg;
-  msg.set_sunset(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnWindSpeed(double _v)
-{
-  msgs::Sky msg;
-  msg.set_wind_speed(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnWindDirection(double _v)
-{
-  msgs::Sky msg;
-  msg.set_wind_direction(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnHumidity(double _v)
-{
-  msgs::Sky msg;
-  msg.set_humidity(_v);
-  this->pub->Publish(msg);
-}
-
-/////////////////////////////////////////////////
-void SkyWidget::OnAvgCloudSize(double _v)
-{
-  msgs::Sky msg;
-  msg.set_mean_cloud_size(_v);
-  this->pub->Publish(msg);
-}

File gazebo/gui/SkyWidget.hh

-/*
- * Copyright 2012 Open Source Robotics Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-#ifndef _SKY_WIDGET_HH_
-#define _SKY_WIDGET_HH_
-
-#include "gui/qt.h"
-#include "gazebo/transport/TransportTypes.hh"
-
-class QPushButton;
-
-namespace gazebo
-{
-  namespace gui
-  {
-    class SkyWidget : public QWidget
-    {
-      Q_OBJECT
-
-      /// \brief Constructor
-      public: SkyWidget(QWidget *_parent = 0);
-
-      /// \brief Destructor
-      public: virtual ~SkyWidget();
-
-      private slots: void OnTime(double _v);
-      private slots: void OnSunrise(double _v);
-      private slots: void OnSunset(double _v);
-      private slots: void OnWindSpeed(double _v);
-      private slots: void OnWindDirection(double _v);
-      private slots: void OnHumidity(double _v);
-      private slots: void OnAvgCloudSize(double _v);
-
-      private: transport::NodePtr node;
-      private: transport::PublisherPtr pub;
-
-      private: QDoubleSpinBox *timeLineEdit;
-      private: QDoubleSpinBox *sunriseLineEdit;
-      private: QDoubleSpinBox *sunsetLineEdit;
-
-      private: QDoubleSpinBox *windSpeedLineEdit;
-      private: QDoubleSpinBox *windDirectionLineEdit;
-      private: QPushButton *cloudAmbientColorButton;
-      private: QDoubleSpinBox *humidityLineEdit;
-      private: QDoubleSpinBox *avgCloudSizeLineEdit;
-    };
-  }
-}
-#endif

File gazebo/gui/TopicSelector.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "gazebo/transport/transport.hh"
+
+#include "gazebo/common/Events.hh"
+#include "gazebo/gui/JointControlWidget.hh"
+#include "gazebo/gui/TopicSelector.hh"
+
+using namespace gazebo;
+using namespace gui;
+
+/////////////////////////////////////////////////
+TopicSelector::TopicSelector(QWidget *_parent)
+  : QDialog(_parent)
+{
+  // This name is used in the qt style sheet
+  this->setObjectName("topicSelector");
+  this->setWindowIcon(QIcon(":/images/gazebo.svg"));
+  this->setWindowTitle(tr("Gazebo: Topic Selector"));
+
+  // Create the main layout for this widget
+  QVBoxLayout *mainLayout = new QVBoxLayout;
+
+  this->treeWidget = new QTreeWidget();
+  this->treeWidget->setColumnCount(1);
+  this->treeWidget->header()->hide();
+  this->treeWidget->setMinimumSize(400, 400);
+  this->treeWidget->setFocusPolicy(Qt::NoFocus);
+  this->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  this->treeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
+  this->treeWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+  connect(this->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
+          this, SLOT(OnSelection(QTreeWidgetItem *, int)));
+
+  connect(this->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+          this, SLOT(OnDoubleClickSelection(QTreeWidgetItem *, int)));
+
+  this->GetTopicList();
+
+  QFrame *frame = new QFrame;
+  QVBoxLayout *frameLayout = new QVBoxLayout;
+
+  QLabel *topicLabel = new QLabel("Topics:");
+
+  frameLayout->addWidget(topicLabel);
+  frameLayout->addWidget(this->treeWidget);
+  frameLayout->setContentsMargins(4, 4, 4, 4);
+  frame->setLayout(frameLayout);
+
+  QHBoxLayout *buttonLayout = new QHBoxLayout;
+  QPushButton *cancelButton = new QPushButton("Cancel");
+  connect(cancelButton, SIGNAL(clicked()),
+          this, SLOT(OnCancel()));
+
+  this->okayButton = new QPushButton("Okay");
+  this->okayButton->setEnabled(false);
+  connect(this->okayButton, SIGNAL(clicked()),
+          this, SLOT(OnOkay()));
+
+  buttonLayout->addWidget(cancelButton);
+  buttonLayout->addStretch(2);
+  buttonLayout->addWidget(this->okayButton);
+
+  mainLayout->addWidget(frame);
+  mainLayout->addLayout(buttonLayout);
+
+  // Let the stylesheet handle the margin sizes
+  mainLayout->setContentsMargins(4, 4, 4, 4);
+
+  // Assign the mainlayout to this widget
+  this->setLayout(mainLayout);
+}
+
+/////////////////////////////////////////////////
+TopicSelector::~TopicSelector()
+{
+}
+
+/////////////////////////////////////////////////
+void TopicSelector::GetTopicList()
+{
+  std::map<std::string, std::list<std::string> > topics;
+  topics = transport::getAdvertisedTopics();
+
+  for (std::map<std::string, std::list<std::string> >::iterator
+       iter = topics.begin(); iter != topics.end(); ++iter)
+  {
+    QTreeWidgetItem *topItem = new QTreeWidgetItem(
+        static_cast<QTreeWidgetItem*>(0),
+        QStringList(QString::fromStdString(iter->first)));
+    this->treeWidget->addTopLevelItem(topItem);
+
+    std::list<std::string> added;
+
+    // Add all the topic names
+    for (std::list<std::string>::iterator topicIter = iter->second.begin();
+        topicIter != iter->second.end(); ++topicIter)
+    {
+      if ((*topicIter).find("__dbg") == std::string::npos &&
+          std::find(added.begin(), added.end(), *topicIter) == added.end())
+      {
+        QTreeWidgetItem *topicItem = new QTreeWidgetItem(topItem,
+            QStringList(QString::fromStdString(*topicIter)));
+        this->treeWidget->addTopLevelItem(topicItem);
+        added.push_back(*topicIter);
+      }
+    }
+
+    // Automatically expand the list of topics.
+    topItem->setExpanded(true);
+  }
+}
+
+/////////////////////////////////////////////////
+void TopicSelector::OnOkay()
+{
+  this->done(QDialog::Accepted);
+}
+
+/////////////////////////////////////////////////
+void TopicSelector::OnCancel()
+{
+  this->done(QDialog::Rejected);
+}
+
+/////////////////////////////////////////////////
+std::string TopicSelector::GetTopic() const
+{
+  return this->topicName;
+}
+
+/////////////////////////////////////////////////
+std::string TopicSelector::GetMsgType() const
+{
+  return this->msgType;
+}
+
+/////////////////////////////////////////////////
+void TopicSelector::OnSelection(QTreeWidgetItem *_item, int /*_column*/)
+{
+  if (_item->parent())
+  {
+    this->topicName = _item->text(0).toStdString();
+    this->msgType = _item->parent()->text(0).toStdString();
+    this->okayButton->setEnabled(true);
+  }
+  else
+  {
+    _item->setExpanded(!_item->isExpanded());
+    this->topicName.clear();
+    this->msgType.clear();
+    this->okayButton->setEnabled(false);
+  }
+}
+
+/////////////////////////////////////////////////
+void TopicSelector::OnDoubleClickSelection(QTreeWidgetItem *_item,
+                                           int /*_column*/)
+{
+  if (_item->parent())
+  {
+    this->topicName = _item->text(0).toStdString();
+    this->msgType = _item->parent()->text(0).toStdString();
+    this->OnOkay();
+  }
+  else
+  {
+    _item->setExpanded(!_item->isExpanded());
+    this->topicName.clear();
+    this->msgType.clear();
+    this->okayButton->setEnabled(false);
+  }
+}

File gazebo/gui/TopicSelector.hh

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef _TOPICSELECTOR_HH_
+#define _TOPICSELECTOR_HH_
+
+#include <string>
+
+#include "gazebo/gui/qt.h"
+
+namespace gazebo
+{
+  namespace gui
+  {
+    /// \addtogroup gazebo_gui
+    /// \{
+
+    /// \class TopicSelector TopicSelector.hh gui/TopicSelector.hh
+    /// \brief A widget that provides a list of topics to select from.
+    class TopicSelector : public QDialog
+    {
+      Q_OBJECT
+
+      /// \brief Constructor
+      /// \param[in] _parent Parent widget pointer.
+      public: TopicSelector(QWidget *_parent = 0);
+
+      /// \brief Destructor
+      public: virtual ~TopicSelector();
+
+      /// \brief Get the topic that was selected.
+      /// \return The selected topic, which can be an empty string if no
+      /// topic was selected.
+      public: std::string GetTopic() const;
+
+      /// \brief Get the message type that was selected.
+      /// \return The selected topic's published message type.
+      public: std::string GetMsgType() const;
+
+      /// \brief Utility function to get the list of topic names.
+      private: void GetTopicList();
+
+      /// \brief Callback when okay button is selected.
+      private slots: void OnOkay();
+
+      /// \brief Callback when cancel button is selected.
+      private slots: void OnCancel();
+
+      /// \brief Callback when an item is selected with a single mouse click.
+      /// \param[in] _item Pointer to the item selected.
+      /// \param[in] _column Column selected.
+      private slots: void OnSelection(QTreeWidgetItem *_item, int _column);
+
+      /// \brief Callback when an item is selected with a double mouse click.
+      /// \param[in] _item Pointer to the item selected.
+      /// \param[in] _column Column selected.
+      private slots: void OnDoubleClickSelection(QTreeWidgetItem *_item,
+                                                 int _column);
+
+      /// \brief The tree widget which holds all the topics.
+      private: QTreeWidget *treeWidget;
+
+      /// \brief Button used to finalize topic selection
+      private: QPushButton *okayButton;
+
+      /// \brief The name of the selected topic.
+      private: std::string topicName;
+
+      /// \brief The message type of the selected topic.
+      private: std::string msgType;
+    };
+    /// \}
+  }
+}
+#endif

File gazebo/gui/images/down_arrow.png

Added
New image

File gazebo/gui/images/no_image.png

Added
New image

File gazebo/gui/resources.qrc

   <file>images/translate.png</file>
   <file>images/rotate.png</file>
   <file>images/arrow.png</file>
+  <file>images/down_arrow.png</file>
   <file>images/box_selection.png</file>
   <file>images/redo.png</file>
   <file>images/rulers.png</file>
   <file>images/snap_to_grid.png</file>
   <file>images/undo.png</file>
+  <file>images/no_image.png</file>
   <file>images/copy_object.png</file>
   <file>images/paste_object.png</file>
   <file>images/rotate_object.png</file>

File gazebo/gui/style.qss

+QLabel
+{
+  color: #d0d0d0;
+}
+
+QWidget#topicSelector,
+QWidget#cameraSensor
+{
+  background-color: #303030;
+}
+
+QWidget#cameraSensor > QFrame
+{
+  background-color: #808080;
+}
+
+QWidget#cameraSensor > QLabel
+{
+  color: #d0d0d0;
+  background-color: #303030;
+}
+
+
 QMainWindow#mainWindow
 {
   margin: 0px;
   background-color: #454545;
 }
 
-QLabel
-{
-  color: #353535;
-}
-
 QListView
 {
   color: #d0d0d0;
   border: 2px inset #727272;
 }
 
+QPushButton:!enabled
+{
+  padding: 2px;
+  margin: 2px;
+  color: #909090;
+  border: 2px solid #707070;
+  background: #707070;
+  border-radius: 4px;
+}
+
 QScrollBar:vertical
 {
   border: 1px solid #808080;
 QWidget#toolsWidget
 {
   background: #808080;
+  color: #d0d0d0;
 }
 
 
   border-radius: 4px;
 }
 
+QListView
+{
+  border: 1px solid #000000;
+  border-radius: 4px;
+}
+
+QListView::item
+{
+  color: #ffffff;
+  border-radius: 4px;
+}
+
+/*
+QListWidget#topicTextList::item
+{
+  border-bottom: 1px solid black;
+  border-radius: 4px;
+  background-color: #404040;
+  margin: 4px;
+}
+*/
+
+QListWidget#topicTextList::item
+{
+  border-bottom: 1px solid black;
+  border-radius: 4px;
+  color: #101010;
+  background-color: #b0b0b0;
+  margin: 4px;
+}
+
+QComboBox QListView::item
+{
+  color: #f58113;
+  background: #ffffff;
+}
+
 QComboBox:on
-{ /* shift the text when the popup opens */
+{
+  /* shift the text when the popup opens */
   padding-top: -10px;
   padding-left: 4px;
 }
+
+/* This modifies the drop-down arrow container */
+QComboBox::drop-down
+{
+   subcontrol-origin: padding;
+   subcontrol-position: top right;
+   width: 15px;
+
+   border-left-width: 0px;
+   border-left-color: #000000;
+   border-left-style: solid; /* just a single line */
+   border-top-right-radius: 3px; /* same radius as the QComboBox */
+   border-bottom-right-radius: 3px;
+}
+
+QComboBox::down-arrow
+{
+  image: url(:/images/down_arrow.png);
+}
+
+QFrame#blackBorderFrame
+{
+  border: 1px solid #000000;
+  padding: 0px;
+  margin: 0px;
+}

File gazebo/gui/viewers/ImageView.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "gazebo/transport/Transport.hh"
+#include "gazebo/transport/Node.hh"
+#include "gazebo/transport/Publisher.hh"
+
+#include "gazebo/common/Image.hh"
+
+#include "gazebo/gui/viewers/ViewFactory.hh"
+#include "gazebo/gui/viewers/ImageView.hh"
+
+using namespace gazebo;
+using namespace gui;
+
+GZ_REGISTER_STATIC_VIEWER("gazebo.msgs.ImageStamped", ImageView)
+
+/////////////////////////////////////////////////
+ImageView::ImageView(QWidget *_parent)
+: TopicView(_parent, "gazebo.msgs.ImageStamped", "image")
+{
+  this->setWindowTitle(tr("Gazebo: Image View"));
+
+  // Create the image display
+  // {
+  QVBoxLayout *frameLayout = new QVBoxLayout;
+
+  this->pixmap = QPixmap(":/images/no_image.png");
+  QPixmap image = (this->pixmap.scaled(320, 240, Qt::KeepAspectRatio,
+                                 Qt::SmoothTransformation));
+  this->imageLabel = new QLabel();
+  this->imageLabel->setPixmap(image);
+  this->imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+  this->imageLabel->setMinimumSize(320, 240);
+  this->imageLabel->setScaledContents(true);
+
+  frameLayout->addWidget(this->imageLabel);
+  this->frame->setObjectName("blackBorderFrame");
+  this->frame->setLayout(frameLayout);
+  // }
+}
+
+/////////////////////////////////////////////////
+ImageView::~ImageView()
+{
+  this->sub.reset();
+}
+
+/////////////////////////////////////////////////
+void ImageView::UpdateImpl()
+{
+  // Update the image output
+  this->imageLabel->setPixmap(this->pixmap);
+}
+
+/////////////////////////////////////////////////
+void ImageView::SetTopic(const std::string &_topicName)
+{
+  TopicView::SetTopic(_topicName);
+
+  // Subscribe to the new topic.
+  this->sub.reset();
+  this->sub = this->node->Subscribe(_topicName, &ImageView::OnImage, this);
+}
+
+/////////////////////////////////////////////////
+void ImageView::OnImage(ConstImageStampedPtr &_msg)
+{
+  // Update the Hz and Bandwidth info
+  this->OnMsg(msgs::Convert(_msg->time()),
+      _msg->image().data().size());
+
+  unsigned char *rgbData = NULL;
+  unsigned int rgbDataSize = 0;
+
+  // Convert the image data to RGB
+  common::Image img;
+  img.SetFromData(
+      (unsigned char *)(_msg->image().data().c_str()),
+      _msg->image().width(),
+      _msg->image().height(),
+      (common::Image::PixelFormat)(_msg->image().pixel_format()));
+
+  img.GetRGBData(&rgbData, rgbDataSize);
+
+  // Get the image data in a QT friendly format
+  QImage image(_msg->image().width(), _msg->image().height(),
+               QImage::Format_RGB888);
+  // Store the image data
+  memcpy(image.bits(), rgbData, rgbDataSize);
+
+  // Set the pixmap used by the image label.
+  this->pixmap = QPixmap::fromImage(image);
+
+  delete [] rgbData;
+}

File gazebo/gui/viewers/ImageView.hh

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef _IMAGEVIEW_HH_
+#define _IMAGEVIEW_HH_
+
+#include <string>
+
+#include "gazebo/common/Time.hh"
+#include "gazebo/msgs/msgs.hh"
+
+#include "gazebo/transport/TransportTypes.hh"
+
+#include "gazebo/gui/qt.h"
+#include "gazebo/gui/viewers/TopicView.hh"
+
+namespace gazebo
+{
+  namespace gui
+  {
+    class ImageView : public TopicView
+    {
+      Q_OBJECT
+
+      /// \brief Constructor
+      /// \param[in] _parent Pointer to the parent widget.
+      public: ImageView(QWidget *_parent = NULL);
+
+      /// \brief Destructor
+      public: virtual ~ImageView();
+
+      // Documentation inherited
+      public: virtual void SetTopic(const std::string &_topicName);
+
+      // Documentation inherited
+      private: virtual void UpdateImpl();
+
+      /// \brief Receives incoming image messages.
+      /// \param[in] _msg New image message.
+      private: void OnImage(ConstImageStampedPtr &_msg);
+
+      /// \brief A label is used to display the image data.
+      private: QLabel *imageLabel;
+
+      /// \brief Storage mechansim for image data.
+      private: QPixmap pixmap;
+    };
+  }
+}
+#endif

File gazebo/gui/viewers/LaserView.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "gazebo/transport/Transport.hh"
+#include "gazebo/transport/Node.hh"
+#include "gazebo/transport/Publisher.hh"
+
+#include "gazebo/gui/viewers/ViewFactory.hh"
+#include "gazebo/gui/viewers/LaserView.hh"
+
+using namespace gazebo;
+using namespace gui;
+
+GZ_REGISTER_STATIC_VIEWER("gazebo.msgs.ImageStamped", LaserView)
+
+/////////////////////////////////////////////////
+LaserView::LaserView(QWidget *_parent)
+: TopicView(_parent, "gazebo.msgs.ImageStamped", "laser")
+{
+  this->setWindowTitle(tr("Gazebo: Laser View"));
+
+  // Create the image display
+  // {
+  QVBoxLayout *frameLayout = new QVBoxLayout;
+
+  this->pixmap = QPixmap(":/images/no_image.png");
+  QPixmap image = (this->pixmap.scaled(320, 240, Qt::KeepAspectRatio,
+                                 Qt::SmoothTransformation));
+  this->imageLabel = new QLabel();
+  this->imageLabel->setPixmap(image);
+  this->imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+  this->imageLabel->setMinimumSize(320, 240);
+  this->imageLabel->setScaledContents(true);
+
+  frameLayout->addWidget(this->imageLabel);
+  this->frame->setObjectName("blackBorderFrame");
+  this->frame->setLayout(frameLayout);
+  // }
+}
+
+/////////////////////////////////////////////////
+LaserView::~LaserView()
+{
+}
+
+/////////////////////////////////////////////////
+void LaserView::UpdateImpl()
+{
+}
+
+/////////////////////////////////////////////////
+void LaserView::SetTopic(const std::string &_topicName)
+{
+  TopicView::SetTopic(_topicName);
+
+  // Subscribe to the new topic.
+  this->sub.reset();
+  this->sub = this->node->Subscribe(_topicName, &LaserView::OnScan, this);
+}
+
+/////////////////////////////////////////////////
+void LaserView::OnScan(ConstLaserScanPtr &_msg)
+{
+  // Update the Hz and Bandwidth info
+  this->OnMsg(msgs::Convert(_msg->time()), _msg->ByteSize());
+}

File gazebo/gui/viewers/LaserView.hh

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef _LASERVIEW_HH_
+#define _LASERVIEW_HH_
+
+#include <string>
+
+#include "gazebo/common/Time.hh"
+#include "gazebo/msgs/msgs.hh"
+
+#include "gazebo/transport/TransportTypes.hh"
+
+#include "gazebo/gui/qt.h"
+#include "gazebo/gui/viewers/TopicView.hh"
+
+namespace gazebo
+{
+  namespace gui
+  {
+    class LaserView : public TopicView
+    {
+      Q_OBJECT
+
+      /// \brief Constructor
+      /// \param[in] _parent Pointer to the parent widget.
+      public: LaserView(QWidget *_parent);
+
+      /// \brief Destructor
+      public: virtual ~LaserView();
+
+      // Documentation inherited
+      public: virtual void SetTopic(const std::string &_topicName);
+
+      // Documentation inherited
+      private: virtual void UpdateImpl();
+
+      /// \brief Receives incoming laser scan messages.
+      /// \param[in] _msg New laser scan message.
+      private: void OnScan(ConstLaserScantampedPtr &_msg);
+    };
+  }
+}
+#endif

File gazebo/gui/viewers/TextView.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "gazebo/transport/Transport.hh"
+#include "gazebo/transport/Node.hh"
+#include "gazebo/transport/Publisher.hh"
+
+#include "gazebo/msgs/MsgFactory.hh"
+#include "gazebo/gui/viewers/TextView.hh"
+
+using namespace gazebo;
+using namespace gui;
+
+/////////////////////////////////////////////////
+TextView::TextView(QWidget *_parent, const std::string &_msgType)
+  : TopicView(_parent, _msgType, "text")
+{
+  this->setWindowTitle(tr("Gazebo: Text View"));
+
+  this->bufferSize = 10;
+  this->paused = false;
+
+  // Create the text list
+  // {
+  QVBoxLayout *frameLayout = new QVBoxLayout;
+
+  this->msgList = new QListWidget();
+  this->msgList->setVerticalScrollMode(
+      QAbstractItemView::ScrollPerPixel);
+  this->msgList->setObjectName("topicTextList");
+
+  QHBoxLayout *controlLayout = new QHBoxLayout;
+
+  QSpinBox *bufferSpin = new QSpinBox();
+  bufferSpin->setMinimum(1);
+  bufferSpin->setValue(this->bufferSize);
+  connect(bufferSpin, SIGNAL(valueChanged(int)), this, SLOT(OnBuffer(int)));
+
+  controlLayout->addWidget(new QLabel(tr("Buffer: ")));
+  controlLayout->addWidget(bufferSpin);
+
+  QCheckBox *pauseCheck = new QCheckBox();
+  pauseCheck->setChecked(this->paused);
+  connect(pauseCheck, SIGNAL(clicked(bool)), this, SLOT(OnPause(bool)));
+
+  controlLayout->addWidget(new QLabel(tr("Pause: ")));
+  controlLayout->addWidget(pauseCheck);
+  controlLayout->addStretch(1);
+
+  frameLayout->addWidget(this->msgList);
+  frameLayout->addLayout(controlLayout);
+
+  this->frame->setObjectName("blackBorderFrame");
+  this->frame->setLayout(frameLayout);
+  // }
+}
+
+/////////////////////////////////////////////////
+TextView::~TextView()
+{
+}
+
+/////////////////////////////////////////////////
+void TextView::UpdateImpl()
+{
+}
+
+/////////////////////////////////////////////////
+void TextView::SetTopic(const std::string &_topicName)
+{
+  TopicView::SetTopic(_topicName);
+
+  this->msg = msgs::MsgFactory::NewMsg(this->msgTypeName);
+
+  this->msgList->clear();
+
+  // Subscribe to the new topic if we have generated an appropriate message
+  if (this->msg)
+  {
+    this->sub.reset();
+    this->sub = this->node->Subscribe(_topicName, &TextView::OnText, this);
+  }
+  else
+  {
+    this->msgList->addItem(new QListWidgetItem(QString::fromStdString(
+          std::string("Unable to parse message of type[") +
+          this->msgTypeName + "]")));
+  }
+}
+
+/////////////////////////////////////////////////
+void TextView::OnText(const std::string &_msg)
+{
+  if (this->paused)
+    return;
+
+  // Update the Hz and Bandwidth info.
+  this->OnMsg(common::Time::GetWallTime(), _msg.size());
+
+  // Convert the raw data to a message.
+  this->msg->ParseFromString(_msg);
+
+  {
+    boost::mutex::scoped_lock lock(this->mutex);
+
+    // Create a new list item.
+    QListWidgetItem *item = new QListWidgetItem(
+        QString::fromStdString(msg->DebugString()));
+
+    // Add the new text to the output view.
+    this->msgList->addItem(item);
+
+    // Remove items if the list is too long.
+    while (this->msgList->count() > this->bufferSize)
+      delete this->msgList->takeItem(0);
+  }
+}
+
+/////////////////////////////////////////////////
+void TextView::OnPause(bool _value)
+{
+  boost::mutex::scoped_lock lock(this->mutex);
+  this->paused = _value;
+}
+
+/////////////////////////////////////////////////
+void TextView::OnBuffer(int _value)
+{
+  boost::mutex::scoped_lock lock(this->mutex);
+
+  this->bufferSize = _value;
+
+  // Remove and item if the list is too long.
+  while (this->msgList->count() > this->bufferSize)
+    delete this->msgList->takeItem(0);
+}

File gazebo/gui/viewers/TextView.hh

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef _TEXTVIEW_HH_
+#define _TEXTVIEW_HH_
+
+#include <string>
+#include <boost/thread/mutex.hpp>
+
+#include "gazebo/common/Time.hh"
+#include "gazebo/msgs/msgs.hh"
+
+#include "gazebo/transport/TransportTypes.hh"
+
+#include "gazebo/gui/qt.h"
+#include "gazebo/gui/viewers/TopicView.hh"
+
+namespace gazebo
+{
+  namespace gui
+  {
+    class TextView : public TopicView
+    {
+      Q_OBJECT
+
+      /// \brief Constructor
+      /// \param[in] _msgType Type of message to view.
+      public: TextView(QWidget *_parent, const std::string &_msgType);
+
+      /// \brief Destructor
+      public: virtual ~TextView();
+
+      // Documentation inherited
+      public: virtual void SetTopic(const std::string &_topicName);
+
+      // Documentation inherited
+      private: virtual void UpdateImpl();
+
+      /// \brief Receives incoming text messages.
+      /// \param[in] _msg New text message.
+      private: void OnText(const std::string &_msg);
+
+      /// \brief QT callback when the buffer spin box has been changed.
+      /// \param[in] _value New value of the spin box.
+      private slots: void OnBuffer(int _value);
+
+      /// \brief QT callback when the pause check box has been changed.
+      /// \param[in] _value New value of the check box.
+      private slots: void OnPause(bool _value);
+
+      /// \brief A scolling list of text data.
+      private: QListWidget *msgList;
+
+      /// \brief Size of the text buffer. The size is the number of
+      /// messages.
+      private: int bufferSize;
+
+      /// \brief The protobuf message used to decode incoming message data.
+      private: boost::shared_ptr<google::protobuf::Message> msg;
+
+      /// \brief Mutex to protec message buffer.
+      private: boost::mutex mutex;
+
+      /// \brief Flag used to pause message parsing.
+      private: bool paused;
+    };
+  }
+}
+#endif

File gazebo/gui/viewers/TopicView.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "gazebo/gui/Gui.hh"
+#include "gazebo/gui/GuiEvents.hh"
+
+#include "gazebo/transport/Transport.hh"
+#include "gazebo/transport/Node.hh"
+#include "gazebo/transport/Publisher.hh"
+
+#include "gazebo/gui/viewers/TopicView.hh"
+
+using namespace gazebo;
+using namespace gui;
+
+/////////////////////////////////////////////////
+TopicView::TopicView(QWidget *_parent, const std::string &_msgTypeName,
+                     const std::string &_viewType)
+: QDialog(_parent), msgTypeName(_msgTypeName)
+{
+  this->node = transport::NodePtr(new transport::Node());
+  this->node->Init();
+
+  this->setWindowIcon(QIcon(":/images/gazebo.svg"));
+  this->setWindowTitle(tr("Gazebo: Topic View"));
+  this->setObjectName("cameraSensor");
+
+  // Create the topic label and combo box
+  // {
+  QHBoxLayout *topicLayout = new QHBoxLayout;
+  QLabel *topicLabel = new QLabel(tr("Topic: "));
+  this->topicCombo = new TopicCombo(this, this->msgTypeName,
+      _viewType, this->node);
+  this->topicCombo->setObjectName("comboList");
+  this->topicCombo->setMinimumSize(300, 25);
+
+  topicLayout->addSpacing(10);
+  topicLayout->addWidget(topicLabel);
+  topicLayout->addWidget(this->topicCombo);
+  topicLayout->addSpacing(10);
+  topicLayout->addStretch(4);
+  // }
+
+  // Create the Hz and bandwidth labels
+  // {
+  QHBoxLayout *infoLayout = new QHBoxLayout;
+  QLabel *hzLabel = new QLabel("Hz: ");
+  this->hzEdit = new QLineEdit;
+  this->hzEdit->setReadOnly(true);
+  this->hzEdit->setFixedWidth(80);
+
+  QLabel *bandwidthLabel = new QLabel("Bandwidth: ");
+  this->bandwidthEdit = new QLineEdit;
+  this->bandwidthEdit->setReadOnly(true);
+  this->bandwidthEdit->setFixedWidth(110);
+
+  infoLayout->addSpacing(10);
+  infoLayout->addWidget(hzLabel);
+  infoLayout->addWidget(this->hzEdit);
+  infoLayout->addSpacing(4);
+  infoLayout->addStretch(1);
+  infoLayout->addWidget(bandwidthLabel);
+  infoLayout->addWidget(this->bandwidthEdit);
+  infoLayout->addStretch(4);
+  // }
+
+  // Create the frame used to display information
+  this->frame = new QFrame;
+
+  QVBoxLayout *mainLayout = new QVBoxLayout;
+  mainLayout->addLayout(topicLayout);
+  mainLayout->addLayout(infoLayout);
+  mainLayout->addWidget(frame);
+  this->setLayout(mainLayout);
+  this->layout()->setContentsMargins(8, 8, 8, 10);
+
+  this->setSizeGripEnabled(true);
+  QTimer::singleShot(500, this, SLOT(Update()));
+}
+
+/////////////////////////////////////////////////
+TopicView::~TopicView()
+{
+  delete this->topicCombo;
+}
+
+/////////////////////////////////////////////////
+void TopicView::Update()
+{
+  // Update the child class.
+  this->UpdateImpl();
+
+  // Update the Hz output
+  {
+    std::ostringstream stream;
+    stream << std::fixed << std::setprecision(2) << this->hz;
+    this->hzEdit->setText(tr(stream.str().c_str()));
+  }
+
+  // Update the Bandwidth output
+  {
+    std::ostringstream stream;
+
+    // Sum up the byte information
+    int sumBytes = 0;
+    for (std::list<int>::iterator iter = this->msgSizes.begin();
+        iter != this->msgSizes.end(); ++iter)
+    {
+      sumBytes += *iter;
+    }
+
+    // Compute the bandwidth
+    common::Time dt = this->times.back() - this->times.front();
+    double bandwidth = 0;
+
+    if (dt != common::Time(0, 0))
+      bandwidth = sumBytes / dt.Double();
+
+    // Format the bandwidth output
+    stream << std::fixed << std::setprecision(2);
+
+    if (bandwidth < 1000)
+      stream << bandwidth << " B/s";
+    else if (bandwidth < 1000000)
+      stream << bandwidth / 1024.0f << " KB/s";
+    else
+      stream << bandwidth/1.049e6 << " MB/s";
+
+    this->bandwidthEdit->setText(tr(stream.str().c_str()));
+  }
+
+  // Set the timer to update again.
+  QTimer::singleShot(500, this, SLOT(Update()));
+}