Something went wrong. Try again.
Behaviour Tree for memory constrained devices. icpmoles.tngl.io/orchard
Something went wrong. Try again.
Files
Latest
- C++ 44%
- C 35%
- Python 12%
- CMake 4%
- Shell 3%
- 1 more language 2%
README.md
Orchard #
Behavior trees for microcontrollers and embedded systems, in plain C.
A behavior tree describes what a device should do as a tree of small decisions: check this, then do that, otherwise fall back to something else. Orchard runs these trees on anything from a Cortex-M0+ under Zephyr to a Linux or QNX system. You write the leaves in C (a condition that reads a button, an action that drives an LED) and describe how they fit together in a tree file. Change the file and reload it, and the device behaves differently, without rebuilding the firmware.
{
"root": {
"type": "reactive_fallback",
"children": [
{ "type": "reactive_sequence", "children": [
{ "type": "condition", "name": "button", "arg": 0 },
{ "type": "action", "name": "led_on", "arg": 1 }
]},
{ "type": "action", "name": "led_off", "arg": 1 }
]
}
}
Properties #
- No heap. Nodes live in a pool that the application allocates, 28 bytes each on 32-bit targets (32 with the 64-bit clock). RAM use is the pool, one 40-byte tree structure and, only while loading, the file buffer.
- Small, portable core. C99, depending only on the freestanding headers and
<string.h>. The OS is reached through two functions, a monotonic clock and a file read, and both are optional. From C++,orchard.hppchecks trees at compile time. - Errors at load time, not at run time. Unknown node types, unknown leaf names and malformed trees are rejected with a line, a column and a message. Leaf names are resolved to function pointers once, so a tick never compares strings.
- JSON or C. Load trees from a file at run time, or build fixed ones in C with the same checks, and leave the JSON parser out of the image.
- Bounded stack. Parsing recursion is capped at 24 levels of nesting, ticking recursion is the depth of the tree.
- Observable. Every node keeps the status of its last tick. Print it as text or, on Zephyr, read it live from a host over MCUmgr (SMP).
- Platforms. Zephyr, as a module using the native kernel and file system APIs, and POSIX.1-2008, tested on Linux and on QNX SDP 8.0.
Getting started #
- Introduction: repository layout, node types, a minimal program, and building for Zephyr and POSIX
- Documentation: tree format, C API, platforms, serialization formats and the SMP group. An HTML and PDF version with the API reference is built with Doxygen, see Building the documentation.
- Examples: examples/zephyr (Raspberry Pi Pico, buttons and PWM LEDs), examples/posix (the same tree in a terminal) and examples/cpp (the same tree from C++)
Background #
- Michele Colledanchise and Petter Ögren, Behavior Trees in Robotics and AI: An Introduction. The standard introduction to behavior trees: the node types, why reactive trees suit robots, and how they compare to state machines.
- Behavior tree (artificial intelligence, robotics and control) on Wikipedia, a shorter overview.
Orchard's sequence, fallback and their reactive variants follow the definitions in
the book.
License #
MIT, see LICENSE.
Credits #
Favicon from Mona Font (OFL)