Skip to content

机器人应用中的行为树和状态机

论文“机器人应用中的行为树和状态机”(见后)对机器人领域中行为树(Behavior Trees,BT)和状态机(State Machines,SM)这两种行为建模语言的关键概念、实际应用及其实现进行了深入的实证研究。

音频概览:

研究背景与目的 自主机器人通过组合各种技能来形成日益复杂的行为,即“任务”。虽然技能通常在较低抽象层次上编程,但其协调通常在较高层次的语言或框架中表达。几十年来,状态机一直是行为建模的首选语言,但最近行为树在机器人专家中获得了关注。行为树最初设计用于模拟电脑游戏中自主角色的行为,提供了一种可扩展的树状任务表示,并被认为支持模块化设计和代码复用。然而,关于行为树在实际世界中的使用和范围,以及它们与传统状态机语言的关系知之甚少。本研究旨在通过分析开源机器人应用中行为树和状态机领域特定语言(DSLs)的实际概念和使用模式,填补这一知识空白。

研究问题 论文旨在回答以下三个主要研究问题: * RQ1:语言实现(库)中提供了哪些行为树和状态机的建模概念? * RQ2:这些语言(库)在实践中是如何设计的? * RQ3:行为树和状态机模型在机器人项目中是如何使用的?

研究方法 研究采用探索性方法,结合定性和定量数据分析。 1. 识别语言和概念 (RQ1): * 通过GitHub搜索和机器人学文献,识别了支持ROS的Python和C++语言中活跃维护且有文档的行为树DSL。 * 对于状态机DSL,主要通过ROS wiki平台进行搜索,以确保其支持ROS,并排除了缺乏文档、过时或无开源项目使用的库。 * 通过检查文档和执行小型测试脚本,分析了所选DSL提供的关键语言构造和概念。 2. 语言实现分析 (RQ2): * 检查了GitHub上的库实现、文档、教程和相关出版物,以理解其设计原则和实现技术。 * 关注了库的语言设计、具体语法、模型在运行时的动态修改能力以及所使用的并发模型。 3. 识别语言项目和分析 (RQ3): * 挖掘GitHub:使用Python脚本在GitHub上挖掘使用识别出的行为树和状态机DSL的开源机器人项目。 * 项目过滤:应用多步过滤机制,排除分叉仓库、重复仓库、工具仓库以及属于教程或课程的项目,以确保数据反映真实应用。 * 模型下载与分析:下载包含行为模型的源文件。随机抽取了75个行为树模型和75个状态机模型进行深入分析,以确保样本的可比性。 * 度量指标:计算了衡量模型核心结构方面的指标,包括模型大小(节点/状态数量)、树深度(行为树)、平均分支因子(行为树)、嵌套级别(状态机)和节点类型百分比。 * 重用分析:通过结合视觉检查和代码级检查,识别了项目中技能(动作)和任务(子树/复合状态)的重用模式。

研究结果 1. RQ1:建模概念与语言设计: * 相似性:行为树和状态机DSL在语言设计和所提供概念方面存在相似之处,都支持领域特定模式和开放性,允许项目根据需要扩展DSL。 * 行为树概念: * 编程模型:支持同步和异步,时间驱动,基于活动。 * 简单节点:叶节点,实现基本计算,可以是动作(执行命令)或条件(评估布尔值并返回成功/失败)。 * 复合节点:内部节点,定义遍历顺序。包括序列 (Sequence)选择 (Selector)并行 (Parallel)装饰器 (Decorator)。其中,序列节点要求所有子节点都成功才成功,选择节点只需一个子节点成功即可。并行节点是序列和选择的泛化,允许自定义策略,但并非真正并发执行。 * 执行语义:通过从根节点发送“ticks”来遍历树,节点执行任务后返回状态(成功、失败、运行中)。每次tick都会定期重新执行树。 * 装饰器:单目复合节点,修改子树的数据或控制流,如反转器 (Inverter)成功器 (Succeeder)重复 (Repeat)重试 (Retry)。 * 开放性:DSL元模型不固定,用户需要通过实现自定义动作节点来扩展元模型,然后将其链接到语法树中。 * 耦合性:行为树模型通常与底层软件系统紧密耦合,使得模型难以在系统外部操作和重用。 * 状态机概念: * 编程模型:事件驱动,通常异步。 * 状态:表示行为模式,机器人执行的行为由与状态关联的动作表示。 * 分层嵌套:通过“容器”设计模式支持分层状态机,增加模型的模块化和减少所需转换的数量。 * 控制流容器:提供预定义的容器来支持常见的控制流模式,如并发 (Concurrence)序列 (Sequence)迭代器 (Iterator)。 * 数据流:使用局部作用域的UserData字典处理状态间和系统间的数据流,与行为树的全局Blackboard不同。 * 开放性:也具有开放性,用户可以扩展容器和状态的元类。

  1. RQ2:语言实现

    • BT DSLs
      • 分布:主要作为库分发,如BehaviorTree.CPP是C++库,PyTrees是Python库。
      • 可视化:BehaviorTree.CPP提供图形编辑器和运行时监视器Groot,支持XML格式的模型构造。PyTrees_ros是内部DSL,模型与Python代码混杂,可视化和分析更困难。
      • 并发:不严格规定并发模型,通常依赖底层ROS平台实现交错和真正的并发。
      • DSL类型:BehaviorTree.CPP技术上是外部DSL,但支持运行时修改。PyTrees_ros是完全动态的内部DSL。
      • 执行:模型通常是解释执行的。
    • SM DSLs
      • 分布与可视化:FlexBe作为建模环境,提供GUI(FlexBE App)用于模型构建、监视和运行时修改。SMACH主要作为Python库使用,其smach_viewer仅用于检查和调试已创建的状态机,不支持构建或修改。
      • MDE实践:FlexBe使用模型驱动工程(MDE)技术,支持从模型(半)自动生成代码,并进行语法和语义一致性检查,支持角色分离。
      • 并发:不严格规定并发模型。提供并发容器,通过Python线程实现多状态同时活跃(交错执行而非并行)。
      • DSL类型:FlexBe是外部DSL,支持通过补丁在运行时修改模型结构。SMACH是内部DSL,通过编辑Python代码进行扩展。
      • 执行:都是运行时解释执行。FlexBe在应用修改前会进行验证检查。
    • 设计启示:提供GUI工具进行模型构建和监控有助于更好地理解模型和提高代码重用。外部DSL(如BehaviorTree.CPP和FlexBe)倾向于强制使用DSL构造,而内部DSL(如PyTrees_ros和SMACH)则更容易偏离并使用普通编程语言构造。
  2. RQ3:模型使用

    • 语言流行度
      • 行为树:BehaviorTree.CPP和PyTrees在开源项目中的使用在2018年后迅速增长,到2021年达到2018年的近十倍,这可能与ROS 2将其作为导航栈核心组件有关。
      • 状态机:SMACH在2015年前是唯一可用的语言,之后FlexBe虽然总体使用量低于SMACH,但其自2018年以来的增长速度远高于SMACH。
    • 模型结构特性
      • 模型大小:行为树模型的平均大小(26个节点)是状态机模型(9个状态)的三倍。这可能与行为树同时表示执行节点和控制流节点有关,也可能是因为状态机模型在变大时理解起来更复杂。
      • 嵌套与深度:状态机模型平均嵌套级别为1,行为树模型平均深度为5。样本项目中的开发者倾向于保持模型结构简单和浅层,以提高可理解性。
      • 概念使用频率
        • 行为树:66%的节点是叶节点,34%是复合节点。复合节点中,序列节点使用最广泛(56%),其次是选择器(21%)。并行节点使用较少(7%)。装饰器在BehaviorTree.CPP中比PyTrees_ros中使用更频繁(19% vs. 6%),这可能与BehaviorTree.CPP的GUI支持有关,使得装饰器更容易可视化和监控。
        • 状态机:控制流容器的使用远少于行为树。只有12%的状态机模型使用了控制流构造,而所有行为树模型都使用了某种控制流节点。并发容器在FlexBe中更常用,而迭代器在SMACH中是第二常用。
    • 代码重用模式
      • 研究观察到三种主要的重用模式:模型内引用 (intra-model referencing)克隆与拥有 (clone-and-own)模型间引用 (inter-model referencing)
      • 模型内引用:主要用于行为树模型,在任务层面通过创建子树并在模型内多处引用,在技能层面通过将叶节点定义为函数并传递参数来重用。在行为树模型中,技能层面的模型内引用更常见 (30%),任务层面较少 (18%)。在状态机模型中很少使用。
      • 克隆与拥有:是任务级别重用中最常用的模式(行为树模型中占48%,状态机模型中占29%)。开发者通过对现有子树或整个模型进行少量修改来重用。在技能级别重用中不太流行。
      • 模型间引用:是技能级别重用中最常用的模式(状态机模型中占67%,行为树模型中占56%),通过在外部文件定义技能(动作节点或与状态关联的动作)并导入到主模型中实现。对于任务级别重用,模型间引用是使用最少的方法。预定义技能API(如FlexBe提供的)能有效促进重用。
      • 影响因素:重用机制的选择受DSL实现以及重用技能还是任务的影响。具备专用XML格式和可视化工具的BehaviorTree.CPP项目表现出比PyTrees_ros更高的重用频率。

结论与启示 该研究揭示了在机器人领域中流行的DSL的设计和使用实践。 * GUI的重要性:提供GUI工具(如Groot for BehaviorTree.CPP和FlexBE App)进行模型构建、编辑和运行时监控,是良好的实践,因为它支持可视化和抽象,并促进了代码重用。 * 实用主义的DSL开发:在没有数百页规范文档的情况下,以实用主义方式开发DSL,并提供可扩展的元模型,这种策略似乎是成功的,因为它吸引了未受过语言和建模技术正式培训的实践者,并使他们能够以更高抽象层次实现机器人任务。 * 关注点分离和角色分离:BehaviorTree.CPP在设计时考虑了关注点分离和角色分离,使得模型可以与机器人系统解耦,便于可视化和测试。FlexBe通过代码生成支持角色分离,减少了重复性编码。 * 技能要求:尽管这些DSL提高了抽象层次,但它们仍然需要用户具备语言导向编程(元编程)的技能,这对于缺乏相关培训的机器人工程师来说是一个挑战。软件语言工程社区可以设计更易于访问但仍具灵活性的行为树方言。 * 模型驱动工程(MDE):MDE实践在机器人社区中日益普及,以提高系统的可重用性和可维护性。研究观察到许多DSL采用了MDE和软件工程中的通用实践,并得到了实践者的良好反馈。

未来工作 未来的研究可以进一步探讨不同行为建模语言的可用性、理解性和表达性,并系统地探索如何将任务需求(例如,以自然语言指定的需求)映射到不同的行为建模语言中。此外,可以制定促进MDE实践并源于当前实践的良好设计指南。利用现有数据集,开发自动工具从行为树模型生成自然语言的任务规范,以支持遗留项目的自动化再工程。还可以收集更广泛的机器人项目中行为建模语言使用的实证数据,而不仅仅局限于行为树和状态机DSL。

贡献 论文贡献了一个开源行为模型的数据集,以鼓励社区进一步使用和开发这些语言、相关工具和分析技术。

论文原文链接