ROS2 Foxy + Qt5 on Linux Platform

简介

本文章简单介绍了如何在Ubuntu 20.04上编译、运行ROS2 Foxy + Qt5。

可以将Qt5 cmake工程放到ROS2 workspace里,用colcon编译ROS2包 + Qt5 cmake工程;也可以从QtCreator打开ROS2包,用QtCreator编译ROS2包 + Qt5 cmake工程。

环境

平台:Ubuntu 20.04
ROS2版本:Foxy
Qt5版本:5.12.8
cmake版本:3.16.3
C编译器:GNU 9.3.0
CXX编译器:GNU 9.3.0
ament_cmake版本:0.9.8

colcon编译ROS2包 + Qt5 cmake工程

  1. 在ROS2 workspace里新建一个包,例如qt_example。
  2. 打开qtcreator,创建Qt5 cmake工程,工程保存在上一个步骤创建的qt_example里。
  3. 修改Qt5 cmake工程的目录结构,以适应qt_example包的目录结构,如下图所示:在这里插入图片描述
  4. 修改CMakeLists.txt和package.xml。CMakeLists.txt融合了qt_example包、Qt5的cmake要素(在本例中,qt_example包引用了我自己写的ROS2 algo包);package.xml声明了colcon编译工具需要知道的qt_example包的依赖。CMakeLists.txt和package.xml详见附录。
  5. 用"colcon build"命令编译ROS2 workspace。
  6. 新开一个终端,输入"source /path_to_your_ROS2_ws/install/local_setup.bash",再输入"ros2 run qt_example qt_example_node",即可运行Qt GUI。

附录

  1. CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(qt_example)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

# Note: Compilation flag -fPIC is necessary. Otherwise, you'll receive error "You must build your code with position independent code if Qt was built with -reduce-relocations."
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic -fPIC)
endif()

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(algo REQUIRED)
find_package(Qt5 COMPONENTS Widgets REQUIRED)

# Note that ament_target_dependencies() in algo cannot export Boost::thread to downstream. As a result, qt_example_node, as a downstream of libalgo.so, needs to explicitly find_package() for Boost again so that qt_example_node is able to link to Boost::thread.
find_package(Boost 1.71.0 REQUIRED COMPONENTS thread)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

include_directories(
	include
	${Qt5Widgets_INCLUDE_DIRS}
)

# Note: moc is not processing mainwindow.h (included by main.cpp and mainwindow.cpp unless it is in the same folder as the source files which included it). As a result, we need to explicitly call qt_wrap_cpp() on mainwindow.h (not on mainwindow.cpp) and then include the resulting file in the call to add_executable(). See link: https://stackoverflow.com/questions/19761767/qt-5-cmake-fails-with-undefined-reference-to-vtable-on-hello-world-with-inc-sr
qt5_wrap_cpp(header_SRC include/${PROJECT_NAME}/mainwindow.h)

add_executable(${PROJECT_NAME}_node
	src/main.cpp
	src/mainwindow.cpp
	src/mainwindow.ui
	${header_SRC}
)

# Note that ament_target_dependencies() in algo cannot export Boost::thread to downstream. As a result, qt_example_node, as a downstream of libalgo.so, needs to explicitly ament_target_dependencies() for Boost again so that qt_example_node is able to link to Boost::thread.
ament_target_dependencies(${PROJECT_NAME}_node rclcpp algo Boost)

target_link_libraries(${PROJECT_NAME}_node
	Qt5::Widgets
)

install(TARGETS ${PROJECT_NAME}_node
	DESTINATION lib/${PROJECT_NAME}
)

ament_package()
  1. package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>qt_example</name>
  <version>0.0.0</version>
  <description>This is a ROS2 demo package which demostrates how to build and run Qt5 package within ROS2 workspace. Qt5 project has been adjusted in compliance with ROS2 package layout. Run "colcon build" to build this package.</description>
  <maintainer email="maintainer@mailbox.com">feng_wang</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  
  <build_depend>algo</build_depend>
  <build_depend>Qt5</build_depend>
  
  <exec_depend>Qt5</exec_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>
  1. mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "algo/rc_interface/rc_interface.hpp"

QT_BEGIN_NAMESPACE
namespace Ui {
    class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
   
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_jog_start_clicked<
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值