一、配置QT中的ROS环境
参考下面文章
x86架构与ARM架构(AGX、TX2、NX等)下配置带ROS插件的QtCreator(Qt+ROS+ubuntu18)(源码编译安装方式)_带插件的qtcreator_灰灰子衿的博客-CSDN博客
二、在QT中添加简单的ROS项目
1.添加工作空间
点击【New Project】添加工作空间,选择【其他项目】,选中【ROS Workspace】选项,点击【Choose...】按钮。
输入【Name】工作空间名称,选择【Workspace Path】工作空间地址 ,【Distribution】默认为melodic,【Build System】默认为CatkinMake,点击【下一步】按钮。
点击【完成】按钮即完成工作空间的添加。
此时生成下面工作控件目录。
如果没有出现src目录,点击【过滤器树形视图】(即下面按钮),将菜单里的勾选框全部取消选中。
2.添加包
选中【src】目录,右击鼠标,点击【添加新文件...】 。
弹出下面弹窗,选择【ROS】下面的【Package】,点击【Choose...】按钮 。
填写【Name】名称,和【Catkin】依赖,点击【下一步】按钮。
点击【完成】按钮。
此时目录结构如下
3. 添加节点
选中已添加包下面的src,右击鼠标出现菜单,选中【添加新文件...】 。
选择【Ros】下的【Basic Node】,点击【Choose...】按钮。
输入【名称】信息,点击【下一步】按钮。
点击【完成】按钮。
生成以下目录。
生成代码如下。
4.修改CMakeLists.txt文件
#指定项目所需的最低 CMake 版本。
cmake_minimum_required(VERSION 3.0.2)
#定义项目的名称
project(marker)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
#查找并导入外部依赖库。
find_package(catkin REQUIRED COMPONENTS
roscpp
)
#这用于指定包的依赖关系,由依赖于这个包的其他软件包使用。
catkin_package(
#包的导出包含路径
INCLUDE_DIRS include
#从项目中导出的库
# LIBRARIES marker
#本项目依赖的其他catkin项目
# CATKIN_DEPENDS roscpp
#此项目所依赖的非 catkin CMake 项目
DEPENDS system_lib
)
#添加头文件搜索路径,编译器使用这些目录来查找头文件,第一个参数“include”表示包中的include/目录也是路径的一部分。
include_directories(
include
${catkin_INCLUDE_DIRS}
)
#指定将要构建的可执行文件的名称,以及它所依赖的源文件
add_executable(${PROJECT_NAME}_node src/marker_test.cpp)
#设置可执行文件依赖的库。
target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})
5.构建
点击左侧工具栏中的【项目】,选中【Build】,选择【Build System】为【CatkinMake】,默认即为该选项。
点击QT界面上的构建图标,或者键盘Ctrl+B,进行构建。
6.运行(方法1)
点击左侧工具栏中的【项目】,选中【Run】,点击【Add Run Step】,选择【Ros Run Step】。
出现下面界面。
选择【Package】中刚刚创建的功能包,我的包名为marker。
选择【Target】可执行文件名,在CMakeLists.txt中add_executable(${PROJECT_NAME}_node src/marker_test.cpp)语句中设置的可执行文件名称为marker_node。
点击【运行】按钮即可运行。
查看终端
7.运行(方法2)
打开终端,到创建的工作空间根目录下
设置项目环境
执行运行命令
rosrun 包名称 执行文件名称
参考下面文章
Qt+ROS+ubuntu18.04配置教程(带界面)_qt ros_灰灰子衿的博客-CSDN博客
三、在QT中添加RVIZ消息推送
8.添加界面
在上述操作步骤下,继续有机包下面的【src】,点击【添加新文件...】。
选择【Qt】下的【Qt设计师界面类】,点击【Choose...】按钮。
选择【Widget】,点击【下一步】按钮。
输入【类名】,点击【下一步】按钮。
点击【完成】按钮。
此时目录结构如下:
9.添加消息推送代码(以Marker消息类型为例)
修改marker_test.cpp文件
#include <ros/ros.h>
#include <QApplication>
#include "basic.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "marker_test");
ros::NodeHandle nh;
QApplication a(argc,argv);
Basic w;
w.show();
return a.exec();
//ROS_INFO("Hello world!");
}
添加basic.ui界面
修改basic.h
#ifndef BASIC_H
#define BASIC_H
#include <QWidget>
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
namespace Ui {
class Basic;
}
class MyPublisher;
struct MarkerMsg
{
QString ns;
int id;
uint32_t shape;
float pos_x;
float pos_y;
float pos_z;
float orientation_x;
float orientation_y;
float orientation_z;
float orientation_w;
float scale_x;
float scale_y;
float scale_z;
float color_r;
float color_g;
float color_b;
float color_a;
};
class Basic : public QWidget
{
Q_OBJECT
public:
explicit Basic(QWidget *parent = 0);
~Basic();
private slots:
void on_pushButton_clicked();
signals:
void sigToStart();
private:
Ui::Basic *ui;
QThread *thread;
MyPublisher *myPublisher;
};
class MyPublisher : public QObject
{
Q_OBJECT
public:
MyPublisher(QObject *parent = nullptr);
~MyPublisher();
void setMarkerMsg(MarkerMsg msg){marker_msg = msg;}
public slots:
void publishMsg();
private:
MarkerMsg marker_msg;
};
#endif // BASIC_H
修改basic.cpp
#include "basic.h"
#include "ui_basic.h"
#include <QDebug>
#include <QThread>
Basic::Basic(QWidget *parent) :
QWidget(parent),
ui(new Ui::Basic)
{
ui->setupUi(this);
myPublisher = new MyPublisher;
thread = new QThread;
connect(this,&Basic::sigToStart,myPublisher,&MyPublisher::publishMsg);
myPublisher->moveToThread(thread);
thread->start();
on_pushButton_clicked();
emit sigToStart();
}
Basic::~Basic()
{
delete ui;
}
void Basic::on_shape_valueChanged(int arg1)
{
if(arg1 == 0)
ui->label_shape->setText("ARROW");
else if(arg1 == 1)
ui->label_shape->setText("CUBE");
else if(arg1 == 2)
ui->label_shape->setText("SPHERE");
else if(arg1 == 3)
ui->label_shape->setText("CYLINDER");
}
void Basic::on_pushButton_clicked()
{
MarkerMsg msg;
msg.ns = ui->ns->text();
msg.id = ui->id->text().toInt();
msg.shape = ui->shape->value();
msg.pos_x = ui->pos_x->text().toFloat();
msg.pos_y = ui->pos_y->text().toFloat();
msg.pos_z = ui->pos_z->text().toFloat();
msg.orientation_x = ui->orientstion_x->text().toFloat();
msg.orientation_y = ui->orientstion_y->text().toFloat();
msg.orientation_z = ui->orientstion_z->text().toFloat();
msg.orientation_w = ui->orientstion_w->text().toFloat();
msg.scale_x = ui->scale_x->text().toFloat();
msg.scale_y = ui->scale_y->text().toFloat();
msg.scale_z = ui->scale_z->text().toFloat();
msg.color_r = ui->color_r->text().toFloat();
msg.color_g = ui->color_g->text().toFloat();
msg.color_b = ui->color_b->text().toFloat();
msg.color_a = ui->color_a->text().toFloat();
myPublisher->setMarkerMsg(msg);
}
MyPublisher::MyPublisher(QObject *parent)
{
}
MyPublisher::~MyPublisher()
{
}
void MyPublisher::publishMsg()
{
//初始化ROS,并在visualization_marker主题上创建一个ros::Publisher。
ros::NodeHandle n;
//用于设置循环频率,适用于Publisher程序无限循环 ros::Rate对象可以允许你指定自循环的频率
ros::Rate r(1);
ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);
//uint32_t shape = visualization_msgs::Marker::CUBE;
while (ros::ok())
{
visualization_msgs::Marker marker;
marker.header.frame_id = "basic";
marker.header.stamp = ros::Time::now();
//命名空间 (ns) 和 id 用于为此标记创建唯一名称。如果收到具有相同 ns 和 id 的标记消息,则新标记将替换旧标记。
marker.ns = marker_msg.ns.toStdString();
marker.id = marker_msg.id;
marker.type = marker_msg.shape;
//action 字段指定如何处理标记。选项是visualization_msgs::Marker::ADD 和visualization_msgs::Marker::DELETE。
//ADD 有点用词不当,它的真正意思是“创建或修改”。
marker.action = visualization_msgs::Marker::ADD;
//设置了marker的位姿。 geometry_msgs/Pose 消息由一个 geometry_msgs/Vector3 来指定位置和一个 geometry_msgs/Quaternion 来指定方向。
//这里将位置设置为原点,将方向设置为恒等方向(注意 w 的 1.0)。
marker.pose.position.x = marker_msg.pos_x;
marker.pose.position.y = marker_msg.pos_y;
marker.pose.position.z = marker_msg.pos_z;
marker.pose.orientation.x = marker_msg.orientation_x;
marker.pose.orientation.y = marker_msg.orientation_y;
marker.pose.orientation.z = marker_msg.orientation_z;
marker.pose.orientation.w = marker_msg.orientation_w;
//指定标记的比例。对于基本形状,所有方向上的 1 表示边长为 1 米。
marker.scale.x = marker_msg.scale_x;
marker.scale.y = marker_msg.scale_y;
marker.scale.z = marker_msg.scale_z;
//标记的颜色被指定为 std_msgs/ColorRGBA。每个成员应介于 0 和 1 之间。alpha (a) 值为 0 表示完全透明(不可见),1 表示完全不透明。
marker.color.r = marker_msg.color_r;
marker.color.g = marker_msg.color_g;
marker.color.b = marker_msg.color_b;
marker.color.a = marker_msg.color_a;
//生命周期字段指定此标记在被自动删除之前应该保留多长时间。 ros::Duration() 的值意味着永远不会自动删除。
//如果在达到生命周期之前收到新的标记消息,则生命周期将重置为新标记消息中的值。
marker.lifetime = ros::Duration();
//我们等待标记有订阅者,然后发布标记。
while (marker_pub.getNumSubscribers() < 1)
{
if (!ros::ok())
{
return;
}
ROS_WARN_ONCE("Please create a subscriber to the marker");
sleep(1);
}
marker_pub.publish(marker);
// switch (shape)
// {
// case visualization_msgs::Marker::CUBE:
// shape = visualization_msgs::Marker::SPHERE;
// break;
// case visualization_msgs::Marker::SPHERE:
// shape = visualization_msgs::Marker::ARROW;
// break;
// case visualization_msgs::Marker::ARROW:
// shape = visualization_msgs::Marker::CYLINDER;
// break;
// case visualization_msgs::Marker::CYLINDER:
// shape = visualization_msgs::Marker::CUBE;
// break;
// }
r.sleep();
}
}
10.修改CMakeLists.txt文件
#指定项目所需的最低 CMake 版本。
cmake_minimum_required(VERSION 3.0.2)
#定义项目的名称
project(marker)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
#查找并导入外部依赖库。
find_package(catkin REQUIRED COMPONENTS
roscpp
)
#寻找Qt的包
find_package(Qt5 REQUIRED COMPONENTS Widgets )
#设置自动生成moc文件,一定要设置
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)#设置工程包含当前目录,非必须
#这用于指定包的依赖关系,由依赖于这个包的其他软件包使用。
catkin_package(
#包的导出包含路径
INCLUDE_DIRS include
#从项目中导出的库
# LIBRARIES marker
#本项目依赖的其他catkin项目
CATKIN_DEPENDS roscpp
#此项目所依赖的非 catkin CMake 项目
DEPENDS system_lib
)
#添加头文件搜索路径,编译器使用这些目录来查找头文件,第一个参数“include”表示包中的include/目录也是路径的一部分。
include_directories(
include
${catkin_INCLUDE_DIRS}
)
#指定将要构建的可执行文件的名称,以及它所依赖的源文件
add_executable(${PROJECT_NAME}_node src/marker_test.cpp
src/basic.cpp
src/basic.ui)
#在定义消息类型时,编译的可执行文件依赖这些动态生成的代码,需要使用${PROJECT_NAME}_generate_messages_cpp进行配置。
#add_dependencies(${PROJECT_NAME}_node ${PROJECT_NAME}_generate_messages_cpp)
#设置可执行文件依赖的库。
target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})
target_link_libraries(${PROJECT_NAME}_node Qt5::Widgets )#链接Qt库
11.构建与运行
上面二中已经进行了构建与运行的配置,直接运行即可。
运行会出现下面错误:
这是没有打开ros环境的原因,需打开终端,执行roscore命令
此时即可打开程序。
12.打开rviz可视化工具显示插件
打开rviz可视化工具也需在已经运行roscore的情况下才能打开。
点击【Displays】下的【Add】按钮,选择Marker插件,点击【OK】按钮。
根据上面代码将【Fixed Frame】修改为basic。
此时即可出现Marker类型的图形, 修改属性即可修改rviz中相应的属性。
13.查看推送的消息信息
查看所有的订阅消息列表
rostopic list
查看某个消息
rostopic echo /消息名称
例如:rostopic echo /visualization_marker
资源链接https://download.csdn.net/download/m0_67254672/88180519?spm=1001.2014.3001.5501