Qt_ROS Package学习与修改

1.学习package

最近一直在思考,命令行上启动程序不太友好,想要GUI与用户交互,之前接触过Qt。自然,还是从Qt开始。找了一些地方,发现一个叫qt_ros的package,先用起来再慢慢做修改。

http://wiki.ros.org/qt_ros

作者给的tutorial比较简单,catkin_make之后,我们有四个可执行的程序:他们分别是qadd_client、qadd_server、qlistener和qtalker。

前两个将ROS的service包含在了界面中,后面两个将ROS的node包含在GUI中了。下面我先启动后面两个看看:

这里,我使用的是系统的环境变量,做过ros by example的应该知道,在~/.bashrc如果想要连接到远程机器人的roscore是需要做一点改动的。在书上《Networking between a robot and a desktop computer》这一节。

因此,我这里的roscore就是在本机上启动的,这里勾选那个checkbox就好,点击connect(两边都要connect哦)。

查看node

非常简单,就是两个node和一个topic。根据tutorial,我们如果要建立自己的qt_ros的package,必须用catkin_ws/src下使用catkin_create_qt_package来建立,这里我建立的package目录名为qtros_btn.

2. 修改(举一反三)

既然是两个node和一个topic,我首先想到的是小乌龟,能否改掉它给乌龟发送信号,让它旋转呢?这里要有一点以前的知识,启动用rosrun turtlesim turtlesim_node,然后rostopic list一下,看到有关于cmd_vel的topic,然后给他发送信号,让乌龟一直旋转。


进入源程序,看到它的主要目录结构,这里我把自己用catkin_create_qt_package建立的和tutorial里放在一起作对比。

我们主要关注的还是qnode.cpp

这里我直接贴上程序,不难的,其实就是改掉它的publish那部分,因为我们是turtlesimnode作为subscriber,所以只要有publisher就好了

/**
 * @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/qtros_btn/qnode.hpp"

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

namespace qtros_btn {

/*****************************************************************************
** 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,"qtros_btn");
	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,"qtros_btn");
	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;
}

void QNode::run() {
	ros::Rate loop_rate(1);
	int count = 0;
	while ( ros::ok() ) {

        geometry_msgs::Twist msg;
        msg.linear.x = 2.0;
        msg.angular.z = 2.0;

		chatter_publisher.publish(msg);
//        log(Info, msg.linear.x);
//        log(Info, msg.angular.z);
        logging_model.insertRows(logging_model.rowCount(),1);
        std::stringstream logging_model_msg;
        logging_model_msg << "[DEBUG] [" << ros::Time::now() << "]: " <<"linear = "<< msg.linear.x<<" angular = "<<msg.angular.z;
        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

		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::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 qtros_btn

说个题外话,这里我曾经尝试过删除一些ui文件,因为这里我主要只用到了一个button,但是发现,作者的控件都是关联的,不太容易修改,之前有改动过编译通过但是运行直接core dump的。它里面有多线程。


因此,我才会直接根据它的template修改,添加自己需要的部分。这是运行截图

3. 小结

有个地方我还需要说一下,在运行截图那里,实际的log界面,也就是打印信息的界面,作者的愿意图是封装了一个QNode::log()函数,它的第一个参数是level,第二个参数是string类型的msg,但是我怎么也没有找到将geometry_msg转化为string 的办法,没办法,直接霸王硬上弓,不通过那个函数直接调用里面的实现方法。

//        log(Info, msg.linear.x);
//        log(Info, msg.angular.z);
        logging_model.insertRows(logging_model.rowCount(),1);
        std::stringstream logging_model_msg;
        logging_model_msg << "[DEBUG] [" << ros::Time::now() << "]: " <<"linear = "<< msg.linear.x<<" angular = "<<msg.angular.z;
        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

也就是这一段程序,试过下面这样用sprintf

        std::stringstream s1;
        std::stringstream s2;

        sprintf(s1,"Sent: linear = %f", msg.linear.x);

        sprintf(s2,"Sent: angular = %f", msg.angular.z);

        log(Info,std::string(s1)+std::string (s2));
不过不行,大家也开动脑筋帮我思考一下吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yaked19

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值