BT7:ControlNodes源码解析之Sequence

大家好,欢迎大家关注我的知乎专栏慢慢悠悠小马车


SequenceNode

最常见的control node,按从左到右的顺序依次执行子节点。

如果某个子节点返回RUNNING,返回RUNNING,且下次tick()时之前的子节点不会再执行。类内维护当前执行节点的标号current_child_idx_。

如果某个子节点返回SUCCESS,立即执行下一个子节点(不会等下一次tick())。如果所有子节点返回SUCCESS,返回SUCCESS。

如果某个子节点返回FAILURE,返回FAILURE,并且复位所有成员变量(尤其注意current_child_idx_)。当再次tick()时,从头开始。

NodeStatus SequenceNode::tick() {
  const size_t children_count = children_nodes_.size();
  setStatus(NodeStatus::RUNNING);
  while (current_child_idx_ < children_count) {
    TreeNode* current_child_node = children_nodes_[current_child_idx_];
    const NodeStatus child_status = current_child_node->executeTick();
    switch (child_status) {
      case NodeStatus::RUNNING: {
        return child_status;
      }
      case NodeStatus::FAILURE: {
        // Reset on failure
        haltChildren();
        current_child_idx_ = 0;
        return child_status;
      }
      case NodeStatus::SUCCESS: {
        current_child_idx_++;
      } break;
      case NodeStatus::IDLE: {
        throw LogicError("A child node must never return IDLE");
      }
    }  // end switch
  }    // end while loop

  // The entire while loop completed. This means that all the children returned SUCCESS.
  if (current_child_idx_ == children_count) {
    haltChildren();
    current_child_idx_ = 0;
  }
  return NodeStatus::SUCCESS;
}

SequenceStarNode

同上,不同之处在于如果某个子节点返回FAILURE,返回FAILURE,终止所有节点的执行,但不复位current_child_idx_。所以当再次tick()时,从FAILURE的子节点开始。

NodeStatus SequenceStarNode::tick() {
  ...
  while (current_child_idx_ < children_count) {
    TreeNode* current_child_node = children_nodes_[current_child_idx_];
    const NodeStatus child_status = current_child_node->executeTick();
    switch (child_status) {      
      case NodeStatus::FAILURE: {
        // DO NOT reset current_child_idx_ on failure
        for (size_t i = current_child_idx_; i < childrenCount(); i++) {
          haltChild(i);
        }
        return child_status;
      }
      ...
    }  // end switch
  }    // end while loop
  ...
}

ReactiveSequence

是SequneceNode的reactive版本,和ParallelNode类似,常用来周期检查某个外部条件是否成立。类内不保存当前执行节点的标号。

如果某个子节点返回RUNNING,返回RUNNING,终止其他节点,下次tick()时从头开始执行。reactive所在。

如果某个子节点返回SUCCESS,立即执行下一个子节点(不会等下一次tick())。如果所有子节点返回SUCCESS,返回SUCCESS。

如果某个子节点返回FAILURE,返回FAILURE,终止所有节点,下次tick()时从头开始执行。

NodeStatus ReactiveSequence::tick() {
  for (size_t index = 0; index < childrenCount(); index++) {
    TreeNode* current_child_node = children_nodes_[index];
    const NodeStatus child_status = current_child_node->executeTick();
    switch (child_status) {
      case NodeStatus::RUNNING: {
        for (size_t i = index + 1; i < childrenCount(); i++) {
          haltChild(i);
        }
        return NodeStatus::RUNNING;
      }
      case NodeStatus::FAILURE: {
        haltChildren();
        return NodeStatus::FAILURE;
      }
      ...
    }  // end switch
  }    // end for
  ...
}

3种node的差异可以总结如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值