【ROS2】【源码展示】ROS2中Rviz2增加一个可以实现收发节点双击修改图表等功能的插件panel

发布时间 2023-12-19 10:48:37作者: 铃灵狗

使用说明

源代码在这里,本文基于源代码进行功能增加和修改。主要应用Qt中的一些方法,结合ros2中rviz2对增加panel功能的一些封装。实现双击修改图表中的内容,节点的收发,图表根据收到的msg进行更新等功能。代码未进行编译检测,可能存在一些错误。可参考设计思路。

CPP文件

#include "demo_panel/demo_panel.h"

#include "rviz_common/properties/property_tree_widget.hpp"
#include "rviz_common/interaction/selection_manager.hpp"
#include "rviz_common/visualization_manager.hpp"



namespace demo_panel
{

    MyPanel::MyPanel(QWidget *parent)
            : rviz_common::Panel(parent)
    {
        auto layout = new QVBoxLayout();
        layout->setContentsMargins(0, 0, 0, 0);

        auto text = new QLabel("This is a demo");
        auto lineEdit = new QLineEdit();
        auto radio = new QRadioButton();

        tree_ = new QTreeWidget(this);
        tree_->setColumnCount(2);
        tree_->resize(600, 300);

        top_item_ = new QTreeWidgetItem();
        top_item_->setText(0, "robot");

        tree_->addTopLevelItem(top_item_);

        string_leave_ = new QStringList();
        string_leave_ << "name" << "leave";
        leave_ = new QTreeWidgetItem(top_item_, *string_leave_);


        layout->addWidget(text);
        layout->addWidget(lineEdit);
        layout->addWidget(radio);
        layout->addWidget(button_flash_);
        layout->addWidget(tree_);
        setLayout(layout);

        QTimer* publish_timer = new QTimer(this);
        connect(tree_, SIGNAL(itemDoubleClicked(QTreeWidgetItem* int)), this, SLOT(openEditor(QTreeWidgetItem* int)));
        // connect(tree_, SIGNAL(editingFinished()), this, SLOT(closeEditor()));
        connect(button_flash_, SIGNAL(clicked()), this, SLOT(flash()));
        publish_timer->start(100);
    }

    void MyPanel::onInitialize()
    {
//        tree_widget_->setModel(getDisplayContext()->getSelectionManager()->getPropertyModel());
        node_ = rviz_common::Panel::getDisplayContext()->getRosNodeAbstraction().lock()->get_raw_node();
        object_info_pub_ = node->create_publisher<Object>("topic", 1);
        object_info_sub_ = node->create_subscription<Object>("topic/sub", 1, std::bind(&MyPanel::sub_callback, this, std::placeholders::_1));
    }

    void MyPanel::openEditor(QTreeWidgetItem* item, int col)
    {
        item_tmp_ = nullptr;

        if(col == 0)
        {
            item_tmp_ = item;
            QLineEdit* lineEdit = new QLineEdit(tree_);
            lineEdit->setText(QStringLiteral(" "));
            connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(closeEditor()));
            tree_->setItemWidget(item_tmp_, 0, lineEdit);
        }
    }

    void MyPanel::closeEditor()
    {
        if(item_tmp_ != nullptr)
        {
            QLineEdit* edit = qobject_cast<QLineEdit*>(tree_->itemWidget(item_tmp_, 0));
            if(!edit)
            {
                return;
            }
            QString text = edit->text();
            tree_->removeItemWidget(item_tmp_, 1);
            item_tmp_->setText(0, text);
        }
    }

    void MyPanel::flash()
    {
        leave_->setText(1, QString::number(123, 'd', 2));
    }

}  // namespace demo_panel


#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(demo_panel::MyPanel, rviz_common::Panel)

H文件

#pragma once

#include <QMainWindow>
#include "rviz_common/panel.hpp"

#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QRadioButton>
#include <qpushbutton.h>
#include <QTreeWidget>
#include <qtimer.h>
#include <rclcpp/node.hpp>


namespace demo_panel
        {

                class MyPanel : public rviz_common::Panel // QMainWindow
        {
            Q_OBJECT

            public:
            explicit MyPanel(QWidget *parent = nullptr);

            void onInitialize() override;

            protected Q_SLOTS:
            void sub_callback(const object msg);
            void publishTopic();

            void flash();

            void openEditor(QTreeWidgetItem* item, int col);
            void closeEditor();

            protected:
            QPushButton* button_flash_;
            QVBoxLayout* layout_;
            QTreeWidget* tree_;
            QTreeWidgetItem* item_tmp_;
            QTreeWidgetItem* top_item_;

            QTreeWidgetItem* leave_;

            QStringList* string_leave_;

            int col_;

            rclcpp::Node::SharedPtr node_;
            std::shared_ptr<rclcpp::Publisher<Object>> object_info_pub_;
            std::shared_ptr<rclcpp::Subscription<Object>> object_info_sub_;
        };

        } // namespace demo_panel

xml文件

增加如下内容

<class  name="demo_panel/MyPanel"
		type="demo_panel::MyPanel"
		base_class_type="rviz_common::Panel">
		<description>
		demo_panel
		</description>
</class>

CMakeLists.txt文件

对原码中进行了修改,删掉冗余的部分。

cmake_minimum_required(VERSION 3.5)

project(demo_panel LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
    set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rviz_ogre_vendor REQUIRED)
find_package(Qt5 REQUIRED Core Widgets)
set(QT_LIBS Qt5::Widgets)

find_package(pluginlib REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_action REQUIRED)
find_package(rviz_default_plugins REQUIRED)
find_package(rviz_assimp_vendor REQUIRED)
find_package(rviz_rendering REQUIRED)
find_package(rviz_common REQUIRED)

ament_package_xml()
set(ROS_DISTRO "ROS 2")
set(OGRE_PLUGIN_PATH "rviz_ogre_vendor")

set(${PROJECT_NAME}_headers_to_moc
        include/demo_panel/demo_panel.h
        )

foreach(header "${${PROJECT_NAME}_headers_to_moc}")
    qt5_wrap_cpp(${PROJECT_NAME}_moc_files "${header}")
endforeach()

set(${PROJECT_NAME}_source_files
        src/demo_panel.cpp
        )

add_library(${PROJECT_NAME} SHARED
        ${${PROJECT_NAME}_moc_files}
        ${${PROJECT_NAME}_source_files}
        )

ament_target_dependencies(${PROJECT_NAME}
        PUBLIC
        pluginlib
        rclcpp
        rviz_assimp_vendor
        rviz_rendering
        rviz_common
        rclcpp_action
        rviz_default_plugins
        )

pluginlib_export_plugin_description_file(rviz_common plugin_description.xml)

install(
        TARGETS ${PROJECT_NAME}
        EXPORT ${PROJECT_NAME}
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
        INCLUDES DESTINATION include
)

install(
        DIRECTORY include/
        DESTINATION include
)

ament_package()