简介
刚开始时,词汇可能会造成很大的困惑。 - 讨论 BT 时使用的“节点”与 ROS 2 上下文中的“节点”完全不同
BT 上下文中的“ActionNode”不一定与 ROS 2 上下文中的 Action Server 相连(但通常是相连的)
有相当多的自定义 Nav2 BT 节点可供以 Nav2 特定方式使用。下面将介绍一些常用的 Nav2 节点。 自定义 BT 节点的完整列表可在 nav2_behavior_tree 插件文件夹 中找到。 配置指南 也非常有用。
动作节点
ComputePathToPose - ComputePathToPose 动作服务器客户端(规划器接口)
FollowPath - FollowPath 动作服务器客户端(控制器接口)
Spin、Wait、Backup - Behaviors 动作服务器客户端
ClearCostmapService - ClearCostmapService 服务器客户端
完成后,如果操作服务器认为操作已正确完成,这些操作节点将返回“SUCCESS”,如果仍在运行时,则返回“RUNNING”,否则将返回“FAILURE”。请注意,在上面的列表中,“ClearCostmapService”操作节点不是操作服务器客户端,而是服务客户端。
条件节点
GoalUpdated - 检查目标主题上的目标是否已更新
GoalReached - 检查目标是否已达成
InitialPoseReceived - 检查“intial_pose”主题上的姿势是否已收到
isBatteryLow - 通过监听电池主题检查电池电量是否不足
上述条件节点列表可用于探测系统的特定方面。通常,如果条件为真,它们将返回“SUCCESS”,否则将返回“FAILURE”。 默认 Nav2 BT 中使用的关键条件是“GoalUpdated”,该条件在特定子树内异步检查。此条件节点允许描述为“如果目标已更新,则我们必须重新规划”的行为。 条件节点通常与 ReactiveFallback 节点配对。
装饰节点
距离控制器 - 每次机器人行进一定距离时,都会勾选子节点
速率控制器 - 以恒定频率控制其子节点的勾选。勾选速率是一个公开端口
目标更新器 - 将通过 BT 上的端口更新子节点的目标
单一触发器 - 只会勾选其子节点一次,并且将为所有后续勾选返回“FAILURE”
速度控制器 - 以与机器人速度成比例的速率控制其子节点的勾选
控制:PipelineSequence
当子节点返回“RUNNING”时,“PipelineSequence”控制节点会重新勾选之前的子节点。 此节点类似于“Sequence”节点,但具有一个附加属性,即重新勾选“current”之前的子节点(类似于管道中的水流)。 如果子节点在任何时候返回“FAILURE”,则所有子节点都将停止,父节点也将返回“FAILURE”。当序列中的**最后一个节点**“SUCCESS”时,此节点将停止并返回“SUCCESS”。
为了进一步解释这一点,这里有一个使用 PipelineSequence 的示例 BT。
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<PipelineSequence>
<Action_A/>
<Action_B/>
<Action_C/>
</PipelineSequence>
</BehaviorTree>
</root>
“Action_A”、“Action_B”和“Action_C”都处于“IDLE”状态。
当父 PipelineSequence 首次被勾选时,我们假设“Action_A”返回“RUNNING”。父节点现在将返回“RUNNING”,并且没有其他节点被勾选。
现在,我们假设“Action_A”返回“SUCCESS”,“Action_B”现在将被勾选并返回“RUNNING”。“Action_C”尚未被勾选,因此将返回“IDLE”。
“Action_A” 再次被勾选并返回“RUNNING”,而“Action_B”被重新勾选并返回“SUCCESS”,因此 BT 继续第一次勾选“Action_C”。我们假设“Action_C”返回“RUNNING”。重新勾选“Action_A”使得 PipelineSequence 变得有用。
序列中的所有操作都将重新勾选。假设“Action_A”仍返回“RUNNING”,而“Action_B”再次返回“SUCCESS”,并且“Action_C”现在在此勾选上返回“SUCCESS”。序列现已完成,因此“Action_A”已停止,即使它仍处于“RUNNING”状态。
回想一下,如果“Action_A”、“Action_B”或“Action_C”在任何时间点返回“FAILURE”,则父级将返回“FAILURE”并停止所有子级。
有关“PipelineSequence”的更多详细信息,请参阅“PipelineSequence 配置指南 <../../configuration/packages/bt-plugins/controls/PipelineSequence.html>”。
控制:恢复
恢复控制节点只有两个子节点,当且仅当第一个子节点返回“SUCCESS”时,才会返回“SUCCESS”。 如果第一个子节点返回“FAILURE”,则第二个子节点将被勾选。此循环将持续,直到:
第一个子节点返回“SUCCESS”(导致父节点“SUCCESS”)
第二个子节点返回“FAILURE”(导致父节点“FAILURE”)
违反了“number_of_retries”输入参数
此节点通常用于将操作和顾名思义的恢复操作连接在一起。第一个操作通常是“主要”行为, 而第二个操作则是在主要行为“失败”的情况下要执行的操作。通常,第二个子操作的勾选会增加第一个操作成功的机会。
<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/packages/bt-plugins/controls/RecoveryNode.html>”。
控制:循环赛
RoundRobin 控制节点以循环方式勾选其子节点,直到子节点返回“SUCCESS”,此时父节点也将返回“SUCCESS”。 如果所有子节点都返回“FAILURE”,父 RoundRobin 也将返回“FAILURE”。
下面是我们将用来解释这个概念的一个 BT 示例。
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<RoundRobin>
<Action_A/>
<Action_B/>
<Action_C/>
</RoundRobin>
</BehaviorTree>
</root>
所有节点从“IDLE”状态开始
2. 勾选父节点后,第一个子节点(“Action_A”)被勾选。假设勾选后子节点返回“RUNNING”。 在这种情况下,没有其他子节点被勾选,父节点也返回“RUNNING”。
3. 下一次勾选时,我们假设“Action_A”返回“FAILURE”。 这意味着“Action_B”接下来会被勾选,而“Action_C”保持未勾选状态。 我们假设这次“Action_B”返回“RUNNING”。这意味着父 RoundRobin 节点也将返回“RUNNING”。
4. 在下一个滴答声中,我们假设“Action_B”返回“SUCCESS”。父 RoundRobin 现在将停止所有子节点并返回“SUCCESS”。 父节点保留此状态信息,并将在下一个滴答声中滴答“Action_C”,而不是像步骤 2 那样从“Action_A”开始。
在此勾选上,我们假设“Action_C”返回“RUNNING”,父 RoundRobin 也是如此。没有勾选其他节点。
在最后一次勾选时,我们假设“Action_C”返回“FAILURE”。父节点将再次循环并勾选“Action_A”。“Action_A”返回“RUNNING”,父节点 RoundRobin 节点也将返回“RUNNING”。除非所有子节点都返回“FAILURE”,否则此模式将无限期持续下去。
有关“恢复模式”的更多详细信息,请参阅“循环配置指南<../../configuration/packages/bt-plugins/controls/RoundRobin.html>”。