
需要特别说明:ROS版本必须与Ubuntu系统版本匹配
实验环境:
ROS Fuerte
Ubuntu 12.04
ROS软件框架附带了大量功能强大的工具,包括调试工具、数据可视化工具、系统监测组件。ROS提供了一系列通用绘图工具,其中有针对标量值的时序绘图工具、支持双目立体视觉的图像展示工具、rviz等3D可视化工具(能够呈现点云、激光扫描等3D数据)。
1 调试ROS节点
(1)使用GDB调试器调试ROS节点
在ROS系统中允许使用GDB调试器对常规的C/C++程序进行调试。这里我们展示如何在GDB中运行chapter3_tutorials功能包中的example1节点。创建chapter3_tutorials功能包,并新建编译example1节点,example1.cpp中的代码如下:
#include "ros/ros.h"
int main( int argc, char **argv )
{
ros::init( argc, argv, "example1" );
ros::NodeHandle n;
const double val = 3.14;
ROS_DEBUG( "This is a simple DEBUG message!" );
ROS_DEBUG( "This is a DEBUG message with an argument: %f", val );
ROS_DEBUG_STREAM(
"This is DEBUG stream message with an argument: " << val
);
ros::spinOnce();
return EXIT_SUCCESS;
}进入功能包路径:
$ roscd davebobo_tutorials/然后,在GDB里面运行以下命令:
$ gdb bin/example1一旦roscore已经启动,你就可以通过点击R键或Enter键从GDB中启动节点,也可以用L键列出相关的源代码。如果一切正常,在调试器内运行节点后就能在GDB终端看到下面的输出

(2)ROS节点启动时调用GDB调试器
如果在启动节点时使用启动文件来完成的话,就可以通过XML语法修改启动文件中的节点属性,在节点启动时调用GDB调试器。在chapter3_tutorials功能包中的example1,添加以下节点信息到launch文件夹下,文件名称为example1_gdb.launch内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<!-- Logger config -->
<env name="ROSCONSOLE_CONFIG_FILE"
value="$(find chapter3_tutorials)/config/chapter3_tutorials.config"/>
<!-- Example 1 -->
<node pkg="chapter3_tutorials" type="example1" name="example1"
output="screen" launch-prefix="xterm -e gdb --args"/>
</launch>注意功能包传递给pkg属性,节点名称传递给type属性。
除此之外,我们可以通过调试信息(ROS内置log4cxx)和使用rosconsole以及rxconsole在运行时修改调试级别。
(3)监视系统状态
在系统运行时可能同时有多个节点和多个主题在发布消息,通过订阅与其他节点连接。ROS提供了一些基本而又非常强大的工具,它们不仅能实现状态监视,还能探测节点状态图中任何节点发生的功能失效。
①使用rxgraph在线监视节点状态图
ROS框架可以使用
rxgraph工具通过一个有向图显示在系统中运行的节点和这些节点通过主题实现的发布者到订阅者的连接。这里展示一个案例
第一步:创建服务SetSpeed.srv,记得将CMakeLists.txt中的rosbuild_gensrv()前的#去掉
float32 desired_speed
---
float32 previous_speed
float32 new_speed
bool stalled第二步:新建节点example4和example5
example4.cpp中的代码
#include <ros/ros.h>
#include <ros/console.h>
#include <std_msgs/Int32.h>
#include <geometry_msgs/Vector3.h>
#include <chapter3_tutorials/SetSpeed.h>
int main( int argc, char **argv )
{
ros::init( argc, argv, "example4" );
ros::NodeHandle n;
ros::Publisher pub_temp = n.advertise< std_msgs::Int32 >( "temp", 1000 );
ros::Publisher pub_accel = n.advertise< geometry_msgs::Vector3 >( "accel", 1000 );
ros::ServiceClient srv_speed = n.serviceClient< chapter3_tutorials::SetSpeed>( "speed" );
std_msgs::Int32 msg_temp;
geometry_msgs::Vector3 msg_accel;
chapter3_tutorials::SetSpeed msg_speed;
int i = 0;
ros::Rate rate( 1 );
while( ros::ok() ) {
msg_temp.data = i;
msg_accel.x = 0.1 * i;
msg_accel.y = 0.2 * i;
msg_accel.z = 0.3 * i;
msg_speed.request.desired_speed = 0.01 * i;
pub_temp.publish( msg_temp );
pub_accel.publish( msg_accel );
if( srv_speed.call( msg_speed ) )
{
ROS_INFO_STREAM(
"SetSpeed response:n" <<
"previous speed = " << msg_speed.response.previous_speed << "n" <<
"new speed = " << msg_speed.response.new_speed << "n" <<
"motor stalled = " << ( msg_speed.response.stalled ? "true" : "false" )
);
}
else
{
// Note that this might happen at the beginning, because
// the service server could have not started yet!
ROS_ERROR_STREAM( "Call to speed service failed!" );
}
++i;
ros::spinOnce();
rate.sleep();
}
return EXIT_SUCCESS;
}example5.cpp中的代码
#include <ros/ros.h>
#include <ros/console.h>
#include <std_msgs/Int32.h>
#include <geometry_msgs/Vector3.h>
#include <chapter3_tutorials/SetSpeed.h>
float previous_speed = 0.;
float new_speed = 0.;
void callback_temp( const std_msgs::Int32::ConstPtr& msg )
{
ROS_INFO_STREAM( "Temp = " << msg->data );
}
void callback_accel( const geometry_msgs::Vector3::ConstPtr& msg )
{
ROS_INFO_STREAM(
"Accel = (" << msg->x << ", " << msg->y << ", " << msg->z << ")"
);
}
bool callback_speed(
chapter3_tutorials::SetSpeed::Request &req,
chapter3_tutorials::SetSpeed::Response &res
)
{
ROS_INFO_STREAM(
"speed service request: desired speed = " << req.desired_speed
);
new_speed = 0.9 * req.desired_speed;
res.previous_speed = previous_speed;
res.new_speed = new_speed;
res.stalled = new_speed < 0.1;
previous_speed = new_speed;
return true;
}
int main( int argc, char **argv )
{
ros::init( argc, argv, "example5" );
ros::NodeHandle n;
ros::Subscriber sub_temp = n.subscribe( "temp", 1000, callback_temp );
ros::Subscriber sub_accel = n.subscribe( "accel", 1000, callback_accel );
ros::ServiceServer srv_speed = n.advertiseService( "speed", callback_speed );
while( ros::ok() ) {
ros::spin();
}
return EXIT_SUCCESS;
}第三步:在launch文件夹下新建example4_5.launch,内容如下
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<!-- Example 4 and 5 -->
<node pkg="chapter3_tutorials" type="example4" name="example4"
output="screen"/>
<node pkg="chapter3_tutorials" type="example5" name="example5"
output="screen"/>
</launch>第四步:编辑CMakeLists.txt,将以下命令行复制到文件的末尾处,编译
rosbuild_add_executable(example4 src/example4.cpp)
rosbuild_add_executable(example5 src/example5.cpp)第五步:将使用以下文件同时运行example4和example5节点
$ roslaunch chapter3_tutorials example4_5.launch用rxgraph 工具对当前运行的系统中状态图形化显示
$ rxgraph --
②roswtf检测功能包中所有组件潜在的问题
使用roscd移动到你想要分析的功能包路径下,然后运行roswtf。

References:
[1]. Aaron Martinez Enrique Fern andez, ROS机器人程序设计[B], P43-58, 2014.
http://wiki.ros.org/rxgraph
http://www.ncnynl.com/
本文介绍ROS中的调试工具和技术,包括使用GDB调试器的方法、通过XML语法在启动时调用GDB,以及如何利用rxgraph工具监视节点状态图。此外还介绍了roswtf工具用于检测功能包中组件的潜在问题。
4240

被折叠的 条评论
为什么被折叠?



