ROS开发:QT插件操控小乌龟

1 安装QT-ROS插件

本插件在安装过程中自行安装QT,无需额外安装。

1.1 Ubuntu16.04 安装步骤

打开Terminal,输入:

sudo add-apt-repository ppa:levi-armstrong/qt-libraries-xenial  
sudo add-apt-repository ppa:levi-armstrong/ppa  
sudo apt-get update && sudo apt-get install qt57creator-plugin-ros

可能需要删除旧的PPA:

sudo add-apt-repository --remove ppa:beineri/opt-qt57-xenial
sudo add-apt-repository --remove ppa:beineri/opt-qt571-xenial

如果您收到错误,请手动删除它:

sudo rm /etc/apt/sources.list.d/beineri-opt-qt57-xenial-xenial.list
sudo rm /etc/apt/sources.list.d/beineri-opt-qt571-xenial-xenial.list

1.2 测试插件

由于插件的更新,不需要安装qtcreator,插件自己依赖安装。
安装完成后在指令行输入qt,按Tab键看自己安装的。如图:
在这里插入图片描述

然后输入存在的qtcreatot-ros回车,qtcreator就启动了,就会看到有关于ros的创建选项了。如图:
在这里插入图片描述

安装有问题可以借鉴:

  1. http://blog.csdn.net/zhangrelay/article/details/52068657
  2. http://blog.csdn.net/u013453604/article/details/52186375
  3. http://blog.csdn.net/qq_30460905/article/details/79034633

2 使用QT编写ROS程序

2.1 实现步骤

  • Terminal新建工作空间catkin_qt,并创建src文件夹
mkdir -p catkin_qt/src
  • Terminal运行插件
qtcreator-ros

然后点击New Project,命名为catkin_qt(工程名称),选择第一步新建的功能包路径catkin_qt,点击Next,Finish。
这样新建的ROS.workspace就在新建的文件夹路径下了。文件夹内如图所示:
在这里插入图片描述

  • 创建测试包rostest

在QT界面下,打开工程目录,右键选择src文件夹,在当前路径下打开Terminal并创建测试功能包:

catkin_create_qt_pkg rostest

注意:需要预先安装建包工具:

sudo apt-get install ros-kinetic-qt-ros

注意catkin_qt/devel/setup.bash路径添加到bash文件中
在这里插入图片描述

  • 修改运行设置

点击Projects,选择Run选型,添加Add Run Step选项,Package和Target选项都选为新建的rostest,如图所示
在这里插入图片描述

  • 设计UI

在UI界面拖放几个按钮,右键更改Text名称为up,down,left,right
然后右键Go to slot…
选择clicked()
这样就新建了4个按键点击事件,如图所示:
在这里插入图片描述
在这里插入图片描述

  • 添加控制函数

打开主窗口qnode.hpp,注释void run(),并添加代码前进后退左转右转指令,如图所示:
在这里插入图片描述
然后写qnode.cpp文件,主要是一处头文件,两处ros通信程序,以及四个控制函数的修改。

/**
 * @file /src/qnode.cpp
 *
 * @brief Ros communication central!
 *
 * @date February 2011
 **/

/*****************************************************************************
** Includes
*****************************************************************************/

#include <ros/ros.h>
#include <ros/network.h>
#include <string>
#include <std_msgs/String.h>
#include <geometry_msgs/Twist.h>    //添加的地方
#include <sstream>
#include "../include/rostest/qnode.hpp"

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace rostest {

/*****************************************************************************
** Implementation
*****************************************************************************/

QNode::QNode(int argc, char** argv ) :
	init_argc(argc),
	init_argv(argv)
	{}

QNode::~QNode() {
    if(ros::isStarted()) {
      ros::shutdown(); // explicitly needed since we use ros::start();
      ros::waitForShutdown();
    }
	wait();
}

bool QNode::init() {
	ros::init(init_argc,init_argv,"rostest");
	if ( ! ros::master::check() ) {
		return false;
	}
	ros::start(); // explicitly needed since our nodehandle is going out of scope.
	ros::NodeHandle n;
	// Add your ros communications here.
	//添加的地方
    chatter_publisher = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 1000);
	start();
	return true;
}

bool QNode::init(const std::string &master_url, const std::string &host_url) {
	std::map<std::string,std::string> remappings;
	remappings["__master"] = master_url;
	remappings["__hostname"] = host_url;
	ros::init(remappings,"rostest");
	if ( ! ros::master::check() ) {
		return false;
	}
	ros::start(); // explicitly needed since our nodehandle is going out of scope.
	ros::NodeHandle n;
	// Add your ros communications here.
	//添加的地方
    chatter_publisher = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 1000);
	start();
	return true;
}
/*注释run()
void QNode::run() {
	ros::Rate loop_rate(1);
	int count = 0;
	while ( ros::ok() ) {

		std_msgs::String msg;
		std::stringstream ss;
		ss << "hello world " << count;
		msg.data = ss.str();
		chatter_publisher.publish(msg);
		log(Info,std::string("I sent: ")+msg.data);
		ros::spinOnce();
		loop_rate.sleep();
		++count;
	}
	std::cout << "Ros shutdown, proceeding to close the gui." << std::endl;
	Q_EMIT rosShutdown(); // used to signal the gui for a shutdown (useful to roslaunch)
}

*/
//---------------------主要添加的程序--------------------------------
void QNode::up()
{
  ros::Rate loop_rate(1);
  if( ros::ok() )
  {
    geometry_msgs::Twist msg;
    msg.linear.x = 1.0;
    msg.angular.z = 0.0;
    chatter_publisher.publish(msg);

    ros::spinOnce();
    loop_rate.sleep();
  }
}
void QNode::down()
{
  ros::Rate loop_rate(1);
  if( ros::ok() )
  {
    geometry_msgs::Twist msg;
    msg.linear.x = -1.0;
    msg.angular.z = 0.0;
    chatter_publisher.publish(msg);

    ros::spinOnce();
    loop_rate.sleep();
  }
}
void QNode::left()
{
  ros::Rate loop_rate(1);
  if( ros::ok() )
  {
    geometry_msgs::Twist msg;
    msg.linear.x = 0.0;
    msg.angular.z = 1.0;
    chatter_publisher.publish(msg);

    ros::spinOnce();
    loop_rate.sleep();
  }
}
void QNode::right()
{
  ros::Rate loop_rate(1);
  if( ros::ok() )
  {
    geometry_msgs::Twist msg;
    msg.linear.x = 0.0;
    msg.angular.z = -1.0;
    chatter_publisher.publish(msg);

    ros::spinOnce();
    loop_rate.sleep();
  }
}
//--------------------------------------------------------------------
void QNode::log( const LogLevel &level, const std::string &msg) {
	logging_model.insertRows(logging_model.rowCount(),1);
	std::stringstream logging_model_msg;
	switch ( level ) {
		case(Debug) : {
				ROS_DEBUG_STREAM(msg);
				logging_model_msg << "[DEBUG] [" << ros::Time::now() << "]: " << msg;
				break;
		}
		case(Info) : {
				ROS_INFO_STREAM(msg);
				logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
				break;
		}
		case(Warn) : {
				ROS_WARN_STREAM(msg);
				logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
				break;
		}
		case(Error) : {
				ROS_ERROR_STREAM(msg);
				logging_model_msg << "[ERROR] [" << ros::Time::now() << "]: " << msg;
				break;
		}
		case(Fatal) : {
				ROS_FATAL_STREAM(msg);
				logging_model_msg << "[FATAL] [" << ros::Time::now() << "]: " << msg;
				break;
		}
	}
	QVariant new_row(QString(logging_model_msg.str().c_str()));
	logging_model.setData(logging_model.index(logging_model.rowCount()-1),new_row);
	Q_EMIT loggingUpdated(); // used to readjust the scrollbar
}

}  // namespace rostest

把控制函数添加进按钮触发函数中(设计UI的那四个按键函数)
如图所示:
在这里插入图片描述

  • 编译运行

可以在运行设置Turtlesim_node,如图所示:
在这里插入图片描述
然后点击小锤子编译,完成编译。

  • 若main_window.hpp出现按钮事件函数声明错误:‘slots’ does not name a type

可将private slots:改为 private Q_SLOTS:
主要是因为编译器c++和ros编译器识别不同type。
在这里插入图片描述
在这里插入图片描述

2.2 测试QT程序

1.启动roscore
2.运行qt程序
3.勾选环境变量按钮,点击connect连接
4.使用按键进行控制小乌龟
在这里插入图片描述
在这里插入图片描述

3 参考资料

参考资料:

https://blog.csdn.net/weixin_43377151/article/details/84306914
https://blog.csdn.net/qq_39989653/article/details/79189605
https://blog.csdn.net/LOVE1055259415/article/details/80575432

此部分代码已上传github:
https://github.com/ShuaiWang-Code/ROS-ROBOT/tree/master/QT-ROS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章