Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedicated pause method for behaviors #884

Open
kevrab opened this issue Nov 19, 2024 · 0 comments
Open

Dedicated pause method for behaviors #884

kevrab opened this issue Nov 19, 2024 · 0 comments

Comments

@kevrab
Copy link

kevrab commented Nov 19, 2024

I've seen a couple other topics on pausing, but I have a particular case I haven't seen covered. Our use-case is to use BT for mission control of a robot. A user can pause the robot's mission and resume it later from the same execution point, but right now we don't have a good way to pause the BT with proper cleanup of BT behaviors.

One method we tried was simply not ticking the tree, but many behaviors interact asynchronously with action servers to accomplish long-running tasks (e.g. sending a goal to navigation action server), meaning even if we stop ticking, the other servers are still executing goals. This necessitates running cleanup logic to pause any external systems the behavior is interacting with.

The other method is just halting the entire tree, meaning our overridden halt methods can properly clean up ongoing action goals. However halt also clears index state on control nodes, meaning we can't resume tree execution from the previous state after unpause.

Finally we considered just having behaviors within the tree that check for paused state, and explicitly control tree execution in the event of a pause. So taking above example of pausing navigation, doing something like:

<Sequence/>
    <ReactiveFallback>
        <Sequence>
            <IsPaused/>
            <Fallback>
                <IsRobotIdle/>
                <CancelGoal/>
            </Fallback>
            <WaitForUnpause/>
        </Sequence>
        <NavigateToGoal/>
    </ReactiveSequence>
</Sequence>

However, as the tree gets larger and more complex with more async behaviors, ensuring the pauses are put in all the correct places becomes unmanageable and error prone. Essentially the stability of our robot's pause behavior is dependent on correct tree design, which doesn't scale as we make many different trees.

I think the concrete issue is that pausing and cancelling may both need to have cleanup logic in behaviors, but they differ in whether or not to clear state. To meet both requirements of both running behavior cleanup logic + maintaining state, I'd like to propose having a pause method, similar to halt, which has explicit cleanup logic for pausing a behavior's execution without resetting state in control nodes.

Right now we implemented this with a hacky override of the halt method. Essentially we halt the tree, but use Resumable versions of control behaviors to maintain internal index state:

  void halt() override {
    if (PauseMissionAction::is_paused) {
      ControlNode::halt();
      return;
    }
    BT::SequenceNode::halt();
  }

This is not ideal as we have to ensure we're using resumable versions of control behaviors, ensure halt methods don't clear state incorrectly during pause (and do correctly clear when not paused), and use a nasty global state across behaviors for detecting pause. With a dedicated pause method, developers can have explicit handling separate from halt to manage cleanup and state.

One downside of a dedicated pause method is that cleanup is constrained to just one behavior, meaning this won't allow cleanup involving multiple behaviors. However, I think for most cases this is sufficient, and this seems to be an open issue outside the scope of this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant