rviz是ROS官方的一款3D可视化工具,几乎我们需要用到的所有机器人相关数据都可以在rviz中展现,当然由于机器人系统的需求不同,很多时候rviz中已有的一些功能仍然无法满足我们的需求,这个时候rviz的plugin机制就派上用场了。上一篇我们探索了插件的概念和基本实现,这一篇通过rviz中的插件实现,来进行巩固加深。
rviz作为一种可扩展化的视图工具,可以使用这种插件机制来扩展丰富的功能,进行二次开发,我们在rviz中常常使用的激光数据可视化显示、图像数据可视化显示,其实都是官方提供的插件。所以,我们完全可以在rviz的基础上,打造属于我们自己的机器人人机界面。
一、目标
在《Mastering ROS for Robotics Programming》这本书的第六章,讲解了一个发布速度控制的rviz plugin,这里我们就根据这个plugin的实现来学习。
plugin的整体效果如下:
从上边的图片我们有一个大致的感性认识:
首先,这是一个可视化的界面,在ros的编程中,好像没有可视化的编程语句,那么如何实现可视化编程呢?如果你使用过ROS的rqt工具箱,应该就会想到Qt,没错,Qt是一个实现GUI的优秀框架,ROS中的可视化工具绝大部分都是基于Qt进行开发的,rviz的plugin也不例外。所以我们需要了解Qt的一些相关知识。
其次,这个界面里包含三个输入框,分别对应topic名称、线速度值、角速度值,这就需要我们读取用户的输入,然后转换成ROS的topic,这里也会涉及到Qt中的重要概念——信号、槽,类似于回调函数,可以自行百度学习一下。
好的,接下来,我们就分步骤看一下如何实现这个plugin,也可以跟着一起做。
完整的功能包代码可以在github上下载。
二、创建功能包
首先,我们来创建一个功能包,用来放置plugin的所有相关代码:
$ catkin_create_pkg rviz_telop_commander roscpp rviz std_msgs
这个功能包的依赖于rviz,因为rviz是基于Qt开发的,所以省去了对Qt的依赖。
三、实现主代码
接下来,我们在功能包的src文件夹下开始做代码的实现,这个plugin相对简单,只需要一个cpp文件就可以完成,当然对应的还要有它的头文件。
3.1 头文件
#ifndef TELEOP_PAD_H
#define TELEOP_PAD_H
//所需要包含的头文件
#include <ros/ros.h>
#include <ros/console.h>
#include <rviz/panel.h> //plugin基类的头文件
class QLineEdit;
namespace rviz_telop_commander
{
// 所有的plugin都必须是rviz::Panel的子类
class TeleopPanel: public rviz::Panel
{
// 后边需要用到Qt的信号和槽,都是QObject的子类,所以需要声明Q_OBJECT宏
Q_OBJECT
public:
// 构造函数,在类中会用到QWidget的实例来实现GUI界面,这里先初始化为0即可
TeleopPanel( QWidget* parent = 0 );
// 重载rviz::Panel积累中的函数,用于保存、加载配置文件中的数据,在我们这个plugin
// 中,数据就是topic的名称
virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
// 公共槽.
public Q_SLOTS:
// 当用户输入topic的命名并按下回车后,回调用此槽来创建一个相应名称的topic publisher
void setTopic( const QString& topic );
// 内部槽.
protected Q_SLOTS:
void sendVel(); // 发布当前的速度值
void update_Linear_Velocity(); // 根据用户的输入更新线速度值
void update_Angular_Velocity(); // 根据用户的输入更新角速度值
void updateTopic(); // 根据用户的输入更新topic name
// 内部变量.
protected:
// topic name输入框
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的publisher,用来发布速度topic
ros::Publisher velocity_publisher_;
// The ROS node handle.
ros::NodeHandle nh_;
// 当前保存的线速度和角速度值
float linear_velocity_;
float angular_velocity_;
};
} // end namespace rviz_plugin_tutorials
#endif // TELEOP_PANEL_H
3.2 cpp文件
接下来是cpp代码文件 teleop_pad.cpp。
#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_telop_commander
{
// 构造函数,初始化变量
TeleopPanel::TeleopPanel( QWidget* parent )
: rviz::Panel( parent )
, linear_velocity_( 0 )
, angular_velocity_( 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_ );
// 创建一个输入线速度的窗口
topic_layout->addWidget( new QLabel( "Linear Velocity:" ));
output_topic_editor_1 = new QLineEdit;
topic_layout->addWidget( output_topic_editor_1 );
// 创建一个输入角速度的窗口
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 );
// 创建一个定时器,用来定时发布消息
QTimer* output_timer = new QTimer( this );
// 设置信号与槽的连接
connect( output_topic_editor_, SIGNAL( editingFinished() ), this, SLOT( updateTopic() )); // 输入topic命名,回车后,调用updateTopic()
connect( output_topic_editor_1, SIGNAL( editingFinished() ), this, SLOT( update_Linear_Velocity() )); // 输入线速度值,回车后,调用update_Linear_Velocity()
connect( output_topic_editor_2, SIGNAL( editingFinished() ), this, SLOT( update_Angular_Velocity() ));// 输入角速度值,回车后,调用update_Angular_Velocity()
// 设置定时器的回调函数,按周期调用sendVel()
connect( output_timer, SIGNAL( timeout() ), this, SLOT( sendVel() ));
// 设置定时器的周期,100ms
output_timer->start( 100 );
}
// 更新线速度值
void TeleopPanel::update_Linear_Velocity()
{
// 获取输入框内的数据
QString temp_string = output_topic_editor_1->text();
// 将字符串转换成浮点数
float lin = temp_string.toFloat();
// 保存当前的输入值
linear_velocity_ = lin;
}
// 更新角速度值
void TeleopPanel::update_Angular_Velocity()
{
QString temp_string = output_topic_editor_2->text();
float ang = temp_string.toFloat() ;
angular_velocity_ = ang;
}
// 更新topic命名
void TeleopPanel::updateTopic()
{
setTopic( output_topic_editor_->text() );
}
// 设置topic命名
void TeleopPanel::setTopic( const QString& new_topic )
{
// 检查topic是否发生改变.
if( new_topic != output_topic_ )
{
output_topic_ = new_topic;
// 如果命名为空,不发布任何信息
if( output_topic_ == "" )
{
velocity_publisher_.shutdown();
}
// 否则,初始化publisher
else
{
velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>( output_topic_.toStdString(), 1 );
}
Q_EMIT configChanged();
}
}
// 发布消息
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 );
}
}
// 重载父类的功能
void TeleopPanel::save( rviz::Config config ) const
{
rviz::Panel::save( config );
config.mapSetValue( "Topic", output_topic_ );
}
// 重载父类的功能,加载配置数据
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_plugin_tutorials
// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_telop_commander::TeleopPanel,rviz::Panel )
// END_TUTORIAL
代码文件就是这样,并没有很多代码,还是比较好理解的。
四、完成编译文件
为了编译成功,还需要完成一些编译文件的设置。
4.1 plugin的描述文件
在功能包的根目录下需要创建一个plugin的描述文件 plugin_description.xml:
<library path="lib/librviz_telop_commander">
<class name="rviz_telop_commander/Teleop"
type="rviz_telop_commander::TeleopPanel"
base_class_type="rviz::Panel">
<description>
A panel widget allowing simple diff-drive style robot base control.
</description>
</class>
</library>
4.2 package.xml
然后在 package.xml文件里添加plugin_description.xml。
<export>
<rviz plugin="${prefix}/plugin_description.xml"/>
</export>
4.3 CMakeLists.txt
当然, CMakeLists.txt文件也必须要加入相应的编译规则:
## This plugin includes Qt widgets, so we must include Qt like so:
find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
include(${QT_USE_FILE})
## 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.
qt4_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})
现在就可以开始编译了!
五、实现效果
编译成功后,我们来运行rviz,需要注意的是:一定要source devel文件夹下的setup脚本,来生效路径,否则会找不到插件:
rosrun rviz rviz
启动之后应该并没有什么不同,点击菜单栏中的“Panels”选项,选择“Add New Panel”,在打开的窗口中的最下方,就可以看到我们创建的plugin了,点中之后,可以在下方的“Description”中看到我们在plugin_description.xml文件中对plugin的描述。
点击“OK”,就会弹出“TeleopPanel”插件啦:
我们分别填写三行所对应的内容:
然后打开一个终端查看消息:
OK,实现一个rviz的plugin是不是很简单,重点是理解ROS和Qt的结合使用。使用类似的方法和Qt的编程技巧,就可以基于rviz打造属于自己的人机交互界面了!
评论列表(101条)
古月老师你好,请问如果我想添加按钮,该如何调整按钮的大小和尺寸呢?我看代码里好像没有设计控件的位置和大小的部分
老师你好,我使用一个插件,用一个按钮来驱动机器人连续运动,但我发现用execute()去执行的时候,是会卡的(看了评论发现是阻塞的),但是卡完以后发现直接是到终点的,不会有机器人运动过程,请问这种情况怎么办
古月老师,您好!
咨询您一个问题!
我在编写ros plugin中增加TCP\IP socket 与一个ARM(linux系统)开发板通信(自己编写协议,底层ARM没有安装ROS),发现连接通信没问题,但是只要循环发送和接受的过程中增加延时,通信就会断开,发送失败,直接编写QT程序,通信不会出问题,一直保持连接,想知道ros在这里有影响?
以解决,谢谢
老师您好,我在编译过程发现:
/home/sunxiaoqin/catkin_ws/src/rviz_telop_commander/src/teleop_pad.cpp: In constructor ‘rviz_telop_commander::TeleopPanel::TeleopPanel(QWidget*)’:
/home/sunxiaoqin/catkin_ws/src/rviz_telop_commander/src/teleop_pad.cpp:42:13: error: ‘class QHBoxLayout’ has no member named ‘addlayout’
layout->addlayout(topic_layout);
^
/home/sunxiaoqin/catkin_ws/src/rviz_telop_commander/src/teleop_pad.cpp:49:57: error: ‘editingFinished’ was not declared in this scope
connect(output_topic_editor_,SINGAL(editingFinished()),this,SLOT(updateTopic()));
^
/home/sunxiaoqin/catkin_ws/src/rviz_telop_commander/src/teleop_pad.cpp:49:58: error: ‘SINGAL’ was not declared in this scope
connect(output_topic_editor_,SINGAL(editingFinished()),this,SLOT(updateTopic()));
^
/home/sunxiaoqin/catkin_ws/src/rviz_telop_commander/src/teleop_pad.cpp:53:41: error: ‘timeout’ was not declared in this scope
connect(output_timer,SINGAL(timeout()),this,SLOT(sendVel()));
^
rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/build.make:66: recipe for target ‘rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/src/teleop_pad.cpp.o’ failed
make[2]: *** [rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/src/teleop_pad.cpp.o] Error 1
CMakeFiles/Makefile2:1951: recipe for target ‘rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/all’ failed
make[1]: *** [rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/all] Error 2
Makefile:138: recipe for target ‘all’ failed
make: *** [all] Error 2
请问怎么解决,谢谢
编程问题吧,google下
谢谢老师,已解决
胡老师您好,我按照您的程序编写,并在Cmakelist文件添加了以上内容,但是编译显示:
usr/include/boost/type_traits/detail/has_binary_operator.hp:50: Parse error at “BOOST_JOIN”
usr/include/boost/type_traits/detail/has_binary_operator.hp:50: Parse error at “BOOST_JOIN”
rviz_telop_commander/CMakeFiles/teleop_pad.dir/build.make:62: recipe for target ‘rviz_telop_commander/src/moc_teleop_pad.cxx’ failed
rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/build.make:62: recipe for target ‘rviz_telop_commander/src/moc_teleop_pad.cxx’ failed
make[2]: *** [rviz_telop_commander/src/moc_teleop_pad.cxx] Error 1
make[2]: *** [rviz_telop_commander/src/moc_teleop_pad.cxx] Error 1
CMakeFiles/Makefile2:2502: recipe for target ‘rviz_telop_commander/CMakeFiles/teleop_pad.dir/all’ failed
make[1]: *** [rviz_telop_commander/CMakeFiles/teleop_pad.dir/all] Error 2
make[1]: *** 正在等待未完成的任务….
CMakeFiles/Makefile2:1953: recipe for target ‘rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/all’ failed
make[1]: *** [rviz_telop_commander/CMakeFiles/rviz_telop_commander.dir/all] Error 2
Makefile:138: recipe for target ‘all’ failed
我用的是kinetic版本的,应该是在添加Cmakelist文件内容时出错,请问我如何解决这个问题,谢谢
古月老师您好,1.请问moveit中机械臂的动作规划组中在rviz中显示的时候只有有末端执行器的动作规划组才会有末端的交互小球吗?为什么我下载的机械臂模型里有的规划组不存在交互拖拽小球呢?
2.然后在没有末端规划小球的动作组做动作规划时,当然这就不能拖拽,只能随机有效位置,出现错误如下:
[ WARN] [1545915929.504385536]: Controller right_arm failed with error code INVALID_JOINTS
[ WARN] [1545915929.504691837]: Controller handle right_arm reports status FAILED
1. 需要setup assistant配置规划组之后才会出现
2. 感觉配置有问题
那请问老师,跟规划组有没有添加end_effector 没有关系吗
可以试一下
好的,谢谢古月老师
古月老师你好, 我用server 产生一个三次方的trajectory , 然后用rosrun package node 运行,并且把起点 终点通过rosservice call 赋值,想要通过rqt_plot得到trajectory 的轨迹,可是就没办法显示出这条三次曲线。terminal 中也显示了 trajectory finish 了,trajectory 这条三次曲线应该是产生成功了,但就是不能用rqt_plot 显示出来。
请问要如何把这个三次方trajectory 用rqt_plot 显示出来
多谢老师
rqt_plot是通过订阅话题把其中的数据绘制出来的
可以指教一下,如何在插件中实现订阅话题的功能?案例只有发布话题的,订阅话题要用到spinonce和回调函数,这个在类里面要如何实现,十分困扰。
和写ros的节点是一样的,创建一个订阅者的节点即可,qt中有定时器可以做处理,也可以用多线程处理
胡老师您好我下载了您的包之后编译不能通过编译到百分之6的时候就不行了 显示这个Makefile:138: recipe for target ‘all’ failed
make: *** [all] Error 2
Invoking “make -j4 -l4” fai
该怎么解决呢
ROS 版本?这里用的是indigo,kinetic编译会有问题
古月老师,我的rqt打开后没有菜单栏,是个空白页面,请问是怎么了?万分感谢
rqt打开之后默认就是空白的,在最上边应该有菜单可以选择添加的显示插件的
老师您好,我的打开在最上面没有菜单栏,全部是空白的界面
你好 我也遇到了这种情况 请问您怎么解决的?
古月老师你好,我打算做一个采集机械臂各个关节运动轨迹数据这个该怎么写,和plugin类似吗?
机器人的关节状态会通过joint_states发布出来,写个节点订阅这个话题就可以,然后需要怎么处理就在节点里处理
如果想通过rqt_plot在rviz当中实时显示出来,我在rqt_plot当中输入joint_states,但是并没有显示出轨迹曲线(通过rostopic list 已查看到joint_states有运行),请问古月老师这是什么问题
rqt_plot /joint_states position[0]:position[1]…….便可实现
joint_states是一个结构体,要把里边的具体成员变量也输入的,类似:joint_states/position[0]
古月老师请问如何实现在rviz拖动机械臂末端示教,并记录关键位置点,以便后期的轨迹再现
在demo.launch里终端是有一个拖动的控制球的,至于记录关键点,要自己实现,没有现成的功能包,请参考moveit官方的API手册
谢谢古月老师
月哥,我运行rosrun rviz rviz 时打开的界面只有一个黑色的框框了,没有左右两边的显示项了,想问一下应该怎么解决?
其他工具栏被关掉了吧,在菜单栏里找到打开就行了
古月老师你好,我在做到 点击“OK”,就会弹出“TeleopPanel”插件 这一步时没有弹出这个插件是什么原因呢?我之前也source过的,但就是找不到原因。
可以看到TeleopPanel么?你用的是哪个版本的ROS,如果是Kinetic的话,会因为Qt版本的问题打不开,需要修改编译选项
看不到的,古月老师。我纠结了好几天了 😥 。我是Ubuntu14.04版本的。
你先用《Mastering ROS for Robotics Programming》中的源码试一下,这个代码应该没问题,把source加入到bashrc中,有时候环境变量生效需要重启系统
您好,我想在Qt界面中显示rviz的地图,请问怎么在Qt中实现地图显示呢?或者说rviz显示地图消息的原理是什么?它是怎么将消息转化为地图显示的?求指点
不好意思,这个我也不是很清楚,可以找来rviz的源码看一下
有Librviz可以用
古月老师您好,我想做一个初始化机械臂的一个插件,就是那种只含一个button的插件,按照这个思路写了,显示找不到相应的库,这个例子里plugin_description.xml的lib/librviz_telop_commander是自带的库是吗?那在我这个例子里,这个库应该写什么呢?
librviz_telop_commander这个是此处生成的插件名,你插件编译的是什么名称这里就是什么
老师你好,请问use_sim_time可不可以在一个launch文件里用两次?
最好不要这样做,可以分解为两个launch
胡老师,我试了一下您上面提供的github里的包,build通过了,但是在加载的时候出现[ERROR] [1511083575.461585030]: PluginlibFactory: The plugin for class ‘rviz_teleop_commander/TeleopPanel’ failed to load. Error: Could not find library corresponding to plugin rviz_teleop_commander/TeleopPanel. Make sure the plugin description XML file has the correct name of the library and that the library actually exists.我试了一下mastering ros for robotics里的包,也出现了同样的问题。代码我都是直接用的您的,没有改动过,我的环境是ubuntu14.04+indigo,Q&A里看了一下,有的说没有source,大部分说description有问题,试着改了改,但是没有效果。
package.xml文件修改了么?
重试了一遍好了,谢谢胡老师
请问您是怎么改好的?我出现了类似的问题,我的版本是ubuntu16.04
胡老师,还有个问题,例程中的save函数和load函数都已经overide了,但是在cpp文件中定义了这两个函数后在哪里调用的呢,没有看见调用的地方。函数参数中的config配置文件也没有找到。所以这两个函数不是很清楚,请问是怎样被调用的呢?
这个是rviz插件机制需要调用的,没有体现在我们自己的程序中
那是意味着所有自己写的的插件都必须要重载这两个函数吗?是只需重载这两个函数还是其他的类成员函数也要重载呢?
只需要重载这两个函数就行
谢谢老师回复。胡老师,还有点小问题想请教:
1.我是否可以这样理解:这两个函数是在rviz插件加载的时候调用load,然后将存于“Topic”的话题名称给到qstring topic然后更新output_topic_editor_的内容?save函数是rviz 插件关闭的时候,将output_topic_里的话题名称存到“Topic”里吗?但是我delte panel 后重新add这个插件并没有自动在要发布的话题名称框里显示上次的话题,这样理解不对吧?
2.假如是这样的话重载的部分应该不是必须要有的吧?也就是说我网一个固定的话题/服务/action接口上发布数据,您例程里的load函数和save函数需要怎样重写还是不需要重写?
这两个重载的函数是用来更新界面的,但应该不是必须重载:virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
古月老师您好,请问在您在ros-industrial中介绍的调试界面是如上述在rviz中不断的添加插件做出来的吗?
是的,是通过插件做的
古月老师您好,咨询您一个问题。我用ROS采集两间教室的地图,再用cartographer离线跑着两组数据,分开跑是可以的,请问可不可以将两组数据同时在一个RVIZ中跑出来??
可以创建两个地图显示项,地图话题不能同名,然后分别订阅,试试可不可以
这里两个地图数据不是同时采集的对同时显示有没有影响,也就是时间戳这边会不会出现问题?
这个我也没做过,感觉没问题,你可以试试
对的,时间戳这边没有问题,试过了,现在就是话题名的问题,不知改怎么修改?
话题名可以重映射
重映射要不要修改发布与订阅的.cpp文件呢?
重映射不用,在launch里remap就可以
问题有点多啊,崩溃!!是不是在采集数据的时候就可以改变话题名?这个还怎么修改呢?
看你需要修改哪些话题名了,一般是在launch或者命令行里重命名,也可以启动的时候加上命名空间试试
用turtlebot搭载激光雷达采集激光雷达和里程计的数据,要把这两个数据的话题名改了?
如果有两个机器人发布同样话题的消息的话,就需要修改话题名了,否则数据会出问题
采集好的地图数据话题信息怎么修改,是通过修改发布消息和订阅消息的文件吗?
古月前辈,您好!
我想请教大神一个问题,请问urdf文件,除了做仿真,还有什么其他的作用吗?
你好,还可以可视化显示,有些功能包中的算法也会用到机器人的URDF模型
大神,我想请问一下在QT-ros环境下开发rviz的插件,开发过程中,我先不让他编译成库,先让他生成可执行文件,可是怎么不能运行呢,一直报The program has unexpectedly finished.这样的错误,我检查了一下,如果不继承自rviz::Panel这个类,继承QT原生的QWidget就可以运行。还有我调试的时候直接进到像内存一样的界面,完全看不懂的那种。就像是正常调试程序出现段错误进去那种界面。请问是不是rviz::Panel不可以实例化?
现在在开发过程中我无法运行看效果,这样比较困惑,怎样设置才可以呢,古月大神。
如果不需要rviz,用qt creator做开发调试比较方便
如果继承QT原生的QWidget,应该就是一个原生的qt程序,可以编译成可执行文件,但不算是插件,如果不需要依托rviz,这样做是没问题的。关于rviz::Panel,可以看相关的文档:http://docs.ros.org/jade/api/rviz/html/c++/classrviz_1_1Panel.html
可是我就是需要开发一个rviz的插件,所以我要继承rviz::Panel,但是这样就无法调试吗?
rviz插件的在线调试我也没试过,不确定是否可以
古月老师您好,我按照步骤都弄完了,但是我在rviz 中add时没有看到那个插件,我的编译没有问题,source也做了。我是个新手,目前比较困惑 🙂
你好,不是点rviz左下角的add,是在菜单栏里选Panel –> Add New Panel
古月老师您好,我按照步骤都弄完了,但是我在rviz 中add时没有看到那个插件,我的编译没有问题,source也做了。我是个新手,目前比较困惑
是在rviz界面的左上角,有files panels help
大神你好,有个问题,机械臂在moveit中从a点到b点的轨迹需要保持rx,ry坐标不变,怎么在程序中设置约束?
你好,也就是只在z向运动么?可以使用moveit中的cartesian_path走直线
不是z方向运动 是规划轨迹时约束末端执行器运动时orientation保持水平(即orientation x 和orientation y不变) 但是orientation z 是可变的(由moveit规划决定),这样的约束如何实现
不好意思,这个我还不太清楚
古月老师,您好!
我按照按照本篇博客的内容搭了环境,跑下来碰到两个问题:
1. 用catkin_make编译时,qt4有报错: “/usr/include/boot/type_traits/detail/has_binary_operator.hp: Parse error at “BOOST_JOIN” “,有workaround可以绕过:https://stackoverflow.com/questions/15455178/qt4-cgal-parse-error-at-boost-join,最终编译可以通过。
2. 编译成功以后,打开rviz,在”Add New Panel”里面可以找到新添加的”TeleopPanel”插件,但只要一运行程序就崩溃: Segmentation fault (core dumped)。以前没调试过这种段错误,所以这个问题没找到怎么解决,特来请教。非常感谢。
不确定是否是我环境的问题,我用的是generic Ubuntu 16.04 (desktop x64), 系统自带了QT (QMake version 2.01a, Qt version 4.8.7),ROS版本是Kinetic。现在官网QT版本最新已经是5.9了,不太清楚是不是因为Qt版本太旧了。
我用的是ubuntu14.04+ros indigo版本,在16.04和kinetic上可能会有依赖软件版本不同的问题,这个我还没试过
谢谢古月老师回复,通过修改CMakelists.txt解决了这个问题,看起来的确是一些运行时的依赖库问题。
能否具体说下修改了什么?我也学习一下
我也遇到同样的情况,运行就是段错误,请问下,您是如何修改的呢?
qt版本不一样,你试下把CMakelists.txt里边的qt4都改成qt5
古月大侠,不改前,包能编译通过,都改为qt5,出错如下:
CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5/Qt5Config.cmake:26 (find_package):
Could not find a package configuration file provided by “Qt5QtCore” with
any of the following names:
Qt5QtCoreConfig.cmake
qt5qtcore-config.cmake
Add the installation prefix of “Qt5QtCore” to CMAKE_PREFIX_PATH or set
“Qt5QtCore_DIR” to a directory containing one of the above files. If
“Qt5QtCore” provides a separate development package or SDK, be sure it has
been installed.
Call Stack (most recent call first):
ros_blog_sources/rviz_teleop_commander/CMakeLists.txt:14 (find_package)
— Configuring incomplete, errors occurred!
See also “/root/catkin_ws/build/CMakeFiles/CMakeOutput.log”.
See also “/root/catkin_ws/build/CMakeFiles/CMakeError.log”.
Makefile:2908: recipe for target ‘cmake_check_build_system’ failed
make: *** [cmake_check_build_system] Error 1
Invoking “make cmake_check_build_system” failed
查了资料,经实践测试通过,更改为qt5需要在CMakelists.txt中更改的内容为如下:
(1)添加
set (Qt5QtCore_DIR /usr/lib/x86_64-linux-gnu/cmake)
(2)Qt4 QtCore QtGui改为如下
## This plugin includes Qt widgets, so we must include Qt like so:
#find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
find_package(Qt5 COMPONENTS Core Gui REQUIRED)
## Here we specify which header files need to be run through “moc”,
## Qt’s meta-object compiler.
#qt4_wrap_cpp(MOC_FILES
qt5_wrap_cpp(MOC_FILES
src/teleop_pad.h
)
(3)编译依赖库更改如下,删除 ${QT_LIBRARIES}
#target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
添加
target_link_libraries(rviz_teleop_commander Qt5::Widgets)
编译包catkin_make –pkg rviz_teleop_commander后,运行rviz可以使用rviz plugin了
更正,查了资料,经实践测试通过,更改为qt5需要在CMakelists.txt中更改的内容为如下:
(1)添加find_package(Qt5Widgets) 以及设置Qt5QtCore_DIR,位置如下
find_package(Qt5Widgets)
catkin_package()
include_directories(${catkin_INCLUDE_DIRS})
link_directories(${catkin_LIBRARY_DIRS})
set (Qt5QtCore_DIR /usr/lib/x86_64-linux-gnu/cmake)
(2)Qt4 QtCore QtGui改为如下
## This plugin includes Qt widgets, so we must include Qt like so:
#find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
find_package(Qt5 COMPONENTS Core Gui REQUIRED)
## Here we specify which header files need to be run through “moc”,
## Qt’s meta-object compiler.
#qt4_wrap_cpp(MOC_FILES
qt5_wrap_cpp(MOC_FILES
src/teleop_pad.h
)
(3)编译依赖库更改如下,删除 ${QT_LIBRARIES}
#target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
添加
target_link_libraries(rviz_teleop_commander Qt5::Widgets)
编译包catkin_make –pkg rviz_teleop_commander后,运行rviz可以使用rviz plugin了
赞,学习了,非常感谢!
还有一个需要改动的:
#include(${QT_USE_FILE})
include_directories(${QT_USE_FILE})
不然还是会报错。
古月老师,您好,想问下,您有做过ROS与android的通讯连接吗?我在示例中看有rosbridge这个包,但是不是特别懂
ros有java的接口实现,可以在android上跑ros节点,可以google找一下,turtlebot好像也有android的控制客户端
好的,那我找找看,谢谢您了
古月老师,您好!
咨询您一个问题!
我现在使用的是window操作系统,想远程控制Ubuntu,嘿嘿,就是Ubuntu上面安装了ROS。
现在按照网络上的教材可以远程连接上了,问题是只有命令行界面,没有图形化界面。
只要运行类似RVIZ,GAZEBO之类的就不行。
请问,有什么办法能够让远程控制的Ubuntu能够运行这些图形界面么?
非常感谢!
Celine
Best Regards
Hope you happy every day!
可以用teamviewer