Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions docs/guides/asynchronous_nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ When designing reactive Behavior Trees, it is important to understand two main c

## Concurrency vs Parallelism

If you Google those words, you will read many good articles about this topic.
If you google these words, you will read many good articles about this topic.

:::info
**Concurrency** is when two or more tasks can start, run, and complete in overlapping time periods.
Expand All @@ -20,7 +20,7 @@ It doesn't necessarily mean they'll ever both be running at the same instant.
**Parallelism** is when tasks run at the same time in different threads, e.g., on a multicore processor.
:::

BT.CPP executes all the nodes **Concurrently**, in other words:
BT.CPP executes all the nodes **concurrently**. In other words:

- The Tree execution engine is **single-threaded**.
- All the `tick()` methods are executed **sequentially**.
Expand All @@ -33,7 +33,7 @@ return as soon as possible the state RUNNING.

This tells the tree executor that the action was started and needs more time to return
the state SUCCESS or FAILURE.
We need to tick that Node again, to know if the state changed or not (polling).
We need to tick that Node again to know if the state changed or not (polling).

An Asynchronous node may delegate this long execution either to another process
(using inter-process communication) or another thread.
Expand Down Expand Up @@ -170,7 +170,7 @@ That was a bad idea, for multiple reasons:
- You probably don't need to.
- People think that this will magically make the Action "asynchronous", but they
forget that it is still **their responsibility** to stop that thread "somehow" and **fast** when
the `halt()`method is invoked.
the `halt()` method is invoked.

For this reason, users are usually discouraged from using `BT::ThreadedAction` as a
base class. Let's have a look again at the SleepNode.
Expand Down Expand Up @@ -220,14 +220,14 @@ class ThreadedSleepNode : public BT::ThreadedAction

NodeStatus tick() override
{
// This code run in its own thread, therefore the Tree is still running.
// This code runs in its own thread, therefore the Tree is still running.
int msec = 0;
getInput("msec", msec);

using namespace std::chrono;
const auto deadline = system_clock::now() + milliseconds(msec);

// periodically check isHaltRequested()
// Periodically check isHaltRequested()
// and sleep for a small amount of time only (1 millisecond)
while( !isHaltRequested() && system_clock::now() < deadline )
{
Expand All @@ -244,7 +244,7 @@ class ThreadedSleepNode : public BT::ThreadedAction
As you can see, this looks more complicated than the version we implemented
first, using `BT::StatefulActionNode`.
This pattern can still be useful in some case, but you must remember that introducing
multi-threading make things more complicated and **should be avoided by default**.
multi-threading makes things more complicated and **should be avoided by default**.

## Advanced example: client / server communication

Expand All @@ -261,6 +261,5 @@ ActionLib provides exactly the kind of API that we need to implement correctly a

None of these operations is "blocking", therefore we don't need to spawn our own thread.

More generally, we may assume that the developer has their own inter-processing communication,
More generally, we may assume that the developer has their own inter-process communication,
with a client/server relationship between the BT executor and the actual service provider.

16 changes: 8 additions & 8 deletions docs/learn-the-basics/BT_basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ more time to return a valid result.

- If a TreeNode has one or more children, it is its
responsibility to propagate the tick; each Node type may
have different rules about if, when and how many times children are ticked.
have different rules about if, when, and how many times children are ticked.

- The __LeafNodes__, those TreeNodes which don't have any children,
are the actual commands, i.e. the Nodes where the behavior tree
interacts with the rest of the system.
__Actions__ nodes are the most common type of LeafNodes.
__Action__ nodes are the most common type of LeafNodes.

:::tip
The word __tick__ will be often used as a *verb* (to tick / to be ticked)
Expand All @@ -49,7 +49,7 @@ its children one after the other and, if they all Succeed,
it returns SUCCESS too.

1. The first tick sets the Sequence node to RUNNING (orange).
2. Sequence tick the first child, "OpenDoor", that eventually returns SUCCESS.
2. Sequence ticks the first child, "OpenDoor", that eventually returns SUCCESS.
3. As a result, the second child "Walk" and later "CloseDoor"
are ticked.
4. Once the last child is completed, the entire Sequence
Expand All @@ -62,7 +62,7 @@ switches from RUNNING to SUCCESS.
| Type of TreeNode | Children Count | Notes |
| ----------- | ------------------ | ------------------ |
| ControlNode | 1...N | Usually, ticks a child based on the result of its siblings or/and its own state. |
| DecoratorNode | 1 | Among other things, it may alter the result of the children or tick it multiple times.
| DecoratorNode | 1 | Among other things, it may alter the result of its child or tick it multiple times.
| ConditionNode | 0 | Should not alter the system. Shall not return RUNNING. |
| ActionNode | 0 | This is the Node that "does something" |

Expand Down Expand Up @@ -99,13 +99,13 @@ representation, the order of execution is __from left to right__.
In short:

- If a child returns SUCCESS, tick the next one.
- If a child returns FAILURE, then no more children are ticked and the Sequence returns FAILURE.
- If a child returns FAILURE, then no more children are ticked, and the Sequence returns FAILURE.
- If __all__ the children return SUCCESS, then the Sequence returns SUCCESS too.

:::caution Find the BUG!

If the action __GrabBeer__ fails, the door of the
fridge will remain open, since the last action __CloseFridge__ is skipped.
fridge will remain open since the last action __CloseFridge__ is skipped.
:::

### Decorators
Expand All @@ -129,7 +129,7 @@ __isDoorOpen__ is, therefore, equivalent to
The node __Retry__ will repeat ticking the child up to __num_attempts__ times (5 in this case)
if the child returns FAILURE.

__Apparently__, the branch on the right side means:
__Apparently__, the branch on the left side means:

If the door is closed, then try to open it.
Try up to 5 times, otherwise give up and return FAILURE.
Expand All @@ -138,7 +138,7 @@ But...

:::caution Find the BUG!
If __isDoorOpen__ returns FAILURE, we have the desired behavior.
But if it returns SUCCESS, the left branch fails and the entire Sequence
But if it returns SUCCESS, the left branch fails, and the entire Sequence
is interrupted.
:::

Expand Down
4 changes: 2 additions & 2 deletions docs/learn-the-basics/main_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ NodeStatus HelloTick()
factory.registerSimpleAction("Hello", std::bind(HelloTick));
```

:::tip
::::tip
The factory may create multiple instances of the node __Hello__.
::::

Expand All @@ -62,7 +62,7 @@ The factory may create multiple instances of the node __Hello__.
In the example above, a specific type of TreeNodes which invoke
`HelloTick` was created using a __function pointer__ (dependency injection).

More generally, to define a custom TreeNode, you should inherit from the
Generally, to define a custom TreeNode, you should inherit from the
class `TreeNode` or, more specifically, its derived classes:

- `ActionNodeBase`
Expand Down
6 changes: 3 additions & 3 deletions docs/learn-the-basics/xml_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ As explained in the [second tutorial](tutorial-basics/tutorial_02_basic_ports.md
input/output ports can be remapped using the name of an entry in the
Blackboard, in other words, the __key__ of a __key/value__ pair of the BB.

An BB key is represented using this syntax: `{key_name}`.
A BB key is represented using this syntax: `{key_name}`.

In the following example:

Expand Down Expand Up @@ -127,7 +127,7 @@ As we saw in [this tutorial](tutorial-basics/tutorial_06_subtree_ports.md), it i
a Subtree inside another tree to avoid "copy and pasting" the same tree in
multiple location and to reduce complexity.

Let's say that we want to incapsulate few action into the behaviorTree "__GraspObject__"
Let's say that we want to encapsulate a few actions into the behaviorTree "__GraspObject__"
(being optional, attributes [name] are omitted for simplicity).

``` XML
Expand All @@ -151,7 +151,7 @@ Let's say that we want to incapsulate few action into the behaviorTree "__GraspO
</root>
```

We may notice as the entire tree "GraspObject" is executed after "SaySomething".
We may notice that the entire tree "GraspObject" is executed after "SaySomething".

## Include external files

Expand Down
4 changes: 2 additions & 2 deletions docs/nodes-library/FallbackNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ To understand how the two ControlNodes differ, refer to the following table:
child of the list.

- "__Tick again__" means that the next time the fallback is ticked, the
same child is ticked again. Previous sibling, which returned FAILURE already,
same child is ticked again. Previous siblings, which returned FAILURE already,
are not ticked again.

## Fallback
Expand All @@ -45,7 +45,7 @@ Check first (and once) if the door is open.

## ReactiveFallback

This ControlNode is used when you want to interrupt an __asynchronous__
This ControlNode is used when we want to interrupt an __asynchronous__
child if one of the previous Conditions changes its state from
FAILURE to SUCCESS.

Expand Down
2 changes: 1 addition & 1 deletion docs/nodes-library/SequenceNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To understand how the three ControlNodes differ, refer to the following table:
child of the list.

- "__Tick again__" means that the next time the sequence is ticked, the
same child is ticked again. Previous sibling, which returned SUCCESS already,
same child is ticked again. Previous siblings, which returned SUCCESS already,
are not ticked again.

## Sequence
Expand Down
2 changes: 1 addition & 1 deletion docs/ros2_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ In terms of system architecture, we should remember that:
for the execution of the behavior. This will be further called "Task Planner"
and it will be implemented with BT.CPP

- All other elements of the system should be"service-oriented" components,
- All other elements of the system should be "service-oriented" components,
and should delegate any business logic and decision-making to the Task Planner.

:::caution
Expand Down
6 changes: 3 additions & 3 deletions docs/tutorial-basics/tutorial_02_basic_ports.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ In this tutorial, we will create the following tree:
- A "Blackboard" is a simple __key/value storage__ shared by all the nodes
of the Tree.
- An "entry" of the Blackboard is a __key/value pair__.
- __Input ports__ can read an entry in the Blackboard, whilst an __Output port__
- An __Input port__ can read an entry in the Blackboard, whilst an __Output port__
can write into an entry.
:::

## Inputs ports

A valid Input can be either:
A valid input can be either:

- a __static string__ that the Node will read and parse, or
- a "pointer" to an entry of the Blackboard, identified by a __key__.
Expand Down Expand Up @@ -117,7 +117,7 @@ It is __always__ recommended to call the method `getInput()` inside the
`tick()`, and __not__ in the constructor of the class.

The C++ code should expect the actual value of the input
to __change at run-time__, for this reason it should be updated
to __change at run-time__, and for this reason, it should be updated
periodically.
:::

Expand Down
5 changes: 3 additions & 2 deletions docs/tutorial-basics/tutorial_03_generic_ports.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ namespace BT
{
throw RuntimeError("invalid input)");
}
else{
else
{
Position2D output;
output.x = convertFromString<double>(parts[0]);
output.y = convertFromString<double>(parts[1]);
Expand Down Expand Up @@ -119,7 +120,7 @@ class PrintTarget: public SyncActionNode
We can now connect input/output ports as usual, pointing to the same
entry of the Blackboard.

The tree in the next example is a Sequence of 4 actions
The tree in the next example is a Sequence of 4 actions:

- Store a value of `Position2D` in the entry __GoalPosition__,
using the action `CalculateGoal`.
Expand Down
8 changes: 4 additions & 4 deletions docs/tutorial-basics/tutorial_04_sequence.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Actions. You will find an extensive article
[here](guides/asynchronous_nodes.md).
:::

## StatefulActionNode
## StatefulActionNode

The __StatefulActionNode__ is the preferred way to implement asynchronous Actions.

Expand All @@ -46,14 +46,14 @@ or you may want to move that computation to another thread
A derived class of __StatefulActionNode__ must override the following virtual methods,
instead of `tick()`:

- __NodeStatus onStart()__: called when the Node was in IDLE state.
- `NodeStatus onStart()`: called when the Node was in IDLE state.
It may succeed or fail immediately or return RUNNING. In the latter case,
the next time the tick is received the method `onRunning` will be executed.

- __NodeStatus onRunning()__: called when the Node is in RUNNING state.
- `NodeStatus onRunning()`: called when the Node is in RUNNING state.
Return the new status.

- __void onHalted()__: called when this Node was aborted by another Node
- `void onHalted()`: called when this Node was aborted by another Node
in the tree.

Let's create a dummy Node called __MoveBaseAction__:
Expand Down
19 changes: 7 additions & 12 deletions docs/tutorial-basics/tutorial_08_additional_args.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ If all these conditions are met, using ports or the blackboard is highly discour

Consider the following custom node called **Action_A**.

We want to pass three additional arguments; they can be arbitrarily complex objects,
We want to pass two additional arguments; they can be arbitrarily complex objects,
you are not limited to built-in types.

``` cpp
Expand All @@ -47,7 +47,7 @@ class Action_A: public SyncActionNode
public:
// additional arguments passed to the constructor
Action_A(const std::string& name, const NodeConfig& config,
int arg_int, std::string arg_str ):
int arg_int, std::string arg_str):
SyncActionNode(name, config),
_arg1(arg_int),
_arg2(arg_str) {}
Expand All @@ -71,7 +71,7 @@ BT::BehaviorTreeFactory factory;
factory.registerNodeType<Action_A>("Action_A", 42, "hello world");

// If you prefer to specify the template parameters
// factory.registerNodeType<Action_A, int , std::string>("Action_A", 42, "hello world");
// factory.registerNodeType<Action_A, int, std::string>("Action_A", 42, "hello world");
```

## Use an "initialize" method
Expand All @@ -90,10 +90,10 @@ public:
SyncActionNode(name, config) {}

// We want this method to be called ONCE and BEFORE the first tick()
void initialize( int arg_int, const std::string& arg_str_ )
void initialize(int arg_int, const std::string& arg_str)
{
_arg1 = arg_int;
_arg2 = arg_str_;
_arg2 = arg_str;
}

// this example doesn't require any port
Expand All @@ -114,7 +114,7 @@ The way we register and initialize Action_B is different:
BT::BehaviorTreeFactory factory;

// Register as usual, but we still need to initialize
factory.registerNodeType<Action_B>( "Action_B" );
factory.registerNodeType<Action_B>("Action_B");

// Create the whole tree. Instances of Action_B are not initialized yet
auto tree = factory.createTreeFromText(xml_text);
Expand All @@ -127,12 +127,7 @@ auto visitor = [](TreeNode* node)
action_B_node->initialize(69, "interesting_value");
}
};

// Apply the visitor to ALL the nodes of the tree
tree.applyVisitor(visitor);

```





Loading