로봇 개발에서의 편의성을 위해 이런 저런 GUI 개발을 시도해 보고 있는데, FoxGlove, Flutter를 이용한 웹앱 등 여러 가지 툴을 써 봤지만 가장 대중적인 Qt는 안 써봐서 이참에 시도해 보는 글
1. Installation
# 필요한 qt 패키지
sudo apt-get update
sudo apt-get install qt5-default qtcreator
# UI를 시각적으로 디자인할 수 있는 도구
sudo apt-get install qttools5-dev-tool
qtcreator
2. Make project
# ROS 워크스페이스의 src 폴더에서
catkin_create_pkg qt_ros_app roscpp std_msgs
cd qt_ros_app
# filetree
qt_ros_app/
├── include/qt_ros_app/
│ └── mainwindow.h
├── src/
│ ├── main.cpp
│ └── mainwindow.cpp
└── CMakeLists.txt
그리고 내부의 CMakeLists.txt를 다음과 같이 수정해준다.
cmake_minimum_required(VERSION 3.0.2)
project(qt_ros_app)
# C++ 14 사용
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Qt 설정
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
find_package(Qt5 REQUIRED COMPONENTS
Core
Widgets
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp std_msgs
)
include_directories(
include
${catkin_INCLUDE_DIRS}
${Qt5Core_INCLUDE_DIRS}
${Qt5Widgets_INCLUDE_DIRS}
)
# 소스 파일 설정
set(qt_ros_app_node_SRCS
src/main.cpp
src/mainwindow.cpp
)
# 헤더 파일 설정
set(qt_ros_app_node_HDRS
include/${PROJECT_NAME}/mainwindow.h
)
# 실행 파일 생성
add_executable(${PROJECT_NAME}_node
${qt_ros_app_node_SRCS}
${qt_ros_app_node_HDRS}
)
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
Qt5::Core
Qt5::Widgets
)
include/qt_ros_app/mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <ros/ros.h>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
ros::NodeHandle nh_;
// ROS 구독자와 발행자를 여기에 선언할 예정
};
#endif
src/mainwindow.cpp
#include "qt_ros_app/mainwindow.h"
#include <QVBoxLayout>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 중앙 위젯 생성
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// 레이아웃 설정
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
// 레이블 추가
QLabel *label = new QLabel("ROS Qt Application", this);
layout->addWidget(label);
// 윈도우 크기 설정
resize(800, 600);
}
MainWindow::~MainWindow()
{
}
src/main.cpp
#include <QApplication>
#include "qt_ros_app/mainwindow.h"
#include <ros/ros.h>
int main(int argc, char *argv[])
{
// ROS 초기화
ros::init(argc, argv, "qt_ros_app");
// Qt 애플리케이션 생성
QApplication app(argc, argv);
// 메인 윈도우 생성 및 표시
MainWindow w;
w.show();
// Qt 이벤트 루프와 ROS 스핀을 함께 실행
while (ros::ok())
{
ros::spinOnce();
app.processEvents();
}
return app.exec();
}
3. Compile
catkin_make --pkg qt_ros_app
source devel/setup.bash
rosrun qt_ros_app qt_ros_app_node
그러면 이와 같은 GUI가 실행된다.
https://youtu.be/EpEoFR8ihcc?si=iREl1CtDpjLDhI_J
VIDEO
+ 덧
하루이틀 써보니까 느낀건데, 엄청 쉽고 편하긴 한데 Client 단에서 ROS 디펜던시를 없앨 수 없다는 점이 조금 아쉽다. Qt 자체는 ROS 디펜던시는 없는데, 어쨌든 (ROS 없는 Qt) + ROS 제어를 하려면 ROS 메시지, 서비스 등을 앱에다 전달해주는 애가 하나 더 붙어야 한다는 점. 만약에 ROS가 안 깔려있는 아무 컴퓨터에서나 해 볼 수 있으려면 역시 웹소켓 Rosbridge를 이용한 웹앱이 좋은 것 같다. 공수만 좀 덜 들이고 할 수 있으면 둘 다 개발해봐야지
(ROS 디펜던시 없음 + 웹브라우저에서 접속 가능함 + 데이터 트래픽 조절 가능)이라는 점에서 Flutter 웹앱이 사용성 면에서는 Qt 압승... but (그냥 ROS 깔려 있는 리눅스 컴터에서 돌릴 거임 + 항상 모니터가 있는 환경임 + 빨리 C++로 개발하고 싶음)일 경우에는 Qt가 더 적합한 선택