zoukankan      html  css  js  c++  java
  • Rviz 实现 pannel 插件

    这个是鉴于另一个Github上的项目学习的

    https://github.com/chaoli2/rviz_teleop_commander/tree/master/src

    其中代码注释很清楚,大家也可以去看源代码

    首先是CmakeList.txt文件

    cmake_minimum_required(VERSION 2.8.3)
    project(bing_pannel)
    find_package(catkin REQUIRED COMPONENTS rviz)
    catkin_package()
    include_directories(${catkin_INCLUDE_DIRS})
    link_directories(${catkin_LIBRARY_DIRS})
    
    set(CMAKE_AUTOMOC ON)
    
    if(rviz_QT_VERSION VERSION_LESS "5")
      message(STATUS "Using Qt4 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
      find_package(Qt4 ${rviz_QT_VERSION} EXACT REQUIRED QtCore QtGui)
      include(${QT_USE_FILE})
    else()
      message(STATUS "Using Qt5 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
      find_package(Qt5 ${rviz_QT_VERSION} EXACT REQUIRED Core Widgets)
      set(QT_LIBRARIES Qt5::Widgets)
    endif()
    
    add_definitions(-DQT_NO_KEYWORDS)
    set(SOURCE_FILES
      src/bing_pannel.cpp ##这里是你的主文件
      ${MOC_FILES}
    )
    add_library(${PROJECT_NAME} ${SOURCE_FILES})
    
    target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})
    
    install(TARGETS
      ${PROJECT_NAME}
      ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
      LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
      RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    )
    
    install(FILES
      plugin_discription.xml ##这里是你的plugin_discription.xml
      DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})

    只要在workspace下catkin_make后,这个包里的插件便直接安装了。package.xml文件应该如下:

    <?xml version="1.0"?>
    <package format="1">
      <name>bing_pannel</name>
      <version>0.0.0</version>
      <description>The bing_pannel package</description>
    
      <!-- One maintainer tag required, multiple allowed, one person per tag -->
      <!-- Example:  -->
      <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
      <maintainer email="bing@todo.todo">bing</maintainer>
    
    
      <!-- One license tag required, multiple allowed, one license per tag -->
      <!-- Commonly used license strings: -->
      <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
      <license>TODO</license>
    
    
      <!-- Url tags are optional, but multiple are allowed, one per tag -->
      <!-- Optional attribute type can be: website, bugtracker, or repository -->
      <!-- Example: -->
      <!-- <url type="website">http://wiki.ros.org/bing_pannel</url> -->
    
    
      <!-- Author tags are optional, multiple are allowed, one per tag -->
      <!-- Authors do not have to be maintainers, but could be -->
      <!-- Example: -->
      <!-- <author email="jane.doe@example.com">Jane Doe</author> -->
    
    
      <!-- The *depend tags are used to specify dependencies -->
      <!-- Dependencies can be catkin packages or system dependencies -->
      <!-- Examples: -->
      <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
      <!--   <depend>roscpp</depend> -->
      <!--   Note that this is equivalent to the following: -->
      <!--   <build_depend>roscpp</build_depend> -->
      <!--   <exec_depend>roscpp</exec_depend> -->
      <!-- Use build_depend for packages you need at compile time: -->
      <!--   <build_depend>message_generation</build_depend> -->
      <!-- Use build_export_depend for packages you need in order to build against this package: -->
      <!--   <build_export_depend>message_generation</build_export_depend> -->
      <!-- Use buildtool_depend for build tool packages: -->
      <!--   <buildtool_depend>catkin</buildtool_depend> -->
      <!-- Use exec_depend for packages you need at runtime: -->
      <!--   <exec_depend>message_runtime</exec_depend> -->
      <!-- Use test_depend for packages you need only for testing: -->
      <!--   <test_depend>gtest</test_depend> -->
      <!-- Use doc_depend for packages you need only for building documentation: -->
      <!--   <doc_depend>doxygen</doc_depend> -->
      <buildtool_depend>catkin</buildtool_depend>
    
      <build_depend>roscpp</build_depend>
      <build_depend>rviz</build_depend>
      <build_depend>std_msgs</build_depend>
      <run_depend>roscpp</run_depend>
      <run_depend>rviz</run_depend>
      <run_depend>std_msgs</run_depend>
    
      <!-- The export tag contains other, unspecified, tags -->
      <export>
        <!-- Other tools can request additional information be placed here -->
          <rviz plugin="${prefix}/plugin_discription.xml"/>
        <!-- 这里面可以修改plugin_discription.xml -->
      </export>
    </package>    

    而真正描述的plugin_discription.xml为如下:

    <library path="lib/libbing_pannel">
      <class name="bing_pannel/BingPannel"
             type="bing_rviz_plugin::BingPannel"
             base_class_type="rviz::Panel">
        <description>
          Bing test pannel.
        </description>
      </class>
    </library>
    <class name="bing_pannel/BingPannel"
             type="bing_rviz_plugin::BingPannel"
             base_class_type="rviz::Panel">
    中name中的bing_pannel/BingPannel里,写的是package的名字加class type中是namespace加class名。

    我们在src文件夹下加入bing_pannel.cpp和bing_pannel.h。这个package的文件夹如下。

    我们先看.h文件。

    #ifndef BING_PANNEL_H
    #define BING_PANNEL_H
    
    #include <ros/ros.h>
    #include <ros/console.h>
    #include <rviz/panel.h>
    
    class QLineEdit;
    
    namespace bing_rviz_plugin
    {
      class  BingPannel: public rviz::Panel
      {
          Q_OBJECT
          public:
            BingPannel( QWidget* parent = 0 );
            virtual void load( const rviz::Config& config );
            virtual void save( rviz::Config config ) const;
    
          public Q_SLOTS:
            void setTopic( const QString& topic );
    
          protected Q_SLOTS:
            void sendVel();
            void update_Linear_Velocity();
            void update_Angular_Velocity();
            void updateTopic();
    
          protected:
            QLineEdit* output_topic_editor_;
            QString output_topic_;
            QLineEdit* output_topic_editor_1;
            QString output_topic_1;
    
            ros::Publisher velocity_publisher_;
            ros::NodeHandle nh_;
            float linear_velocity_;
      };
    }
    
    #endif

     头文件中,rviz/panel.h 就是 pannel头文件。插件显示如下图。在rviz中加入pannel的话,要在标题栏中,找到Panels 〉Add New Panel。选择并加入需要的pannel。

     选择添加的Pannel。

    我们这里的插件会通过文本框里的输入发送一个输入的Topic名字的消息。在后面需要填写速度X和速度Y,并且回车就可以发布消息了。 

    回车后,rostopic list会显示/test_velocity。我们这里发布的是geometry_msgs::Twist。

    下面我们的代码,里面是.h文件。

    #ifndef BING_PANNEL_H
    #define BING_PANNEL_H
    
    #include <ros/ros.h>
    #include <ros/console.h>
    #include <rviz/panel.h>
    
    class QLineEdit;
    
    namespace bing_rviz_plugin
    {
      class  BingPannel: public rviz::Panel
      {
          Q_OBJECT
          public:
        //用QWigdet的实例来实现GUI界面 BingPannel( QWidget
    * parent = 0 ); virtual void load( const rviz::Config& config ); virtual void save( rviz::Config config ) const; public Q_SLOTS:
        //当填写完时候,回车后,执行会调函数
    void setTopic( const QString& topic ); protected Q_SLOTS: void sendVel(); void update_Linear_Velocity_X(); void update_Linear_Velocity_Y(); void updateTopic(); protected:
        //这里是三个显示的文字框的定义 QLineEdit
    * output_topic_editor_; QString output_topic_; QLineEdit* output_topic_editor_1; QString output_topic_1; QLineEdit* output_topic_editor_2; QString output_topic_2;     //Ros消息发布 ros::Publisher velocity_publisher_; ros::NodeHandle nh_;

        //x速度,y速度
    float linear_velocity_X; float linear_velocity_Y; }; } #endif

    相应的.cpp文件如下:

    #include <stdio.h>
    
    #include <QPainter>
    #include <QLineEdit>
    #include <QVBoxLayout>
    #include <QHBoxLayout>
    #include <QLabel>
    #include <QTimer>
    
    #include <geometry_msgs/Twist.h>
    #include <QDebug>
    
    #include "bing_pannel.h"
    
    namespace bing_rviz_plugin{
      BingPannel::BingPannel( QWidget* parent ): rviz::Panel( parent ), linear_velocity_X( 0 ),linear_velocity_Y( 0 ){
      //topic窗口
        QVBoxLayout* topic_layout = new QVBoxLayout;
        topic_layout->addWidget( new QLabel( "Teleop Topic:" ));
        output_topic_editor_ = new QLineEdit;
        topic_layout->addWidget( output_topic_editor_ );
      //xvelocity窗口
        topic_layout->addWidget( new QLabel( "Linear Velocity X:" ));
        output_topic_editor_1 = new QLineEdit;
        topic_layout->addWidget( output_topic_editor_1 );
      //yvelocity窗口
        topic_layout->addWidget( new QLabel( "Linear Velocity Y:" ));
        output_topic_editor_2 = new QLineEdit;
        topic_layout->addWidget( output_topic_editor_2 );
    
        QHBoxLayout* layout = new QHBoxLayout;
        layout->addLayout( topic_layout );
        setLayout( layout );
    
        QTimer* output_timer = new QTimer( this );
      
      
      //回车回调函数,设置信号连接 connect( output_topic_editor_, SIGNAL( editingFinished() ),
    this, SLOT( updateTopic() )); connect( output_topic_editor_1, SIGNAL( editingFinished() ), this, SLOT( update_Linear_Velocity_X() )); connect( output_topic_editor_1, SIGNAL( editingFinished() ), this, SLOT( update_Linear_Velocity_Y() ));
      //定时器回调,定时运行sendVel()
       connect( output_timer, SIGNAL( timeout() ),
    this, SLOT( sendVel() )); output_timer->start( 100 ); }   //读取x速度 void BingPannel::update_Linear_Velocity_X() { QString temp_string = output_topic_editor_1->text(); float lin = temp_string.toFloat(); linear_velocity_X = lin; }
      //读取y速度
    void BingPannel::update_Linear_Velocity_Y() { QString temp_string = output_topic_editor_2->text(); float lin = temp_string.toFloat(); linear_velocity_Y = lin; }   //更新topic void BingPannel::updateTopic() { setTopic( output_topic_editor_->text() ); }   //topic名字 void BingPannel::setTopic( const QString& new_topic ) { if( new_topic != output_topic_ ) { output_topic_ = new_topic; if( output_topic_ == "" ) { velocity_publisher_.shutdown(); } else { velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>( output_topic_.toStdString(), 1 ); } Q_EMIT configChanged(); } } void BingPannel::sendVel() { if( ros::ok() && velocity_publisher_ ) { geometry_msgs::Twist msg; msg.linear.x = linear_velocity_X; msg.linear.y = linear_velocity_Y ; msg.linear.z = 0; msg.angular.x = 0; msg.angular.y = 0; msg.angular.z = 1; velocity_publisher_.publish( msg ); } } void BingPannel::save( rviz::Config config ) const { rviz::Panel::save( config ); config.mapSetValue( "Topic", output_topic_ ); } void BingPannel::load( const rviz::Config& config ) { rviz::Panel::load( config ); QString topic; if( config.mapGetString( "Topic", &topic )) { output_topic_editor_->setText( topic ); updateTopic(); } } } #include <pluginlib/class_list_macros.h> PLUGINLIB_EXPORT_CLASS(bing_rviz_plugin::BingPannel,rviz::Panel )

    保存后,catkin_make 就可以在rviz里找到了。

    参考:

    http://www.guyuehome.com/945

  • 相关阅读:
    python -基础-强大的列表推导式
    python-基础-字符串拼接
    tkinter学习-- 控件一、Label、Button
    python -re模块
    Apache POI XWPF 爬坑指南之二特定位置插入表格、段落、图片
    mybatis报错:Invalid bound statement (not found):
    bootstrap中input输入框后面添加图标
    bootstrap悬浮显示内容
    layui中使用laydate
    与SQL相关解释表关联(left join ... on ... and ...)
  • 原文地址:https://www.cnblogs.com/TIANHUAHUA/p/8337979.html
Copyright © 2011-2022 走看看