Nav2特定节点介绍

警告

在刚开始的时候,词汇可能是这里的一大困惑点。 [校准@混沌无形]
  • 在讨论BT时, Node 与ROS2环境下的 Node 完全不同。 [校准@混沌无形]

  • 在BT环境下的 Recovery 不同于导航 中的 Recovery 行为 [校准@小鱼]

  • BT环境中的 ActionNode 不一定和ROS2环境中的Action服务器有关系 (但通常是) [校准@greg]

这有相当多的自定义Nav2 BT节点被提供给Nav2特定的方式使用。一些常用的Nav2节点将在下面描述。自定义BT节点的完整列表可以在 nav2_behavior_tree plugins folder 中找到。 configuration guide 也非常有用。 [校准@混沌无形]

动作节点(Action)

完成后,如果操作服务器认为操作已正确完成,这些操作节点将返回 SUCCESS ,如果仍在运行,则返回 RUNNING ,否则返回 FAILURE 。请注意,在上面的列表中, ClearCostmapService 操作节点不是操作服务器客户端,而是服务客户端。 [校准@混沌无形]

Condition节点 [校准@混沌无形]

上面列表中的condition节点可以用来探测系统的特定方面。通常情况下,当 "TRUE "时,它们将返回 "SUCCESS",当 "FALSE "时,将返回 "FAILURE"。在默认的Nav2 BT中使用的关键条件是 "GoalUpdated",它在特定的子树中被异步检查。此condition节点允许描述为 “如果目标已更新,则我们必须重新计划” 的行为。Condition节点通常与ReactiveFallback节点配对使用。 [校准@小鱼]

Decorator(装饰)节点

  • Distance Controller(距离控制器)-每当机器人运动过一定的距离,就会核对子节点。 [校准@混沌无形]

  • Rate Controller(速率控制器)-控制它的子节点的滴答时钟(ticking)运行在恒定的频率。滴答频率(tick rate)是一个暴露的端口 [校准@混沌无形]

  • 目标更新器(Goal Updater)-将通过BT上的端口更新子节点的目标 [校准@混沌无形]

  • 单触发器(Single Trigger)-将只对其子节点产生一次滴答(tick),并将为所有后续的滴答(tick)返回 FAILURE [校准@混沌无形]

  • 速度控制器(Speed Controller)-以与机器人速度成正比的速度控制其子节点的滴答(tick) [校准@混沌无形]

控制(Control): 管道序列(PipelineSequence) [校准@混沌无形]

当一个子节点返回 "RUNNING "时,"PipelineSequence "控制节点会重新标记之前的子节点。该节点类似于 Sequence 节点,具有重新标记 "current" 之前的子节点的附加特性 (类似于管道中的水流)。如果子节点在任何时候返回 FAILURE ,所有子节点都将停止,父节点也将返回 FAILURE 。在 SUCCESS 最后节点序列,该节点将停止并返回 SUCCESS[校准@混沌无形]

为了进一步解释这一点,这里有一个使用 PipelineSequence 的BT示例。 [校准@小鱼]


../../_images/control_pipelineSequence.png

<root main_tree_to_execute="MainTree">
    <BehaviorTree ID="MainTree">
        <PipelineSequence>
            <Action_A/>
            <Action_B/>
            <Action_C/>
        </PipelineSequence>
    </BehaviorTree>
</root>
  1. 这里 Action_AAction_BAction_C 都是 IDLE[校准@greg]

  2. 当父级管道序列(PipelineSequence)第一次被勾选时,让我们假设``Action_A`` 返回 RUNNING 。父节点现在将返回``RUNNING`` ,并且没有其他节点被选中。 [校准@混沌无形]


../../_images/control_pipelineSequence_RUNNING_IDLE_IDLE.png

  1. 现在,让我们假设 Action_A 返回 SUCCESSAction_B 现在会被标记,并返回 RUNNINGAction_C 尚未被标记,因此将返回 IDLE[校准@混沌无形]


../../_images/control_pipelineSequence_SUCCESS_RUNNING_IDLE.png

  1. 这个 Action_A 再次被标记并返回 RUNNINGAction_B 再次被标记并返回 SUCCESS ,因此BT第一次继续标记``Action_C`` 。假设 Action_C 返回 RUNNING 。这个 Action_A 的重新标记使得管道序列有用。 [校准@混沌无形]


../../_images/control_pipelineSequence_RUNNING_SUCCESS_RUNNING.png

  1. 序列中的所有动作(action)都将被重新标记。让我们假设 Action_A 仍然返回 RUNNING ,而 Action_B 再次返回 SUCCESSAction_C 现在返回 SUCCESS 。序列现在是完整的,因此 Action_A 停止了,尽管它仍然是 RUNNING[校准@混沌无形]


../../_images/control_pipelineSequence_RUNNING_SUCCESS_SUCCESS.png

回想一下,如果 Action_AAction_BAction_C 在任何时候归返回 FAILURE ,父节点就会返回 FAILURE ,并终止所有的子节点。 [校准@小鱼]

关于 PipelineSequence 的更多细节,请参见 PipelineSequence configuration guide[校准@混沌无形]

控制(Control): 恢复(Recovery) [校准@混沌无形]

当且仅当第一个子节点返回 SUCCESS 时,恢复控制节点(Recovery control node)只有两个子节点返回 SUCCESS 。如果第一个子节点返回 FAILURE ,第二个子节点将被标记。这个循环将持续到: [校准@混沌无形]

该节点通常用于将动作(action)和恢复动作(recovery action) (顾名思义) 链接在一起。第一动作(action)通常会是 "main" 行为,而第二个动作(action)将是在主行为 FAILURE 的情况下所做的事情。通常,第二个子节点动作(action)的标记(tick)会促进第一个动作(action)的成功机会。 [校准@混沌无形]


../../_images/control_recovery_node.png

<root main_tree_to_execute="MainTree">
    <BehaviorTree ID="MainTree">
        <RecoveryNode number_of_retries="1">
            <ComputePathToPose/>
            <ClearLocalCostmap/>
        </RecoveryNode>
    </BehaviorTree>
</root>

在上面的例子中,让我们假设 ComputePathToPose 失败了。 ClearLocalCostmap 将被标记作为回应,并返回 SUCCESS 。既然我们已经清除了成本地图,让我们说机器人能够正确地计算路径, ComputePathToPose 现在返回 SUCCESS 。然后,父恢复节点(RecoveryNode)也将返回 SUCCESS ,BT将完成。 [校准@混沌无形]

有关 RecoveryNode 的更多细节,请参见 RecoveryNode configuration guide[待校准@206]

控制(Control): 轮询(RoundRobin) [校准@混沌无形]

轮循控制节点(RoundRobin control node)以循环的方式标记子节点,直到子节点返回 SUCCESS ,其中父节点也将返回 SUCCESS 。如果所有的子节点都返回了 FAILURE ,那么父节点也会轮循。 [校准@混沌无形]

这是我们用来介绍这个概念的BT示例。 [校准@混沌无形]


../../_images/control_round_robin.png

<root main_tree_to_execute="MainTree">
    <BehaviorTree ID="MainTree">
        <RoundRobin>
            <Action_A/>
            <Action_B/>
            <Action_C/>
        </RoundRobin>
    </BehaviorTree>
</root>
  1. All the nodes start at IDLE


../../_images/control_round_robin_IDLE_IDLE_IDLE.png

2.在父节点运行时,第一个子节点 ( Action_A ) 被运行。让我们假设子节点在运行时返回 RUNNING 。在这种情况下,没有其他子节点被运行,父节点也返回 RUNNING[校准@混沌无形]


../../_images/control_round_robin_RUNNING_IDLE_IDLE.png

3.在下一个标记上,让我们假设 Action_A 返回 FAILURE 。这意味着 Action_B 接下来会被运行,而 Action_C 仍然没有运行。假设 Action_B 这次返回 RUNNING 。这意味着父轮询节点也将返回 RUNNING[校准@混沌无形]


../../_images/control_round_robin_FAILURE_RUNNING_IDLE.png

4.在下一个标记(tick)上,让我们假设 Action_B 返回 SUCCESS 。父轮询节点现在将停止所有的子节点并返回 SUCCESS 。父节点保留了该状态信息,并将在下一次滴答(tick)中运行 Action_C ,而不是像步骤2那样从 Action_A 开始。 [校准@混沌无形]


../../_images/control_round_robin_FAILURE_SUCCESS_IDLE.png

  1. 在这个标记(tick)上,让我们假设 Action_C 返回 RUNNING ,父轮询节点也是如此。没有运行其他节点。 [校准@混沌无形]


../../_images/control_round_robin_FAILURE_SUCCESS_RUNNING.png

  1. 在最后一个标记(tick)上,让我们假设 Action_C 返回 FAILURE 。父节点将再次圈出并运行 Action_AAction_A 返回 RUNNING ,父轮询节点也将返回 RUNNING 。这种模式将无限期地持续下去,除非所有的子节点都返回 FAILURE[校准@混沌无形]


../../_images/control_round_robin_RUNNING_IDLE_FAILURE.png

有关 RecoveryNode 的更多细节,请参见 RoundRobin configuration guide[待校准@216]