Rust如何改变机器人:
在大约九个月的时间里用Rust从头开始编写了整个设施控制系统
我们用Rust编写了一个完整的10万行工厂控制器,我们从来没有使用过不安全的C
以下是对 AMP Robotics 机器人架构师 Carter Schultz 的采访,他是AMP Robotics的机器人架构师。AMP Robotics是一家专注于回收领域的尖端机器人技术公司。采访中,Carter分享了他的背景、AMP正在做的工作,以及他对Rust如何根本改变典型机器人架构的思考。
教育成长
Carter在高中时期通过参与机器人竞赛队对机器人技术产生了浓厚的兴趣,并在大学期间获得了机械工程学位,同时选修了许多电气工程课程。
本科毕业后,我的计划是读研究生。我是整个家族中唯一没有研究生学位的人。所以,我以为这就是出路。我被录取去佐治亚理工学院攻读博士学位,或去卡内基梅隆大学攻读硕士学位。我当时正在筛选这些选择,然后我随意地向 SpaceX 投了简历。我没怎么想,直到我接到了面试电话。大学四年后,我决定也许工作会更好。
所以,我在最后一刻做出了转变。我最终在 SpaceX 的一个叫做运载工具操作开发的小组工作,该小组负责自动处理发射场的火箭。大部分工作都在卡纳维拉尔角进行。
该小组正在制造用于拾取火箭、转动火箭等的设备。我花了很多时间在机库内起重机的软件控制上。
我被录用的小组只有机械工程师。当时 SpaceX 正遭受着部落主义和工作阻碍。该小组负责制造机器人,但全部由机械工程师组成。因此,机械工程师会设计机器人,然后他们会被困几个月等待电气工程小组,然后电气工程小组又会等待软件小组。将整个集成系统整合在一起是一项真正的挑战。
因此,我被聘为机械工程系的软件工程师。我几乎什么都不做,只是为他们编写软件。
入职AMP
当我第一次来到 AMP 时,我非常不确定这是否是我想要做出的选择。我之所以能来到这里,很大程度上是因为我打电话询问了业内人士 Matanya 的情况,他享有金童般的声誉。人们会说,“我甚至不知道 AMP 在做什么,但如果 Matanya 在做这件事,你应该去那里工作。”最后,Matanya 带我出去吃饭,我当时想,好吧,计划是什么?当时,他们刚刚开始生产第一批拾取和放置回收机器人,而他根本没有谈论它们。这些只是飞轮,最终将让 AMP 建造全新的未来回收设施。
当我加入公司时,公司已经运营了两年半左右,公司里的每个人都在给回收的帧贴标签,以建立初始数据集。好像公司里没有不给帧贴标签的人:离总部 15 分钟路程的地方有一个回收设施,基本上给我们提供了一段传送带,让我们想做什么就做什么。所以,最初的团队立即就把相机放下来,开始将帧上传到云端。
AMP 在物体分类领域还处于早期阶段,当时还没有现成的解决方案来构建自己的数据集。因此,我们不得不从头开始编写自己的标记工具。如今,有大约 20 家公司向我们敲门。因此,无论好坏,我们最终都从头开始构建了大量的基础设施。
转向Rust
Carter的职位涉及多个领域,他负责为项目设定技术基础和结构,确保最终产品符合预期。
Carter对C++感到失望,因此开始探索使用Rust作为替代语言。AMP决定在其新建的回收设施中使用Rust从头开始构建控制系统,Carter认为这是一个正确的决定。
最终,一个大型绿地项目的机会出现了。AMP 决定首次建造自己的回收设施,我们需要一个可以运行整个设施的控制系统。该系统将与网络上的数十个子系统和数百台设备进行通信。这不是一件非常复杂的事情,但由于它控制着整个设施,所以它必须是万无一失的。
所以,这是一个足够新的项目,我们可以用 Rust 从头开始。我决定用 Rust 来做,我坚信这是正确的决定。
我们一开始只是对 Rust 进行了一些尝试,每个人都同意他们喜欢它并且它会起作用,所以我们继续前进。所以,我们在大约九个月的时间里用 Rust 从头编写了一个完整的设施控制系统。实际上,我在 RustConf 2023 上发表了关于构建这个系统的演讲。该项目的成功基本上让我成为了一名完整的 Rust 布道者。现在,我想知道我们能多快摆脱 C++ 并将所有内容转移到 Rust?
我不是疯子。我知道把我们所有的 C++ 代码都扔掉并说现在一切都是 Rust 是不对的。我们必须逐步迁移。我们必须尊重遗留代码,找到与 C++ 功能相匹配的库,并重新培训开发人员。但是,我现在肯定会尽我所能,在 AMP 上转向 Rust。
机器人操作系统 ROS
首先,ROS 不是一个操作系统,而是一个框架。更重要的是,它是机器人的微服务。基本上,有一个消息总线,您可以使用它来编写机器人应用程序,它是一堆微服务,它们相互发布和订阅消息。这是机器人堆栈的基本架构。
所以我深受微服务文化的影响。这是我过去 10 年编写软件的方式。我相信微服务是机器人的基本架构。因此,该进程间通信层允许您使用不同的语言编写每个微服务,并且它们可以相互操作,因为它们只是传递消息。
因此,我们实际上可以通过一次重写一个微服务来逐步迁移堆栈。我希望我们可以在重写这些服务时逐一重写它们。
当我开始在 AMP 工作时,我们的代码库大约 40% 是 Python,60% 是 C++。这两种语言是ROS 支持的两种主要语言。
很多人在开始使用 ROS 构建东西时,会用 Python 编写所有内容,因为这样开发速度更快。我认为这也是一个很好的开始方式。然后,一旦你把所有东西都放到了正确的位置,你就可以开始寻找瓶颈。
我想我职业生涯的四分之一都在用 C++ 重写 Python,使其速度提高 100-200 倍。我不是 Python 的反对者。你可以编写非常快的 Python 代码。但是,通常我会选择人们匆忙编写的代码,根本不考虑性能。所以,我们真的有很多机会重写微服务。
我在 ROSCon 上发表了一个演讲,介绍了 roslibrust,这是一个 ROS 到 Rust 的接口库。这是我们的控制系统与设施中的所有 ROS 设备通信所必需的,所以我们非常频繁地使用它。它的架构和实施方式不利于同一台计算机上的微处理器之间的通信。它的开销相当高。但是,它非常灵活,这对于我们需要中央控制器完成的工作非常有用。
当我们谈论同一台计算机上的两个进程来回传递 GB 的图像数据时,我们确实需要为此获得正确的工具。
有几个库可以做到这一点。我认识这些库的一些维护者。但不幸的是,这里更广泛的背景是,ROS 可以很容易地建立机器人堆栈,但没有标准方法来执行诸如在世界各地部署的系统上更新软件之类的事情。
而且,ROS 没有现成的打包和分发解决方案。因此,围绕我们的 C++ 代码,我们拥有一个完整的 CI 基础架构,而所有内容实际上都是在 Docker 之上构建的。我们有来自其他 Docker 镜像的 Docker 镜像,将 Nvidia 驱动程序、TensorFlow 和 OpenCV 以及我们依赖的所有这些软件安装到最终的 Docker 镜像中,然后可以部署。
而且,我们拥有所有这些有关如何部署这些 Docker 镜像的工具。因此,很多东西都必须更新才能支持另一个编译器、另一种语言和另一组依赖项。
ROS 的未来可能有点不明朗,或者说人们渴望改变。
在过去四年左右的时间里,ROS 的框架发生了重大变化,最终发展为 ROS 2。我理解他们为什么在 ROS 2 中做出这些改变,但他们这样做并没有考虑到向后兼容性。而且,他们为ROS 2 做出的设计选择只适合某些人的需求。例如,在我看来,它们适合许多学术界、群体机器人和通过不良网络通信相互通信的机器人组。
这些对我们来说都不重要,我们在嵌入在一个位置的一台计算机上运行一个堆栈,并且我们有一个硬线以太网电缆连接到它。
因此,业内很多人并没有迁移到 ROS 2。
我认为今年是 ROS 2 下载量超过 ROS 1 下载量的第一年。越来越多的教育材料和学习 ROS 的新人正在转向 ROS 2,但有大量公司仍在使用 ROS 1,可能不会放弃它。我亲自与其中几家公司交谈过,迁移故事相当残酷。所以,这是关于 ROS 的第一个重要知识点。
第二个重要知识点是,ROS 不仅仅是一个进程间通信框架,它还可以让微服务相互发送数据。ROS 1 发明了自己的通信协议,用于序列化和反序列化消息。我对所有这些都非常熟悉,因为我已经用 Rust 从头开始重新实现了很多。
但无论如何,这是 ROS 自己 开发的东西。在编写 ROS 1 时,还没有现成的优秀等效产品。因此,编写自己的产品是合理的。从那时起,现在有几十种产品可以为您做到这一点。一个很好的例子就是协议缓冲区。协议缓冲区解决了许多与 ROS 相同的问题。因此,这是 ROS 生态系统的重要组成部分,现在有更多标准的现成解决方案。因此,当他们转向 ROS 2 时,他们决定这次不会推出自己的通信系统。
他们从货架上拿来的一个东西就是 DDS,我不是这方面的专家,所以我不能很好地谈论它。我认为它来自汽车行业或航空航天行业。但是,DDS 很混乱。使用ROS 实现 DDS 的方法不止一种。有三个 DDS 后端是插件,它们之间有奇怪的差异,在不同的系统上表现不同。所以,一般来说,ROS 社区都觉得 DDS 有点糟糕。所以,这是人们还没有转向 ROS 2 的原因之一。
去年在 ROSCon 上,Alphabet 宣布收购了开源机器人基金会的一部分。我认为这是件好事,因为至少从理论上讲,他们将拥有更多火力来对抗 ROS。但是,他们还宣布将在 ROS 2 中提供 DDS 的替代方案。他们选择的替代方案是 Zenoh。而且,它是用 Rust 编写的!
因此,ROS 即将把 Rust 置于项目的核心。
他们有很多博客文章介绍 Zenoh 为何如此优秀,因为它是用 Rust 编写的,Rust 更好、更可靠。有点搞笑的是,他们不会让你直接用 Rust 和 Zenoh 对话!看,在 ROS 1 中,他们决定定义这种 通信机制,然后每种语言都必须实现该通信协议。这导致了大量错误和社区兼容性问题。
例如,Java 处理事情的方式与 Python 略有不同,当 Python 与 Java 对话时会出现奇怪的错误。因此,对于 ROS 2,他们决定找到一个 C 库作为机器人中间件,每种语言都会调用该 C 库。因此,他们将 Rust Zenoh 层放在该 C 库后面。您仍将调用 C 库,然后在它的另一端是 Rust。因此,您必须经过一堆奇怪的间接层。您不会感受到 Rust 的原生感觉,而且您必须处理链接和安装。
ROS 正在向 Rust 靠拢
我认为你不需要 ROS,因为如果你使用 Rust,我不知道你是否真的需要微服务。
使用微服务的第一个根本原因是异步和并行。你想将机器人思维的概念描述为一个异步计算图,其中你在一端接收传感器输入,在另一端输出操作。信息流经该图,每个节点都尽可能快地处理最新可用的数据。这是编写机器人的一种非常好的方法。你不想用中央循环或类似的东西来编写机器人。这会给你带来很多性能瓶颈问题。
因此,最好将应用程序分解成许多异步任务,这些任务动态地相互发送和接收信息。这可以让你更好地利用现代计算硬件,并行运行更大、更重的算法。
在 C++ 中,很难有效地编写,而不会出现各种内存泄漏、各种线程锁定问题和互斥地狱。在 Python 中,由于 GIL 和多线程 Python 的性能问题,这几乎不可能实现。因此,ROS 提供了一种将所有这些作为单独 进程编写的方法。因此,如果任何单个微服务分段发生故障或丢失内存,它将终止该节点。该节点将重新启动,但整个应用程序不会关闭,因为内存损坏和未定义行为被锁定在各个节点的进程边界上。所有这些都会带来大量开销,因为序列化所有这些消息并通过 ipc 层发送它们比共享内存访问要慢得多。
那么,如果我现在有了 Rust 会怎样?这是一种语言,我可以在其中编写一个相互连接的各个任务的异步图,并且可以知道其中任何一个任务都不会发生未定义的行为。我知道不会发生内存损坏,其中一个任务会拖垮其他任务。而且,您不必使用 ipc 层来序列化数据并通过套接字发送出去,而是可以使用 Rust 的通道和低级同步机制免费传递数据。这取代了我主张使用ROS 的大多数理由。
现在,实现任何这些目标都面临一个巨大的障碍。那就是驱动程序。驱动程序是我整个职业生涯中都在处理的一大问题。例如,我们在机器人上运行的应用程序可能有 150,000-200,000 行 C++ 代码。但是,我们调用了其他人的四百万行 C++ 代码。你根本无法完全靠自己编写机器人。你必须引入其他人的东西,而且所有这些代码仍然是用 C++ 编写的,并且仍然有缺陷。
所以,今天我不能说你应该将整个机器人应用程序编写成一个 Rust 整体,因为现实情况是,一旦你开始调用一些供应商代码,它就会开始破坏内存。它会拖垮你的整个应用程序。
所以,我们还没有到那一步。但是,看看 Rust 已经走了多远。如果 10 年后我的相机驱动程序是用 Rust 编写的,我的电机控制器驱动程序是用 Rust 编写的,我使用的路径规划库是用 Rust 编写的,那么我可以将我的整个应用程序作为一个 Rust 整体来运行。这比我现在使用一组 ipc 微服务所花的开销要低得多。我还认为调试和发布会更容易。
ROS 有一个减少一些开销的解决方案,即你可以在单独的进程中编写所有内容,然后翻转标志以将它们编译为节点。因此,看似单独的进程会被编译成一个进程。你可以在 ROS 中以这种方式进行共享内存访问以消除一些开销。
但是,你仍然会遇到一个问题,即如果其中一个失败,它会导致整个集合崩溃。如果不这样做,我们可能会损失 10-20% 的性能。但我认为更大的问题是,将所有内容编写为单独编译的单独进程会限制编译器进行大量良好检查的能力。如果将所有内容编译为一个 Rust 应用程序,借用检查器可以跨任务边界进行检查,而当你编译所有内容时,你无法做到这一点。
许多公司都加入进来,在 ROS 之上构建了层,以使其更容易使用。Formant 是一家大公司。Foxglove 是该领域的另一家大公司。他们扩展了免费的 ROS。然后,还有一家名为 Viam 的公司。Viam 基本上是在编写 ROS 的替代品,据说这种替代品更加友好,使用起来也更方便。我认为他们的做法完全错了。他们试图通过创建 Web 界面之类的东西,让你进一步远离源代码,你可以在其中进行 json 配置之类的操作。这不是一件疯狂的事情。它确实解决了使用 ROS 的许多挑战,但我担心他们会被现代软件开发潮流打败。当你拥有像 rust 这样的语言时,对许多抽象层的需求就会消失,这种语言可以让你按照实际应该编写的方式编写 API。
有很多软件工程师对机器人感兴趣。您会给这些人提供什么建议或想法?
我有很多建议,可能涉及几个不同的方向。首先我想说的是学习 ROS。这是我哥哥给我的建议。我早期用 ROS 做过一个个人项目。这对招聘机器人工程师的人来说非常有吸引力。ROS 目前在世界上大多数地方都是王者,它是一个很好的框架,值得了解,也是一件值得学习的事情。所以,这是非常具体的事情。刚开始有点痛苦,但也不是那么糟糕。
第二点我想说的是去制造机器人。即使它们很糟糕,即使这个想法很愚蠢,也要自己从头开始做。你应该用 CAD 设计它,用 3D 打印零件,从 SparkFun 购买电机,把它们连在一起,装上软件,让它做最愚蠢的事情。自己经历整个过程,了解基础知识,会让你变得非常有价值。你会比仅仅成为一名软件开发人员更有价值。你需要知道机械师们在谈论扭矩、电流或诸如此类的东西时在说什么。拥有广泛的基础,了解一切工作原理,会让事情变得更好。
此外,实际动手经验很重要。自己动手做东西比参加无数次讲座学到的东西要多得多。
在找工作方面,做一个作品集网站。让我兴奋的是 YouTube 上有人制作的机器人很糟糕的视频。向我展示你做过的东西是十分重要的。我要强调的另一件事是自己解决问题。你遵循的教程越多,你从中获得的经验就越少。
机器人技术的一个著名特点是,机器人比人们想象的要难得多。
所以,你会想出一个太难的想法,你会做到一半,意识到它有多复杂,然后你会抛弃它,想出一个更简单的想法,并真正做到这一点。我见过五只机械臂组成的时钟,可以在白板上写上时间。
听起来很简单,但这些项目很难!如果你真的能做到,我会为你鼓掌。我知道这需要多长时间才能完成。
作者:老J
参考:
https://filtra.io/rust/interviews/amp-feb-24
本文为 @ 万能的大雄 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。