当前位置:网站首页>ROS learning (25) rviz plugin
ROS learning (25) rviz plugin
2022-07-07 01:52:00 【Ice cream with code】
List of articles
Preface
RVIZ yes ROS One provided 3D Visualization tools , As an extensible view tool , You can use the plug-in mechanism to add rich functional modules .RVIZ Laser data commonly used in 、 The visual display of image data is actually an official plug-in .
below , By implementing a speed control plug-in , be familiar with rviz plugin The implementation process of plug-ins .
The source code of this article comes from teacher Hu's book -《ROS Robot development practice 》.
One 、 Function description
The interface is as shown in the figure :
This plug-in uses Qt Development , Contains three input boxes , Topic names 、 Linear velocity and angular velocity .
Two 、 Create Feature Pack
The order is as follows :
catkin_create_pkg rviz_teleop_commander roscpp rviz std_msgs
This feature pack depends on RVIZ, because RVIZ Is based on Qt Developed , So there is no need to list right Qt Dependence .
3、 ... and 、 Code implementation
1、 establish teleop_pad.h file
The contents of the document are as follows :
#ifndef TELEOP_PAD_H
#define TELEOP_PAD_H
// The header file to be included
#ifndef Q_MOC_RUN
#include <ros/ros.h>
#include <ros/console.h>
#include <rviz/panel.h> //plugin Header file of base class
#endif
class QLineEdit;
namespace rviz_teleop_commander
{
// be-all plugin It has to be rviz::Panel Subclasses of
class TeleopPanel: public rviz::Panel
{
// You need to use Qt Signals and slots , All are QObject Subclasses of , So you need to declare Q_OBJECT macro
Q_OBJECT
public:
// Constructors , In the class will be used QWidget To achieve GUI Interface , Here, it is initialized to 0 that will do
TeleopPanel( QWidget* parent = 0 );
// heavy load rviz::Panel Functions in accumulation , Used to hold 、 Load the data in the configuration file , Here we are plugin
// in , The data is topic The name of
virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
// Common trough .
public Q_SLOTS:
// When user input topic After naming and pressing enter , The callback uses this slot to create a corresponding named topic publisher
void setTopic( const QString& topic );
// Internal slot .
protected Q_SLOTS:
void sendVel(); // Release the current speed value
void update_Linear_Velocity(); // Update the linear speed value according to the user's input
void update_Angular_Velocity(); // Update the angular velocity value according to the user's input
void updateTopic(); // Update according to user input topic name
// Internal variables .
protected:
// topic name Input box
QLineEdit* output_topic_editor_;
QString output_topic_;
// Linear velocity value input box
QLineEdit* output_topic_editor_1;
QString output_topic_1;
// Angular velocity value input box
QLineEdit* output_topic_editor_2;
QString output_topic_2;
// ROS Of publisher, Used to release speed topic
ros::Publisher velocity_publisher_;
// ROS inode handle
ros::NodeHandle nh_;
// Current saved linear and angular velocity values
float linear_velocity_;
float angular_velocity_;
};
} // end namespace rviz_teleop_commander
#endif // TELEOP_PANEL_H
2、 establish teleop_pad.cpp file
The contents of the document are as follows :
#include <stdio.h>
#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>
#include <geometry_msgs/Twist.h>
#include <QDebug>
#include "teleop_pad.h"
namespace rviz_teleop_commander
{
// Constructors , Initialize variable
TeleopPanel::TeleopPanel( QWidget* parent )
: rviz::Panel( parent )
, linear_velocity_( 0 )
, angular_velocity_( 0 )
{
// Create an input topic Named window
QVBoxLayout* topic_layout = new QVBoxLayout;
topic_layout->addWidget( new QLabel( "Teleop Topic:" ));
output_topic_editor_ = new QLineEdit;
topic_layout->addWidget( output_topic_editor_ );
// Create a window for inputting linear velocity
topic_layout->addWidget( new QLabel( "Linear Velocity:" ));
output_topic_editor_1 = new QLineEdit;
topic_layout->addWidget( output_topic_editor_1 );
// Create a window for entering angular velocity
topic_layout->addWidget( new QLabel( "Angular Velocity:" ));
output_topic_editor_2 = new QLineEdit;
topic_layout->addWidget( output_topic_editor_2 );
QHBoxLayout* layout = new QHBoxLayout;
layout->addLayout( topic_layout );
setLayout( layout );
// Create a timer , Used to publish messages regularly
QTimer* output_timer = new QTimer( this );
// Set the connection between the signal and the slot
// Input topic name , After returning , call updateTopic()
connect( output_topic_editor_, SIGNAL( editingFinished() ), this, SLOT( updateTopic() ));
// Enter the linear speed value , After returning , call update_Linear_Velocity()
connect( output_topic_editor_1, SIGNAL( editingFinished() ), this, SLOT( update_Linear_Velocity() ));
// Enter the angular velocity value , After returning , call update_Angular_Velocity()
connect( output_topic_editor_2, SIGNAL( editingFinished() ), this, SLOT( update_Angular_Velocity() ));
// Set the timer's callback function , Call by cycle sendVel()
connect( output_timer, SIGNAL( timeout() ), this, SLOT( sendVel() ));
// Set the period of the timer ,100ms
output_timer->start( 100 );
}
// Update the linear speed value
void TeleopPanel::update_Linear_Velocity()
{
// Get the data in the input box
QString temp_string = output_topic_editor_1->text();
// Convert a string to a floating-point number
float lin = temp_string.toFloat();
// Save the current input value
linear_velocity_ = lin;
}
// Update the angular velocity value
void TeleopPanel::update_Angular_Velocity()
{
QString temp_string = output_topic_editor_2->text();
float ang = temp_string.toFloat() ;
angular_velocity_ = ang;
}
// to update topic name
void TeleopPanel::updateTopic()
{
setTopic( output_topic_editor_->text() );
}
// Set up topic name
void TeleopPanel::setTopic( const QString& new_topic )
{
// Check topic Change or not .
if( new_topic != output_topic_ )
{
output_topic_ = new_topic;
// If the name is empty , Do not publish any information
if( output_topic_ == "" )
{
velocity_publisher_.shutdown();
}
// otherwise , initialization publisher
else
{
velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>( output_topic_.toStdString(), 1 );
}
Q_EMIT configChanged();
}
}
// Release the news
void TeleopPanel::sendVel()
{
if( ros::ok() && velocity_publisher_ )
{
geometry_msgs::Twist msg;
msg.linear.x = linear_velocity_;
msg.linear.y = 0;
msg.linear.z = 0;
msg.angular.x = 0;
msg.angular.y = 0;
msg.angular.z = angular_velocity_;
velocity_publisher_.publish( msg );
}
}
// Overload the function of the parent class
void TeleopPanel::save( rviz::Config config ) const
{
rviz::Panel::save( config );
config.mapSetValue( "Topic", output_topic_ );
}
// Overload the function of the parent class , Load configuration data
void TeleopPanel::load( const rviz::Config& config )
{
rviz::Panel::load( config );
QString topic;
if( config.mapGetString( "Topic", &topic ))
{
output_topic_editor_->setText( topic );
updateTopic();
}
}
} // end namespace rviz_teleop_commander
// Declare that this class is a rviz Plug in for
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_teleop_commander::TeleopPanel,rviz::Panel )
// END_TUTORIAL
Four 、 Compile the plug-in
1、 establish plugin Description file for
Under the root directory of the function package , establish plugin Description file for , The file named plugin_description.xml, The contents are as follows :
<library path="lib/librviz_teleop_commander">
<class name="rviz_teleop_commander/TeleopPanel"
type="rviz_teleop_commander::TeleopPanel"
base_class_type="rviz::Panel">
<description>
A panel widget allowing simple diff-drive style robot base control.
</description>
</class>
</library>
2、 modify package.xml file
stay package.xml Add... To the file plugin_description.xml File path , The contents are as follows :
<export>
<rviz plugin="${prefix}/plugin_description.xml"/>
</export>
3、 modify CMakeLists.txt file
Add Compilation Rules , The contents are as follows :
## This plugin includes Qt widgets, so we must include Qt like so:
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
set(QT_LIBRARIES Qt5::Widgets)
## I prefer the Qt signals and slots to avoid defining "emit", "slots",
## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here.
add_definitions(-DQT_NO_KEYWORDS)
## Here we specify which header files need to be run through "moc",
## Qt's meta-object compiler.
qt5_wrap_cpp(MOC_FILES
src/teleop_pad.h
)
## Here we specify the list of source files, including the output of
## the previous command which is stored in ``${MOC_FILES}``.
set(SOURCE_FILES
src/teleop_pad.cpp
${
MOC_FILES}
)
## An rviz plugin is just a shared library, so here we declare the
## library to be called ``${PROJECT_NAME}`` (which is
## "rviz_plugin_tutorials", or whatever your version of this project
## is called) and specify the list of source files we collected above
## in ``${SOURCE_FILES}``.
add_library(${
PROJECT_NAME} ${
SOURCE_FILES})
## Link the library with whatever Qt libraries have been defined by
## the ``find_package(Qt4 ...)`` line above, and with whatever libraries
## catkin has included.
##
## Although this puts "rviz_plugin_tutorials" (or whatever you have
## called the project) as the name of the library, cmake knows it is a
## library and names the actual file something like
## "librviz_plugin_tutorials.so", or whatever is appropriate for your
## particular OS.
target_link_libraries(${
PROJECT_NAME} ${
QT_LIBRARIES} ${
catkin_LIBRARIES})
## END_TUTORIAL
## Install rules
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_description.xml
DESTINATION ${
CATKIN_PACKAGE_SHARE_DESTINATION})
After making the above changes , You can compile the function package , The order is as follows :
catkin_make --pkg rviz_teleop_commander
5、 ... and 、 Running plug-ins
The first run roscore, The order is as follows :
roscore
function RVIZ, The order is as follows :
rosrun rviz rviz
Click on the Panels Options , choice Add New Panel, You can see the plug-in just created in the plug-in list , Pictured :

Click on OK after , You can see that , The interface of the plug-in , Enter the parameter value , as follows :
Run the command :
rostopic echo /cmd_vel
The effect is as follows :
You can see ROS There are already nodes in the release /cmd_vel The news of the topic .
边栏推荐
猜你喜欢

LeetCode. 剑指offer 62. 圆圈中最后剩下的数

鼠标右键 自定义

Yunna | work order management measures, how to carry out work order management

Yunna | work order management software, work order management software app

mongodb查看表是否导入成功

dvajs的基础介绍及使用

Baidu flying general BMN timing action positioning framework | data preparation and training guide (Part 2)

Appium自动化测试基础 — uiautomatorviewer定位工具
![JS reverse -- ob confusion and accelerated music that poked the [hornet's nest]](/img/40/da56fe6468da64dd37d6b5b0082206.png)
JS reverse -- ob confusion and accelerated music that poked the [hornet's nest]

LeetCode:1175. Prime permutation
随机推荐
JS how to quickly create an array with length n
json学习初体验–第三者jar包实现bean、List、map创json格式
C语言关于链表的代码看不懂?一篇文章让你拿捏二级指针并深入理解函数参数列表中传参的多种形式
图片打水印 缩放 和一个输入流的转换
Modify the system time of Px4 flight control
Shell script quickly counts the number of lines of project code
npm install 编译时报“Cannot read properties of null (reading ‘pickAlgorithm‘)“
AcWing 1148. Secret milk transportation problem solution (minimum spanning tree)
2022/0524/bookstrap
The use of video in the wiper component causes full screen dislocation
LeetCode. Sword finger offer 62 The last remaining number in the circle
C language instance_ two
ZOJ Problem Set – 2563 Long Dominoes 【如压力dp】
Gin introduction practice
Domestic images of various languages, software and systems. It is enough to collect this warehouse: Thanks mirror
C语言【23道】经典面试题【下】
AcWing 1142. Busy urban problem solving (minimum spanning tree)
ROS学习(26)动态参数配置
修改px4飞控的系统时间
CISP-PTE之命令注入篇