简介:一套针对Apollo配置中心1.4.0源码进行PostgreSQL数据库适配的完整改造包,主要面向需要将配置中心数据源从MySQL切换为PostgreSQL的Java后端开发人员。由于官方发行版默认仅支持MySQL,作者基于PostgreSQL 11.4完成全部适配工作,同时引入42.2.5版本的数据库驱动,帮助使用者避开常见的驱动版本不匹配、SQL语法差异等兼容性陷阱。压缩包内共收录2000个文件,以646个Java源码文件与607个编译后的class文件为核心,既能看到改动逻辑,也能直接对照成品;前端部分以215张图片、160个脚本和76个页面文件为主,覆盖配置管理界面相关资源;另有64个SQL脚本、62个属性配置以及61个XML等框架配置,用于完成建表、初始化与运行调优。资源整体大小约11.46MB,保留原始工程目录结构,便于按模块定位。目前已有4184人学习下载,适合期望快速获得适配方案或复用改造结果的开发者。
1. apollo-1.4.0.zip:一个老得掉渣的发行包,为什么现在还有人翻出来部署
apollo-1.4.0.zip 这个文件名,放到今天看很古老:它没有 Cyber RT,没有复杂的云仿真,连 DreamView 都带着早期 Web 界面的朴素质感。但老版本有老版本的价值——整个系统跑在一条相对干净的依赖链上,感知、规划、控制模块边界清晰,从解压到第一帧感知结果出来,一个下午就能走通。适合三类人:想搞懂自动驾驶工程落地顺序的人,需要做离线演示或预研的团队,以及想把自动驾驶源码从头摸一遍的学生。它跑不了今天的复杂场景,却能让“看懂一辆自动驾驶车在干什么”这件事变得非常轻松。
2. 部署前先把硬环境看死:apollo 1.4.0 在 Linux 上的 zip 解压与预处理
2.1 apollo 1.4.0 部署测试选 Windows 还是 Linux:没有悬念
进入正题前,先把部署测试最常被问的“选 Windows 还是 Linux”说死。Apollo 1.4.0 那年头还没有跨平台的 Cyber RT 通信层,代码里的感知、定位、规划全都挂在 ROS 的话题发布订阅上,同时大量模块直接依赖 CUDA 和 GPU 运算。Windows 上既没有原生 ROS 支持,也不方便做 GPU 透传,所以下载 apollo-1.4.0.zip 之后的第一件事,是找一台 Linux 机器,而不是在 Windows 上硬撑。
我一般会准备一台 Ubuntu 16.04 或 14.04 的独立机器,或者给 Windows 加个双系统。虚拟机不是不行,但有一个硬伤:后面要跑点云、跑感知、在 DreamView 里拖动视角,这些操作都需要 GPU 在物理层面被容器访问到。VMware 的 GPU 透传对普通 N 卡来说往往性能折扣很大,感知模块跑起来像慢放。我自己的经验是:老老实实装双系统,或者找一台配置还行的退役台式机专门跑。
| 部署方式 | GPU 访问 | 感知模块跑点云 | 适合场景 |
|---|---|---|---|
| Windows 原生 | 不可用 | 编译都过不去 | 不建议浪费时间 |
| Windows + 虚拟机 | 性能差 | 勉强出结果 | 只做阅读代码用 |
| Linux 双系统 | 完全可用 | 正常跑 | 个人学习、毕设 |
| Linux 独立机器 | 完全可用 | 正常跑 | 团队预研、离线演示 |
这个表的意思是:如果只是想看代码,Windows 上解压后用编辑器看也行;如果想让 apollo 1.4.0 真正跑起来出感知结果,那就一条路走到底选 Linux,别绕。
2.2 zip 解压之前先做三件事:校验、大小写检查和权限修复
apollo-1.4.0.zip 通常从网盘或内部文件服务器拿到,这种传播方式最容易遇到坏包。zip 解压本身不复杂,但解压之前我习惯先做一次完整校验,免得编译到一半才发现源文件是残缺的。老手翻车往往不是翻在算法上,而是翻在压缩包坏道上。
# 1. 校验 zip 包完整性,防止解压一半报 CRC 错误 sha256sum apollo-1.4.0.zip # 2. 解压到独立目录,避免和已有工程混在一起 unzip apollo-1.4.0.zip -d apollo-1.4.0-src cd apollo-1.4.0-src # 3. 看一眼顶层结构,并补上丢失的执行权限 ls -la find . -name "*.sh" -exec chmod +x {} \;逻辑说明:sha256sum会把整个 zip 文件的二进制内容压成一个 64 位十六进制字符串。如果你能从 Release 说明里拿到对应的校验值,两个值一致再继续;如果不一致,解压后很可能出现某个.cpp文件缺一半,编译时冒出一堆没法理解的报错。unzip -d指定输出目录,比直接解在当前目录干净。ls -la的目的是看两级信息:一是有没有modules、docker、scripts这些顶层目录,二是权限位里可执行文件是否保留x。
参数说明:-d后面的目录名建议小写,不带空格;如果你拿到的包源自某台 Windows 机器,zip 打包时可能把 Unix 可执行位丢光,所以用find -exec chmod +x一次性补上。这个坑我遇到过不止一次,脚本全报 permission denied,排查半天才发现是权限位问题,而不是代码问题。另外,解压目录不要放在 NTFS 或 Windows 共享目录里,否则文件权限和时间戳会持续出幺蛾子。
2.3 显卡驱动与 Docker 基座:一张入门卡到底够不够
Apollo 1.4.0 对硬件的要求不高但很具体。CPU 8 核以上,内存 16G 以上,硬盘至少空出 80G(源码、镜像加数据包很占空间),显卡建议是一张显存 4G 以上的 N 卡。那时候官方开发机常见的是 1080 或 1080Ti,放到现在 1660 甚至 2060 都足够。但显卡驱动和 CUDA 的版本关系比硬件本身更敏感,这一块留到第 5 章避坑里细讲。
Docker 是 apollo 1.4.0 运行的基座,因为老版本的依赖库版本非常死,手动装很容易把环境搞坏。常见做法是安装 Docker,再配好能让容器访问 GPU 的运行时。Ubuntu 16.04 上配置 Docker 的老流程是:
# 安装 docker,并把当前用户加到 docker 组 sudo apt-get update sudo apt-get install -y docker.io sudo usermod -aG docker $USER # 验证 docker 能否正常执行 docker run --rm hello-world逻辑说明:usermod -aG docker $USER把当前用户加进 docker 组,之后执行 docker 命令就不用反复加 sudo。docker run hello-world是最小的核验动作,能跑说明 docker 守护进程正常。Apollo 自带的dev_start.sh启动时还会检查 GPU,所以要提前确认 GPU 运行时已经装好。最简单的自检是在宿主机执行nvidia-smi,能看到显卡信息就说明驱动层没问题。
参数说明:这部分不要追求最新版。Apollo 1.4.0 的容器脚本针对当时主流的 Docker 版本做过适配,用太新的 Docker 引擎偶发兼容问题。我的建议是装系统源里的 docker.io 就好,够用且省事。镜像第一次拉取体积很大,网络条件正常的情况下也要等一阵,别中途 Ctrl+C,断了重拉更难受。
3. 用 Docker 把 apollo 1.4.0 编译起来:容器脚本与三条构建命令
3.1 先看 dev_start.sh 的三个默认参数:挂载、GPU 与端口映射
源码解压好、硬件准备就绪后,进入构建流程。老版本仓库里维护了一套docker/scripts/脚本,最先执行的是dev_start.sh。这个脚本的作用是读取参数,启动一个带全部依赖的容器,并把当前目录挂载到容器内部的/apollo。我每次执行前都会先过一次参数,避免容器起来了才发现端口或 GPU 没对上。
# 查看脚本支持的启动参数 bash docker/scripts/dev_start.sh --help # 正式启动,挂载当前源码目录进容器 bash docker/scripts/dev_start.sh逻辑说明:--help在 1.4.0 时代已经存在,会列出所有可选开关。比较常用的是--gpu(启用 GPU 支持)、--local(使用本地已有镜像而不是重新拉取)、以及指定容器名字的参数。如果你在 N 卡机器上,默认参数通常已经带 GPU;如果在只有 CPU 的机器上强行启动,后续感知模块会因为找不到 CUDA 直接崩。
参数说明:dev_start.sh默认把宿主机的 8888 端口映射到容器的 8888,这个端口是后续 DreamView 的关键。如果 8888 被别的服务占了,要在脚本里改映射。一个常见问题是宿主机 8888 被占用,脚本却没报错,结果浏览器打开一片白。启动成功后用docker ps看容器状态,STATUS 应该是 Up 而不是 Exited。
3.2 进入容器与全量构建:为什么要进容器再编译
容器起来后,通过dev_into.sh进入容器,所有构建动作都要在容器内部完成,不要在宿主机上直接执行./apollo.sh build,因为依赖全部在容器里,宿主机缺库缺到没法看。
# 进入 apollo 容器 bash docker/scripts/dev_into.sh # 进入容器后,确认当前目录 cd /apollo # 全量构建,这一步会编译感知、定位、规划、控制等全部模块 ./apollo.sh build逻辑说明:dev_into.sh实际上执行的是docker exec -it apollo /bin/bash,进去之后你会看到/apollo目录和宿主机解压出的源码完全一致,因为脚本启动时就加了-v挂载参数。./apollo.sh build是这一版的主构建入口,它会先检查环境变量、生成必要配置,再按依赖顺序逐个模块编译。首次全量构建在机械硬盘上可能超过一两个小时,SSD 上会明显快一些。
参数说明:apollo.sh在 1.4.0 里支持若干子命令,我一般先用./apollo.sh build做全量编译,之后改到某个模块时再增量构建对应部分,速度能从几十分钟降到几十秒。构建日志很长,只要看最后输出的结果标志,以及有没有error:开头的内容。有报错先别急着改代码,老版本百分之八十的构建失败是环境问题而不是源码问题。
3.3 最小启动 DreamView:bootstrap 脚本做了哪几件事
编译通过后,启动 DreamView 是最有成就感的时刻。Apollo 1.4.0 里主要跑bootstrap.sh,它负责拉起 DreamView 后端和基础模块。最小启动组合是:
# 在容器内执行,拉起 DreamView 相关服务 ./scripts/bootstrap.sh # 看到提示后,浏览器访问 # http://localhost:8888逻辑说明:bootstrap.sh做的事情可以拆成三步:启动 DreamView 对应的后端进程,检查模块 manager 是否活着,输出访问地址。它本身不启动感知、规划这些大数据量模块——那些要等你在界面上手动勾选。这也是我建议新手先只跑 bootstrap 的原因:防止多个模块同时启动导致日志刷屏,没法定位问题。执行完如果终端里出现类似 “DreamView is running at http://localhost:8888” 的提示,说明 Web 服务端起来了。
参数说明:如果 8888 被改成其他端口,浏览器地址要跟着改。DreamView 还依赖一个 websocket 端口做实时推送,通常是 8889,部分版本由单独的脚本负责。看到页面但地图不加载,按 F12 打开开发者工具看 console,八成是 websocket 没连上,对照端口占用列表排查就行。这里我吃过一次亏:页面能开但地图空白,排查半天发现是宿主机防火墙把 8889 拦了,放行之后一切正常。
4. 跑通第一轮感知:录制包回放与 Lidar 参数的真问题
4.1 从 demo 包开始:rosbag 数据完整度检查
DreamView 界面里能看到车辆模型和地图后,下一步是给它喂数据。Apollo 1.4.0 的感知主要依赖激光雷达点云,数据载体是一段 ROS bag 包。官方文档里的 demo 包包含一段封闭道路上的激光雷达、相机和定位数据,进入容器后先找到它:
# 进入容器,查看自带 demo 数据是否存在 cd /apollo/data/bag/demo ls -lh # 用 rosbag 检查数据完整度 rosbag info demo.bag逻辑说明:rosbag info会输出这个包里的 topic 列表、消息类型、消息总数、起止时间。这一步非常重要,因为网盘下载的 demo bag 经常被截断,截断后回放会定格到某一帧就跳不动。检查重点有三个:/apollo/sensor/lidar128/PointCloud2(点云)、/apollo/localization/pose(定位)、/apollo/canbus/chassis(底盘)这些关键 topic 是否有数据,duration 是否和预期一致,消息总数是否合理。如果时长只有几秒甚至 0,直接换包,别浪费时间。
参数说明:bag 里 topic 名字每个数据集略有不同,如果是自己录制的包,要看录制方的定义。老版本也支持把多个 bag 串联回放,命令是rosbag play -l -i,但在 1.4.0 上跑 demo 不需要这么复杂,一次播放即可。同时注意时区:系统时区不对会造成 bag 时间戳和当前时间乱跳,回放着就卡住。
4.2 perception 模块的 Lidar 参数到底该调什么
数据包没问题后,在 DreamView 里勾选 Perception 模块,但别急着看界面,先确认 Lidar 配置是对的。Apollo 1.4.0 的感知模块配置主要在modules/perception/conf/下的文件里,常见参数是激光雷达型号、话题名、点云最小距离和障碍物检测阈值:
# 这段是示意,具体以你这份源码里的 conf 为准 lidar: sensor_name: "velodyne_vls128" topic: "/apollo/sensor/lidar128/PointCloud2" min_range: 2.0 # 米,太小会把车顶盲区杂点扫进来 max_range: 80.0 # 米,太大对算力不友好 threshold: 0.5 # 障碍物分割阈值,调大丢检,调小过检逻辑说明:Apollo 1.4.0 时期感知默认用 128 线激光雷达,所以这两个字段通常和你的数据包一致。min_range和max_range定义了感兴趣区域,老版本没有特别强的去噪能力,车顶雷达下方往往会有车辆顶盖产生的杂点,把min_range设成 2 米以上能明显减少误检。threshold是点云聚类分割的敏感度,不同数据集的统计特性不一样,我调的时候先跑一帧看可视化结果,再按 0.1 的步长调整。
参数说明:如果 demo 包里用的是 64 线或 16 线雷达,需要把sensor_name、topic都改成匹配值,否则感知模块订阅不到数据,DreamView 里一直是空场景。新手最容易在这里卡住:界面有地图有车,但没有障碍物,翻日志全是 waiting for pointcloud 超时。改完参数后重启 perception 模块即可,不用重新编译。
4.3 在 DreamView 里验证感知结果:坐标系先对起来
参数调好后,回放 bag 的同时看 DreamView 的主视图。1.4.0 的界面左下角有模块开关,右上角是视角切换。你希望看到的效果是:地图上的自车沿道路运动,同时 128 线点云变成障碍物的彩色包围框。这里最容易迷糊的点是坐标系。如果车模不动、障碍物乱飞,先看定位模块是否输出。
# 在容器里监听定位输出,确认 topic 有数据 rostopic echo -n 1 /apollo/localization/pose逻辑说明:rostopic echo -n 1只取一条消息然后退出,用来确认定位是否正常。感知模块需要点云和定位对齐,定位若没有输出,点云里的障碍物会全部出现在原点附近。输出里重点看position字段的 x/y/z 是不是有合理变化,如果一直是 0,说明定位模块没有跑起来,问题不在感知而在定位。
参数说明:-n 1表示只取一条,避免终端被刷屏。如果你看到的是WARNING: no messages received,多半是 bag 里定位 topic 名对不上,用rostopic list把实际话题列出来再核对。坐标系对齐这件事,是你在 1.4.0 上学到的第一课,也是后面看 openspace 算法时绕不开的基础。
5. Apollo 1.4.0 部署避坑:依赖翻车、驱动黑屏与版本冲突排查
5.1 镜像拉取失败或容器起不来:先分清楚网络还是权限
现象:dev_start.sh执行后长时间卡在拉取镜像,或者报Got permission denied while trying to connect to the Docker daemon socket。
原因:前一种情况多半是网络条件差,镜像地址无法访问;后一种最常见,是当前用户不在 docker 组里。
解决:先看docker images能不能正常列出。权限问题执行下面两步后重新登录会话再试;网络问题先检查宿主机 DNS 和连通性,不要把锅甩给源码本身。
# 重新配置用户组 sudo usermod -aG docker $USER # 重新登录后验证 docker images真实环境里,这个坑经常因为 SSH 会话没重新打开而“明明配置了却还报错”,所以记住:配置完 user group 后必须重开一次终端。
5.2 感知模块崩溃:先查 CUDA 与驱动版本
现象:容器能起,编译能过,但一回放 bag,Perception 模块进程直接退出,日志里有CUDA error或no kernel image available的字样。
原因:宿主机显卡驱动太新或太旧,与容器里 CUDA 对应的驱动接口不匹配。Apollo 1.4.0 编译时的 CUDA 版本较老,新的驱动不一定兼容旧接口。
解决:降级驱动到该版本适配的区间,别在容器里单独升级 CUDA,那是把简单问题复杂化。判断方法是先确认容器里nvcc --version,再对照驱动版本是否在兼容范围内。
这个坑我踩得最狠,曾经在新显卡上编译全过,一启动感知就崩,最后换老卡解决。老项目配新卡,往往就是这种玄学问题。
5.3 编译卡在编译器版本过新:别急着升级编译器
现象:编译 planning、perception 时出现一长串报错,大多来自.h文件里的老旧写法,比如auto_ptr被删除、隐式类型转换被拒绝。
原因:Ubuntu 16.04 的默认 g++ 版本是 5.x,如果你在 Ubuntu 18.04 及以上编译,g++ 版本高于模块预期。
解决:优先用容器脚本里封装的编译环境,不要用宿主机直接编译。如果容器默认编译器确实还是高版本,看看容器内有没有多版本 g++,切换即可。
# 在容器内查看可用的 g++ 版本并切换 ls /usr/bin/g++* sudo update-alternatives --config g++编译器版本是 1.4.0 部署里的经典坑,报错信息五花八门,实际原因只有一个:太新。别去改代码适配新编译器,切回旧版本最省事。
5.4 DreamView 打不开或白屏:端口、hosts 和浏览器三连
现象:bootstrap.sh显示运行正常,但浏览器输入 localhost:8888 后白屏或拒绝连接。
原因:最常见的是宿主机 8888 端口被占,或者浏览器访问的 localhost 不是容器映射的地址。
解决:用netstat -tlnp | grep 8888查端口占用;用docker ps看端口映射是否成对出现;再用无痕窗口打开一次。还白屏就检查/etc/hosts里是否有异常的 localhost 映射。白屏时优先看浏览器 F12 console,能定位到是 websocket 连不上还是静态资源加载失败。
5.5 回放 bag 时时间轴乱跳:时区与 NTP 同步
现象:bag 回放时,DreamView 里的车一下前进一下后退,日志频繁出现 time sync 相关提示。
原因:Apollo 各模块之间的时间戳没有对齐,通常是容器系统时区与宿主机不一致,或者时间同步服务没开启,导致系统时间被回跳。
解决:容器与宿主机都设成统一时区,并启用时间同步服务。对 1.4.0 这种老版本来说,比自动驾驶本身更值得重视的是底层的系统时间,只有时间对齐了,那堆传感器消息才拼得出完整世界。这个坑很隐蔽,因为它不影响编译,只影响运行表现。
6. 顺着 apollo 1.4.0 学 openspace 算法雏形:源码才是最好的注释
很多来找 apollo-1.4.0.zip 的人,嘴上说要部署,心里其实想学 apollo openspace 算法。这两件事并不冲突。1.4.0 里还没有真正独立成模块的 openspace,但已经埋了它的雏形。打开modules/planning/,你能看到 planner 下面的场景规划器,处理车辆掉头、泊车这类低速场景时,轨迹生成逻辑里已经有“把空间离散成网格、再做路径搜索”的痕迹。这和后续 openspace 算法的思路一脉相承:先在自由空间里做几何搜索,再用优化迭代平滑轨迹。
我自己学习时会做一件事:用老版本源码当静态参考,把 planning 里的路径搜索部分单独抽出来,打印每个节点的代价函数值,观察搜索过程。这个做法效率很高,因为它让我理解了为什么 openspace 对泊车场景要单独做一套高精度规划——普通道路规划器基于参考线,而停车场的自由空间场景根本没有参考线,必须在障碍物中间实时开辟一条路。
# 在源码里定位规划器相关目录 ls modules/planning/planner如果你把 1.4.0 的容错机制搞明白,再去看后续版本里 openspace 的开源实现,会发现它的架构并不神秘:一条独立的规划链、一个以自由空间为主的场景定义、一组针对低速和高曲率路径的优化器。老版本没有这些,却把这部分内容暴露得最简单。我的习惯是先把老版本跑通、跑熟,再对照新代码做 diff。这种“先用老版看骨架,再用新版看肌肉”的方式,能让你在几天之内把一个看似高深的算法拆成若干块,逐一消化。
老 zip 包的乐趣就在这,它不像新版本那样包了一层又一层的抽象,而是把骨架直接晾给你。哪怕只是想弄懂 openspace 的来龙去脉,从 apollo-1.4.0.zip 入手也比直接啃最新源码轻松得多。希望我踩过的这些坑能让你少走弯路,也祝你能在这个老版本里找到自己想找的东西。希望帮到你。
本文还有配套的精品资源,点击获取