ROS外传:程序调试(c++)

选择调试器

写了ROS程序,如果调试呢?很长一段时间,我都是通过cout变量看哪儿除了问题进行调试的,大佬勿笑话.其实程序不大的话还是蛮方便,什么多余的设置都不用.然而面对大型的程序这就有些吃力了.一般大家通过IDE调试程序,ROS官方列出了许多可用的IDE
http://wiki.ros.org/IDEs
调试程序最常用的一般来说无非就是: 加断点,显示变量值,执行下一步等几个命令.
大家使用的IDE可能不一样.我使用的VScode,有的使用Qtcreator, Ecllipse, Clion,有的不使用IDE.要调试ROS的话,每个IDE都有不同的设置方法.VScode我目前为止都不知道怎么设置= =...在上面的网址下给出了VScode关于ROS的plugin,我安装了.这个plugin能给出的功能其实自身并不包含调试,而是使一些ros命令方便在VScode里实现.
我注意到qtCreator等几个IDE貌似添加了很好的ROS辅助功能,不过我查找了一番(并没有花太多时间,也许遗漏了),里面讲了怎么在IDE里设置ROS啊什么的,但是没有讲之后该怎么做.也就就是普通的在某一行程序旁添加断点??我也许以后才取试了,我想找一个比较universal的方法.跟什么IDE没有关系,那么这就非使用gdb莫属了.
gdb就相当于ubuntu自带的debugger吧.具体能调试哪些语言什么见官网.
https://www.gnu.org/software/gdb/
使用gdb调试,和程序猿理想中的调试方法有些出入.使用IDE习惯了的用户,设置断点会在程序旁某个位置点一下,然后运行程序调试.程序就会在断点处暂停.
gdb调试,一切都在terminal中使用命令行实现
https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf
上面pdf中的内容包含了gdb调试最常用的命令,我们根据它来调试程序.

普通的非ROS程序用gdb怎么调试呢?在编译好后(编译的方法和正常的程序一样,不过要在cmakelists前面添加)

set(CMAKE_BUILD_TYPE Debug)

之后直接使用
gdb 可执行程序 就可以进入gdb调试模式了.如果你的程序需要添加一些输入,比如说,你正常跑程序是下面这样

./可执行程序 arg1 arg2 arg3

那么你使用gdb的话就是

gdb 可执行程序
r arg1 arg2 arg3

r代表的是run
ROS里调试稍微有些不一样,不过大体相同.
我们先写一段ROS代码.再使用gdb尝试添加断点,查看变量等内容.使用的代码是我们在ROS从入门到放弃第二讲的内容中用到的pub数据类型Int8的代码.没看过那个的也没关系,和ROS官方tutorial发布一个string的代码几乎一样.下面列出代码

#include "ros/ros.h"
#include "std_msgs/Int8.h" //#include "std_msgs/String.h"

#include <sstream>

//publish int8 number
int main(int argc, char **argv)
{
  ros::init(argc, argv, "talker");

  ros::NodeHandle n;

  ros::Publisher chatter_pub = n.advertise<std_msgs::Int8>("chatter", 1000); //ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  int count = 0;
  while (ros::ok())
  {
    std_msgs::Int8 msg; //std_msgs::String msg;

    // std::stringstream ss;
    // ss << "hello world " << count;
    msg.data = count;// msg.data = ss.str();

    ROS_INFO("%d", msg.data); //ROS_INFO("%f", msg.data.c_str())

    chatter_pub.publish(msg); //line 28

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }


  return 0;
}

把这段程序随意写入一个ros package当中,写入CMakeLists.txt进行编译.我们还需要在pakcage的CMakeLists.txt接近顶部添加

set(CMAKE_BUILD_TYPE Debug)

其实这个我没试过哈哈哈,但是应该能针对某一个package作用,自己我直接把所有ros package都设置成debug模式了.方法是使用catkin_make编译的时候,往后添加一点东西

catkin_make -DCMAKE_BUILD_TYPE=Debug 

这样编译之后,你的所有程序都可以使用gdb进行debug了.

开始调试

跑ros程序的两个方法一个是rosrun,一个是roslaunch.使用下面语句执行文件

rosrun --prefix 'gdb -ex run --args' [package_name] [node_name] 

执行完上面的语句,你会发现程序直接开始跑了,我还来不及设置断点什么的呢.问题应该出在run那个参数上,不过我暂时没找到替代的,得想想其他办法.
rosrun其实就相当于直接执行二进制文件./文件.那么我们直接找到catkin_make产生的二进制文件进行运行不就完了?每一个package产生的二进制文件存放的位置在

you_catkin_workspace/devel/lib/your_package_name

里.cd进去上面的地址,你应该能看到你在CMakeLists.txt里通过add_executable产生的那个二进制文件的名字(就是rosNode了).在terminal中输入

gdb node_name

就会发现进入gdb模式了,terminal的输出像下面这样

gdbDebug.png

这时候我们可以输入第三个链接pdf中的命令进行调试了.
设置断点
pdf中写的设置断点的方法为break <where>,这个where指的是程序的哪一行,由于简书的代码段貌似不能显示行数,我在上面的程序的28行注释了一下line 28.我们在terminal中输入

break 28

会看到一则消息关于断点设置的.然后我们就可以跑程序了.在terminal中输入

run

我们根据terminal的输出应该能很轻易的知道28行程序暂停了.断点已经设置成功了.
另外也可以

break 函数名

设置断点,这样进入函数的时候程序会暂停
查看变量值 
现在我们要查看某个变量的值呢?pdf中显示是print/format <what>或者display/format <what>.what表示是什么变量.我们在terminal中输入

display count

便能看到程序中变量count的值了.
执行下一步
同样查看pdf得知,在terminal中输入next就可以了.
设置被包含的程序的断点
我们写大型程序的时候,一个rosnode肯定include了好多文件,上面的break 28默认在主函数中设置断点了,那么我们想在其他不在同一个cpp文件中的函数设置断点之类的呢?比如我们在CMakeLists.txt中编译的时候使用的下面语句

add_executable(main main.cpp b.cpp c.cpp)

之后使用

gdb main

进行调试,如果我们想在b.cpp中加一个断点,我们只需要在terminal中特殊指明是哪个cpp加上行数即可,比如

break b.cpp:line_number

其中line_number表示你想在b.cpp中的哪行代码添加breakpoint.
显示出错的位置
gdb调试出错了,比如出现segmentation fault,通常会自动显示出错位置,输入where可以显示出更详细的内容
退出gdb
程序正在运行,按下crtl+c,在输入q退出.
程序没有运行,直接输入q退出.
总之根据pdf我们慢慢尝试,把gdb调试运用熟练.上面的调试其实和ROS没有什么关系,普通的c++程序编译好后也是这么调试.使用roslaunch时则稍有不同.但是非常简单.比在需要调试的那个node之后添加一句话就可以了.比如上面的发布int8的程序,假设名字叫debugTest1.cpp,在test包里,由他编译出来的node的名字是debugTest1.跑这个nodelaunch文件名叫debugTest.launch,内容如下

<launch>
<node pkg="test"
      type="debugTest1" name="debugTest1" output="screen"/>
</launch>

那么为了debug,只需要再该node改成下面即可

<launch>
<node pkg="test"
      type="debugTest1" name="debugTest1" output="screen"
         launch-prefix="xterm -e gdb --args"/>
</launch>

之后仍旧如常地跑文件roslaunch test debugTest.launch
会出现下面的窗口

debugRoslaunch.png

你会在上方小的黑色窗口里输入gdb的相关命令进行调试.
roslaunch里添加的那一行内容也可以更换,见
http://wiki.ros.org/roslaunch/Tutorials/Roslaunch%20Nodes%20in%20Valgrind%20or%20GDB
我们选择的是第一个.你可以自己添加其他内容试试.

一些小的trick或者命令

print Eigen矩阵
如果x代表矩阵,那么命令这么书写

print *x.data()@length_x

其中length_x是矩阵的row*column.如果length_x小于矩阵的size的话,那么会由第一行第一个从左往右输出到第二行到第三行...由此到length_x长度.
如果直接print x则除了矩阵的内容之外还有一大堆多余的东西.
在load shared library的时候暂停

set stop-on-solib-events 1

使用了这行命令在每次有shared library载入的时候程序会暂停.这时候你可以针对该lib设置断点什么的.其实可以直接设置尚未载入的lib的source文件的断点,语法和设置被包含的程序的断点那部分一样.不过由于lib尚为被载入所以找不到程序,gdb会问你

No source file named System.cpp.
Make breakpoint pending on future shared library load? (y or [n]) 

选y就可以了.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容