标签 Cpp 下的文章

Go正走在成为下一个企业级编程语言的轨道上

发展演化了十年的Go语言已经被证明了是云计算时代的首选编程语言,但Go的用武之地显然不局限于此。Kevin Goslar近期在Hacker Noon发表了一篇名为:《Go is on a Trajectory to Become the Next Enterprise Programming Language》的文章,阐述了Go可能成为下一个企业编程语言的理由,这里是那篇文章的中文译文,分享给大家。

img{512x368}

摘要

Go是一种专门为大规模软件开发而设计的编程语言。它提供了强大的开发体验并避免了现有编程语言存在的许多问题。这些因素使其成为最有可能在未来替代Java主导企业软件平台的候选者之一。对于那些寻求在未来几十年内构建大规模云基础架构的安全和前瞻性技术的公司和开源计划而言,我建议它们将Go视为其主要的编程语言。Go的优势如下:

  • 基于现实世界的经验
  • 专注于大型工程
  • 专注于可维护性
  • 保持简单明了
  • 使事情显式且明显
  • 很容易学习
  • 仅提供了一种做事方式
  • 支持简单地内置并发
  • 提供面向计算的语言原语
  • 使用OO – 好的部分
  • 拥有现代化的标准库
  • 强制执行标准化格式
  • 有一个非常快的编译器
  • 使交叉编译变得容易
  • 执行得非常快
  • 需要较小的内存占用
  • 部署规模小
  • 部署完全独立
  • 支持vendor依赖
  • 提供兼容性保证
  • 鼓励提供良好的文档
  • 商业支持的开源

请继续阅读有关上述每个优势点的更多详细信息。然而,在进入Go之前,你应该注意:

  • 不成熟的库
  • 即将到来的改变
  • 没有“硬实时”支持

简介

Go是Google开发的一种编程语言,在过去几年中取得了很大的成功。大部分现代云计算,网络和DevOps平台都是Go语言编写的,例如:DockerKubernetesTerraformETCDistio等。许多公司也将它用于通用软件开发。Go所具备的功能让这些项目吸引了大量用户,而Go的易用性也使得这些项目有了很多的贡献者。

Go的优势来自于简单和经过验证的想法的结合,同时避免了其他语言中出现的许多问题。这篇博客文章概述了Go背后的一些设计原则和工程智慧,并展示它们是如何结合在一起的 – 它们使Go成为下一代大型软件开发平台的优秀候选者。许多编程语言在个别领域都比较强大,但是在将所有领域都结合起来时,没有其他语言能够如此一致地“得分”,特别是在大型软件工程方面。

基于现实世界的经验

Go是由经验丰富的软件行业资深人士创建的,他们长期以来一直感受到现有语言的缺点带来的痛苦。几十年前,Rob PikeKen Thompson在Unix,C和Unicode的发明中发挥了重要作用。在实现了用于JavaScript和Java的V8和HotSpot虚拟机之后,Robert Griesemer在编译器和垃圾收集方面拥有着数十年的经验。在太多次的不得不等待他们的谷歌规模的C++/Java代码库的编译过程的推动下,他们开始着手创建一门新的编程语言,这门语言中凝聚了他们通过编写半个世纪代码过程中所学到的一切。

专注于大型工程

几乎任何编程语言都可以成功构建小型工程项目。当成千上万的开发人员在数十年的持续时间压力下在包含数千万行代码的大量代码库上进行协作时,真正痛苦的问题就会发生。这会导致以下问题:

  • 超长的编译时长会中断开发过程
  • 代码库由几个人/团队/部门/公司拥有,混合了不同的编程风格
  • 该公司雇佣了数千名工程师,架构师,测试人员,Ops专家,审计员,实习生等,他们需要了解代码库,但需要具有广泛的编码经验
  • 依赖于许多外部库或运行时,其中一些不再以其最初的形式存在
  • 每行代码在代码库的生命周期内平均被重写了10次,留下了疤痕,瑕疵和技术偏移
  • 文档不完整

Go专注于减轻这些大规模的工程难题,有时是以使小型工程变得更加繁琐为代价,例如在这里和那里需要一些额外的代码。

专注于可维护性

Go强调尽可能多地将工作转交到自动代码维护工具中。Go工具链提供了最常用的功能,如格式化代码和自动package导入、查找符号的定义和用法、简单的重构以及代码味道的识别。由于标准化的代码格式化和单一的惯用方式,机器生成的代码更改看起来非常接近Go中人为生成的更改。并而使用类似的模式,使得人和机器的协作更加无缝。

保持简单直接

初级程序员为简单问题创建简单的解决方案。高级程序员为复杂问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。-  查尔斯康奈尔

很多人都对Go不包含他们喜欢的其他语言概念感到惊讶。Go确实是一种非常小而简单的语言,只包含最少的正交和经过验证的概念。这鼓励开发人员以最少的认知开销编写最简单的代码,以便许多其他人可以理解并使用它。

使事情显式而明显

良好的代码是显而易见的,避免聪明,模糊的语言功能,扭曲的控制流和间接性。

许多语言都致力于使编写代码变得高效。然而,在其生命周期中,人们将花费大约(100倍)的时间阅读代码,而不是首先编写所需的代码。例如,审查,理解,调试,更改,重构或重用它。在查看代码时,通常只能看到并理解它的一小部分,通常没有对整个代码库的完整理解。为了解释这一点,Go将一切都显式化了。

一个例子是错误处理。让异常在各个点中断代码并使沿着调用链处理可能会更容易。Go需要手动处理或返回每个错误。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说,这使得错误处理更容易编写,但更容易理解。

简单易学

Go非常小而且简单,可以在短短几天内研究整个语言及其基本概念。根据我们的经验,经过不超过一周的培训(与其他语言的以月为单位相比),初学者可以理解Go专家编写的代码,并为此做出贡献。为了方便大量人群,Go网站提供了所需的所有教程和深入的文章。这些教程在浏览器中运行,允许人们在将Go安装到本地计算机上之前学习和使用Go。

一种做事方式

Go语言通过个人自我表达赋予团队合作能力。

在Go(和Python)中,所有语言特征都是正交的并且彼此互补,通常做某事只有一种方法。如果您要求10位Python或Go程序员解决问题,您将获得10个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更有家的感觉。在查看其他人的代码时,每分钟的WTF更少,而且人们的工作更好地融合在一起,从而形成一个人人都为之骄傲并且喜欢工作的一致性。这避免了大规模的工程问题,例如:

  • 开发人员将良好的工作代码视为“混乱”,并要求在他们可以使用之前重写它,因为他们不会像原作者那样思考。
  • 不同的团队成员在该语言的不同子集中编写相同代码库的部分内容。

img{512x368}
来源:https://www.osnews.com/story/19266/wtfsm

简单,内置并发

Go专为现代多核硬件而设计。

目前使用的大多数编程语言(Java,JavaScript,Python,Ruby,C,C ++)都是在20世纪80年代到2000年代设计的,当时大多数CPU只有一个计算核心。这就是为什么它们本质上是单线程的,并将并行化视为事后增加的边缘情况,通过诸如线程和同步点之类的附加组件实现,这些附加组件既麻烦又难以正确使用。第三方库提供了更简单的并发形式,如Actor模型,但总有多个选项可用,导致语言生态系统碎片化。今天的硬件拥有越来越多的计算内核,软件必须并行化才能在其上高效运行。Go是在多核CPU时代编写的,并且在语言中内置了简单,高级的CSP风格的并发特性。

面向计算的语言原语

在基础层面上,计算机系统接收数据,处理它(通常经过几个步骤),并输出结果数据。例如,Web服务器从客户端接收HTTP请求,并将其转换为一系列数据库或后端调用。一旦这些调用返回,它就会将接收到的数据转换为HTML或JSON并将其输出给调用者。Go的内置语言原语直接支持这种范例:

  • 结构体代表数据
  • reader和writer代表流式IO
  • 函数处理数据
  • goroutines提供(几乎无限制的)并发
  • 通道用于管理并发处理步骤之间的数据

由于所有计算原语都是由语言以直接的形式提供的,因此Go源代码可以更直接地表达服务器执行的操作。

OO – 好的部分

img{512x368}
在基类中改变某些东西的副作用

面向对象非常有用。这几十年OO的应用是富有成效的,并且让我们了解它的哪些部分比其他部分可以更好地扩展。基于这些认知,Go采用面向对象的新方法。它保留了封装和消息传递等优点。Go避免了继承,因为它现在被认为是有害的,Go为组合提供头等的支持

现代标准库

许多当前使用的编程语言(Java,JavaScript,Python,Ruby)是在互联网成为当今无处不在的计算平台之前设计的。因此,这些语言的标准库仅为未针对现代互联网优化的网络提供相对通用的支持。Go是十年前创建的,当时互联网已经全面展开。Go的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这可以防止使用第三方库的常见问题:

  • 碎片化:实现相同功能的总有多种选择
  • 膨胀:库通常实现的不仅仅是它们的用途
  • 依赖地狱:库通常依赖于特定版本的其他库
  • 质量未知:第三方代码可能具有可疑的质量和安全性
  • 未知支持:第三方库的开发可以随时停止
  • 意外更改:第三方库通常不像标准库那样进行严格的版本管理

Russ Cox的更多背景信息。

标准化格式

Gofmt的风格是没有人喜欢的,但gofmt是每个人的最爱。 – Rob Pike

Gofmt是一种以标准化方式格式化Go代码的程序。它不是最漂亮的格式化方式,而是最简单,最不讨厌的方式。标准化的源代码格式化具有惊人的积极影响:

  • 重点讨论重要主题:它消除了围绕标签与空格,缩进深度,每行长度,空行,花括号放置等的一系列无意义的争论
  • 开发人员在彼此的代码库中感到宾至如归,因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式格式化代码,但如果其他人冒昧地按照他们自己喜欢的方式格式化>代码,那么每个人都讨厌它。
  • 自动代码更改不会弄乱手写代码的格式,例如通过引入意外的空白更改。

许多其他语言社区现在正在开发gofmt等价物。当构建为第三方解决方案时,通常会有几种竞争格式标准。例如,JavaScript世界提供PrettierStandardJS。可以一起使用其中之一或两者。许多JS项目都没有采用它们,因为这是一个额外的决定。Go的格式化程序内置于该语言的标准工具链中,因此只有一个标准,每个人都在使用它。

快速编译

img{512x368}
来源:https://xkcd.com/303

大型代码库的长编译时间是引发Go语言起源的一个微小的原因。Google主要使用C++和Java,与Haskell,Scala或Rust等更复杂的语言相比,它可以相对快速地编译。尽管如此,当编译大型代码库时,即使是少量的慢速也会把人激怒,编译工作流中断导致编译延迟。Go是从头开始设计的,以使编译更有效,因此编译器速度非常快,几乎没有编译延迟。这为Go开发人员提供了类似于脚本语言的即时反馈,并具有静态类型检查的额外好处。

交叉编译

由于语言运行时非常简单,因此它已被移植到许多平台,如macOS,Linux,Windows,BSD,ARM等。Go可以开箱即用于编译所有这些平台的二进制文件。这使得我们可以轻松地从一台机器来进行部署。

快速执行

Go有着接近C的速度。与JITed(即时编译)语言(Java,JavaScript,Python等)不同,Go二进制文件不需要启动或预热时间,因为它们作为已编译和完全优化的本机代码提供。Go垃圾收集器仅以微秒的指令引入可忽略的暂停。在其快速的单核性能上面,Go使得利用所有的CPU内核更容易

小内存占用

像JVM,Python或Node这样的运行时不仅仅在运行时加载程序代码。它们还会加载大型且高度复杂的基础架构,以便在每次运行时编译和优化程序。这使得它们的启动时间变慢并导致它们使用大量(数百MB)的RAM。Go进程的开销较小,因为它们已经完全编译和优化,只需要运行。Go还以非常节省内存的方式存储数据。这在内存有限且昂贵的云环境中以及在开发期间非常重要,在开发期间我们希望在单个机器上快速启动整个堆栈,同时为其他软件留下内存。

小部署规模

Go二进制文件的大小非常简洁。Go应用程序的Docker镜像通常比用Java或Node编写的等效文件小10倍,因为它不需要包含编译器,JIT,并且需要更少的运行时基础结构。这在部署大型应用程序时很重要。想象一下,将一个简单的应用程序部署到100个生产服务器上 使用Node / JVM时,我们的docker仓库必须提供100个docker镜像@ 200 MB = 20 GB(总共)。这需要镜像仓库耗费一些时间来服务。想象一下,我们希望每天部署100次。使用Go服务时,Docker镜像仓库只需提供100个Docker镜像@ 20 MB = 2 GB。可以更快,更频繁地部署大型Go应用程序,从而允许重要更新更快地实现生产。

自包含部署

Go应用程序部署为包含所有依赖项的单个可执行文件。不需要安装特定版本的JVM,Node或Python运行时。不必将库下载到生产服务器上。不需要对运行Go二进制文件的机器进行任何更改。甚至不需要将Go二进制文件包装到Docker中来共享它们。您只需将Go二进制文件拖放到服务器上,无论该服务器上运行的是什么,它都会在那里运行。上述描述的唯一例外是使用net和os/user包时的动态链接glibc库时。

vendor依赖关系

Go故意避免使用第三方库的中央存储库。Go应用程序直接链接到相应的Git存储库,并将所有相关代码下载(vendor保存)到他们自己的代码库中。这有很多好处:

  • 我们可以在使用之前查看,分析和测试第三方代码。此代码与我们自己的代码一样,是我们应用程序的一部分,应符合相同的质量,安全性和可靠性标准。
  • 无需永久访问存储依赖项的各个位置。可以一次性的从任何地方(包括私人Git仓库)获取您的第三方库,并永久拥有它们。
  • 在checkout后编译代码库不需要进一步下载依赖项。
  • 如果互联网上某处的代码存储库突然提供不同的代码,也不会造成surprises。
  • 即使软件包存储库服务性能变慢或托管软件包不再存在,部署也不会中断。

兼容性保证

Go团队承诺,现有的程序将继续适用于新版本语言。这使得即使是大型项目也可以轻松升级到更新编译器的版本,并从新版本带来的许多性能和安全性改进中受益。同时,由于Go二进制文件包含了他们需要的所有依赖项,因此可以在同一服务器计算机上并行运行使用不同版本的Go编译器编译的二进制文件,而无需进行复杂的设置多个版本的运行时或虚拟化。

文档

在大型工程中,文档对于使软件易于访问和维护非常重要。与其他功能类似,Go中的文档简单实用:

  • 它嵌入在源代码中,因此两者可以同时维护。
  • 它不需要特殊的语法 – 文档只是普通的源代码注释。
  • 可运行的单元测试通常是最好的文档形式,所以Go允许你将它们嵌入到文档中
  • 所有文档实用程序都内置在工具链中,因此每个人都使用它们。
  • Go linter需要导出元素的文档,以防止“文档债务”的积累。

商业支持的开源

当商业实体在公开场合发展时,一些最流行和最全面设计的软件就会发生。这种设置结合了商业软件开发的优势 – 一致性和优化,使系统健壮,可靠,高效 – 具有开放式开发的优势,如来自许多行业的广泛支持,来自多个大型实体和许多用户的支持,以及长期支持,即使商业支持停止。Go就是这样开发的。

缺点

当然,Go并不完美,每种技术选择总是有利有弊。在进入Go之前,这里有一小部分需要考虑的方面。

未成熟

虽然Go的标准库在支持HTTP/2服务器推送等许多新概念方面处于行业领先地位,但与JVM生态系统中存在的相比,用于外部API的第三方Go库可能还不那么成熟。

即将到来的变化

Go团队知道几乎不可能改变现有的语言元素,因此只有在完全开发后才会添加新功能。在经历了10年稳定的故意阶段后,Go团队正在考虑对语言进行一系列更大的改进,作为Go 2.0之旅的一部分。

没有硬实时

虽然Go的垃圾收集器只引入了非常短的中断,但支持硬实时需要没有垃圾收集的技术,例如Rust。

结论

这篇博客文章给出了一些明智的背景知识,但往往没有那么明显的选择进入Go的设计,以及当他们的代码库和团队成数量级增长时,他们将如何从许多痛苦中拯救大型工程项目。总的来说,他们将Go定位为寻求Java之外的现代编程语言的大型开发项目的绝佳选择。


我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信:企业级短信平台定制开发专家 https://51smspush.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

Hello, Apollo

要说目前哪个技术领域投资最火热,莫过于人工智能。而人工智能领域中最火的(或者说之一)肯定要算上自动驾驶。自动驾驶的概念不是什么新鲜的玩意了,只是随着近两年这一波人工智能的大热,自动驾驶又被推到了风口浪尖。各大汽车厂商、互联网公司也都跃跃欲试,准备给汽车这一“历经百年的黄金平台”做一次新的“赋能”。

今年7月5日,国内搜索引擎No.1企业百度在其首届百度AI开发者大会上发布了Apollo自动驾驶开放平台,同时百度也对外宣布baidu正式从互联网公司转型为一家人工智能公司。作为“错过了移动互联网时代”的典型公司代表,百度这次押宝人工智能,我觉得也是战略上迫不得已的选择:在现有现金牛“搜索广告业务”还能带来大量利润的时候,为抓住未来那头现金牛而进行的努力。而Apollo自动驾驶平台恰是百度人工智能战略的重要组成部分。

Apollo,阿波罗是古希腊神话中的光明之神,这个名字在西方文化中“自带光环”。提到Apollo,很多人还会想到半个多世纪前美国著名的“登月计划”。百度将其自动驾驶平台命名为Apollo,我猜测是有“借势之意”,即期望Apollo这个项目能在百度众多人工智能业务中拥有美好光明的前景。

作为技术人员,我们不能像一般媒体人员那样根据官方提供的“说辞”做宽泛的介绍,我们要与Apoll亲密接触,看看Apollo究竟是什么,究竟能做什么。这里就和大家一起来Say Hello to Apollo。

一、自动驾驶汽车- “百年黄金平台”的新时代赋能

在正式入门Apollo之前,还要说点“废话”。在接触Apollo之前,我从未认真思考过“汽车”这个平台,这次算是“顿悟”,虽然也算不上深刻。就我看来,汽车 是一个不可多得的“黄金平台”。作为一个平台,汽车已经有了上百年的历史,见证了人类科学技术的发展,是跨学科之集大成者。这百年多时间,任何新的、先进的民用技术都会赋能在汽车工业上。以一个长不足5米,重量不超过2t的一般家用乘用车为例,我们在其上面能看到先进的能源技术、材料技术、化工技术、电子技术、通讯技术以及精密的机械原件和组装技术等,可以说汽车为各个公司的创造力提供了展示的舞台。

就普通老百姓的衣食住行而言,汽车也是史无前例的高频使用典范,且是最直接、最贴近普通百姓生活的,这些都是飞机、火车等无法媲美的(如果非要选一个,那只有智能终端能与汽车媲美了,尤其是在集成度方面)。即便是到了科幻片中的漫天跑飞行器的时候,汽车也可能依旧是短距离交通的首选。当然届时的汽车很可能与我们此时的汽车大不相同了。随着时代的进步,汽车也在演化,日新月异的新技术、新材料、新能源对汽车的进一步赋能,因此汽车依旧是朝阳产业,这也是国际资本依旧积极群雄逐鹿汽车工业发展的根本原因了。比如:通过新能源方式赋能汽车的特斯拉、通过无人驾驶技术赋能的Google的waymo等。当然,不仅是从技术方面,从商业模式方面也有围绕着汽车这一平台创新的经典案例,典型的比如:uber滴滴等的高效出行以及近期日渐升温的共享汽车出行。

可以说,各大公司都在从自身优势出发,考虑如何为汽车这一百年黄金平台赋能。从这一点出发,我们就能大致理解百度Apollo的出现了:它是baidu结合自身的技术优势和数据优势拥抱汽车工业、为汽车做新时代赋能而迈出的重要一步。

二、Apollo的技术架构

Apollo是一套完整的自动驾驶技术方案,官方架构原图的截图较为模糊,这里自己画了一个简单的四层结构,每层内的模块暂未画出,因为不是本次入门的重点:

img{512x368}

按照上图,apollo自动驾驶分成四层技术栈,从下到上分别为:

1、Reference Vehicle Platform(参考车辆平台)

自动驾驶最终都要落地到车上,因此apollo抽象了一个”参考车辆平台”层,通过电子化的方式控制车辆的行驶行为。

Note: 在开发者大会上,百度展示了由美国创业公司AutonomouStuff基于Apollo 1.0开放平台改装而成的循迹自动驾驶车,这辆车是一辆美系的林肯MKZ。也就是说当前发布的Apollo适配林肯MKZ是没有问题的。但这款中型车对于普通开发者来说门槛算是稍高了。如果百度能拿出一款大众系、丰田系或至少也应该是一个本田系这样的车型,那对自动驾驶领域的开发者或者说爱好者来说,才是福利。相比而言,著名黑客George Hotz创立的自动驾驶技术公司comma.ai为其openpilot初始选用的车型则是Honda系的思域和CR-V,滥大街的车型,容易搞到,且低成本搞到,也容易改装。

2、Reference Hardware Platform(参考硬件平台)

这一层为自动驾驶汽车提供计算、感知、交互的硬件能力,包括计算单元(车载处理器设备)、GPS/IMU(惯性测量设备)、摄像头、激光雷达、声波雷达、HMI(人机接口)等。在发布的Apollo 1.0版本中,开放的硬件能力包括:计算单元、GPS/IMU(惯性测量设备)以及HMI。

3、Apollo open software Platform (开放软件平台)

这一层是百度Apollo 1.0开放的核心部分,见下图(蓝色的代表在apollo 1.0.0中已经开放的能力):

img{512x368}

从图中看到,这一层还可以分为三个子层,从下至上分别是:

  • apollo kernel层

这一层是运行于硬件上面的OS,对于自动驾驶这种实时性要求特别强的领域,这里显然只能是RTOS(实时操作系统)。Apollo 1.0开放的源码中包含一个”Apollo Kernel“的项目,在这个项目下汇集着可以满足实时性需求的OS kernel。当然目前还仅有一个选择:realtime linux kernel。这是apollo基于Linux Kernel 4.4.32+realtime patch定制的一款专用linux内核。

  • apollo platform层

在Kernel层的上面就是apollo的runtime framework了,提供platform级的支撑。Apollo 1.0同样也创建了一个专用项目:apollo-platform,用于汇集满足apollo平台级支撑需求的platform。当前该项目下也仅提供了一种选择:Apollo ROS,是基于ROS1的Indigo版二次开发后的定制版ROS。Apollo ROS基于自动驾驶需求出发,对ROS1主要做了三方面改进:

  • 为优化自动驾驶大量使用传感器引发很大的传输带宽需求, Apollo ROS改变基于socket的网络传输模式,大量采用共享内存的node间通信机制,减少传输中的数据拷贝,显著提升传输效率, 尤其是在满足一对多的传输场景下效果明显;

  • 从鲁棒性出发,使用RTPS(Real-Time Publish Subscribe)服务发现协议实现完全的P2P网络拓扑,避免原ROS的以Master作为拓扑网络的中心的单点故障问题;

  • 使用protobuf替代原ROSmessage,提供很好的向后兼容,避免接口升级后,不同版本的模块难以兼容的问题。

其实第二点改进也是ROS2正在做的事情。关于Apollo ROS的详尽变化,可以参考前不久百度工程师的一个分享:《Apollo代码开放框架—ROS 探索与实践》

  • apollo modules层

在这一层是apollo的功能modules,当前似乎依旧是基于ROS的package开发的,在github.com/ApolloAuto/apollo/modules/common/apollo_app.cc你大致能看出来一个ROS Package的开发模板。这一层提供诸如:规划(planning)、洞察(perception)、控制(control)、预测(prediction)、决策(decision)、定位等诸多功能。但Apollo 1.0仅仅开放了Control、Localization和HMI三个module,因为这三块足以构成Apollo 1.0提供的封闭场地循迹驾驶体系了。

4、Cloud Services(云端服务)

Apollo 1.0还开放了云端数据平台,以及唤醒万物的DuerOS能力。DuerOS也是Baidu人工智能战略的重要棋子,似乎也是目前Baidu在AI方面最为成熟的、应用最广的产品。当然这一层还包括仿真、高精度地图等服务,不过目前尚未开放。

三、上手Apollo

买不起林肯MKZ的童鞋也不要担心,Apollo 1.0提供了一个本地仿真工具,给你一个与Apollo亲密接触的途径,让你可以在PC上肆无忌惮地玩耍,毕竟Apollo 1.0仅提供封闭场地的寻迹能力,相对简单。

我们的重点是Apollo open software Platform这一层,而这一层中,我们不关心apollo kernel,只关心Apollo ROS和三个已经开放的apollo modules。

1、下载release版本

截至目前为止,Apollo仅发布了一个版本:apollo-v1.0.0,我们可以从github上将其下载到本地:

# wget -c https://github.com/ApolloAuto/apollo/archive/v1.0.0.tar.gz
# tar zxvf v1.0.0.tar.gz
# cd apollo-1.0.0
# ls -F
apollo_docker.sh*  apollo.doxygen  apollo.sh*  AUTHORS.md  BUILD  CPPLINT.cfg
docker/  docs/  LICENSE  modules/  README.md  scripts/  third_party/  tools/  WORKSPACE

注意:我的实验环境为ubuntu 16.04.1 amd64。

2、本地源码构建

对于基于Apollo这个framework的开发者,Apollo官方强烈建议直接采用官方预定义好的专用docker环境(for dev)。对于爱折腾的我而言,必须要在本地做一次源码构建,即使这个体验是糟糕的,甚至最终是失败的^0^。源码构建的命令很简单,一行即可:

# cd apollo-1.0.0
# bash apollo.sh build

在这个过程中,我遇到了两个错误:

  • bazel不存在

Apollo的构建依赖google出品的bazel构建工具,我个人对bazel并没有什么研究,这里先装上再说:

# echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" |  tee /etc/apt/sources.list.d/bazel.list
deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8

# curl https://bazel.build/bazel-release.pub.gpg | apt-key add -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3157  100  3157    0     0   3202      0 --:--:-- --:--:-- --:--:--  3201
OK

# apt-get update && apt-get install bazel
  • third_party/ros/setup.bash: No such file or directory

apollo的编译要依赖ros,但apollo并没有自带ros。我们需要到apollo platform那个项目中去下载Apollo ROS:

# wget -c https://github.com/ApolloAuto/apollo-platform/releases/download/1.0.0/ros-indigo-apollo-1.0.0.x86_64.tar.gz
# tar zxvf ros-indigo-apollo-1.0.0.x86_64.tar.gz
# cd ros
# ls -F
bin/  BUILD  env.sh*  etc/  include/  lib/  setup.bash  setup.sh  _setup_util.py*  setup.zsh  share/

将下载的ros目录copy到apollo-1.0.0/third_party下,并chmod +x third_party/ros/setup.bash。

我们再次执行bash apollo.sh build,这次执行前面的error和warning基本都消失了,apollo.sh脚本开始下载依赖包并编译:

# bash apollo.sh build
ROS_DISTRO was set to 'kinetic' before. Please make sure that the environment does not mix paths from different distributions.
[WARNING] ESD CAN library supplied by ESD Electronics does not exit.
[WARNING] If you need ESD CAN, please refer to third_party/can_card_library/esd_can/README.md
.
____Loading package: modules/common/util/testing
____Loading package: @com_github_grpc_grpc//
____Loading package: @google_styleguide//
____Loading package: @glog//
____Loading package: @eigen//
____Loading package: @gtest//
____Loading package: @civetweb//
____Loading package: @com_github_google_protobuf//
____Loading package: @websocketpp//
____Loading package: @curlpp//
Building on x86_64, with targets:
//tools/platforms:x86_64
//tools/platforms:aarch64
//modules/prediction:prediction
//modules/prediction:prediction_lib
... ...
//modules/common:log
//modules/canbus/proto:canbus_proto.pb
//:x86_64
//:arm64
WARNING: Running Bazel server needs to be killed, because the startup options are different.
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,750,374 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3309 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,773,664 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3314 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,795,584 bytes
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,504,198 bytes

INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,522,008 bytes
INFO: Found 190 targets...
[34 / 41] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/java/java_message_lite.cc [for host]
[41 / 48] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/command_line_interface.cc [for host]
[157 / 163] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc [for host]
[752 / 756] Compiling external/com_github_grpc_grpc/src/core/ext/client_config/resolver_result.c

ERROR: /root/test/apolloauto/apollo-1.0.0/modules/canbus/BUILD:32:1: Linking of rule '//modules/canbus:canbus' failed: gcc failed: error executing command /usr/bin/gcc -o bazel-out/local-dbg/bin/modules/canbus/canbus '-Wl,-rpath,$ORIGIN/../../_solib_k8/_U_S_Sthird_Uparty_Sros_Cros_Ucommon___Uthird_Uparty_Sros_Slib' ... (remaining 8 argument(s) skipped): com.google.devtools.build.lib.shell.BadExitStatusException: Process exited with status 1.
modules/canbus/main.cc:21: error: undefined reference to 'ros::init(int&, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
third_party/ros/include/ros/publisher.h:107: error: undefined reference to 'ros::console::initializeLogLocation(ros::console::LogLocation*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ros::console::levels::Level)'
... ...
collect2: error: ld returned 1 exit status
INFO: Elapsed time: 578.172s, Critical Path: 26.62s
============================
[ERROR] Build failed!
[INFO] Took 597.189 seconds
============================

经过漫长的等待后,还是以失败告终。并且C++的错误输出分析起来真是好痛苦,于是暂时放弃本地源码编译。

3、pre-specified Docker dev环境

既然apollo已经为我们准备好了pre-specified Docker dev环境,我们不妨用一下,下载和启动该环境可以用下面命令:

# cd apollo-1.0.0
# bash docker/scripts/dev_start.sh

apolloauto/apollo:dev-latest这个image超级庞大,大约有7个G左右,所以你需要耐心等待一会儿了。docker运行起来后,我们在另外一个terminal windows下可以执行下面命令切入到该docker容器内部:

# bash docker/scripts/dev_into.sh
root@myhost: /apollo#

在dev container中,我们可以来编译一下apollo源码:

root@myhost:/apollo# bash apollo.sh build
... ...
Copyright (c) 2017 Various License Holders. All Rights Reserved
Apollo software is built on top of various other open source software packages,
a complete list of licenses are located at https://github.com/ApolloAuto/apollo/blob/master/third_party/ACKNOWLEDGEMENT.txt

You agree to the terms of all the License Agreements.

Type 'y' or 'Y' to agree to the license agreement above, or type any other key to exit
y[WARNING] ESD CAN library supplied by ESD Electronics does not exit.
[WARNING] If you need ESD CAN, please refer to third_party/can_card_library/esd_can/README.md
____Loading package: modules/monitor/common
____Loading package: modules/common/adapters
____Loading package: modules/dreamview/conf
____Loading package: modules/control/integration_tests
____Loading package: @google_styleguide//
____Loading package: @com_github_google_protobuf//
... ...
[502 / 1,099] Compiling external/com_github_grpc_grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.c
[914 / 1,524] Compiling external/com_github_grpc_grpc/src/core/ext/census/tracing.c
[1,304 / 1,527] Linking modules/canbus/vehicle/libmessage_manager_base.a

INFO: Elapsed time: 371.151s, Critical Path: 260.93s
============================
[ OK ] Build passed!
[INFO] Took 401.521 seconds
============================

由于dev环境中相关的依赖已经就绪,因此无需过多干预,在漫长的一段等待后,我们看到编译ok了。

4、运行apollo demo

在dev enviroment中或apollo:release-latest中,我们都可以运行apollo的一个寻迹小车的demo。以apollo:release-latest image环境为例:

// 启动基于apollo:release-latest image的apollo container(image size大约为3G,耐心等待下载):

# cd apollo-1.0.0/
# bash docker/scripts/release_start.sh

//切入到容器中去
# bash docker/scripts/release_into.sh
root@myhost:/apollo#

在容器中启动HMI(human-machine interface):

root@myhost:/apollo# bash scripts/hmi.sh
Start roscore...
HMI ros node service running at localhost:8887
HMI running at http://localhost:8887

root@myhostr:/apollo# rosnode list
/hmi_ros_node_service
/rosout

可以看到,hmi.sh脚本启动了roscore(ros master节点和相关服务)以及hmi的service,我们打开浏览器,输入:http://host_ip:8887即可看到如下场景:

img{512x368}

在容器内继续执行如下命令,回放小车的轨迹数据:

# rosbag play -l ./docs/demo_guide/demo.bag

[ INFO] [1502809442.462789096]: Opening ./docs/demo_guide/demo.bag

Waiting 0.2 seconds after advertising topics... done.

Hit space to toggle paused, or 's' to step.
 [RUNNING]  Bag Time: 1497125289.756657   Duration: 20.614178 / 41.613536
 [RUNNING]  Bag Time: 1497125289.896669   Duration: 20.754189 / 41.613536
... ...

我们打开hmi页面上的Debug开关,点击右上角的”Dreamview”按钮,稍后片刻,你就会在新打开的页面上看到小车仿真寻迹行驶的场景了:

img{512x368}

最初实验时,由于没有在阿里云的防火墙打开8888端口,导致dreamview的websocket建立连接失败,dreamview页面始终无法显示出小车。后经与apollo team的ycool在线联调才发现这个问题。这个问题的解决方法也已更新到Apollo的FAQ中了。

四、小结

Baidu为apollo项目做了一个4年的规划(见下面的roadmap),并计划在2020年实现全路网自动驾驶,这个说法似乎有意避开了自动驾驶的级别,这个2020目标到底是L4呢还是L5呢?不过无论是L4还是L5,这个目标都十分有挑战啊。

img{512x368}

个人觉得:未来的L4、L5级别的自动驾驶一定不光光是依靠车辆自身的设备与算法,还要与道路基础设施相配合去实现。甚至是依赖车与车之间的通信才能做到全天候、全路况的自动驾驶。apollo虽然迈出了第一步,但任重道远,让我们拭目以待吧!


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! 图片广告位1 图片广告位2 图片广告位3 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats