平台Ubuntu20.04 + ROS noetic
程序算法:VINS-mono
在阅读本文之前,建议先行了解基本的vscode调试工具与流程,以及如何安装vscode的ROS扩展,详情请参考博文:Ubuntu20.04+vscode快速调试ROS通用程序_tanmx219的博客-CSDN博客(PlaceHolder.....)这里假设你已经安装好了ROS noetic和git。(1) 安装vscode和extensionsubuntu上如何安装vscode可以参考官网,Running Visual Studio Code on Linux需要安装的vscode扩展如下,C/C++ (c++ intellisense and configuration help) -> MandatoryClangd (Alternative intellisense provhttps://blog.csdn.net/tanmx219/article/details/122799015
Ubuntu上安装vscode可参考官网,
Running Visual Studio Code on Linux我
我把其实的安装那段摘录如下,
The easiest way to install Visual Studio Code for Debian/Ubuntu based distributions is to download and install the .deb package (64-bit), either through the graphical software center if it's available, or through the command line with:
sudo apt install ./.deb
# If you're on an older Linux distribution, you will need to run this instead:
# sudo dpkg -i .deb
# sudo apt-get install -f # Install dependencies
Note that other binaries are also available on the VS Code download page.
Installing the .deb package will automatically install the apt repository and signing key to enable auto-updating using the system's package manager. Alternatively, the repository and key can also be installed manually with the following script:
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/
sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
rm -f packages.microsoft.gpg
Then update the package cache and install the package using:
sudo apt install apt-transport-https
sudo apt update
sudo apt install code # or code-insiders
过程和使用gdb调试没什么不同,主要是生成带调试符号的二进制文件(库文件或可执行文件),
catkin_make -DCMAKE_BUILD_TYPE=Debug
或者,直接在vscode中修改各个CMmakeLists.txt,
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
这里顺带说明一下,用
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -Wall -g -ggdb")
或
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
没看出有什么区别,指令($env | grep CXX)找了一下,什么也没找到,也没看到VINS-Mono中哪里有定义,不知道是不是我对cmake理解不到位。
如果纯粹使用gdb的话,这里就可以开始调试了,注意要source setup.bash先,然后逐个打开terminal用gdb调试节点。
我个人更偏向于使用vscode这种IDE调试的方式,所以下面重点讲解,
我的vins-estimator下面euroc.launch的内容如下,
可以看到有3个节点,vs这个IDE大家应该都会用,配置C++配置文件的过程就不多讲了,配置和参考中给出的稍有不同,有些默认的参数我没有修改,比如cStandard,没发现什么问题。当然你也可以选不同的编译器,对vins_mono和vins_fusion,一般cStandard是c11,cppStandard是c++17。
快捷键ctrl+shift+p,找到C/C++ :Edit configurations (JSON),添加c_cppproperties.json文件,这个文件应该是指定一些路径和语言标准,如下,
c_cpp_properties.json
{
"configurations": [
{
"name": "Linux",
"browse": {
"databaseFilename": "",
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"${workspaceFolder}/**",
"/opt/ros/noetic/include/**",
"/usr/include/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
快捷键ctrl+shift+p,找到Tasks:Configure Task,添加tasks.json文件,这个文件指定一些catkin_make的编译参数。
注意这里的定义"-DCMAKE_BUILD_TYPE=Debug",
tasks.json
{
"tasks": [
{
"label": "prerun",
"type": "shell",
"command": "source ./devel/setup.sh && export ROS_MASTER_URI=http://localhost:11311/ "
},
{
"label": "catkin_make", //代表提示的描述性信息
"type": "shell", //可以选择shell或者process,如果是shell代码是在shell里面运行一个命令,如果是process代表作为一个进程来运行
"command": "catkin_make",//这个是我们需要运行的命令
"args": [],//如果需要在命令后面加一些后缀,可以写在这里,比如-DCATKIN_WHITELIST_PACKAGES=“pac1;pac2”
"group": {"kind":"build","isDefault":true},
"presentation": {
"reveal": "always"//可选always或者silence,代表是否输出信息
},
"problemMatcher": "$msCompile"
},
{
"label": "compound_build",
"dependsOn": [
"catkin_make",
"prerun"
]
}
],
"version": "2.0.0"
}
附加说明
tasks可以附加取launch.json的preLaunchTask指令中(下面的例子里没有填)。
如果需要在launch之前运行tasks.json里的任务,就可以加上这一条,比如这里tasks.json里有一个名字叫"catkin_make",你可以通过
"preLaunchTask": "catkin_make"
这样的语句使程序在启动前都编译一次源码。
如果要运行全部task,可以通过下面的指令实现
"preLaunchTask": "compound_build"
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "feature_tracker",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/devel/lib/feature_tracker/feature_tracker",
"args": ["_config_file:=${workspaceFolder}/src/VINS-Mono/config/euroc/euroc_config.yaml", "_vins_folder:=${workspaceFolder}/src/VINS-Mono/"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ 生成活动文件",
"miDebuggerPath": "/usr/bin/gdb"
},
{
"name": "vins_estimator",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/devel/lib/vins_estimator/vins_estimator",
"args": ["_config_file:=${workspaceFolder}/src/VINS-Mono/config/euroc/euroc_config.yaml", "_vins_folder:=${workspaceFolder}/src/VINS-Mono/"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "pose_graph",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/devel/lib/pose_graph/pose_graph",
"args": ["_config_file:=${workspaceFolder}/src/VINS-Mono/config/euroc/euroc_config.yaml", "_visualization_shift_x:=0", "_visualization_shift_y:=0", "_skip_cnt:=0", "_skip_dis:=0"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
],
"compounds": [
{
"name": "tracker/estimator/pose",
"configurations": [
"feature_tracker",
"vins_estimator",
"pose_graph"
]
}
]
}
这里要注意,如果老是碰到下面的错误,
Unable to open 'raise.c': Unable to read file '/build/glibc-eX1tMB/glibc-2.31/sysdeps/unix/sysv/linux/raise.c'
(Error: Unable to resolve nonexistent file '/build/glibc-eX1tMB/glibc-2.31/sysdeps/unix/sysv/linux/raise.c').
config_file = readParam(n, "config_file");
"/home/matthew/projects/vinsmono/src/vins-mono/config/euroc/euroc_config.yaml"
那十有八九是配置不正确,例如在参考贴里用的vins-mono,但我的地址是VINS-Mono,所以就报错了,总之就是要和实际使用的地址一致。
vscode打的主文件夹,以我自己的文件夹结构为例,打开的是,
/home/matthew/projects/vinsmono/src/VINS-Mono
因为viz和play都不需要调试,在这种情况下,所以我们分别打开两个终端输入下面前两条语句开始运行,运行euroc.launch打开后会弹出调试窗口,
roslaunch vins_estimator vins_rviz.launch
rosbag play YOUR_PATH_TO_DATASET/MH_01_easy.bag
roslaunch vins_estimator euroc.launch
这里play最后实际运行的是文件包,以我自己的运行为例,
rosbag play ~/downloads/vinsmono/machine_hall/MH_01_easy/MH_01_easy.bag
要说明的是,如果你想在调试模式下看到和运行release模式一样的效果,你必须同时开始vins_estimator中的全部任务,也就是下面的多任务模式,否则你只能一个个节点地调试。
launch.json中有一段多任务调试代码,
"compounds": [
{
"name": "tracker/estimator/pose",
"configurations": [
"feature_tracker",
"vins_estimator",
"pose_graph"
]
}
]
如果启动这个的话,会有三个线程(三个terminal)同时启动调试。可能是我对源码了解不够深入,原始的pose graph还没有看到输出,不知道是否还需要一些其他配置,我自己在pose_graph_node.cpp中加了一句打印输出的语句,这样终端就不停有信息输出了,知道程序已经进入了主线程循环(不然没有任何信息输出),
printf("--------------%d--------------\n", pose_dbg++);
其process的代码运行如下,
static int pose_dbg = 0; // <------------added definition
void process()
{
if (!LOOP_CLOSURE)
return;
while (true)
{
.......
m_buf.unlock();
if (pose_msg != NULL)
{
printf("--------------%d--------------\n", pose_dbg++);
//printf(" pose time %f \n", pose_msg->header.stamp.toSec());
//printf(" point time %f \n", point_msg->header.stamp.toSec());
//printf(" image time %f \n", image_msg->header.stamp.toSec());
// skip fisrt few
..............
调试时首先打开两个终端,分别输入下面这两条语句,
roslaunch vins_estimator vins_rviz.launch
rosbag play YOUR_PATH_TO_DATASET/MH_01_easy.bag
然后再启动这个tracker/estimator/pose的compound节点,此时feature_tracker,vins_estimator和pose_graph每个节点都会打开一个终端,可以在terminal看到输出信息。
如果你不需要显示的话,那个viz其实不是必要的。可以不用启动。
现在,你可以愉快地用vscode调试VINS_Mono这样的程序啦。
暂时先写到这里吧,本来想做个动图放在这里,ubuntu下貌似gif动画工具很少。>T_T< 。
官方的办法,
Description: When debugging roscpp nodes that you are launching with roslaunch, you may wish to launch the node in a debugging program like gdb or valgrind instead. Doing this is very simple.
Keywords: roslaunch, valgrind, gdb, pdb
Tutorial Level: INTERMEDIATE
Next Tutorial: Profiling roslaunch nodes
The launch-prefix attribute of the
launch-prefix="xterm -e gdb --args" : run your node in a gdb in a separate xterm window, manually type run to start it
launch-prefix="gdb -ex run --args" : run your node in gdb in the same xterm as your launch without having to type run to start it
launch-prefix="stterm -g 200x60 -e gdb -ex run --args" : run your node in gdb in a new stterm window without having to type run to start it
launch-prefix="valgrind" : run your node in valgrind
launch-prefix="xterm -e" : run your node in a separate xterm window
launch-prefix="nice" : nice your process to lower its CPU usage
launch-prefix="screen -d -m gdb --args" : useful if the node is being run on another machine; you can then ssh to that machine and do screen -D -R to see the gdb session
launch-prefix="xterm -e python -m pdb" : run your python node a separate xterm window in pdb for debugging; manually type run to start it
launch-prefix="yappi -b -f pstat -o
launch-prefix="/path/to/run_tmux": run your node in a new tmux window; you'll need to create /path/to/run_tmux with the contents:
#!/bin/sh tmux new-window "gdb --args $*"
To obtain core dumps when processes crash, first set the core file size limit. To check the limits, run:
$ ulimit -a core file size (blocks, -c) 0 # <-- Prevents core dumps data seg size (kbytes, -d) unlimited scheduling priority (-e) 20 file size (blocks, -f) unlimited pending signals (-i) 16382 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
Set the core size to unlimited:
ulimit -c unlimited
Now crashing processes will attempt to create core files. Currently (2010-07-02) they will fail to create the file because the default roslaunch working directory, $ROS_HOME, contains a directory named "core". This directory prevents the core dump from being created.
To allow core dumps to be created, set the core filename to use the process pid by default. Run the following as root:
echo 1 > /proc/sys/kernel/core_uses_pid
Now core dumps will show up as $ROS_HOME/core.PID
If you get error like below one, you should try to launch node in another windows with gdb.link
launch-prefix="xterm -e gdb --args"
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
ros项目调试:ROS项目使用GDB调试_Coulson的博客-CSDN博客_ros程序调试
GDB常用命令大全 GDB 命令详细解释_Linlei的专栏-CSDN博客_gdb 命令
ROS在线调试(使用GDB) - 古月居
利用vscode调试VINS-FUSION - 知乎
VS Code 调试 VINS-Mono 环境配置_Barry_123的博客-CSDN博客_vscode调试vins
如何配置VSCode来调试ROS节点_白夜行的狼-CSDN博客_vscode调试ros