diff --git a/.gitignore b/.gitignore index 4ebe8e7..06f9b89 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /package-lock.json /.docusaurus/ /build/ +.vscode/* diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..209e3ef --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fba9e0c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,47 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is the official documentation website for BehaviorTree.CPP, a C++ library for building behavior trees used in robotics and AI systems. The site is built with Docusaurus 3 and hosted at https://www.behaviortree.dev/ + +## Common Commands + +```bash +npm install # Install dependencies (requires Node.js 20+) +npm run start # Local dev server at http://localhost:3000 (hot reload) +npm run build # Production build to /build directory +npm run serve # Serve production build locally +npm run clear # Clear Docusaurus cache +``` + +## Architecture + +### Documentation Structure +- `docs/` - Current version (4.8) documentation in Markdown + - `learn-the-basics/` - Fundamental BT concepts + - `tutorial-basics/` - Tutorials 01-11 (beginner) + - `tutorial-advanced/` - Tutorials 12-16 (advanced) + - `guides/` - Topic guides (async nodes, ports, scripting) + - `nodes-library/` - Node type reference +- `versioned_docs/` - Legacy versions (3.8, 4.0.2) +- `blog/` - Release announcements + +### Custom Pages (React) +- `src/pages/index.js` - Homepage with hero section and feature carousel +- `src/pages/groot.js` - Groot2 IDE page with pricing/licensing (uses Chargebee) +- `src/pages/moveit_studio.js` - MoveIt Studio integration page +- `src/components/ContactFormModal/` - Email contact form (EmailJS) +- `src/components/HomepageFeatures/` - Homepage feature cards + +### Configuration +- `docusaurus.config.js` - Main config (versions, navbar, footer, Prism languages) +- `sidebars.js` - Auto-generated from filesystem structure +- `versions.json` - Supported doc versions + +### Key Technical Details +- Prism syntax highlighting configured for `cpp` and `xml-doc` +- Bootstrap 5 + React Bootstrap for UI components +- Download tracking via Netlify Functions + Neon PostgreSQL database +- Dark mode disabled (light mode only) \ No newline at end of file diff --git a/README.md b/README.md index 0434ca3..02552a5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,39 @@ # Website of BehaviorTree.CPP -This website is built using [Docusaurus 2](https://docusaurus.io/). +This website is built using [Docusaurus 3](https://docusaurus.io/). If you find any typo reading the documentation, please submit a Pull Request or an Issue. + +## Prerequisites + +- [Node.js](https://nodejs.org/) version 20.0 or higher + +## Installation + +```bash +npm install +``` + +## Local Development + +```bash +npm run start +``` + +This starts a local development server at `http://localhost:3000` with hot reload enabled. Most changes are reflected live without restarting the server. + +## Build + +```bash +npm run build +``` + +This generates static content into the `build` directory. + +## Preview Build Locally + +```bash +npm run serve +``` + +This serves the production build locally at `http://localhost:3000` for testing before deployment. diff --git a/auryn.png b/auryn.png new file mode 100644 index 0000000..d5ed0be Binary files /dev/null and b/auryn.png differ diff --git a/blog/2023-01-28-beta4.md b/blog/2023-01-28-beta4.md index f015f15..5e5e9a8 100644 --- a/blog/2023-01-28-beta4.md +++ b/blog/2023-01-28-beta4.md @@ -9,9 +9,9 @@ hide_table_of_contents: true I am pleased to announce the release of the 4th Beta of Groot2. These are the most notable new features... -## Support for +## Support for `` -In **BehaviorTree.CPP** it is common to use the XML tag +In **BehaviorTree.CPP** it is common to use the XML tag `` to automatically define the dependency between multiple XML. This is not considered best practice anymore, and you are invited to follow the best practices described in **Tutorial 7**. diff --git a/btcpp-landing-page.html b/btcpp-landing-page.html new file mode 100644 index 0000000..17e0ed0 --- /dev/null +++ b/btcpp-landing-page.html @@ -0,0 +1,1191 @@ + + + + + + BehaviorTree.CPP – The Industry Standard for Robot Intelligence + + + + + + + + + +
+
+
+
+ +
+
+ + Powering Nav2 and 100+ robotics companies +
+

The Industry Standard for Robot Intelligence

+

+ BehaviorTree.CPP is the most advanced, production-ready framework for building + reactive, modular, and debuggable robot behaviors. Design in XML, execute in C++. +

+ +
+
+
3.7k+
+
GitHub Stars
+
+
+
100+
+
Companies
+
+
+
10+
+
Years Active
+
+
+
+
+ + +
+

Trusted by teams building autonomous systems

+
+ + + + + +
+
+ + +
+
+

Why BehaviorTree.CPP?

+

Built for real-world robotics, not just demos

+
+ +
+ +
+
+

Async-First Design

+

Non-blocking actions as first-class citizens. Build reactive behaviors that execute concurrently, making your robots responsive and efficient in complex real-world scenarios.

+
+ +
+
🔌
+

Plugin Architecture

+

Load custom nodes at runtime. Separate behavior design from implementation.

+
+ +
+
📊
+

Type-Safe Blackboard

+

Strongly-typed data flow between nodes. Catch errors at compile time.

+
+ + +
+
📝
+

XML-Defined Trees

+

Modify behaviors without recompiling. Perfect for field engineers.

+
+ +
+
🔍
+

Built-in Logging

+

Record, replay, and analyze state transitions with confidence.

+
+ +
+
🤖
+

ROS2 Integration

+

Official wrappers for actions, services, and topics. Powers the Nav2 navigation stack trusted by hundreds of robots and engineering teams worldwide.

+
+
+
+ + +
+
+
+
+

Meet Groot2

+

The IDE for Behavior Trees. Design, debug, and deploy with confidence.

+ +
+
+
+
+ Visual Editor + Drag-and-drop interface for rapid prototyping +
+
+
+
+
+ Real-time Monitoring + Watch your tree execute live on your robot +
+
+
+
+
+ Log Replay & Analysis + Debug past runs with full state reconstruction +
+
+
+
+
+ Breakpoints & Fault Injection + Pause execution and simulate failures +
+
+
+ + Learn More About Groot2 +
+ +
+
+
+ + + +
+
+
Sequence
+
+
+
Fallback
+
Navigate
+
+
+
+
Check
+
Pick
+
Place
+
+
+
+
+
+
+ + +
+
+

Ready to Build Smarter Robots?

+

Join thousands of engineers using BehaviorTree.CPP to build production-grade autonomous systems.

+ +
+
+ + +
+ + + +
+ + diff --git a/corrected_behavior_tree.svg b/corrected_behavior_tree.svg new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/corrected_behavior_tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/guides/_category_.json b/docs/guides/_category_.json index c630842..0d02b8d 100644 --- a/docs/guides/_category_.json +++ b/docs/guides/_category_.json @@ -1,6 +1,6 @@ { "label": "Guides", - "position": 4, + "position": 5, "link": { "type": "generated-index", "description": "Become a behavior tree whisperer" diff --git a/docs/guides/images/no_ports_sequence.png b/docs/guides/images/no_ports_sequence.png new file mode 100644 index 0000000..459f28c Binary files /dev/null and b/docs/guides/images/no_ports_sequence.png differ diff --git a/docs/guides/images/port_vs_blackboard.drawio b/docs/guides/images/port_vs_blackboard.drawio new file mode 100644 index 0000000..edc8813 --- /dev/null +++ b/docs/guides/images/port_vs_blackboard.drawio @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/guides/images/with_ports_sequence.png b/docs/guides/images/with_ports_sequence.png new file mode 100644 index 0000000..376ccea Binary files /dev/null and b/docs/guides/images/with_ports_sequence.png differ diff --git a/docs/guides/ports_vs_blackboard.md b/docs/guides/ports_vs_blackboard.md new file mode 100644 index 0000000..3a46503 --- /dev/null +++ b/docs/guides/ports_vs_blackboard.md @@ -0,0 +1,114 @@ +--- +sidebar_position: 4 +--- + +# Ports VS Blackboard + +**BT.CPP** is the only implementation (to our knowledge) of Behavior Tree that +introduces the concept of **Input/Output Ports**, as an alternative to **Blackboards**. + +To be more specific, Ports are an interface that adds a level of +indirection and additional semantics to the blackboard. + +To understand why using Ports is recommended and using directly the Blackboard +is **discouraged**, we should first understand some of the core principles +of BehaviorTree.CPP. + +## Goals of BT.CPP + +### Model Driven Development + +It is not the purpose of this article to explain what Model Driven Development is. +But, in short, we want to build a "model" of our Nodes, i.e. some kind of meta-information +that tells us how the Node interacts with the rest of the tree. + +Models are important both for developers (being self-documenting) and +for external tools, such as visual editors, being Groot2 a notable example, +or static analyzers. + +We believe that the **description of the data-flow between Nodes must be part of the model**. +Additionally, we want to clearly express if a blackboard entry is being written (output), +read (input) or both. + +Consider this example: + +![no_ports](images/no_ports_sequence.png) + +In other implementations (or if anybody uses this library inappropriately...) the +only way to know if these two Nodes communicate and depend on each other is either: + +- **inspecting the code**: something that we want to avoid. +- or **reading the documentation**: but documentation is not guaranteed to be accurate and up to date. + +Instead, if Input/Output ports are part of the model, the intent of the Node and it +relationship with the others become more explicit: + +![with_ports](images/with_ports_sequence.png) + +### Nodes composibility and Subtree scoping + +Ideally, we want to offer a platform that allows Behavior Designers to build trees +(i.e., "compose Nodes") implemented by different vendors / users. + +But when the Blackboard is used directly, name-collision will become immediately an issue. + +Think about common names such as `goal`, `results`, `target`, `value`, etc. + +For instance, the Nodes **GraspObject** and **MoveBase** may be developed by different people +and they both read the entry `target` from the blackboard. +Unfortunately, they have different meanings and the type itself is different: +the former expects a 3D pose, whilst the latter a 2D one. + +**Ports** offer one level of indirection, called also "remapping", as explained in +[Tutorial 2](../tutorial-basics/tutorial_02_basic_ports.md). + +This means that, no matter which name is used when defining the Port +(that name is "hardcoded" into your C++ implementation), +you can always "remap" it to a different blackboard entry into your XML, +without modifying the source code. + +The same is true for Subtrees remapping, explained in [Tutorial 6](../tutorial-basics/tutorial_06_subtree_ports.md). +Being the Blackboard a glorified map of global variables, it scales very poorly. +There is a reason why global variables are a no-no in programming! + +Ports remapping offers a solution to this problem. + + +## Summary: never use the Blackboard directly + +You should do this: + +```c++ +// example code in your tick() +getInput("goal", goal); +setOutput("result", result); +``` + +and avoid as much as possible this: + +```c++ +// example code in your tick() +config().blackboard->get("goal", goal); +config().blackboard->set("result", result); +``` + +Both these codes may technically work, but the latter (direct access to the blackboard) +is considered bad practice and **it is highly discouraged**: + +The problems with the 2nd version, i.e. the direct access to the blackboard: + +1. Names "goal" and "result" are hard-coded. To change them, you must recompile your application. Port, instead, can be remapped at run-time, modifying only the XML. + +2. The only way to know if a Node reads or writes one or more entries of the blackboard, +is by inspecting the code. Up to date documentation is a solution, but the Port model is self-documenting. + +3. The `BehaviorTreeFactory` is unaware that those blackboard entries are being accessed. +In contrast, when using Ports, we are able to introspect how ports communicate to each other +and also to check at deployment time if the connection is done correctly. + +4. It may not work as expected when using SubTrees. + +5. The template specialization `convertFromString()` will not work correctly. + + + diff --git a/docs/guides/pre_post_conditions.md b/docs/guides/pre_post_conditions.md index c7cb8fb..cf41de8 100644 --- a/docs/guides/pre_post_conditions.md +++ b/docs/guides/pre_post_conditions.md @@ -25,12 +25,28 @@ reconsider your decision to use them. ## Pre conditions -| Name | Description | -|-------------|---------| -| **_skipIf** | Skip the execution of this Node, if the condition is true | -| **_failureIf** | Skip and return FAILURE, if the condition is true | -| **_successIf** | Skip and return SUCCESS, if the condition is true | -| **_while** | Same as _skipIf, but may also interrupt a RUNNING Node if the condition becomes false. | +| Name | Description | When Evaluated | +|-------------|---------|----------------| +| **_skipIf** | Skip the execution of this Node, if the condition is true | IDLE only (once) | +| **_failureIf** | Skip and return FAILURE, if the condition is true | IDLE only (once) | +| **_successIf** | Skip and return SUCCESS, if the condition is true | IDLE only (once) | +| **_while** | If false when IDLE, skip. If false when RUNNING, halt the node and return SKIPPED. | IDLE and RUNNING (every tick) | + +:::caution Important: One-time vs. Continuous Evaluation +**`_skipIf`, `_failureIf`, and `_successIf` are evaluated only once** when the node +transitions from IDLE to another state. They are **NOT re-evaluated** while the node +is RUNNING. + +Only **`_while`** is checked on every tick, including while the node is running. + +If you need a condition to be re-evaluated on every tick, use the `` +decorator node with `else="RUNNING"` instead of these attributes. +::: + +:::note Evaluation Order +Pre conditions are evaluated in this order: `_failureIf` -> `_successIf` -> `_skipIf` -> `_while`. +The first condition that is satisfied will determine the result. +::: ### Example @@ -59,6 +75,35 @@ we can store a boolean in an entry called `door_closed`, the XML can be rewritte ``` +### Using `` for Per-Tick Evaluation + +When you need a condition to be checked on **every tick** (not just when the node starts), +use the `` decorator node instead of inline attributes. + +This is particularly useful in **ReactiveSequence** or **ReactiveFallback** where you want +the condition to be re-evaluated each time the running child is ticked: + +``` xml + + + + +``` + +With `else="RUNNING"`, if the condition becomes false while the child is running, +the decorator returns RUNNING (keeping the tree alive) instead of immediately +returning FAILURE or SKIPPED. + +Compare this to the inline attribute: + +``` xml + + +``` + +The inline `_successIf` is evaluated once when `MoveToGoal` transitions from IDLE. +If `battery_ok` changes while `MoveToGoal` is RUNNING, the change is ignored. + ## Post conditions | Name | Description | diff --git a/docs/guides/scripting.md b/docs/guides/scripting.md index 968947f..3188d69 100644 --- a/docs/guides/scripting.md +++ b/docs/guides/scripting.md @@ -1,5 +1,6 @@ --- sidebar_position: 1 +sidebar_label: The Scripting Language --- # Introduction to Scripting @@ -108,15 +109,15 @@ val_D := (val_A && val_B) || !val_C | Operators | Description | |----------|---------| | true/false | Booleans. Castable to 1 and 0 respectively | -| && | Logic and | -| \|\| | Logic or | -| ! | Negation | -| == | Equality | -| != | Inequality | -| < | Less | -| <= | Less equal | -| > | Greater | -| >= | Greater equal | +| `&&` | Logic and | +| `\|\|` | Logic or | +| `!` | Negation | +| `==` | Equality | +| `!=` | Inequality | +| `<` | Less | +| `<=` | Less equal | +| `>` | Greater | +| `>=` | Greater equal | ### Ternary operator **if-then-else** @@ -127,6 +128,36 @@ Example: val_B = (val_A > 1) ? 42 : 24 ``` +## Boolean Values +Boolean values can be one of `true` or `false` +and are saved to the blackboard as `1` and `0` respectively. + +Setting booleans: +``` +val_A = true +val_B := !false +``` +The logical `!` works with boolean literals. +`!false` is the equivalent of `true`. +`val_A` and `val_B` above are equivalent. + +Using booleans: +``` + + + +``` +All of the scripts used in precondition nodes above are valid. + +When evaluating the boolean value, it can be: + - checked directly, + - compared with the literals `true` and `false` + - compared with `1` and `0`. + + +Note that capitalization of the words "true" and "false" in any manner will not work. + + ## C++ example Demonstration of the scripting language, including how to use enums to diff --git a/docs/learn-the-basics/BT_basics.md b/docs/learn-the-basics/BT_basics.md index a117f63..5a92c69 100644 --- a/docs/learn-the-basics/BT_basics.md +++ b/docs/learn-the-basics/BT_basics.md @@ -121,10 +121,10 @@ this node could be either: ![Simple Decorator: Enter Room](images/DecoratorEnterRoom.svg) The node __Inverter__ is a Decorator that inverts -the result returned by its child; An Inverter followed by the node called -__isDoorOpen__ is, therefore, equivalent to +the result returned by its child; an Inverter followed by the node called +__isDoorClosed__ is, therefore, equivalent to - "Is the door closed?". + "Is the door open?". The node __Retry__ will repeat ticking the child up to __num_attempts__ times (5 in this case) if the child returns FAILURE. diff --git a/docs/learn-the-basics/_category_.json b/docs/learn-the-basics/_category_.json index 97d3fb8..225cbe2 100644 --- a/docs/learn-the-basics/_category_.json +++ b/docs/learn-the-basics/_category_.json @@ -1,5 +1,5 @@ { - "label": "Learn the Basic Concepts", + "label": "Basic Concepts", "position": 2, "link": { "type": "generated-index", diff --git a/docs/learn-the-basics/images/DecoratorEnterRoom.svg b/docs/learn-the-basics/images/DecoratorEnterRoom.svg index 517c89e..0b7564b 100644 --- a/docs/learn-the-basics/images/DecoratorEnterRoom.svg +++ b/docs/learn-the-basics/images/DecoratorEnterRoom.svg @@ -7,7 +7,7 @@ version="1.1" viewBox="0 0 1798.08 948.96" sodipodi:docname="DecoratorEnterRoom.svg" - inkscape:version="1.2.2 (1:1.2.2+202212051550+b0a8486541)" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" @@ -23,15 +23,16 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" showgrid="false" - inkscape:zoom="0.92022041" - inkscape:cx="239.61651" - inkscape:cy="837.29941" - inkscape:window-width="2472" - inkscape:window-height="1369" - inkscape:window-x="2008" - inkscape:window-y="34" + inkscape:zoom="0.65069409" + inkscape:cx="-120.64041" + inkscape:cy="1308.6026" + inkscape:window-width="2490" + inkscape:window-height="1376" + inkscape:window-x="1990" + inkscape:window-y="27" inkscape:window-maximized="1" - inkscape:current-layer="g372-3" /> + inkscape:current-layer="text3171" + inkscape:pageshadow="2" /> - - - - - - + + + + + + + + + + + + + + - - - - - - SequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeForceSuccessForceSuccessSequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeFallbackFallbackForceFailureForceFailureCloseFridgeCloseFridge \ No newline at end of file + + + + + + + + + + + + + + + + Sequence + + + + Sequence + + + + + + + + + OpenFridge + + + + OpenFridge + + + + + + + + + GrabBeer + + + + GrabBeer + + + + + + + + + CloseFridge + + + + CloseFridge + + + + + + + + + + + ForceSuccess + + + + ForceSuccess + + + + + + + + + + + + + + + Sequence + + + + Sequence + + + + + + + + + OpenFridge + + + + OpenFridge + + + + + + + + + GrabBeer + + + + GrabBeer + + + + + + + + + CloseFridge + + + + CloseFridge + + + + + + + + + + + + + Fallback + + + + Fallback + + + + + + + + + + + ForceFailure + + + + ForceFailure + + + + + + + + + CloseFridge + + + + CloseFridge + + + + diff --git a/docs/learn-the-basics/main_concepts.md b/docs/learn-the-basics/main_concepts.md index dcdf14b..b453ae7 100644 --- a/docs/learn-the-basics/main_concepts.md +++ b/docs/learn-the-basics/main_concepts.md @@ -88,7 +88,7 @@ For the time being, it is important to know that: - The number, name and kind of ports of a Node must be known at _compilation-time_ (C++); connections between ports are done at _deployment-time_ (XML). -- You can store as value any C++ type (we use a __type erasure_ technique +- You can store as value any C++ type (we use a _type erasure_ technique similar to [std::any](https://www.fluentcpp.com/2021/02/05/how-stdany-works/)). diff --git a/docs/learn-the-basics/xml_format.md b/docs/learn-the-basics/xml_format.md index a2143da..a9d279e 100644 --- a/docs/learn-the-basics/xml_format.md +++ b/docs/learn-the-basics/xml_format.md @@ -197,9 +197,8 @@ using the previous example, we may split the two behavior trees into two files: ``` -:::note -Note "Note for ROS users" -If you want to find a file inside a [ROS package](http://wiki.ros.org/Packages), +:::note[Note for ROS users] +If you want to find a file inside a [ROS package](http://wiki.ros.org/Packages), you can use this syntax: ::: diff --git a/docs/migration.md b/docs/migration.md index abd8329..9f72831 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -1,11 +1,11 @@ --- title: Migration from BT.CPP 3.x -description: How to migrate your code from version 3.X +description: How to migrate your code from version 3.8 hide_table_of_contents: false sidebar_position: 7 --- -# Migrating from version 3.X to 4.X +# Migrating from version 3.8 to 4.X You will find that most of the changes in version 4.X are incremental and back compatible with your previous code. @@ -15,14 +15,14 @@ that you should be aware of, when migrating. :::note In the repository you can find a Python script called **convert_v3_to_v4.py** -that may save you some time (thanks to use https://github.com/SubaruArai)! +that may save you some time (thanks to user https://github.com/SubaruArai)! -Try it, but make sure that you double check the result first! +Try it, but make sure that you double-check the result first! ::: ## Class renaming -The name of the following classes / XML tags changed. +The names of the following classes / XML tags changed. | Name in 3.8+ | Name in 4.x | Where | |-------------|---------|---------| @@ -31,7 +31,7 @@ The name of the following classes / XML tags changed. | AsyncActionNode | ThreadedAction | C++ | | Optional | Expected | C++ | -If you want to quickly fix the compilation of your C++ code, **even if refactoring is encorauged**, do: +If you want to quickly fix the compilation of your C++ code (**even if refactoring is encouraged**) add: ```cpp namespace BT @@ -42,10 +42,6 @@ namespace BT } ``` -:::info -These changes can be disabled while compiling BT.CPP with the CMake option __USE_V3_COMPATIBLE_NAMES__. -::: - ## XML You should add the attribute `BTCPP_format` to the \ tag of your XML: @@ -60,26 +56,25 @@ Now: ``` -This will allow us to be compatible -with both versions 3 and 4 (in future releases, not yet). +This will allow us to be compatible with both versions 3 and 4... eventually! ## SubTree and SubTreePlus - -The deafault **SubTree** in 3.X has been deprecated and -**SubtreePlus** is the new default, being easier to use and -more consistent. + +The default **SubTree** in 3.X has been deprecated in favor of **SubtreePlus**. +Being this the new default, we simply call it "SubTree". | Name in 3.8+ | Name in 4.x | |-------------|---------| | `` | Deprecated | | `` | `` | -## SetBlackboard and BlackboardPrecondition +## SetBlackboard and BlackboardCheck -The new [scripting language](/docs/guides/scripting) -is much simpler and more powerful. +The new [scripting language](/docs/guides/scripting) is much simpler and more powerful. -Old code in **3.8+**: +Check also the introduction to [Pre and Post Conditions](/docs/guides/pre_post_conditions). + +Old code in **3.8**: ``` xml @@ -94,26 +89,80 @@ New code in **4.X**: ``` xml - -
-
-
-
-
-

BehaviorTree.CPP 4.4

-

- The C++ library to build Behavior Trees. -
- Batteries included. -

-
- - Tutorials - -
-
+ + {/* Hero Section */} +
+
+
+
+ +
+
+

+ The Industry Standard for +
+ Robot Behaviors +

+

+ BehaviorTree.CPP is the most popular, production-ready framework + for building reactive, modular, and debuggable robot behaviors. +

+
+ + Documentation + + + Try Groot2 + +
-
- behavior tree animation +
+
+
MIT
+
OSS License
+
+
+
{githubStars}
+
GitHub Stars
+
+
+
100+
+
Companies
+
-
-
-
-
-
-
-

- Think in terms of Actions, -
not states -

-

- Unlike state machines, behavior trees emphasize executing - actions, not transitioning between states. -

-
-
-

- Build extensible and
hierarchical behaviors -

-

- Behavior Trees are composable. You can build complex - behaviors reusing simpler ones. -

-
-
-

- The power of C++, -
- the flexibility of scripting -

-

- Implement your Actions in C++ and assemble them into trees using - a scripting language based on XML. -

-
+
+ +
+ Automated Ground Vehicles +
+
+ Quadruped Robots +
+
+ Autonomous Drones +
+
+ Robotic Arms +
+
-
+
-
-
-
-
-

- Perfect for robotics -
- and automation -

-

- BehaviorTree.CPP is increasingly used to implement{" "} - Task Planning in a large variety of robotics systems, - including: -

-
    -
  • Automated Ground Vehicles
  • -
  • Robotic Manipulators
  • -
  • Humanoid and Quadruped robots
  • -
  • Semi-autonomous drones
  • -
  • Social Robots
  • -
-
-
- -
- robots -
-
- quadrupeds -
-
- robots -
-
- robots -
-
-
-
+ {/* Trust Bar */} +
+

+ Used by some of the most popular robotics frameworks: +

+
+ {trustLogos.map((logo, idx) => ( + + {logo} + + ))}
-
+ -
-
-
-
- -
-
-

Visual Editing and Monitoring

-

- Groot2 is our "IDE for Behavior Trees". -
- It allows users to visualize, create and edit Behavior Trees, - using a simple drag and drop interface.
- Trees can be monitored in real-time -

+ {/* Features Section - Bento Grid */} +
+
+

Why BehaviorTree.CPP?

+

+ Built for real-world robotics, not just demos +

+
+ +
+ {features.map((feature) => ( + + ))} +
+
+ + {/* Groot2 Section */} +
+
+
+
+

+ Boost your productivity with{" "} + Groot2 +

+
+ +
+
+
+ {grootFeatures.map((feature, idx) => ( + + ))} +
- About Groot2 + Learn More About Groot2
-
-
-
-
-
-
-
-
-

Software and Technical Support

-

- BehaviorTree.CPP is Open Source software and can be - download for free on - - {" "} - Github. - -
- You can ask questions and reach other users in our - - {" "} - community forum. - -
- If you are using BehaviorTree.CPP in your commercial product - and you need support, - contact us! -

+
+
+
-
- behavior tree animation -
-
+ + ); } -export default Home; +export default Home; \ No newline at end of file diff --git a/src/pages/index.module.css b/src/pages/index.module.css index baf9f17..158cc4d 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -1,102 +1,673 @@ +/* Design System Variables - scoped to avoid affecting docs */ +.hero, +.trustBar, +.featuresSection, +.grootSection { + --green-50: #f0fdf4; + --green-100: #dcfce7; + --green-200: #bbf7d0; + --green-400: #4ade80; + --green-500: #22c55e; + --green-600: #16a34a; + --green-700: #15803d; + --cream: #fdfcfa; + --warm-white: #fffef9; + --sand: #f5f3ef; + --text-dark: #1c1917; + --text-mid: #44403c; + --text-light: #78716c; + --radius-sm: 12px; + --radius-md: 20px; + --radius-lg: 32px; + --radius-xl: 48px; +} -h1 { - font-size: 38px; - padding: 0.5rem 0; +/* Hero Section */ +.hero { + min-height: 90vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 6rem 1rem 4rem; + position: relative; + overflow: hidden; + background: linear-gradient(180deg, var(--warm-white) 0%, var(--cream) 100%); } -h2 { - font-size: 32px; - padding: 0.5rem 0; +.heroInner { + display: grid; + grid-template-columns: 1.1fr 0.9fr; + gap: 4rem; + align-items: center; + max-width: 1400px; + width: 100%; + position: relative; + z-index: 1; } -h3{ - font-size: 24px; +/* Floating organic shapes */ +.blob { + position: absolute; + border-radius: 50%; + filter: blur(80px); + opacity: 0.6; + animation: float 20s ease-in-out infinite; } -p{ - font-size: 18px; +.blob1 { + width: 600px; + height: 600px; + background: var(--green-200); + top: -200px; + right: -100px; + animation-delay: 0s; } -li{ - font-size: 18px; +.blob2 { + width: 400px; + height: 400px; + background: var(--green-100); + bottom: -100px; + left: -100px; + animation-delay: -5s; } -.heroBanner { - padding: 2.5rem 0; - text-align: center; - position: relative; - overflow: hidden; - display: flex; - align-items: center; - justify-content: center; +.blob3 { + width: 300px; + height: 300px; + background: var(--green-200); + top: 40%; + left: 10%; + animation-delay: -10s; } -.heroBanner h1{ - padding: 0.5rem 0; - font-size: 48px; +@keyframes float { + 0%, 100% { transform: translate(0, 0) scale(1); } + 25% { transform: translate(30px, -30px) scale(1.05); } + 50% { transform: translate(-20px, 20px) scale(0.95); } + 75% { transform: translate(20px, 10px) scale(1.02); } } -.heroText { - color: #3b3b3b; - padding: 3.5rem 0; +.heroContent { + text-align: left; } -.heroSvg { - max-width: 550px; - max-height: 550px; +/* Hero Carousel */ +.heroCarousel { + position: relative; + border-radius: var(--radius-xl); + overflow: hidden; + box-shadow: 0 30px 60px rgba(0, 0, 0, 0.15); + animation: fadeInUp 0.8s ease-out 0.5s both; } -@media screen and (max-width: 966px) { - .heroBanner { - padding: 2rem; - } +.heroCarousel img { + border-radius: var(--radius-lg); + object-fit: cover; } -.sectionText { - display: flex; - align-items: center; - justify-content: center; - color: #3b3b3b; +.heroTitle { + font-size: clamp(3.5rem, 8vw, 5.5rem); + font-weight: 800; + line-height: 1.0; + margin-bottom: 1.25rem; + letter-spacing: -0.04em; + animation: fadeInUp 0.8s ease-out 0.1s both; + color: var(--text-dark); } -.sectionText p{ - font-size: 20px; +.heroTitleHighlight { + background: linear-gradient(135deg, #047857 0%, #059669 50%, #10b981 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + animation: shimmer 3s ease-in-out infinite; } -.sectionText li{ - font-size: 20px; +@keyframes shimmer { + 0%, 100% { filter: brightness(1); } + 50% { filter: brightness(1.15); } } -.features { - display: flex; - align-items: center; - padding: 4rem 0; - width: 100%; - background-color: #383838; - color: white; +.heroSub { + font-size: 1.35rem; + color: var(--text-mid); + max-width: 540px; + margin: 0 0 2rem; + animation: fadeInUp 0.8s ease-out 0.2s both; + line-height: 1.5; + font-weight: 400; } -.features h3 { - color: rgb(0, 217, 94); +.heroCtas { + display: flex; + gap: 1rem; + justify-content: flex-start; + flex-wrap: wrap; + animation: fadeInUp 0.8s ease-out 0.3s both; } -.features p { - font-size: 20px; +.btn { + padding: 1rem 2rem; + border-radius: 100px; + font-weight: 600; + font-size: 1.25rem; + text-decoration: none; + transition: all 0.3s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; + border: none; } -.supportFrame { - display: flex; - align-items: center; - padding: 2rem 0; - width: 100%; - color: rgb(53, 53, 53); - background-image: linear-gradient(to bottom, #00a639, #1eb645, #30c651, - #3fd65d, #4de769, #4eef69, #4ff669, #51fe68, #46fe59, #39ff47, #2bff30, #17ff00); +.btnPrimary { + background: var(--green-600); + color: white; + box-shadow: 0 4px 20px rgba(22, 163, 74, 0.3); +} + +.btnPrimary:hover { + background: var(--green-700); + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(22, 163, 74, 0.4); + color: white; + text-decoration: none; +} + +.btnSecondary { + background: white; + color: var(--text-dark); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); +} + +.btnSecondary:hover { + background: var(--green-50); + transform: translateY(-2px); + color: var(--text-dark); + text-decoration: none; +} + +.heroStats { + display: flex; + gap: 3rem; + justify-content: flex-start; + margin-top: 3rem; + animation: fadeInUp 0.8s ease-out 0.4s both; +} + +.stat { + text-align: left; +} + +.statValue { + font-size: 3rem; + font-weight: 800; + color: var(--green-600); + line-height: 1; + letter-spacing: -0.02em; +} + +.statLabel { + font-size: 0.875rem; + color: var(--text-light); + margin-top: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.05em; + font-weight: 500; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Trust Bar */ +.trustBar { + padding: 3rem 1rem; + text-align: center; + background: #303846; +} + +.trustBarTitle { + color: rgba(255, 255, 255, 0.5); + font-size: 1.4rem; + margin-bottom: 1.5rem; + text-transform: uppercase; + letter-spacing: 0.15em; + font-weight: 600; +} + +.trustLogos { + display: flex; + justify-content: center; + align-items: center; + gap: 3rem; + flex-wrap: wrap; +} + +.trustLogo { + color: rgba(255, 255, 255, 0.85); + font-family: 'JetBrains Mono', monospace; + font-size: 2.0rem; + font-weight: 600; + transition: color 0.2s; + cursor: default; +} + +.trustLogo:hover { + color: var(--green-400); +} + +/* Features Section - Bento Grid */ +.featuresSection { + padding: 6rem 1rem; + background: var(--cream); +} + +.featuresHeader { + text-align: center; + margin-bottom: 4rem; +} + +.featuresTitle { + font-size: 3.5rem; + font-weight: 800; + margin-bottom: 0.5rem; + letter-spacing: -0.03em; + color: var(--text-dark); +} + +.featuresSubtitle { + color: var(--text-mid); + font-size: 1.4rem; + font-weight: 400; +} + +.highlight { + color: var(--green-500); +} + +/* Bento Box Grid */ +.bentoGrid { + display: grid; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: auto auto; + gap: 1.25rem; + max-width: 1400px; + margin: 0 auto; +} + +/* Card positions - large boxes 3/7, small boxes 2/7 */ +.bentoCard:nth-child(1) { + grid-column: 1 / 4; +} + +.bentoCard:nth-child(2) { + grid-column: 4 / 6; +} + +.bentoCard:nth-child(3) { + grid-column: 6 / 8; +} + +.bentoCard:nth-child(4) { + grid-column: 1 / 3; +} +.bentoCard:nth-child(5) { + grid-column: 3 / 5; } -.supportFrame a -{ - font-weight: bold; - color: rgb(13, 47, 65); + +.bentoCard:nth-child(6) { + grid-column: 5 / 8; +} + +.bentoCard { + background: white; + border-radius: var(--radius-md); + padding: 2rem; + transition: all 0.3s ease; + display: flex; + flex-direction: column; + border: 1px solid #d1d5db; +} + +.bentoCard:hover { + transform: translateY(-2px); + border: 2px solid var(--green-400); +} + +.bentoCard:hover .bentoIcon { + transform: scale(1.05); +} + + +.bentoHeader { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 0.75rem; } +.bentoIcon { + width: 48px; + height: 48px; + background: var(--green-500); + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.2rem; + flex-shrink: 0; + transition: all 0.3s ease; + color: white; +} + +.bentoCard h3 { + font-size: 1.4rem; + font-weight: 700; + margin: 0; + color: var(--text-dark); + transition: color 0.3s ease; +} + +.bentoCard p { + color: var(--text-mid); + font-size: 1.1rem; + line-height: 1.6; + transition: color 0.3s ease; + margin: 0; +} + +/* Groot2 Section */ +.grootSection { + padding: 6rem 1rem; + background: var(--text-dark); + position: relative; + overflow: hidden; +} + +.grootSection::before { + content: ""; + position: absolute; + top: -200px; + right: -200px; + width: 600px; + height: 600px; + background: radial-gradient(circle, rgba(34, 197, 94, 0.2) 0%, transparent 70%); + pointer-events: none; + animation: floatGlow 20s ease-in-out infinite; +} + +.grootSection::after { + content: ""; + position: absolute; + bottom: -150px; + left: -150px; + width: 500px; + height: 500px; + background: radial-gradient(circle, rgba(34, 197, 94, 0.15) 0%, transparent 70%); + pointer-events: none; + animation: floatGlow 25s ease-in-out infinite reverse; +} + +@keyframes floatGlow { + 0%, 100% { + transform: translate(0, 0) scale(1); + } + 25% { + transform: translate(150px, 100px) scale(1.2); + } + 50% { + transform: translate(-100px, 150px) scale(0.9); + } + 75% { + transform: translate(100px, -80px) scale(1.15); + } +} + +.grootBlob { + display: none; +} + +.grootContent { + max-width: 1400px; + margin: 0 auto; + position: relative; + z-index: 1; +} + +.grootHeader { + text-align: center; + margin-bottom: 3rem; +} + +.grootHeader h2 { + font-size: 3.5rem; + font-weight: 800; + letter-spacing: -0.03em; + color: white; +} + +.grootBody { + display: grid; + grid-template-columns: 0.9fr 1.5fr; + gap: 3rem; + align-items: center; +} + +.grootTextHighlight { + color: var(--green-400); +} + +.grootFeatures { + display: flex; + flex-direction: column; + gap: 1rem; + margin-bottom: 2rem; +} + +.grootFeature { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1rem 1.25rem; + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: var(--radius-md); + transition: all 0.2s; +} + +.grootFeature:hover { + transform: translateX(8px); + background: rgba(255, 255, 255, 0.06); + border-color: rgba(34, 197, 94, 0.3); +} + +.grootFeatureIcon { + width: 28px; + height: 28px; + background: var(--green-500); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: white; + font-size: 0.8rem; + font-weight: 700; +} + +.grootFeatureText strong { + color: rgba(255, 255, 255, 0.9); + font-weight: 600; + display: block; +} + +.grootFeatureText span { + color: rgba(255, 255, 255, 0.6); + font-size: 1.1rem; +} + +.grootVisual { + position: relative; +} + +.grootPreview { + border-radius: var(--radius-sm); + overflow: hidden; + box-shadow: 0 30px 60px rgba(0, 0, 0, 0.4); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.grootPreview video { + width: 100%; + display: block; +} + +.grootText { + display: flex; + flex-direction: column; + align-items: center; +} + +.grootText .btn { + margin-top: 1rem; +} + +/* Responsive */ +@media (max-width: 1024px) { + .heroInner { + grid-template-columns: 1fr; + gap: 3rem; + text-align: center; + } + + .heroContent { + text-align: center; + order: 1; + } + + .heroCarousel { + order: 2; + max-width: 500px; + margin: 0 auto; + } + + .heroCtas { + justify-content: center; + } + + .heroStats { + justify-content: center; + } + + .stat { + text-align: center; + } + + .grootBody { + grid-template-columns: 1fr; + gap: 3rem; + } + + .grootHeader h2 { + font-size: 2.5rem; + } + + .bentoGrid { + grid-template-columns: 1fr 1fr; + } + + .bentoCard:nth-child(1) { + grid-column: 1 / 3; + } + + .bentoCard:nth-child(2) { + grid-column: 1; + } + + .bentoCard:nth-child(3) { + grid-column: 2; + } + + .bentoCard:nth-child(4) { + grid-column: 1; + } + + .bentoCard:nth-child(5) { + grid-column: 2; + } + + .bentoCard:nth-child(6) { + grid-column: 1 / 3; + } +} + +@media (max-width: 768px) { + .heroStats { + flex-direction: row; + gap: 1.5rem; + flex-wrap: wrap; + } + + .heroCarousel { + max-width: 100%; + } + + .trustLogos { + gap: 1.5rem; + } + + .bentoGrid { + grid-template-columns: 1fr; + } + + .bentoCard:nth-child(1), + .bentoCard:nth-child(2), + .bentoCard:nth-child(3), + .bentoCard:nth-child(4), + .bentoCard:nth-child(5), + .bentoCard:nth-child(6) { + grid-column: 1; + } + + .heroTitle { + font-size: 2.5rem; + } + + .grootText h2 { + font-size: 2rem; + } + + .grootText { + text-align: center; + } + + .grootHeader h2 { + font-size: 2rem; + } + + .grootFeature { + text-align: left; + } + + .heroCtas { + flex-direction: column; + align-items: center; + } + + .btn { + width: 100%; + max-width: 280px; + justify-content: center; + } +} \ No newline at end of file diff --git a/static/img/done.png b/static/img/done.png new file mode 100644 index 0000000..e0576da Binary files /dev/null and b/static/img/done.png differ diff --git a/versioned_docs/version-3.8/learn-the-basics/images/FetchBeer.svg b/versioned_docs/version-3.8/learn-the-basics/images/FetchBeer.svg index 880a142..e530a7b 100644 --- a/versioned_docs/version-3.8/learn-the-basics/images/FetchBeer.svg +++ b/versioned_docs/version-3.8/learn-the-basics/images/FetchBeer.svg @@ -1 +1,183 @@ -SequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeForceSuccessForceSuccessSequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeFallbackFallbackForceFailureForceFailureCloseFridgeCloseFridge \ No newline at end of file + + + + + + + + + + + + + + + + Sequence + + + + Sequence + + + + + + + + + OpenFridge + + + + OpenFridge + + + + + + + + + GrabBeer + + + + GrabBeer + + + + + + + + + CloseFridge + + + + CloseFridge + + + + + + + + + + + ForceSuccess + + + + ForceSuccess + + + + + + + + + + + + + + + Sequence + + + + Sequence + + + + + + + + + OpenFridge + + + + OpenFridge + + + + + + + + + GrabBeer + + + + GrabBeer + + + + + + + + + CloseFridge + + + + CloseFridge + + + + + + + + + + + + + Fallback + + + + Fallback + + + + + + + + + + + ForceFailure + + + + ForceFailure + + + + + + + + + CloseFridge + + + + CloseFridge + + + + diff --git a/versioned_docs/version-3.8/learn-the-basics/main_concepts.md b/versioned_docs/version-3.8/learn-the-basics/main_concepts.md index a2dc2b9..60ce42f 100644 --- a/versioned_docs/version-3.8/learn-the-basics/main_concepts.md +++ b/versioned_docs/version-3.8/learn-the-basics/main_concepts.md @@ -88,7 +88,7 @@ For the time being, it is important to know that: - The number, name and kind of ports of a Node must be known at _compilation-time_ (C++); connections between ports are done at _deployment-time_ (XML). -- You can store as value any C++ type (we use a __type erasure_ technique +- You can store as value any C++ type (we use a _type erasure_ technique similar to [std::any](https://www.fluentcpp.com/2021/02/05/how-stdany-works/)). diff --git a/versioned_docs/version-3.8/nodes-library/SequenceNode.md b/versioned_docs/version-3.8/nodes-library/SequenceNode.md index 7abb714..133db9b 100644 --- a/versioned_docs/version-3.8/nodes-library/SequenceNode.md +++ b/versioned_docs/version-3.8/nodes-library/SequenceNode.md @@ -45,7 +45,7 @@ This tree represents the behavior of a sniper in a computer game. This node is particularly useful to continuously check Conditions; but the user should also be careful when using asynchronous children, to be -sure that they are not ticked more often that expected. +sure that they are not ticked more often than expected. Let's take a look at another example: diff --git a/versioned_docs/version-3.8/nodes-library/images/SequenceStar.svg b/versioned_docs/version-3.8/nodes-library/images/SequenceStar.svg index 335116f..932d4bb 100644 --- a/versioned_docs/version-3.8/nodes-library/images/SequenceStar.svg +++ b/versioned_docs/version-3.8/nodes-library/images/SequenceStar.svg @@ -1 +1,4 @@ -SequenceWithMemorySequenceWithMemoryGoTo(C)GoTo(C)RetryUntilSuccessfulRetryUntilSuccessfulGoTo(A)GoTo(A)GoTo(B)GoTo(B) \ No newline at end of file + + + +
RetryUntilSuccessful
RetryUntilSuccessful
ReactiveSequence
ReactiveSequence
isBatteryOK
isBatteryOK
SequenceWithMemory
SequenceWithMemory
GoTo(A)
GoTo(A)
GoTo(B)
GoTo(B)
GoTo(C)
GoTo(C)
Text is not SVG - cannot display
diff --git a/versioned_docs/version-3.8/tutorial-basics/tutorial_04_sequence.md b/versioned_docs/version-3.8/tutorial-basics/tutorial_04_sequence.md index 4c5a4e1..fc2f833 100644 --- a/versioned_docs/version-3.8/tutorial-basics/tutorial_04_sequence.md +++ b/versioned_docs/version-3.8/tutorial-basics/tutorial_04_sequence.md @@ -191,14 +191,8 @@ Expected output: ``` --- ticking [ Battery: OK ] ---- status: RUNNING - ---- ticking Robot says: mission started... ---- status: RUNNING - ---- ticking -[ MoveBase: SEND REQUEST ]. goal: x=1.0 y=2.0 theta=3.0 +[ MoveBase: SEND REQUEST ]. goal: x=1.000000 y=2.000000 theta=3.000000 --- status: RUNNING --- ticking @@ -242,11 +236,7 @@ Expected output: --- ticking [ Battery: OK ] Robot says: mission started... ---- status: RUNNING - ---- ticking -[ Battery: OK ] -[ MoveBase: SEND REQUEST ]. goal: x=1.0 y=2.0 theta=3.0 +[ MoveBase: SEND REQUEST ]. goal: x=1.000000 y=2.000000 theta=3.000000 --- status: RUNNING --- ticking diff --git a/versioned_docs/version-3.8/tutorial-basics/tutorial_06_subtree_ports.md b/versioned_docs/version-3.8/tutorial-basics/tutorial_06_subtree_ports.md index 221867b..fb37f54 100644 --- a/versioned_docs/version-3.8/tutorial-basics/tutorial_06_subtree_ports.md +++ b/versioned_docs/version-3.8/tutorial-basics/tutorial_06_subtree_ports.md @@ -30,8 +30,8 @@ Let's consider this Behavior Tree. // highlight-start - + // highlight-end diff --git a/versioned_docs/version-4.0.2/intro.md b/versioned_docs/version-4.0.2/intro.md deleted file mode 100644 index 90a9422..0000000 --- a/versioned_docs/version-4.0.2/intro.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -sidebar_position: 1 ---- - -# About - -## About this library - -This __C++__ library provides a framework to create **BehaviorTrees**. -It is designed to be flexible, easy to use and fast. - -Even if our main use-case is __robotics__, you can use this library to build -__AI for games__, or to replace Finite State Machines in your application. - -__BehaviorTree.CPP__ has many interesting features, when compared to other implementations: - -- It makes __asynchronous Actions__, i.e. non-blocking routines, a first-class citizen. -- Trees are created at run-time, using an __interpreted language__ (based on XML). -- It includes a __logging/profiling__ infrastructure that allows the user -to visualize, record, replay and analyze state transitions. -- You can link statically your custom TreeNodes or convert them into plugins -which are loaded at run-time. - - -## What is a Behavior Tree? - -A Behavior Tree (__BT__) is a way to structure the switching between different -tasks in an autonomous agent, such as a robot or a virtual entity in a computer game. - -BTs are a very efficient way of creating complex systems that are both modular and reactive. -These properties are crucial in many applications, which has led to the spread -of BT from computer game programming to many branches of AI and Robotics. - -If you are already familiar with Finite State Machines (__FSM__), you will -easily grasp most of the concepts but, hopefully, you will find that BTs -are more expressive and easier to reason about. - -Think about the __Nodes of the tree__ as a set of building blocks. -These blocks are implemented in C++ and are "composable": in other words, they can be -"assembled" to build behaviors. - -![](intro_build_trees.svg) - -In the image above, you can see as we are arranging these actions in a simple Sequence; -actions will be executed in order from left to right. To learn more, visit the page -[Introduction to BTs](learn-the-basics/BT_basics.md). - -### Main Advantages of Behavior Trees - -- __They are intrinsically hierarchical__: we can _compose_ -complex behaviors, including entire trees as sub-branches of a bigger tree. -For instance, the behavior "Fetch Beer" may reuse the tree -"Grasp Object". - -- __Their graphical representation has a semantic meaning__: it is easier to -"read" a BT and understand the corresponding workflow. -State transitions in FSMs, by comparisons, are harder to understand -both in their textual and graphical representation. - -- __They are more expressive__: Ready to use ControlNodes and DecoratorNodes -make it possible to express more complex control flows. The user can extend the -"vocabulary" with his/her own custom nodes. - - -## "Ok, but WHY do we need BehaviorTrees (or FSM)?" - -Many software systems, robotics being a notable example, are inherently -complex. - -The usual approach to manage complexity, heterogeneity and scalability is to -use the concept of -[Component Based Software Engineering](https://en.wikipedia.org/wiki/Component-based_software_engineering). - -Any existing middleware for robotics took this approach either informally or formally, -being [ROS](http://www.ros.org), [YARP](http://www.yarp.it) and -[SmartSoft](http://www.servicerobotik-ulm.de) some notable examples. - -A "good" software architecture should have the following characteristics: - -- Modularity. -- Reusability of components. -- Composability. -- Good separation of concerns. - -If we don't keep these concepts in mind from the very beginning, we create -software that is tightly coupled and less reusable. - -Frequently, the business logic of a software system is "spread" into many -components and it is __hard for the developer -to reason about it and to debug errors__. - -To achieve a strong separation of concerns, it is better to centralize -the business logic in a single location. - -__Finite State Machines__ were created specifically with this goal in mind, but in -recent years, __Behavior Trees__ gained popularity, especially in the game industry. - diff --git a/versioned_docs/version-4.0.2/intro_build_trees.svg b/versioned_docs/version-4.0.2/intro_build_trees.svg deleted file mode 100644 index 08b82c6..0000000 --- a/versioned_docs/version-4.0.2/intro_build_trees.svg +++ /dev/null @@ -1,11 +0,0 @@ - -Sequence - -Find(Beer) - -Close(fridge) - -Grab(Beer) - -Open(fridge) - \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/BT_basics.md b/versioned_docs/version-4.0.2/learn-the-basics/BT_basics.md deleted file mode 100644 index a117f63..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/BT_basics.md +++ /dev/null @@ -1,204 +0,0 @@ -# Introduction to BTs - -Unlike a Finite State Machine, a behavior Tree is a __tree of hierarchical nodes__ -that controls the flow of execution of "tasks". - -## Basic Concepts - -- A signal called "__tick__" is sent to the root of the tree -and propagates through the tree until it reaches a leaf node. - -- Any TreeNode that receives a __tick__ signal executes its callback. - This callback must return either - - - **SUCCESS** - - **FAILURE** - - **RUNNING** - -- RUNNING means that the action needs -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. - - - 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. - __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) -and it means: - - "To invoke the callback `tick()` of a `TreeNode`". -::: - -In a service-oriented architecture, the leaves would contain -the "client" code that communicates with the "server", -that performs the actual operation. - -## How tick works - -To mentally visualize how ticking the tree works, consider the example below. - -![basic sequence](images/sequence_animation.svg) - -A __Sequence__ is the simplest __ControlNode__: it executes -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 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 -switches from RUNNING to SUCCESS. - -## Types of nodes - -![UML hierarchy](images/TypeHierarchy.png) - -| 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 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" | - - -In the context of __ActionNodes__, we may further distinguish between -synchronous and asynchronous nodes. - -The former are executed atomically and block the tree until a SUCCESS or FAILURE is returned. - -Asynchronous actions, instead, may return RUNNING to communicate that -the action is still being executed. - -We need to tick them again, until SUCCESS or FAILURE is eventually returned. - -# Examples - -To better understand how BehaviorTrees work, let's focus on some practical -examples. For the sake of simplicity we will not take into account what happens when an action returns RUNNING. - -We will assume that each Action is executed atomically and synchronously. - - -### First ControlNode: Sequence - -Let's illustrate how a BT works using the most basic and frequently used -ControlNode: the [SequenceNode](nodes-library/SequenceNode.md). - -The children of a ControlNode are always __ordered__; in the graphical -representation, the order of execution is __from left to right__. - -![Simple Sequence: fridge](images/SequenceBasic.svg) - - -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 __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. -::: - -### Decorators - -Depending on the type of [DecoratorNode](nodes-library/DecoratorNode.md), the goal of -this node could be either: - -- to transform the result it received from the child. -- to halt the execution of the child. -- to repeat ticking the child, depending on the type of Decorator. - - -![Simple Decorator: Enter Room](images/DecoratorEnterRoom.svg) - -The node __Inverter__ is a Decorator that inverts -the result returned by its child; An Inverter followed by the node called -__isDoorOpen__ is, therefore, equivalent to - - "Is the door closed?". - -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 left side means: - - If the door is closed, then try to open it. - Try up to 5 times, otherwise give up and return FAILURE. - -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 -is interrupted. -::: - - -### Second ControlNode: Fallback - -[FallbackNodes](nodes-library/FallbackNode.md), also known as __"Selectors"__, -are nodes that can express, as the name suggests, fallback strategies, -i.e. what to do next if a child returns FAILURE. - -It ticks the children in order and: - -- If a child returns FAILURE, tick the next one. -- If a child returns SUCCESS, then no more children are ticked and the - Fallback returns SUCCESS. -- If all the children return FAILURE, then the Fallback returns FAILURE too. - -In the next example, you can see how Sequences and Fallbacks can be combined: - -![FallbackNodes](images/FallbackBasic.svg) - - -> Is the door open? -> -> If not, try to open the door. -> -> Otherwise, if you have a key, unlock and open the door. -> -> Otherwise, smash the door. -> -> If __any__ of these actions succeeded, then enter the room. - -### "Fetch me a beer" revisited - -We can now improve the "Fetch Me a Beer" example, which left the door open -if the beer was not inside the fridge. - -We use the color "green" to represent nodes which return -SUCCESS and "red" for those which return FAILURE. Black nodes haven't -been executed. - -![FetchBeer failure](images/FetchBeerFails.svg) - -Let's create an alternative tree that closes the door even when __GrabBeer__ -returns FAILURE. - - -![FetchBeer failure](images/FetchBeer.svg) - -Both these trees will close the door of the fridge, eventually, but: - -- the tree on the __left__ side will always return SUCCESS, no matter if -we have actually grabbed the beer. - -- the tree on the __right__ side would return SUCCESS if the beer was there, -FAILURE otherwise. - -Everything works as expected if __GrabBeer__ returns SUCCESS. - -![FetchBeer success](images/FetchBeer2.svg) - - - diff --git a/versioned_docs/version-4.0.2/learn-the-basics/_category_.json b/versioned_docs/version-4.0.2/learn-the-basics/_category_.json deleted file mode 100644 index 97d3fb8..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Learn the Basic Concepts", - "position": 2, - "link": { - "type": "generated-index", - "description": "Learn what Behavior Trees are and how to use them." - } -} diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/BT.png b/versioned_docs/version-4.0.2/learn-the-basics/images/BT.png deleted file mode 100644 index 34d1c7c..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/BT.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/CrossDoorSubtree.png b/versioned_docs/version-4.0.2/learn-the-basics/images/CrossDoorSubtree.png deleted file mode 100644 index e7e32e8..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/CrossDoorSubtree.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/DecoratorEnterRoom.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/DecoratorEnterRoom.svg deleted file mode 100644 index 517c89e..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/DecoratorEnterRoom.svg +++ /dev/null @@ -1,1113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.png b/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.png deleted file mode 100644 index ea6a408..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.svg deleted file mode 100644 index 47c4591..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/FallbackBasic.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceFallbackFallbackEnterRoomEnterRoomIsDoorOpenIsDoorOpenSequenceSequenceUnlockDoorUnlockDoorHaveKey?HaveKey?OpenDoorOpenDoorOpenDoorOpenDoorSmashDoor \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.png b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.png deleted file mode 100644 index fa0d15f..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.svg deleted file mode 100644 index 880a142..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeForceSuccessForceSuccessSequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeFallbackFallbackForceFailureForceFailureCloseFridgeCloseFridge \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.png b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.png deleted file mode 100644 index 268ca71..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.svg deleted file mode 100644 index aaca63d..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeer2.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeForceSuccessForceSuccessSequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridgeFallbackFallbackForceFailureForceFailureCloseFridgeCloseFridge \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.png b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.png deleted file mode 100644 index 3750f09..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.svg deleted file mode 100644 index 9a596e9..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/FetchBeerFails.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceOpenFridgeOpenFridgeGrabBeerGrabBeerCloseFridgeCloseFridge \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/LeafToComponentCommunication.png b/versioned_docs/version-4.0.2/learn-the-basics/images/LeafToComponentCommunication.png deleted file mode 100644 index 13a0ea2..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/LeafToComponentCommunication.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/ReadTheDocs.png b/versioned_docs/version-4.0.2/learn-the-basics/images/ReadTheDocs.png deleted file mode 100644 index 6289129..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/ReadTheDocs.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/RunningTree.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/RunningTree.svg deleted file mode 100644 index c78c4a6..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/RunningTree.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceFallbackFallbackActionAActionAActionEActionEActionDActionDActionFActionFActionBActionBrootrootRUNNINGRUNNINGFAILUREFAILURESUCCESSSUCCESS \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceAll.png b/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceAll.png deleted file mode 100644 index 2e4ad99..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceAll.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.png b/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.png deleted file mode 100644 index 1468ef4..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.svg deleted file mode 100644 index 8c1fb00..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/SequenceBasic.svg +++ /dev/null @@ -1 +0,0 @@ -
Sequence
Sequence
OpenFridge
OpenFridge
GrabBeer
GrabBeer
CloseFridge
CloseFridge
\ No newline at end of file diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/TypeHierarchy.png b/versioned_docs/version-4.0.2/learn-the-basics/images/TypeHierarchy.png deleted file mode 100644 index be2c0c9..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/TypeHierarchy.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/lego.jpg b/versioned_docs/version-4.0.2/learn-the-basics/images/lego.jpg deleted file mode 100644 index b959bb4..0000000 Binary files a/versioned_docs/version-4.0.2/learn-the-basics/images/lego.jpg and /dev/null differ diff --git a/versioned_docs/version-4.0.2/learn-the-basics/images/sequence_animation.svg b/versioned_docs/version-4.0.2/learn-the-basics/images/sequence_animation.svg deleted file mode 100644 index 99fb196..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/images/sequence_animation.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - -Sequence - -OpenDoor - -CloseDoor - -Walk - - - diff --git a/versioned_docs/version-4.0.2/learn-the-basics/main_concepts.md b/versioned_docs/version-4.0.2/learn-the-basics/main_concepts.md deleted file mode 100644 index dcdf14b..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/main_concepts.md +++ /dev/null @@ -1,96 +0,0 @@ -# Main Concepts - -__BehaviorTree.CPP__ is a C++ library that can be easily integrated into -your favourite distributed middleware, such as __ROS__ or __SmartSoft__. - -You can statically link it into your application (for example a game). - -These are the main concepts which you need to understand first. - -## Nodes vs Trees - -The user must create his/her own ActionNodes and ConditionNodes (LeafNodes); -this library helps you to compose them easily into trees. - -Think about the LeafNodes as the building blocks which you need to compose a complex system. If Nodes were **lego bricks**, your trees would be lego sets. - -![](images/lego.jpg) - - -By definition, your custom Nodes are (or should be) highly __reusable__. - -## Instantiate trees at run-time using the XML format - -Despite the fact that the library is written in C++, trees themselves -can be created and composed at _run-time_, more specifically, at _deployment-time_, using an XML base scripting language. - -An XML format is described in details [here](xml_format.md), but the best way to -learn the syntax is following the tutorials. - -## The tick() callbacks - -Any TreeNode can be seen as a mechanism to invoke a __callback__, i.e. to -__run a piece of code__. What this callback does is up to you. - -In most of the following tutorials, our Actions will simply -print messages on console or sleep for a certain amount of time to simulate -a long calculation. - -In production code, especially in Model Driven Development and Component -Based Software Engineering, an Action/Condition would probably communicate -to other _components_ or _services_ of the system. - -``` cpp -// The simplest callback you can wrap into a BT Action -NodeStatus HelloTick() -{ - std::cout << "Hello World\n"; - return NodeStatus::SUCCESS; -} - -// Allow the library to create Actions that invoke HelloTick() -// (explained in the tutorials) -factory.registerSimpleAction("Hello", std::bind(HelloTick)); -``` - -::::tip -The factory may create multiple instances of the node __Hello__. -:::: - -## Create custom nodes with inheritance - -In the example above, a specific type of TreeNodes which invoke -`HelloTick` was created using a __function pointer__ (dependency injection). - -Generally, to define a custom TreeNode, you should inherit from the -class `TreeNode` or, more specifically, its derived classes: - -- `ActionNodeBase` -- `ConditionNode` -- `DecoratorNode` - -As a reference please look at the [first tutorial](tutorial-basics/tutorial_01_first_tree.md). - -## Dataflow, Ports and Blackboard - -Ports are explained in detail in the [second](tutorial-basics/tutorial_02_basic_ports.md) -and [third](tutorial-basics/tutorial_03_generic_ports.md) tutorials. - -For the time being, it is important to know that: - -- A __Blackboard__ is a _key/value_ storage shared by all the Nodes of a Tree. - -- __Ports__ are a mechanism that Nodes can use to exchange information between - each other. - -- Ports are _"connected"_ using the same _key_ of the blackboard. - -- The number, name and kind of ports of a Node must be known at _compilation-time_ (C++); - connections between ports are done at _deployment-time_ (XML). - -- You can store as value any C++ type (we use a __type erasure_ technique -similar to [std::any](https://www.fluentcpp.com/2021/02/05/how-stdany-works/)). - - - - diff --git a/versioned_docs/version-4.0.2/learn-the-basics/xml_format.md b/versioned_docs/version-4.0.2/learn-the-basics/xml_format.md deleted file mode 100644 index a2143da..0000000 --- a/versioned_docs/version-4.0.2/learn-the-basics/xml_format.md +++ /dev/null @@ -1,219 +0,0 @@ - -# The XML schema - -In the [first tutorial](tutorial-basics/tutorial_01_first_tree.md) this simple tree -was presented. - -``` XML - - - - - - - - - - -``` - -You may notice that: - -- The first tag of the tree is ``. It should contain __1 or more__ tags ``. - -- The tag `` should have the attribute `[ID]`. - -- The tag `` should contain the attribute `[BTCPP_format]`. - -- Each TreeNode is represented by a single tag. In particular: - - - The name of the tag is the __ID__ used to register the TreeNode in the factory. - - The attribute `[name]` refers to the name of the instance and is __optional__. - - Ports are configured using attributes. In the previous example, the action - `SaySomething` requires the input port `message`. - -- In terms of number of children: - - - `ControlNodes` contain __1 to N children__. - - `DecoratorNodes` and Subtrees contain __only 1 child__. - - `ActionNodes` and `ConditionNodes` have __no child__. - -## Ports Remapping and pointers to Blackboards entries - -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. - -A BB key is represented using this syntax: `{key_name}`. - -In the following example: - -- the first child of the Sequence prints "Hello", -- the second child reads and writes the value contained in the entry of - the blackboard called "my_message"; - -``` XML - - - - - - - - -``` - - -## Compact vs Explicit representation - -The following two syntaxes are both valid: - -``` XML - - -``` - -We will call the former syntax "__compact__" and the latter "__explicit__". -The first example represented with the explicit syntax would become: - -``` XML - - - - - - - - - - -``` - -Even if the compact syntax is more convenient and easier to write, it provides -too little information about the model of the TreeNode. Tools like __Groot__ require either -the _explicit_ syntax or additional information. -This information can be added using the tag ``. - -To make the compact version of our tree compatible with Groot, the XML -must be modified as follows: - - -``` XML - - - - - - - - - - - - - - - - - - - - -``` - -## Subtrees - -As we saw in [this tutorial](tutorial-basics/tutorial_06_subtree_ports.md), it is possible to include -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 encapsulate a few actions into the behaviorTree "__GraspObject__" -(being optional, attributes [name] are omitted for simplicity). - -``` XML - - - - - - // highlight-next-line - - - - - - - - - - - - -``` - -We may notice that the entire tree "GraspObject" is executed after "SaySomething". - -## Include external files - -__Since version 2.4__. - -You can include external files in a way that is similar to '__#include \__' in C++. -We can do this easily using the tag: - -``` XML - -``` - -using the previous example, we may split the two behavior trees into two files: - - -``` XML hl_lines="5" - - - - - - - - - - - - - -``` - -``` XML - - - - - - - - - - - -``` - -:::note -Note "Note for ROS users" -If you want to find a file inside a [ROS package](http://wiki.ros.org/Packages), -you can use this syntax: -::: - -``` XML - -``` - - - - - - - - - - - diff --git a/versioned_docs/version-4.0.2/nodes-library/DecoratorNode.md b/versioned_docs/version-4.0.2/nodes-library/DecoratorNode.md deleted file mode 100644 index f1f1b80..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/DecoratorNode.md +++ /dev/null @@ -1,45 +0,0 @@ -# Decorators - -A decorator is a node that can have only a single child. - -It is up to the Decorator to decide if, when and how many times the child should be -ticked. - -## InverterNode - -Tick the child once and return SUCCESS if the child failed or FAILURE if -the child succeeded. - -If the child returns RUNNING, this node returns RUNNING too. - -## ForceSuccessNode - -If the child returns RUNNING, this node returns RUNNING too. - -Otherwise, it returns always SUCCESS. - -## ForceFailureNode - -If the child returns RUNNING, this node returns RUNNING too. - -Otherwise, it returns always FAILURE. - -## RepeatNode - -Tick the child up to N times, where N is passed as a [Input Port](tutorial-basics/tutorial_02_basic_ports.md), -as long as the child returns SUCCESS. - -Interrupt the loop if the child returns FAILURE and, in that case, return FAILURE too. - -If the child returns RUNNING, this node returns RUNNING too. - -## RetryNode - -Tick the child up to N times, where N is passed as a [Input Port](tutorial-basics/tutorial_02_basic_ports.md), -as long as the child returns FAILURE. - -Interrupt the loop if the child returns SUCCESS and, in that case, return SUCCESS too. - -If the child returns RUNNING, this node returns RUNNING too. - - diff --git a/versioned_docs/version-4.0.2/nodes-library/FallbackNode.md b/versioned_docs/version-4.0.2/nodes-library/FallbackNode.md deleted file mode 100644 index 85639f7..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/FallbackNode.md +++ /dev/null @@ -1,57 +0,0 @@ -# Fallbacks - -This family of nodes are known as "Selector" or "Priority" -in other frameworks. - -Their purpose is to try different strategies, until we find one that "works". - -Currently the framework provides two kinds of nodes: - -- Fallback -- ReactiveFallback - -They share the following rules: - -- Before ticking the first child, the node status becomes __RUNNING__. - -- If a child returns __FAILURE__, the fallback ticks the next child. - -- If the __last__ child returns __FAILURE__ too, all the children are halted and - the fallback returns __FAILURE__. - -- If a child returns __SUCCESS__, it stops and returns __SUCCESS__. - All the children are halted. - -To understand how the two ControlNodes differ, refer to the following table: - -| Type of ControlNode | Child returns RUNNING | -|---|:---:| -| Fallback | Tick again | -| ReactiveFallback | Restart | - -- "__Restart__" means that the entire fallback is restarted from the first - child of the list. - -- "__Tick again__" means that the next time the fallback is ticked, the - same child is ticked again. Previous siblings, which returned FAILURE already, - are not ticked again. - -## Fallback - -In this example, we try different strategies to open the door. -Check first (and once) if the door is open. - -![FallbackNode](images/FallbackSimplified.png) - -## ReactiveFallback - -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. - -In the following example, the character will sleep *up to* 8 hours. If he/she has fully rested, then the node `areYouRested?` will return SUCCESS and the asynchronous nodes `Timeout (8 hrs)` and `Sleep` will be interrupted. - -![ReactiveFallback](images/ReactiveFallback.png) - - - diff --git a/versioned_docs/version-4.0.2/nodes-library/SequenceNode.md b/versioned_docs/version-4.0.2/nodes-library/SequenceNode.md deleted file mode 100644 index 7abb714..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/SequenceNode.md +++ /dev/null @@ -1,77 +0,0 @@ -# Sequences - -A __Sequence__ ticks all its children as long as -they return SUCCESS. If any child returns FAILURE, the sequence is aborted. - -Currently the framework provides three kinds of nodes: - -- Sequence -- SequenceWithMemory -- ReactiveSequence - -They share the following rules: - -- Before ticking the first child, the node status becomes __RUNNING__. - -- If a child returns __SUCCESS__, it ticks the next child. - -- If the __last__ child returns __SUCCESS__ too, all the children are halted and - the sequence returns __SUCCESS__. - -To understand how the three ControlNodes differ, refer to the following table: - - -| Type of ControlNode | Child returns FAILURE | Child returns RUNNING | -|---|:---:|:---:| -| Sequence | Restart | Tick again | -| ReactiveSequence | Restart | Restart | -| SequenceWithMemory | Tick again | Tick again | - -- "__Restart__" means that the entire sequence is restarted from the first - child of the list. - -- "__Tick again__" means that the next time the sequence is ticked, the - same child is ticked again. Previous siblings, which returned SUCCESS already, - are not ticked again. - -## Sequence - -This tree represents the behavior of a sniper in a computer game. - -![SequenceNode](images/SequenceNode.svg) - - -## ReactiveSequence - -This node is particularly useful to continuously check Conditions; but -the user should also be careful when using asynchronous children, to be -sure that they are not ticked more often that expected. - -Let's take a look at another example: - -![ReactiveSequence](images/ReactiveSequence.svg) - -`ApproachEnemy` is an __asynchronous__ action that returns RUNNING until -it is, eventually, completed. - -The condition `isEnemyVisible` will be called many times and, -if it becomes false (i,e, "FAILURE"), `ApproachEnemy` is halted. - - -## SequenceWithMemory - -Use this ControlNode when you don't want to tick children again that -already returned SUCCESS. - -__Example__: - -This is a patrolling agent/robot that must visit locations A, B and C __only once__. -If the action __GoTo(B)__ fails, __GoTo(A)__ will not be ticked again. - -On the other hand, __isBatteryOK__ must be checked at every tick, -for this reason its parent must be a `ReactiveSequence`. - -![SequenceWithMemory](images/SequenceStar.svg) - - - diff --git a/versioned_docs/version-4.0.2/nodes-library/_category_.json b/versioned_docs/version-4.0.2/nodes-library/_category_.json deleted file mode 100644 index b5efacf..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Nodes Library", - "position": 10, - "link": { - "type": "generated-index", - "description": "List of TreeNodes natively implemented by the library" - } -} diff --git a/versioned_docs/version-4.0.2/nodes-library/images/FallbackSimplified.png b/versioned_docs/version-4.0.2/nodes-library/images/FallbackSimplified.png deleted file mode 100644 index b7334fa..0000000 Binary files a/versioned_docs/version-4.0.2/nodes-library/images/FallbackSimplified.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/nodes-library/images/ReactiveFallback.png b/versioned_docs/version-4.0.2/nodes-library/images/ReactiveFallback.png deleted file mode 100644 index 6202556..0000000 Binary files a/versioned_docs/version-4.0.2/nodes-library/images/ReactiveFallback.png and /dev/null differ diff --git a/versioned_docs/version-4.0.2/nodes-library/images/ReactiveSequence.svg b/versioned_docs/version-4.0.2/nodes-library/images/ReactiveSequence.svg deleted file mode 100644 index 7f33658..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/images/ReactiveSequence.svg +++ /dev/null @@ -1 +0,0 @@ -ReactiveSequenceReactiveSequenceApproachEnemyApproachEnemyIsEnemyVisibleIsEnemyVisible \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/nodes-library/images/SequenceNode.svg b/versioned_docs/version-4.0.2/nodes-library/images/SequenceNode.svg deleted file mode 100644 index ef7eec2..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/images/SequenceNode.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceAimAtEnemyAimAtEnemyShootShootIsEnemyVisibleIsEnemyVisibleisRifleLoadedisRifleLoaded \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/nodes-library/images/SequenceStar.svg b/versioned_docs/version-4.0.2/nodes-library/images/SequenceStar.svg deleted file mode 100644 index 335116f..0000000 --- a/versioned_docs/version-4.0.2/nodes-library/images/SequenceStar.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceWithMemorySequenceWithMemoryGoTo(C)GoTo(C)RetryUntilSuccessfulRetryUntilSuccessfulGoTo(A)GoTo(A)GoTo(B)GoTo(B) \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/_category_.json b/versioned_docs/version-4.0.2/tutorial-advanced/_category_.json deleted file mode 100644 index 07dbbc6..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Tutorial - Advanced", - "position": 4, - "link": { - "type": "generated-index", - "description": "Become a behavior tree whisperer" - } -} diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/asynchronous_nodes.md b/versioned_docs/version-4.0.2/tutorial-advanced/asynchronous_nodes.md deleted file mode 100644 index 81ab2f1..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/asynchronous_nodes.md +++ /dev/null @@ -1,265 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Asynchronous Actions - -When designing reactive Behavior Trees, it is important to understand two main concepts: - -- what we mean by **"Asynchronous"** Actions VS **"Synchronous"** ones. -- The difference between **Concurrency** and **Parallelism** in the context of BT.CPP. - -## Concurrency vs Parallelism - -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. -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: - -- The Tree execution engine is **single-threaded**. -- All the `tick()` methods are executed **sequentially**. -- If any `tick()` method is blocking, the entire flow of execution will be blocked. - -We achieve reactive behaviors through "concurrency" and asynchronous execution. - -In other words, an Action that takes a long time to execute should -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). - -An Asynchronous node may delegate this long execution either to another process -(using inter-process communication) or another thread. - -## Asynchronous vs Synchronous - -In general, an Asynchronous Node is one that: - -- May return RUNNING instead of SUCCESS or FAILURE, when ticked. -- Can be stopped as fast as possible when the method `halt()` is invoked. - -Frequently, the method **halt()** must be implemented by the developer. - -When your Tree executes an Asynchronous Action that returns RUNNING, -that state is usually **propagated backward** and the entire Tree is considered -in the RUNNING state. - -In the example below, "ActionE" is asynchronous and RUNNING; when -a node is RUNNING, usually, its parent returns RUNNING too. - -![tree in running state](images/RunningTree.svg) - -Let's consider a simple "SleepNode". A good template to get started is -the __StatefulActionNode__. - -``` cpp - -using namespace std::chrono; - -// Example of Asynchronous node that uses StatefulActionNode as base class -class SleepNode : public BT::StatefulActionNode -{ - public: - SleepNode(const std::string& name, const BT::NodeConfig& config) - : BT::StatefulActionNode(name, config) - {} - - static BT::PortsList providedPorts() - { - // amount of milliseconds that we want to sleep - return{ BT::InputPort("msec") }; - } - - NodeStatus onStart() override - { - int msec = 0; - getInput("msec", msec); - - if( msec <= 0 ) { - // No need to go into the RUNNING state - return NodeStatus::SUCCESS; - } - else { - // once the deadline is reached, we will return SUCCESS. - deadline_ = system_clock::now() + milliseconds(msec); - return NodeStatus::RUNNING; - } - } - - /// method invoked by an action in the RUNNING state. - NodeStatus onRunning() override - { - if ( system_clock::now() >= deadline_ ) { - return NodeStatus::SUCCESS; - } - else { - return NodeStatus::RUNNING; - } - } - - void onHalted() override - { - // nothing to do here... - std::cout << "SleepNode interrupted" << std::endl; - } - - private: - system_clock::time_point deadline_; -}; -``` - -In the code above: - -1. When the SleepNode is ticked the first time, the `onStart()` method is executed. -This may return SUCCESS immediately if the sleep time is 0 or will return RUNNING otherwise. -2. We should continue ticking the tree in a loop. This will invoke the method -`onRunning()` that may return RUNNING again or, eventually, SUCCESS. -3. Another node might trigger a `halt()` signal. In this case, the `onHalted()` method is invoked. - -## Avoid blocking the execution of the tree - -A **wrong** way to implement the `SleepNode` would be this one: - -```cpp -// This is the synchronous version of the Node. Probably not what we want. -class BadSleepNode : public BT::ActionNodeBase -{ - public: - BadSleepNode(const std::string& name, const BT::NodeConfig& config) - : BT::ActionNodeBase(name, config) - {} - - static BT::PortsList providedPorts() - { - return{ BT::InputPort("msec") }; - } - - NodeStatus tick() override - { - int msec = 0; - getInput("msec", msec); - // This blocking function will FREEZE the entire tree :( - std::this_thread::sleep_for( milliseconds(msec) ); - return NodeStatus::SUCCESS; - } - - void halt() override - { - // No one can invoke this method because I froze the tree. - // Even if this method COULD be executed, there is no way I can - // interrupt std::this_thread::sleep_for() - } -}; -``` - -## The problem with multi-threading - -In the early days of this library (version 1.x), spawning a new thread -looked like a good solution to build asynchronous Actions. - -That was a bad idea, for multiple reasons: - -- Accessing the blackboard in a thread-safe way is harder (more about this later). -- 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. - -For this reason, users are usually discouraged from using `BT::ThreadedAction` as a -base class. Let's have a look again at the SleepNode. - -```cpp -// This will spawn its own thread. But it still has problems when halted -class BadSleepNode : public BT::ThreadedAction -{ - public: - BadSleepNode(const std::string& name, const BT::NodeConfig& config) - : BT::ActionNodeBase(name, config) - {} - - static BT::PortsList providedPorts() - { - return{ BT::InputPort("msec") }; - } - - NodeStatus tick() override - { - // This code runs in its own thread, therefore the Tree is still running. - // This seems good but the thread still can't be aborted - int msec = 0; - getInput("msec", msec); - std::this_thread::sleep_for( std::chrono::milliseconds(msec) ); - return NodeStatus::SUCCESS; - } - // The halt() method can not kill the spawned thread :( -}; -``` - -A correct version would be: - -```cpp -// I will create my own thread here, for no good reason -class ThreadedSleepNode : public BT::ThreadedAction -{ - public: - ThreadedSleepNode(const std::string& name, const BT::NodeConfig& config) - : BT::ActionNodeBase(name, config) - {} - - static BT::PortsList providedPorts() - { - return{ BT::InputPort("msec") }; - } - - NodeStatus tick() override - { - // 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() - // and sleep for a small amount of time only (1 millisecond) - while( !isHaltRequested() && system_clock::now() < deadline ) - { - std::this_thread::sleep_for( std::chrono::milliseconds(1) ); - } - return NodeStatus::SUCCESS; - } - - // The halt() method will set isHaltRequested() to true - // and stop the while loop in the spawned thread. -}; -``` - -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 makes things more complicated and **should be avoided by default**. - -## Advanced example: client / server communication - -Frequently, people using BT.CPP execute the actual task in a different process. - -A typical (and recommended) way to do this in ROS is using [ActionLib](http://wiki.ros.org/actionlib). - -ActionLib provides exactly the kind of API that we need to implement correctly an asynchronous behavior: - -1. A non-blocking function to start the Action. -2. A way to monitor the current state of execution of the Action. -3. A way to retrieve the result or the error messages. -4. The ability to preempt/abort an action that is being executed. - -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-process communication, -with a client/server relationship between the BT executor and the actual service provider. diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/images/RunningTree.svg b/versioned_docs/version-4.0.2/tutorial-advanced/images/RunningTree.svg deleted file mode 100644 index c78c4a6..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/images/RunningTree.svg +++ /dev/null @@ -1 +0,0 @@ -SequenceSequenceFallbackFallbackActionAActionAActionEActionEActionDActionDActionFActionFActionBActionBrootrootRUNNINGRUNNINGFAILUREFAILURESUCCESSSUCCESS \ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/images/error_codes.svg b/versioned_docs/version-4.0.2/tutorial-advanced/images/error_codes.svg deleted file mode 100644 index f6bb53d..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/images/error_codes.svg +++ /dev/null @@ -1 +0,0 @@ -
MoveBase

goal={target}
return={error_code}
MoveBase...
Sequence
Sequence
RecoveryOne
RecoveryOne
_skipIf = "error_code!=1"
_skipIf = "error_co...
RecoveryTwo
RecoveryTwo
_skipIf = "error_code!=2"
_skipIf = "error_co...
\ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/images/landing.svg b/versioned_docs/version-4.0.2/tutorial-advanced/images/landing.svg deleted file mode 100644 index 9b0f94b..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/images/landing.svg +++ /dev/null @@ -1 +0,0 @@ -
LowerAltitude

drone_altitude ={altitude}
titude3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%26lt%3Bfont%20style%3D%26quot%3Bfont-size%3A%2015px%3B%26quot%3B%26gt%3B_skipIf%20%3D%20%26quot%3Bstate!%3D'LANDING_REQUESTED'%20%26quot%3B%26lt%3B%2Ffont%26gt%3B%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3BfontSize%3D18%3BfillColor%3D%23fff2cc%3BstrokeColor%3D%23d6b656%3Balign%3Dleft%3BspacingLeft%3D7%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22247.5%22%20y%3D%221670%22%20width%3D%22315%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E
LowerAltitude...
_skipIf = "state!=DO_LANDING"
_skipIf = "state!=DO_LANDING"
_post = "state= (altitude <= 0.1) ? LANDED : state"
_post = "state= (altitude <= 0.1) ? LA...
\ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/images/post_example.svg b/versioned_docs/version-4.0.2/tutorial-advanced/images/post_example.svg deleted file mode 100644 index 903335c..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/images/post_example.svg +++ /dev/null @@ -1 +0,0 @@ -
Sequence
Sequence
MoveBase

goal={target}
MoveBase...
SetBlackboard

output_key={result}
value=0
SetBlackboard...
Fallback
Fallback
ForceFailure
ForceFailure
MoveBase

goal={
target}
MoveBase...
_onSuccess = "result=OK"
_onSuccess = "result=OK"
_onFailure = "result=ERROR"
_onFailure = "result=ERROR"
SetBlackboard

output_key={result}
value=-1
SetBlackboard...
\ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/images/skipIf_example.svg b/versioned_docs/version-4.0.2/tutorial-advanced/images/skipIf_example.svg deleted file mode 100644 index cb9f58a..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/images/skipIf_example.svg +++ /dev/null @@ -1 +0,0 @@ -
IsDoorClosed
IsDoorClosed
OpenDoor
OpenDoor
Fallback
Fallback
Inverter
Inverter
OpenDoor
OpenDoor
_skipIf = "!door_closed"
_skipIf = "!door_cl...
\ No newline at end of file diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/pre_post_conditions.md b/versioned_docs/version-4.0.2/tutorial-advanced/pre_post_conditions.md deleted file mode 100644 index a62233d..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/pre_post_conditions.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Pre and Post conditions - -Leveraging the power of the scripting language -introduced in the [previous tutorial](tutorial-advanced/scripting.md), -BT.CPP 4.x introduces the concept of Pre and Post Conditions, -i.e scripts that can run either before or after the actual -__tick()__ of a Node. - -Pre and Post conditions are supported by __all__ the nodes and - don't need any modifications in your C++ code. - -:::caution -The goal of scripting is __not__ to write complex code, -but only to improve the readability of the tree and -reduce the need for custom C++ Nodes in very simple -use cases. - -If your scripts become too long, you may want to -reconsider your decision to use them. -::: - -## Pre conditions - -| Name | Description | -|-------------|---------| -| **_skipIf** | Skip the execution of this Node, if the condition is true | -| **_failureIf** | Skip and return FAILURE, if the condition is true | -| **_successIf** | Skip and return SUCCESS, if the condition is true | -| **_while** | Same as _skipIf, but may also interrupt a RUNNING Node if the condition becomes false. | - -### Example - -In previous tutorials, we saw how to build an if-then-else -logic in the tree using a fallback. - -The new syntax is much more compact: - -![](images/skipIf_example.svg) - -Previous approach: - -``` xml - - - - - - -``` - -If, instead of using a custom ConditionNode __IsDoorOpen__, -we can store a boolean in an entry called `door_closed`, the XML can be rewritten as: - -``` xml - -``` - -## Post conditions - -| Name | Description | -|-------------|---------| -| **_onSuccess** | Execute this script, if the Node returned SUCCESS | -| **_onFailure** | Execute this script, if the Node returned FAILURE | -| **_post** | Execute this script, if the Node returned either SUCCESS or FAILURE | -| **_onHalted** | Script executed if a RUNNING Node was halted | - - -### Example - -In a [tutorial about subtrees](tutorial-basics/tutorial_06_subtree_ports.md), - we saw how a specific blackboard variable was written based on the result - of __MoveBase__. - -On the left side, you can see how this logic would be -implemented in BT.CPP 3.x and how much simpler it is to use post conditions instead. -Additionally, the new syntax supports **enums**. - -![](images/post_example.svg) - -Previous version: - -``` xml - - - - - - - - - -``` - -New implementation: - -``` xml - -``` - -# Design pattern: error codes - -One of the areas where Behavior Trees may struggle, when -compared to State Machines, is in those patterns where -a different strategy should be executed based on the -result of an Action. - -Since BTs are limited to SUCCESS and FAILURE, that could -be unintuitive. - -A solution is storing the __result / error code__ in the -blackboard, but that was cumbersome in version 3.X. - -Pre conditions can help us implement more readable code, like this one: - -![error_codes.svg](images/error_codes.svg) - -In the tree above, we added an Output port __return__ to -__MoveBase__ and we conditionally take the second or third branch -of the Sequence based on the value of `error_code`. - -# Design pattern: states and declarative trees - -Even if the promise of Behavior Tree is to free us from -the tyranny of states, but the truth is that sometimes it is -hard to reason about our application without states. - -Using states can make our Tree easier. For instance, we can -take a certain branch of the tree only when the robot -(or a subsystem) is in a particular state. - -Consider this Node and its pre/post conditions: - -![landing.svg](images/landing.svg) - -This node will be executed only if the state is equal to **DO_LANDING** and, once the value of `altitude` is small -enough, the state is changed to **LANDED**. - -Note as DO_LANDING and LANDED are enums, not strings - -:::tip -A surprising side effect of this pattern is that we made our -Node more __declarative__ i.e. it is easier to move this specific Node/Subtree into a different portion of the tree. -::: diff --git a/versioned_docs/version-4.0.2/tutorial-advanced/scripting.md b/versioned_docs/version-4.0.2/tutorial-advanced/scripting.md deleted file mode 100644 index 6c04af8..0000000 --- a/versioned_docs/version-4.0.2/tutorial-advanced/scripting.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Introduction to Scripting - -Behavior Tree 4.X introduces a simple but powerful new concept: -a scripting language with XML. - -The implemented scripting language has a familiar syntax; it allows the user to quickly -read from / write to the variables of the blackboard. - -The simpler way to learn how scripting works is using the built-in action __Script__, -which was introduced in the [second tutorial](tutorial-basics/tutorial_02_basic_ports.md) - -## Assignment operators, strings and numbers - -Example: - -``` -param_A := 42 -param_B = 3.14 -message = 'hello world' -``` - -- The first line assigns the number 42 to the blackboard entry __param_A__. -- The second line assigns the number 3.14 to the blackboard entry __param_B__. -- The third line assigns the string "hello world" to the blackboard entry __message__. - -:::tip -The difference between the operator __":="__ and __"="__ is that the former -may create a new entry in the blackboard, if it doesn't exist, whilst the latter will throw -an exception if the blackboard doesn't contain the entry. -::: - -You can also use __semicolons__ to add multiple -commands in a single script. - -``` -A:= 42; B:=24 -``` - -### Arithmetic operators and parenthesis - -Example: - -``` -param_A := 7 -param_B := 5 -param_B *= 2 -param_C := (param_A * 3) + param_B -``` - -The resulting values of `param_B` is 10 and `param_C` is 31. - -The following operators are supported: - -| Operator | Assign Operator | Description | -|----------|---------|---------| -| + | += | Add | -| - | -= | Subtract | -| * | *= | Multiply | -| / | /= | Divide | - -Note that the addition operator is the only one that also works with string (used to concatenate two strings). - -## Bitwise operator and hexadecimal numbers - -These operators work only if the value can be cast to -an integer number. - -Using them with a string or real number will -cause an exception. - -Example: - -``` -value:= 0x7F -val_A:= value & 0x0F -val_B:= value | 0xF0 -``` - -The value of `val_A` is 0x0F (or 15); `val_B` is 0xFF (or 255). - -| Binary Operators | Description | -|----------|---------| -| \| | Bitwise or | -| & | Bitwise and | -| ^ | Bitwise xor | - -| Unary Operators | Description | -|----------|---------| -| ~ | Negate | - -## Logic and comparison operators - -Operators which return a boolean. - -Example: - -``` -val_A := true -val_B := 5 > 3 -val_C := (val_A == val_B) -val_D := (val_A && val_B) || !val_C -``` - -| Operators | Description | -|----------|---------| -| true/false | Booleans. Castable to 1 and 0 respectively | -| && | Logic and | -| \|\| | Logic or | -| ! | Negation | -| == | Equality | -| != | Inequality | -| < | Less | -| <= | Less equal | -| > | Greater | -| >= | Greater equal | - - -### Ternary operator **if-then-else** - -Example: - -``` -val_B = (val_A > 1) ? 42 : 24 -``` - -## C++ example - -Demonstration of the scripting language, including how to use enums to -represent **integer values**. - -The XML: - -``` xml - - - -