你想入门自动驾驶吗?你想入门机器人吗?也许这一个教程就足够了。在开始之前,假设你有如下环境:

  • Ubuntu 16.04+;
  • CUDA9.0, CUDNN 7.5
  • ROS kinetic

环境一般是越高越好的,因为要踩的坑迟早要踩。我们将要获得的收获包括:

  • 跑通Autoware;
  • 看一下autoware里面物体检测的效果;
  • 简单理解一下自动驾驶各个模块之间的设计思路。

开始吧!

编译autoware

开始之前,我假设你已经对ros有了一定的了解。首先clone一下代码,并且下载一下一个用来做例子的ros包:

$ git clone https://github.com/autowarefoundation/autoware
$ wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_data.tar.gz  # data 
$ wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_150324.tar.gz  # rosbag
$ tar xf sample_moriyama_data.tar.gz
$ tar xf sample_moriyama_150324.tar.gz

然后第一件事情得安装一下依赖:

sudo apt-get install -y ros-kinetic-desktop-full
sudo apt-get install -y ros-kinetic-nmea-msgs ros-kinetic-nmea-navsat-driver ros-kinetic-sound-play ros-kinetic-jsk-visualization ros-kinetic-grid-map ros-kinetic-gps-common
sudo apt-get install -y ros-kinetic-controller-manager ros-kinetic-ros-control ros-kinetic-ros-controllers ros-kinetic-gazebo-ros-control ros-kinetic-joystick-drivers
sudo apt-get install -y libnlopt-dev freeglut3-dev qtbase5-dev libqt5opengl5-dev libssh2-1-dev libarmadillo-dev libpcap-dev libgl1-mesa-dev libglew-dev
sudo apt-get install -y ros-kinetic-camera-info-manager-py ros-kinetic-camera-info-manager

(这里的依赖不全,如果你不想感受一下踩坑,可以从下面安装对应依赖, 总之依赖太多).

504ee6b8-930e-4851-8d1b-99bc28383113-image.png

上面就是例子里面的数据。我们接下来要把autoware编译一下,毕竟我们要用它来做自动驾驶。

你克隆完了之后,开始执行:

cd autoware
cd ros
./colcon_release

然后就是一系列的编译过程,但是99.999%的概率你无法一次性编译通过。简单的列举一些我遇到的问题:

  1. error: class "Eigen::half" has no member "x"

这个问题应该是来自于Eigen,由于里面有一个用于定位的包ndt_gpu用到了eigen这个特性,由于某种未知的bug导致无法编译,具体错误信息为:

ptxas info    : Used 40 registers, 380 bytes cmem[0], 8 bytes cmem[2]
/usr/local/include/eigen3/Eigen/src/Core/arch/CUDA/Half.h(569): error: class "Eigen::half" has no member "x"

/usr/local/include/eigen3/Eigen/src/Core/arch/CUDA/Half.h(601): error: class "Eigen::half" has no member "x"

/usr/local/include/eigen3/Eigen/src/Core/arch/CUDA/PacketMathHalf.h(102): error: more than one conversion function from "const __half" to a built-in type applies:
            function "__half::operator short() const"
            function "__half::operator unsigned short() const"
            function "__half::operator int() const"
            function "__half::operator unsigned int() const"
            function "__half::operator long long() const"
            function "__half::operator unsigned long long() const"
            function "__half::operator __nv_bool() const"

14 errors detected in the compilation of "/tmp/tmpxft_00005561_00000000-6_Registration.cpp1.ii".
CMake Error at ndt_gpu_generated_Registration.cu.o.Release.cmake:279 (message):
  Error generating file
  /media/jintain/wd/ai/career/autocar/benchmarks/autoware/ros/build/ndt_gpu/CMakeFiles/ndt_gpu.dir/src/./ndt_gpu_generated_Registration.cu.o


make[2]: *** [CMakeFiles/ndt_gpu.dir/src/ndt_gpu_generated_Registration.cu.o] Error 1
make[1]: *** [CMakeFiles/ndt_gpu.dir/all] Error 2
make: *** [all] Error 2
---
Failed   <<< ndt_gpu	[ Exited with code 2 ]
Aborted  <<< astar_search                                
Aborted  <<< tablet_socket                               
--- stderr: pcl_omp_registration                         
** WARNING ** io features related to pcap will be disabled
** WARNING ** io features related to png will be disabled
** WARNING ** io features related to libusb-1.0 will be disabled
---
Aborted  <<< pcl_omp_registration
Aborted  <<< amathutils_lib                              
Aborted  <<< vector_map                                  
Aborted  <<< autoware_health_checker                     
Aborted  <<< sick_ldmrs_driver                                                       

Summary: 17 packages finished [2min 15s]
  1 package failed: ndt_gpu
  7 packages aborted: amathutils_lib astar_search autoware_health_checker pcl_omp_registration sick_ldmrs_driver tablet_socket vector_map
  4 packages had stderr output: libdpm_ttic ndt_cpu ndt_gpu pcl_omp_registration
  108 packages not processed

如何解决这个问题呢?

我首先尝试的是安装了一通autoreware的依赖:

 sudo apt-get install -y libxmu-dev libxi-dev libnlopt-dev freeglut3-dev qtbase5-dev libqt5opengl5-dev libssh2-1-dev libarmadillo-dev libpcap-dev libgl1-mesa-dev libglew-dev python-wxgtk3.0 software-properties-common libmosquitto-dev libyaml-cpp-dev python-flask python-requests dirmngr libtf2-eigen-dev libpcl-dev python3-pip python3-setuptools

重新编译还是同样的错误。难道是eigen版本的问题?令我感到震惊的是autoware居然没有这个issue出现过:

aef34860-50a3-4e7a-953b-f729130fbc1b-image.png

既然社区都没有人遇到这个题,于是我将3.3.4 Eigen升级到了3.3.7, 这是一个最新的版本。考虑到3.3.4是2017年release的,现在确实可能会出现一些bug,也可能是与CUDA8不兼容。尝试升级Eigen。下载eigen源代码,通过cmake可以快速安装。重新安装之后版本为:3.3.7 。
再次执行编译脚本。这次只有一个包编译失败了,其他都是一些stderr但是没有fail。
安装依赖:

sudo apt install ros-melodic-nmea-msgs

OK, 除了这个错误,现在应该已经编译通过了。

note:

如果你用的是g++5, 那么默认是没有打开c++11的,你需要手动添加一个标志位:

vim colcon_release

# edit
-DCMAKE_CXX_FLAGS=-std=c++11
  1. tinyxml 链接错误

这个错误也是不应该发生的啊,autoware官方文档里面似乎没有丝毫阐述。这个错误为:

nmea2kml.cpp:(.text+0x183): undefined reference to `TiXmlDeclaration::TiXmlDeclaration(char const*, char const*, char const*)'
nmea2kml.cpp:(.text+0x19f): undefined reference to `TiXmlElement::TiXmlElement(char const*)'
nmea2kml.cpp:(.text+0x1b5): undefined reference to `TiXmlElement::SetAttribute(char const*, char const*)'
nmea2kml.cpp:(.text+0x1cb): undefined reference to `TiXmlElement::SetAttribute(char const*, char const*)'
nmea2kml.cpp:(.text+0x1e1): undefined reference to `TiXmlElement::SetAttribute(char const*, char const*)'
nmea2kml.cpp:(.text+0x1f7): undefined reference to `TiXmlElement::SetAttribute(char const*, char const*)'

应该是tinyxml没有安装?但是tinyxml和tinyxml2都已经安装了。我们在 util/packages/autoware_bag_tools/CMakeLists.txt 里面添加这个:

add_executable(nmea2kml nodes/nmea2kml/nmea2kml.cpp nodes/nmea2kml/ReadNMEASentence.cpp)
target_link_libraries(nmea2kml ${catkin_LIBRARIES} -ltinyxml)

表示link一下 tinyxml。在这里吐槽一下autoware的作者们:

  • cmake不添加c++11放肆用c++语法??不考虑g++5?不考虑用户编译困扰?典型的没有产品思维;
  • cmakelist不写链接库名就发布了?不连接库名你们家编译器会自动添加?典型的把用户当傻子。

好在用户爸爸们都有点解决问题的能力,不然分分钟被你们耽误我们研发火箭上天。。

然后再编译,否则autoware里面所有的CMakeLists都没有处理在g++5的情况,所有的c++11语法将导致编译失败。
最后吐槽一下colcon,ros2下面的编译工具,感觉没有catkin_make好用,一个包错了所有的编译包给你从头来过,很蛋疼。所以说珍爱生命,少去做一些复杂的wrapper,如果可以,我宁愿使用纯cmake或者g++来构建。像Bazel这样的工具还好,但是像ninja这样的工具就不知道是谁搞出来的,python的哲学放到哪里都是适用的:simple is better than complexity.

最后总结一下autoware的隐藏依赖:

sudo apt-get install -y ros-kinetic-desktop-full
sudo apt-get install -y ros-kinetic-nmea-msgs ros-kinetic-nmea-navsat-driver ros-kinetic-sound-play ros-kinetic-jsk-visualization ros-kinetic-grid-map ros-kinetic-gps-common
sudo apt-get install -y ros-kinetic-controller-manager ros-kinetic-ros-control ros-kinetic-ros-controllers ros-kinetic-gazebo-ros-control ros-kinetic-joystick-drivers
sudo apt-get install -y libnlopt-dev freeglut3-dev qtbase5-dev libqt5opengl5-dev libssh2-1-dev libarmadillo-dev libpcap-dev libgl1-mesa-dev libglew-dev
sudo apt-get install -y ros-kinetic-camera-info-manager-py ros-kinetic-camera-info-manager

For melodic:

sudo apt install ros-melodic-nmea-msgs ros-melodic-nmea-navsat-driver ros-melodic-sound-play ros-melodic-jsk-visualization ros-melodic-grid-map ros-melodic-gps-common
sudo apt install ros-melodic-automotive-platform-msgs
 sudo apt-get install -y ros-melodic-controller-manager ros-melodic-ros-control ros-melodic-ros-controllers ros-melodic-gazebo-ros-control ros-melodic-joystick-drivers
sudo apt install ros-melodic-robot-state-publisher
sudo apt install ros-melodic-automotive-navigation-msgs
sudo apt install ros-melodic-pacmod-msgs

上面每一行都是我编译一次找到的缺失依赖。。。autoware这个东西,依赖实在是太多了。。。比Apollo多一百倍,总的来说是一个拼凑起来的框架。但是不管怎么样,也算是一个完成度比较高的产品。主要看一下它的架构思路,其他几乎很难有啥参考价值。顺便说一句,如果未来谁要自研自动驾驶系统,可以从autoware入手,先考虑传感器,再考虑如何把每个模块组合起来。对于一个创业公司来说,别上来就Apollo往上堆,文章的末尾我将会从商业上分析一下采用开源自动驾驶软件的局限性。

  1. boost 的某个字符重载错误

具体错误是:

error: unable to find numeric literal operator ‘operator""Q’
/usr/include/boost/math/special_functions/zeta.hpp:691:10: error: unable to find numeric literal operator ‘operator""Q’
          BOOST_MATH_BIG_CONSTANT(T, 113, 0.161843184071894368337068779669116236e-6),

我了个去,这应该不是bug是代码错误了吧。。。。算了,放弃了,从docker试下吧。

如果你看到结果这样:

那么恭喜你,本地编译autoware成功,接下来开始自动驾驶之旅!!(我没有成功。。)

### 从docker安装autoware

首先二话不说,拉取一下镜像吧:

docker pull autoware/autoware:1.11.0-kinetic-cuda

这里 我默认采用cuda版本,如果你不用cuda的镜像那就从dockerhub找一个不带cuda的。但是这里又涉及到一个问题,需要安装一下nvidia-docker,也就是在docker里面运行docker环境。在这种情况下,你可以主机不安装cuda和nvidia-smi,而直接运行nvidia-smi。简单的运行:

docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f
sudo apt-get purge -y nvidia-docker

# Add the package repositories
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
  sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

# Install nvidia-docker2 and reload the Docker daemon configuration
sudo apt-get install -y nvidia-docker2
sudo pkill -SIGHUP dockerd

docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi

note: 这里我建议大家安装nvidia-docker2,也就是上面的步骤,因为2版本不需要单独其中一个nvidia runtime,直接运行即可。此时如果你的宿主机有显卡,应该已经可以看到显卡信息了。过段时间会单独写一篇教程来配置nvidia-docker。

------- 分割线--------
接下来到了魔法时间,突然之间就跳出了autoware窗口:

f7379117-be01-44e2-8a19-676b36243e18-image.png

其实直接从git clone的仓库:

cd docker
cd generic
./run.sh

就可以进入docker镜像,具体原因不像。默认是自带的cuda镜像,运行nvidia-smi可以与主机通信。顺便说一句,这个居然可以弹出可视化窗口,在docker里面!so six!

运行autoware

那么像autoware这种大型的软件是如何运行的呢?这是一个值得深入思考的问题。假设上面大家已经安装好了autoware docker。那么我们来玩一玩如何配置把。OK, 我们是这么开始的,首先docker软件已经准备就绪,也可以进入了,接下来我需要挂载我的硬盘,然后再进入docker,这样可以在docker里面访问我硬盘的数据文件,也就是之前下载ros包和地图等数据。假设你有一个本地硬盘地址为:

/media/yourname/wd

wd是我的硬盘名字,那么你可以把这个目录软链接到:/home/yourname/shared_dir 下面。你需要注意两点,第一点是你的硬盘必须要要是ext4格式的,另外ln的时候都要使用全路径。否则无法在docker里面访问。

sudo ln -s /media/yourname/wd /home/yourname/shared_dir

此时在shared_dir里面可以访问到wd的文件。准备就绪,再次进入autoware的docker看看:

cd autoware/docker/generic
./run.sh

如果这一步你无法成功,直接修改 run.sh 中的: SHARED_HOST_DIR=/home/uftp/cluster4/personal/jfg/shared_dir 路径需改为你自己的路径,这样实际上你在docker里面更新的文件会在你的本地目录中出现。这样你就可以在docker与宿主机之间进行通信了!!

接下来要做什么呢?因为在docker里面是没有任何数据的,而此时你已经下载好了官方的sample的rosbag,把它拷贝到你的shared_dir下面,就可以开始跑demo了!!

Autoware demo show

接下来开始demoshow。我们将上面下载sample里面的rosbag等数据全部拷贝到宿主机的shared_dir下面,这样你就可以在docker里面访问它。

6d9967d4-7b69-4568-8acb-da0f262ece21-image.png

在docker里面可以使用tmux开多终端进行操作。接下来主要看一下这个Runtime Manager怎么用。
首先从tab里面选择simulation,我们要开始仿真测试,所以选择它。然后选择我们之前下载的sample里面的rosbag,此时可以看到这个界面:

75f98829-987e-49d9-9be8-8016719f9922-image.png

播放一段时间之后再Pause。然后再点击右下角的rviz,此时可以打开rviz界面:

65ebe2d0-ffb6-4c67-85b3-0d7593a1ad98-image.png

现在还啥都没有,但是可以看得出来,这个rviz还啥都没有,继续深入。

e8b44013-1f8f-48be-8160-ff4bfe533631-image.png

我们现在可以看到,从Autoware本身一个隐藏路径可以load rviz的配置。配置只是将一些话题添加上,接下来需要按照步骤来了。

  1. 先定位

我们需要先把定位打开,回到runtime manager,切换到quickstart的panel,选择一下map。文件地址为:
c9d679f4-7543-4f55-9fa9-1dc9ec5def89-image.png

实际上,这上面选择的launch会调用 docker里面,.autoware隐藏文件夹下的数据,你进去看看有没有,如果没有相应的pointmap和vectormap以及tf,需要将下载的拷贝过去。最近的docker里面好像没有自带,这就需要你拷贝一下了。否则等一下在rviz里面你会看不到任何东西,因为地图没有,以及tf也没有。

  1. rviz查看地图