当前位置:网站首页>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 .
边栏推荐
- ROS learning (23) action communication mechanism
- AcWing 1142. 繁忙的都市 题解(最小生成树)
- LeetCode. Sword finger offer 62 The last remaining number in the circle
- Shell script quickly counts the number of lines of project code
- curl 命令
- Use nodejs to determine which projects are packaged + released
- Appium基础 — Appium Inspector定位工具(一)
- Set WordPress pseudo static connection (no pagoda)
- 爬虫实战(六):爬笔趣阁小说
- Get to know MySQL for the first time
猜你喜欢
AcWing 1148. 秘密的牛奶运输 题解(最小生成树)
Clickhouse fields are grouped and aggregated, and SQL is queried according to the granularity of any time period
ROS learning (22) TF transformation
JVM memory model
LeetCode:1175. Prime permutation
Blue Bridge Cup 2022 13th provincial competition real topic - block painting
盒子拉伸拉扯(左右模式)
Recognition of C language array
Yiwen takes you into [memory leak]
CISP-PTE之命令注入篇
随机推荐
盒子拉伸拉扯(左右模式)
AcWing 904. Wormhole solution (SPFA for negative rings)
Add PDF Title floating window
蓝桥杯2022年第十三届省赛真题-积木画
糊涂工具类(hutool)post请求设置body参数为json数据
初识MySQL
设置Wordpress伪静态连接(无宝塔)
IDEA常用的快捷键
AcWing 1141. LAN problem solving (kruskalkruskal finding the minimum spanning tree)
AcWing 346. 走廊泼水节 题解(推公式、最小生成树)
JS reverse -- ob confusion and accelerated music that poked the [hornet's nest]
uva 1401 dp+Trie
C language instance_ five
The cradle of eternity
DS-5/RVDS4.0变量初始化错误
AcWing 361. Sightseeing cow problem solution (SPFA seeking positive ring)
Telnet,SSH1,SSH2,Telnet/SSL,Rlogin,Serial,TAPI,RAW
Basic introduction and use of dvajs
鼠标右键 自定义
grep查找进程时,忽略grep进程本身