ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Build RViz plugin from .ui file

asked 2016-08-16 09:30:16 -0600

user23fj239 gravatar image

updated 2016-08-19 01:41:00 -0600

My existing solution simply designs the GUI in qtcreator and then use the uic to generate the dotnect_window.h (link to plugin) which I might have to modify to derive from class ... : public rviz::Panel. How to automate this / do it all?

For example rqt_image_view already uses an .ui file, but it is rqt standalone. So I started with the RViz plugin teleop and added code from rqt_image_view . Maybe I could use the uncommented qt4/5_wrap_ui as a start? Just to give an idea:

cmake_minimum_required(VERSION 2.8.3)
project(rviz_dotnect_plugin)

# ros packages
find_package(catkin REQUIRED COMPONENTS
  rviz
)

catkin_package(
   # INCLUDE_DIRS
   # LIBRARIES ${PROJECT_NAME}
   CATKIN_DEPENDS rviz
   # DEPENDS
)
include_directories(
  ${catkin_INCLUDE_DIRS}
  include
)

link_directories(
  ${catkin_LIBRARY_DIRS}
)

# Bundle headers .h
set(HEADER_FILES
  include/drive_widget.h
  include/teleop_panel.h
)

# Automatically enable Qt's Meta-Object Compiler moc generation
set(CMAKE_AUTOMOC ON)

# Avoid keyword definition to avaid conflicts with boost or xapian etc
# e.g. http://muddyazian.blogspot.de/2012/04/getting-qt-app-working-with-boost-using.html
add_definitions(-DQT_NO_KEYWORDS)

# Use same QT version as rviz and specify headers run through MOC.
# MOC generated .cpp files are included automatically as headers.
if(rviz_QT_VERSION VERSION_LESS "5")
  message(STATUS "Using Qt4 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
  find_package(Qt4 ${rviz_QT_VERSION} EXACT REQUIRED QtCore QtGui)
  include(${QT_USE_FILE})
  qt4_wrap_cpp(HEADER_FILES_MOCS ${HEADER_FILES})
  #qt4_wrap_ui(rqt_image_view_UIS_H ${rqt_image_view_UIS})
else()
  message(STATUS "Using Qt5 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
  find_package(Qt5 ${rviz_QT_VERSION} EXACT REQUIRED Core Widgets)
  set(QT_LIBRARIES Qt5::Widgets)
  qt5_wrap_cpp(HEADER_FILES_MOCS ${HEADER_FILES})
  #qt5_wrap_ui(rqt_image_view_UIS_H ${rqt_image_view_UIS})
endif()

# Bundle source .cpp including the mocs
set(SOURCE_FILES
src/drive_widget.cpp
src/teleop_panel.cpp
${HEADER_FILES_MOCS}
)

# A rviz plugin is a shared library named ${PROJECT_NAME}.so
add_library(${PROJECT_NAME} ${SOURCE_FILES})

# Link executable with Qt libraries
target_link_libraries(${PROJECT_NAME}
  ${QT_LIBRARIES}
  ${catkin_LIBRARIES}
)

## Install rules...

I went on and generated the header from .ui via $ uic -o dotnect_window.h dotnect_window.ui. But uic deprecated the -i arg to generate the implementation file via uic -i PizzaEntry.h -o PizzaEntry.cpp pizza.ui. Argl.


Also the third step is nowhere to be found inside rqt_image_view.
I get confused with what is a rqt standalone and what I actually need to just get the rviz plugin asrviz::Panel building from .ui.

edit retag flag offensive close merge delete

Comments

You definitely shouldn't be doing the conversion from .ui files to C++ code manually; the build system should do that for you. I don't do much work with QT, but the qt4/5_wrap_ui rules look like the right place to start.

ahendrix gravatar image ahendrix  ( 2016-08-16 15:32:49 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
3

answered 2016-08-18 08:31:30 -0600

mgruhler gravatar image

updated 2016-08-19 02:10:26 -0600

Here a sample CMakeLists.txt which allowed us to create rviz panels, I'm not quite sure what you need to adapt, however, we had no manual copying to do. Seems like you are missing the MOC_FILES and the UIC_FILES at the add_library() call...

Note that this is Qt4 only, but I guess the Qt5 way should be pretty similar...

find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
include(${QT_USE_FILE})

add_definitions(-DQT_NO_KEYWORDS)

set(
  HEADER_FILES
  src/my_panel.h
)

# required if you want to add some images, etc. Could be made differently/nicer, probably.
file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resource/*.resource)

qt4_add_resources(
  QT_RESOURCES_CPP
  ${QT_RESOURCES}
)

qt4_wrap_cpp(
  MOC_FILES
  ${HEADER_FILES}
)

qt4_wrap_ui(
  UIC_FILES
  resource/my_panel.ui
)

set(
  SOURCE_FILES
  src/my_panel.cpp
)

add_library(my_panel ${SOURCE_FILES} ${QT_RESOURCES_CPP} ${MOC_FILES} ${UIC_FILES})

target_link_libraries(my_panell ${QT_LIBRARIES} ${catkin_LIBRARIES})

# maybe you also need a add_dependencies() call, we did not...

EDIT

Note that this is implemented as a QWidget. Some more templates:

Our header my_panel.h:

#include <ros/ros.h>
#include <rviz/panel.h>

namespace Ui
{
class MyPanelUi;
}

namespace my_panel
{

class MyPanel: public rviz::Panel
{
Q_OBJECT
public:
  MyPanel( QWidget* parent = 0 );

  ~MyPanel();

protected:
  ros::NodeHandle nh_;

  Ui::MyPanelUi *ui_;

private Q_SLOTS:
  // Q_SLOTS for interaction with buttons, etc.
  void gui_button_stop();

  // your custom stuff
}; // MyPanel

}  // my_panel

The my_panel.cpp

#include "my_panel.h"

#include "ui_my_panel.h"

#include <QMessageBox>

namespace my_panel
{

MyPanel::MyPanel( QWidget* parent )
  : rviz::Panel( parent )
  , ui_(new Ui::MyPanelUi())
{
  // set up the GUI
  ui_->setupUi(this);

  // connecting the signals to the respectiv SLOTs
  /*
   * Main Control Buttons *
   */
  // the button is called pushButton_stop in the ui file
  connect( ui_->pushButton_stop, SIGNAL( clicked() ), this, SLOT( gui_button_stop() ));
}
edit flag offensive delete link more

Comments

Great, extensive answer. I will try to port the code and will post the updates once I got first results.

user23fj239 gravatar image user23fj239  ( 2016-08-19 10:18:58 -0600 )edit

Thanks! This really helped.

demorise gravatar image demorise  ( 2022-04-14 09:44:59 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2016-08-16 09:30:16 -0600

Seen: 1,862 times

Last updated: Aug 19 '16