qt学习之qt界面控制小乌龟运动(二)

PS:小编也是新手,在做界面时也走了很多弯路,很多博主写的不是很明确,所以小编记录了自己制作的全过程,希望对初学者有用,共同进步。
1.新建工作空间catkin_new,并创建src包,。
2.新建ROS workspace ,保存在src文件夹内,打开工程是直接打开是src下的workspace。
3.src目录右键打开terminal利用命令catkin_create_qt_pkg btn 创建包,并编译。(预先安装建包工具,指令:sudo apt-get install ros-kinetic-qt-ros)
4.然后点击project->run,添加节点如图:
在这里插入图片描述
倘若没有btn文件,在工作空间编译一下,就有了。
5.在4的同时,可以不要btn,直接打开turtlesim中的node和key,然后点击运行,就可以案件控制小乌龟了
6.界面控制小乌龟程序:
(1)在UI界面拖放几个按钮,并改名字,右击按钮转到槽,在主窗口main_window.cpp文件中写入qnode.up();(因为qnode里面定义的是up和left),另一按钮同理。
void btn::MainWindow::on_pushButton_clicked()
{
qnode.up();
}
void btn::MainWindow::on_pushButton_2_clicked()
{
qnode.down();
}
void btn::MainWindow::on_pushButton_3_clicked()
{
qnode.left();
}
void btn::MainWindow::on_pushButton_4_clicked()
{
qnode.right();
}
(2)在qnode.hpp中添加:
void up();
void down();
void left();
void right();
(3)主要的是qnode.cpp文件,首先在头文件中定义:
/**

  • @file /src/qnode.cpp

  • @brief Ros communication central!

  • @date February 2011
    /
    /
    ***************************************************************************
    ** Includes
    /
    #include <ros/ros.h>
    #include <ros/network.h>
    #include
    #include <std_msgs/String.h>
    #include <geometry_msgs/Twist.h>
    #include
    #include “…/include/btn/qnode.hpp”
    /

    ** Namespaces
    /
    namespace 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,“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", 1);
    start();
    return true;
    }
    bool QNode::init(const std::string &master_url, const std::string &host_url) {
    std::mapstd::string,std::string remappings;
    remappings["__master"] = master_url;
    remappings["__hostname"] = host_url;
    ros::init(remappings,“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", 1);
    start();
    return true;
    }
    /*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();
    }
    //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::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();
    }
    //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 btn

一定要修改话题类型和发布的话题,否则不会驱动。
(4)在main_window.cpp文件:
/**

  • @file /src/main_window.cpp
  • @brief Implementation for the qt gui.
  • @date February 2011
    /
    /
    ***************************************************************************
    ** Includes
    /
    #include
    #include
    #include
    #include “…/include/btn/main_window.hpp”
    /

    ** Namespaces
    /
    namespace btn {
    using namespace Qt;
    /

    ** Implementation [MainWindow]
    *****************************************************************************/
MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
QMainWindow(parent)
, qnode(argc,argv)
{
ui.setupUi(this); // Calling this incidentally connects all ui’s triggers to on_…() callbacks in this class.
QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp is a global variable for the application
ReadSettings();
setWindowIcon(QIcon(":/images/icon.png"));
ui.tab_manager->setCurrentIndex(0); // ensure the first tab is showing - qt-designer should have this already hardwired, but often loses it (settings?).
QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close()));
/*********************
** Logging
* /
ui.view_logging->setModel(qnode.loggingModel());
QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView()));
/

** Auto Start
**********************/
if ( ui.checkbox_remember_settings->isChecked() ) {
on_button_connect_clicked(true);
}
}
MainWindow::~MainWindow() {}

/*****************************************************************************
** Implementation [Slots]
*****************************************************************************/

void MainWindow::showNoMasterMessage() {
QMessageBox msgBox;
msgBox.setText(“Couldn’t find the ros master.”);
msgBox.exec();
close();
}
/*

  • These triggers whenever the button is clicked, regardless of whether it
  • is already checked or not.
    /
    void MainWindow::on_button_connect_clicked(bool check ) {
    if ( ui.checkbox_use_environment->isChecked() ) {
    if ( !qnode.init() ) {
    showNoMasterMessage();
    } else {
    ui.button_connect->setEnabled(false);
    }
    } else {
    if ( ! qnode.init(ui.line_edit_master->text().toStdString(),
    ui.line_edit_host->text().toStdString()) ) {
    showNoMasterMessage();
    } else {
    ui.button_connect->setEnabled(false);
    ui.line_edit_master->setReadOnly(true);
    ui.line_edit_host->setReadOnly(true);
    ui.line_edit_topic->setReadOnly(true);
    }
    }
    }
    void MainWindow::on_checkbox_use_environment_stateChanged(int state) {
    bool enabled;
    if ( state == 0 ) {
    enabled = true;
    } else {
    enabled = false;
    }
    ui.line_edit_master->setEnabled(enabled);
    ui.line_edit_host->setEnabled(enabled);
    //ui.line_edit_topic->setEnabled(enabled);
    }
    /
    ****************************************************************************
    ** Implemenation [Slots][manually connected]
    ***************************************************************************/
    /
  • This function is signalled by the underlying model. When the model changes,
  • this will drop the cursor down to the last line in the QListview to ensure
  • the user can always see the latest log message.
    /
    void MainWindow::updateLoggingView() {
    ui.view_logging->scrollToBottom();
    }
    /
    ****************************************************************************
    ** Implementation [Menu]
    /
    void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, tr(“About …”),tr(“

    PACKAGE_NAME Test Program 0.10

    Copyright Yujin Robot

    This package needs an about description.

    ”));
    }
    /
    ** Implementation [Configuration]
    *****************************************************************************/
    void MainWindow::ReadSettings() {
    QSettings settings(“Qt-Ros Package”, “btn”);
    restoreGeometry(settings.value(“geometry”).toByteArray());
    restoreState(settings.value(“windowState”).toByteArray());
    QString master_url = settings.value(“master_url”,QString(“http://192.168.1.2:11311/”)).toString();
    QString host_url = settings.value(“host_url”, QString(“192.168.1.3”)).toString();
    //QString topic_name = settings.value(“topic_name”, QString("/chatter")).toString();
    ui.line_edit_master->setText(master_url);
    ui.line_edit_host->setText(host_url);
    //ui.line_edit_topic->setText(topic_name);
    bool remember = settings.value(“remember_settings”, false).toBool();
    ui.checkbox_remember_settings->setChecked(remember);
    bool checked = settings.value(“use_environment_variables”, false).toBool();
    ui.checkbox_use_environment->setChecked(checked);
    if ( checked ) {
    ui.line_edit_master->setEnabled(false);
    ui.line_edit_host->setEnabled(false);
    //ui.line_edit_topic->setEnabled(false);
    }
    }
    void MainWindow::WriteSettings() {
    QSettings settings(“Qt-Ros Package”, “btn”);
    settings.setValue(“master_url”,ui.line_edit_master->text());
    settings.setValue(“host_url”,ui.line_edit_host->text());
    //settings.setValue(“topic_name”,ui.line_edit_topic->text());
    settings.setValue(“use_environment_variables”,QVariant(ui.checkbox_use_environment->isChecked()));
    settings.setValue(“geometry”, saveGeometry());
    settings.setValue(“windowState”, saveState());
    settings.setValue(“remember_settings”,QVariant(ui.checkbox_remember_settings->isChecked()));
    }
    void MainWindow::closeEvent(QCloseEvent *event)
    {
    WriteSettings();
    QMainWindow::closeEvent(event);
    }
    }
    //namespace btn
    void btn::MainWindow::on_pushButton_clicked()
    {
    qnode.up();
    }
    void btn::MainWindow::on_pushButton_2_clicked()
    {
    qnode.down();
    }
    void btn::MainWindow::on_pushButton_3_clicked()
    {
    qnode.left();
    }
    void btn::MainWindow::on_pushButton_4_clicked()
    {
    qnode.right();
    }

最后,编译运行就可以了,(首先在project加入turtlesim小乌龟的节点,然后启动roscore欧)。点击connect连接,就可以按键控制了。

PS:1、头文件包含问题:

用插件创建或导入ROS package之后还需要修改.workspace文件,

在标签下加入下面这行

/opt/ros/indigo/include
这样就可以使得Qt找到ros头文件,比如<ros/ros.h>
加入:

/opt/ros/kinetic/include

**2.connect前一定要、一定要在use environment variable前打钩或者输入ROS IP。
3.需要在qnode.cpp里加入一个头文件,上面程序中有;还需要修改话题类型和话题,这样程序应该不会出错了。
4.运行路径要添加在src下。还有需要source或者添加vim ./zshrc下加工作空间。

参考微博:
https://blog.csdn.net/qq_39989653/article/details/79189605#commentBox

猜你喜欢

转载自blog.csdn.net/weixin_43377151/article/details/84306914