【动手学Apollo】7. 本地开发基础(下):GDB调试

科技   2024-11-18 08:00   上海  

土豆泥老师 (知乎:@土豆泥): 上海交通大学在读博士.

一、前期知识

  1. 了解GDB的运行机制:首先需要生成带调试信息的可执行文件,然后用调试模块启动这个文件,即可进入调试。
  1. 了解Apollo的运行机制:在编译之后会生成可执行文件mainboard,并且会把各个模块编译成动态库。然后由mainboard去调用具体模块的动态库,从而启动各个模块。

二、单步调试的3种方式

  1. 直接用GDB的命令行调试。 对于小型项目还好,对于像Apollo这样的大型项目不方便,参数复杂,容易出错。
  2. 在vscode中直接调用GDB进行调试。需要配置json文件,本文采用这种方式。
  3. 使用cmake构建项目,在cmake tools中调用gdb进行调试。但是,这需要项目在开发初期就采用cmake方式构建,由于apollo包管理构建方式为bazel,如果要用cmake,就要重写很多cmakeLists文件,并且熟悉各模块之间的依赖和包含关系。这对我们来说是不划算的。

三、Apollo调试具体步骤

  1. 用vscode打开Apollo工作目录。

首先打开Apollo源码所在的工作目录,在该目录下打开终端,输入

code .
  1. 安装Docker插件并配置
    1. Docker
    2. Dev Containers

安装插件后,在进入容器前,还需要进行一个配置。

按住ctrl+shfit+P

选择→开发容器:打开附加的容器配置文件…

选择→ register.baidubce.com/apollo/apollo-env-gpu:9.0-latest。

打开一个json的文件,对该文件做如下配置:

{
  "extensions":[   //容器中安装的插件,可以先不配置,进入容器后单独安装
    "franneck94.c-cpp-runner",
    "ms-ceintl.vscode-language-pack-zh-hans",
    "ms-vscode.cmake-tools",
    "ms-vscode.cpptools",
    "ms-vscode.cpptools-extension-pack",
    "ms-vscode.cpptools-themes",
    "twxs.cmake",
    "vadimcn.vscode-lldb"
  ],
  "workspaceFolder":"/",      //指定容器挂载的目录
  "remoteUser""mash"  //指定用户名,具体用户名在@in-dev-docker前面的那个
}
  1. 启动容器,并附加到vscode

在vscode中打开终端,并启动容器

aem start
aem enter

此时,可以看到Docker选项下,在CONTAINERS中容器已经处在打开的状态;右键点击该容器,并选择附加Visual Studio Code

通过这种方式打开一个新的窗口,就进入到这个容器中了。此时,窗口挂载在工作空间的根目录下,而我们的工作空间在apollo_workspace中,包括接下来要调试的源代码也在其中。

注意:由于容器是一个全新的环境,相当于在新环境中打开了vscode。此时需要重新安装C++、Cmake等插件。

  1. 查看运行中的节点

在容器窗口中打开终端,输入

cyber_node list

这时候应该没有节点运行,输出下图所示的结果

  1. 下载并安装planning源码

这部分在之前安装apollo的时候应该已经完成了,如果没有完成,按照顺序执行下列步骤

//先进入工作空间
cd /apollo_workspace

//检查buildtool版本
buildtool -v

//如果buildtool版本需要更新,使用以下指令更新(不过对于刚刚安装apollo用户,一般不需要)
sudo apt update && sudo apt install --only-upgrade apollo-neo-buildtool

//下载安装依赖包:会拉取安装core目录下的cyberfile.xml里面的所有依赖包
buildtool build -p core

//下载planning_base源码(其他包可以在core/cyberfile.xml查看)
buildtool install planning
  1. 编译源码

生成带有调试信息的可执行文件

buildtool build —dbg -j 10 -m 0.7 -p modules/planning

其中:

—dbg是添加调试信息;

-j 10 是使用10个进程;

-m 0.7是使用70%的内存;

关于buildtool的使用,可参考官方安装文档。位置为:文档→个人开发者文档→框架设计→软件核心→包管理工具→buildtool

  1. 根目录下新建文件夹.vscode,创建launch.json文件
//回到根目录
cd
//新建文件夹
mkdir .vscode
//添加权限
sudo chmod -R 777 .vscode/
//进入目录
cd .vscode/
//创建launch.json文件
touch launch.json

这个时候,这个文件应该具备可读可写可执行的权限了,接下来对json进行配置

{
 "version":"0.2.0",
 "configurations":[
  {
   "name":"gdb planning",
   "type":"cppdbg",
   "request":"launch",
   "program":"/opt/apollo/neo/bin/mainboard",
   "args":[  //传递给mainboard的参数
    "-d",  //dag文件所在路径
    "/apollo_workspace/modules/planning_component/dag/planning.dag",
    "-p",  //进程所在的命名空间
    "planning",
    "-s",
    "CYBER_DEFAULT"
   ],
   "stopAtEntry":false,
   "cwd":"/apollo_workspace",    //源码所存放的目录
   "environment":[],
   "externalConsole":false,
   "MIMode":"gdb",
   "setupCommands":[
    {
     "description":"为 GDB 启用整齐打印",
     "text":"-enable-pretty-printing",
     "ignoreFailures":true
    },
    {
     "description":"防止 GDB 打开标准函数库",
     "text":"-interpreter-exec console\"skip -rfu std::.*\"",
     "ignoreFailures":true
    }
   ],
   "miDebuggerPath":"/usr/bin/gdb" //gdb所在路径
  }
 ]
}

检查一下容器内是否安装了GDB

which GDB

如果没有输出路径,则执行下述代码重新安装GDB

sudo apt install gdb
//查看一下版本
gdb --version

8.调试步骤

接下来就可以进行调试了。打开要调试的代码,以planning component为例。这个是planning模块的一个入口,在planning模块被调用后,会优先进入这一部分的代码。

我们在planning_base_→Init(config_);这一行打一个断点。在左侧选择和刚刚json文件对应的配置,点击绿色三角按钮开始,或者按F5。程序会成功命中这个断点。

同时,再开两个终端窗口,一个是cyber_monitor,现在由于程序刚刚启动,在非常早的位置就被停住了,所以cyber_monitor中还没有数据。在另一个终端中输入cyber_node list,同样没有启动的节点。

接下来按单步调试,或F11,会进入到OnLanePlanning::Init这个函数中了,这就是单步调试的过程。

按F5,让程序运行起来。

左侧终端里出现了一些打印信息,显示右边的宽度太小了,应该大于半个车身的宽度,就说明planning模块已经启动了,由于现在没有地图,没有其他输入,所以会有这样的一个判断,这是没关系的。

在cyber_monitor中已经有数据了,都是planning模块相关的一些数据。

在最右侧终端再次输入cyber_node list,看有哪些节点运行了,可以看到有Monitor相关的节点,然后planning,作为一个节点也运行了,就说明我们的调试是成功的。

9.改写源码后重新编译,再调试验证

在on_lane_planning.cc中加入一行

std::cout << "从零开始学Apollo" <<std::endl;

然后重新编译后,先运行到断点,单步调试到这句代码下,可以看到正确打印了,说明我们刚刚的修改已经生效了。

总结

这一部分一共分了三个章节,分别介绍了Apollo环境安装、vscode中代码下载与编译、以及在vscode中使用GDB对Apollo代码进行单步调试。这其中不仅涉及到一些Apollo工程构建的知识点(例如bazel,docker),也包含C++工程调试的基本方法,需要反复练习。

如果我们需要在Apollo代码基础上开发自己的代码,不要像上文演示中直接修改原代码。Cyber RT中提供了组件、插件机制,能够帮助我们扩展代码。因此,接下来将对Apollo的操作系统Cyber RT进行学习。

推荐阅读:

🏎️自动驾驶小白说官网:https://www.helloxiaobai.cn


自动驾驶小白说
输出专业自动驾驶算法教程的开发者社区. 🦈 官网: https://www.helloxiaobai.cn
 最新文章