实验编号: 实验指导书 实验项目: 调试与可视化 所属课程: ROS机器人操作系统基础与实战 课程代码: 面向专业: 机电专业 课程负责人: 朱笑笑 年月 日
实验编号: 实 验 指 导 书 实验项目: 调试与可视化 所属课程: ROS 机器人操作系统基础与实战 课程代码: 面向专业: 机电专业 课程负责人: 朱笑笑 年 月 日
、 实验目的 让学生熟悉程序ROS中程序调试的方法,程序数据可视化等方法。为将来的 程序开发提供指导。 二、 实验内容 1.调试消息的使用 2. 检查系统的运行状态 3. 绘制数值量 4. 显示图像 5. 保存回放图像 6. Rqt的使用 三、 实验过程或其他示意图 1.调试消息的使用 在简单的C+程序开发的时候,我们通常会使用printf,或者cout等输出程序中我们 感兴趣的一些信息。而OS为我们提供了更为功能强大,使用更方便的方法,输出一个调试 信息。 1.1输出一个调试信息 OS包含了一组函数或者宏定义来让我们输出一个调试信息,或者错误信息或者警告, 亦或者只是一些简单的信息。 尝试在程序的任何位置使用以下命令在程序运行的终端来输出一个调试信息。 ROS INFO("My INFO message."); 使用这些功能或者宏我们可以不添加任何新的头文件,但是我们可以添加一个 ros/console.h如下 #include <ros/ros.h> #include <ros/console.h> #include <log4cxx/logger.h> 程序将输出 INFO][1356440230.837067170]:My INFO message. 所有的消息输出时都会显示其等级和当前时间戳如上。其中实践戳时冲1970年1月1 日凌晨0点开始的纳秒时间。 类似于printf,可以在消息中打印出变量的值const double val=3.l4; ROS INFO("My INFO message with argument:%f",val ) 定义一个val变量,以浮点类型输出 另外还可以使用cout初始类似的样式。ROS中支持C+STL流。 ROS INFO STREAM( "My INFO stream message with argument:"<val 2
- 2 - 一、 实验目的 让学生熟悉程序ROS中程序调试的方法,程序数据可视化等方法。为将来的 程序开发提供指导。 二、 实验内容 1. 调试消息的使用 2. 检查系统的运行状态 3. 绘制数值量 4. 显示图像 5. 保存回放图像 6. Rqt 的使用 三、 实验过程或其他示意图 1. 调试消息的使用 在简单的 C++程序开发的时候,我们通常会使用 printf,或者 cout 等输出程序中我们 感兴趣的一些信息。而 ROS 为我们提供了更为功能强大,使用更方便的方法,输出一个调试 信息。 1.1 输出一个调试信息 ROS 包含了一组函数或者宏定义来让我们输出一个调试信息,或者错误信息或者警告, 亦或者只是一些简单的信息。 尝试在程序的任何位置使用以下命令在程序运行的终端来输出一个调试信息。 ROS_INFO( "My INFO message." ); 使用这些功能或者宏我们可以不添加任何新的头文件,但是我们可以添加一个 ros/console.h 如下 #include <ros/ros.h> #include <ros/console.h> #include <log4cxx/logger.h> 程序将输出 [ INFO] [1356440230.837067170]: My INFO message. 所有的消息输出时都会显示其等级和当前时间戳如上。其中实践戳时冲 1970 年 1 月 1 日凌晨 0 点开始的纳秒时间。 类似于 printf,可以在消息中打印出变量的值 const double val = 3.14; ROS_INFO( "My INFO message with argument: %f", val ); 定义一个 val 变量,以浮点类型输出 另外还可以使用cout初始类似的样式。ROS中支持C++STL流。 ROS_INFO_STREAM( "My INFO stream message with argument: " << val );
可以得到和上面一样的效果。注意传统的C+流包含了Cout和cerr,在ROS中并没有显示 的说明使用了哪个流,这个通过对应的调试信息的level来确定。 1.2设置调试信息的1eve1 ROS有5个典型的日志1evel,从低到高为DEBUG,INFO,WARN,ERROR,和FATAL. 在打印消息时可以指定消息的level ROS<LEVEL>「<OTHER>J 其中DEBUG和NFO都会到用cout(或者stdout),而WARN,ERROR,和FATAL将会 进到cerr(或者stderr)。同时各种levelt的消息在打印的时候后有不同的颜色以便于区别。 DEBUG为绿色,NFO白色,WARN黄色,ERROR红色,and FATAL紫色 利用调试消息的LEVEL可以让我们的调试信息组织的更加清晰,在实际使用过程中,我 们可以设定一个最低的Level,低于该Levell的消息将会被忽略掉。 在一个实际的node中配置调试1evel 默认情况下是有INFO或者以上level的消息才会显示.ROS使用这个消息level来滤除一 个实际ode发送的消息。有很多实现方法。可以在程序编译的时候,可以在程序启动的时候 通过一个配置文件来实现,除此之外还可以动态的改变这个level,具体来说可以利用 rosconsloerxconsole 首先,通过源码的形式实现在编译过程中确定调试level。在main函数中,在调用了ros: init后,插入以下代码: /Set the logging level manually to DEBUG ROSCONSOLE AUTOINIT; log4cxx::LoggerPtr my_logger log4cxx::Logger:getLogger(ROSCONSOLE DEFAULT_NAME ) my_logger->setLevel( ros::console::g_level_lookup[ros::console::levels::Debug] 注意,在CMakeLists..txt中需要链接到1og4 cxxlibrary。 find library(LOG4CXX LIBRARY log4cxx) add_executable(examplel src/example1.cpp) target link libraries(examplel Sfcatkin LIBRARIES SLOG4CXX LIBRARY}) 可以观察到这样修改后,DEBUG(或更高)level的消息了。请自己修改成其它的级别查 看效果。 测试通过配置文件来改变调试1evel的方法。 首先,创建一个文件夹config。.并创建一个文件debug_level.config,在该文件中输入 以下内容 log4j.logger.ros.chapter4=DEBUG 然后,我们可以通过设置ROSCONSOLE CONFIG FILE环境变量指向这个文件,就 可以起到作用。也可以通过launch文件的方法来实现。在原来的launch方法文件基础上添加 -3-
- 3 - 可以得到和上面一样的效果。注意传统的C++流包含了Cout和cerr,在ROS中并没有显示 的说明使用了哪个流,这个通过对应的调试信息的level来确定。 1.2 设置调试信息的level ROS有5个典型的日志level,从低到高为DEBUG, INFO, WARN, ERROR,和FATAL. 在打印消息时可以指定消息的level ROS_<LEVEL>「<OTHER>」 其中DEBUG和INFO都会到用cout(或者stdout), 而WARN, ERROR,和FATAL将会 进到cerr(或者stderr)。同时各种level的消息在打印的时候后有不同的颜色以便于区别。 DEBUG为绿色,INFO白色, WARN 黄色, ERROR红色, and FATAL紫色 利用调试消息的LEVEL可以让我们的调试信息组织的更加清晰,在实际使用过程中,我 们可以设定一个最低的Level,低于该Level的消息将会被忽略掉。 在一个实际的node中配置调试level 默认情况下是有INFO或者以上level的消息才会显示。ROS 使用这个消息level来滤除一 个实际node发送的消息。有很多实现方法。可以在程序编译的时候,可以在程序启动的时候 通过一个配置文件来实现,除此之外还可以动态的改变这个level,具体来说可以利用 rosconsloe和rxconsole 首先,通过源码的形式实现在编译过程中确定调试level。在main函数中,在调用了ros:: init后,插入以下代码: // Set the logging level manually to DEBUG ROSCONSOLE_AUTOINIT; log4cxx::LoggerPtr my_logger = log4cxx::Logger::getLogger( ROSCONSOLE_DEFAULT_NAME ); my_logger->setLevel( ros::console::g_level_lookup[ros::console::levels::Debug] ); 注意,在CMakeLists.txt中需要链接到log4cxxlibrary。 find_library(LOG4CXX_LIBRARY log4cxx) add_executable(example1 src/example1.cpp) target_link_libraries(example1 ${catkin_LIBRARIES} ${LOG4CXX_LIBRARY}) 可以观察到这样修改后,DEBUG(或更高)level的消息了。请自己修改成其它的级别查 看效果。 测试通过配置文件来改变调试level的方法。 首先,创建一个文件夹config。并创建一个文件debug_level.config,在该文件中输入 以下内容 log4j.logger.ros.chapter4=DEBUG 然后,我们可以通过设置ROSCONSOLE_ CONFIG_FILE 环境变量指向这个文件,就 可以起到作用。也可以通过launch文件的方法来实现。在原来的launch方法文件基础上添加
env字段。 <launch> <1--Logger config--> <env name="ROSCONSOLE CONFIG FILE" value="$(find chapter4)/config/chapter4. config"/> <1--Example 1--> <node pkg="chapter4"type="examplel"name="examplel" output="screen"/> </launch> 为消息添加一个名字 因为在同一个ode中的任何地方都可以发送消息消息,这样当我们在多处发出消息时就 不确定时哪个位置发出的消息。为了解决这个问题,ROS提供了一个能够在发出消息时附加 一个名字的方法。具体是使用ROS<LEVEL>[STREAM]NAMED功能,请添加以下代码 并观察输出结果 ROS INFO STREAM NAMED( "named msg", "My named INFO stream message;val ="<val 利用这个带有名字的消息,我们可以在前面的config文件中直接设定每一个名字下的系 统系的显示级别。如下,将名字为named msg的消息的显示级别设定为ERROR log4j.logger.ros.chapter4.named_msg=ERROR 带条件和滤除的消息 带条件的消息只有在条件满足的情况下,才会输出。通过 ROS<LEVEL>STREAM]COND[NAMED]函数可以实现该功能。 /Conditional messages: ROS INFO STREAM COND( val <0., "My conditional INFO stream message;val ("<val <<")<0" ROS INFO STREAM COND( val>=0., "My conditional INFO stream message;val ("<val <<")>=0" /Conditional Named messages: ROS INFO STREAM COND NAMED( "cond named msg",val <0., "My conditional INFO stream message;val ("<val <<")<0" ROS INFO STREAM COND( "cond named msg",val >=0., "My conditional INFO stream message;val ("<val <<")>=0" -4-
- 4 - env字段。 <launch> <!-- Logger config --> <env name="ROSCONSOLE_CONFIG_FILE" value="$(find chapter4)/config/chapter4. config"/> <!-- Example 1 --> <node pkg="chapter4" type="example1" name="example1" output="screen"/> </launch> 为消息添加一个名字 因为在同一个node中的任何地方都可以发送消息消息,这样当我们在多处发出消息时就 不确定时哪个位置发出的消息。为了解决这个问题,ROS提供了一个能够在发出消息时附加 一个名字的方法。具体是使用ROS_<LEVEL>[_STREAM]_NAMED 功能,请添加以下代码 并观察输出结果 ROS_INFO_STREAM_NAMED( "named_msg", "My named INFO stream message; val = " << val ); 利用这个带有名字的消息,我们可以在前面的config文件中直接设定每一个名字下的系 统系的显示级别。如下,将名字为named_msg的消息的显示级别设定为ERROR log4j.logger.ros.chapter4.named_msg=ERROR 带条件和滤除的消息 带条件的消息只有在条件满足的情况下,才会输出。通过 ROS_<LEVEL>[_STREAM]_COND[_NAMED] 函数可以实现该功能。 // Conditional messages: ROS_INFO_STREAM_COND( val < 0., "My conditional INFO stream message; val (" << val << ") < 0" ); ROS_INFO_STREAM_COND( val >= 0., "My conditional INFO stream message; val (" << val << ") >= 0" ); // Conditional Named messages: ROS_INFO_STREAM_COND_NAMED( "cond_named_msg", val < 0., "My conditional INFO stream message; val (" << val << ") < 0" ); ROS_INFO_STREAM_COND( "cond_named_msg", val >= 0., "My conditional INFO stream message; val (" << val << ") >= 0" );
滤除的消息功能本质和带条件的非常类似,但是它允许我们去定义一个从 ros:console:FilterBase扩展出来的自定义的滤波器。使用 ROS<LEVEL>STREAM)FILTER[NAMED]函数即可以使用滤波器的消息,其中第一 个参数为滤波器指针。例子如下: struct MyLowerFilter:public ros::console::FilterBase{ MyLowerFilter(const double&val )value(val ) inline virtual bool isEnabled() return value <0.: } double value: struct MyGreaterEqualFilter:public ros::console::FilterBase{ MyGreaterEqualFilter(const double&val )value(val inline virtual bool isEnabled() return value>=0.; double value; ; MyLowerFilter filter_lower(val);方 MyGreaterEqualFilter filter_greater_equal(val ) ROS INFO STREAM FILTER( &filter lower. "My filter INFO stream message;val ("<val <<")<0" ROS INFO STREAM FILTER( &filter_greater_equal, "My filter INFO stream message;val ("<val <<")>=0" 其它类型的消息一单次、定时、组合。 测试控制消息的发出次数。利用ROS<LEVEL>STREAM)ONCE[NAMED]函数可以显 示消息的单次输出。无论函数被调用了几次,只有一次输出 for(int i=0;i<10;+i){ ROS_INFO _STREAM_ONCE( "My once INFO stream message;i="<<i ) 定时的输出,可以控制该消息在一定时间内可以输出,过了该时间短,即使再次调用该函数 也不会再有输出。第一个参数为时间区域。 for(int i=0;i<10;+i){ -5-
- 5 - 滤除的消息功能本质和带条件的非常类似,但是它允许我们去定义一个从 ros::console::FilterBase 扩展出来的自定义的滤波器。使用 ROS_<LEVEL>[_STREAM]_FILTER[_NAMED] 函数即可以使用滤波器的消息,其中第一 个参数为滤波器指针。例子如下: struct MyLowerFilter : public ros::console::FilterBase { MyLowerFilter( const double& val ) : value( val ) {} inline virtual bool isEnabled() { return value < 0.; } double value; }; struct MyGreaterEqualFilter : public ros::console::FilterBase { MyGreaterEqualFilter( const double& val ) : value( val ) {} inline virtual bool isEnabled() { return value >= 0.; } double value; }; MyLowerFilter filter_lower( val ); MyGreaterEqualFilter filter_greater_equal( val ); ROS_INFO_STREAM_FILTER( &filter_lower, "My filter INFO stream message; val (" << val << ") < 0" ); ROS_INFO_STREAM_FILTER( &filter_greater_equal, "My filter INFO stream message; val (" << val << ") >= 0" ); 其它类型的消息—单次、定时、组合。 测试控制消息的发出次数。利用ROS_<LEVEL>[_STREAM]_ONCE[_NAMED] 函数可以显 示消息的单次输出。无论函数被调用了几次,只有一次输出 for( int i = 0; i < 10; ++i ) { ROS_INFO_STREAM_ONCE( "My once INFO stream message; i = " << i ); } 定时的输出,可以控制该消息在一定时间内可以输出,过了该时间短,即使再次调用该函数 也不会再有输出。第一个参数为时间区域。 for( int i = 0; i < 10; ++i ) {