Skip to content

Releases: BehaviorTree/BehaviorTree.CPP

[4.9.0]: 60 issues fixed, new TryCatch node and MUCH MORE

11 Feb 10:02

Choose a tag to compare

Changelog: 4.9.0 (since 4.8.4)

New Features

  • New node TryCatch: similar to a Sequence, but with a "cleanup" node that is execute only if the Sequence failed or was halted. A feature requested by many users!

  • Polymorphic shared_ptr port support. Nodes producing shared_ptr<Derived> can now connect to ports expecting shared_ptr<Base>. Register inheritance relationships with factory.registerPolymorphicCast<Derived, Base>() and the library handles upcasting/downcasting transparently, including transitive chains (e.g. Sphynx -> Cat -> Animal). Issue #943, PR #1107.

  • Exception tracking in nodes. When an exception is thrown during tick(), it is now wrapped in a NodeExecutionError that includes the failing node's name, path, and registration name. Issue #990, PR #1106.

  • Replaced lexy scripting dependency with a hand-written Pratt parser. The lexy third-party dependency has been removed and replaced with a custom tokenizer and recursive-descent Pratt parser. This reduces compilation time, binary size, and eliminates a non-trivial dependency. PR #1099.

Bug Fixes

  • EntryUpdatedDecorator::halt() not halting its child. The decorator was missing the call to DecoratorNode::halt(), leaving the child node running when the decorator was halted. Issue #1111, PR #1112.

  • Use-after-free when factory destroyed before tree. After createTree(), node manifest pointers pointed into the factory's internal map. If the factory was destroyed before ticking, these became dangling pointers. Tree::remapManifestPointers() now re-points each node's manifest to the tree's own copy. Issue #1046, PR #1081.

  • createTreeFromText could not find previously registered subtrees. createTreeFromText() and createTreeFromFile() used a temporary parser that couldn't see subtrees registered via registerBehaviorTreeFromText()/registerBehaviorTreeFromFile(). They now use the factory's shared parser. Issue #880, PR #1105.

  • Groot2Publisher destructor infinite loop. The destructor could hang indefinitely when the ZMQ server thread was waiting on recv(). Fixed by calling zmq_context.shutdown() to interrupt blocking receives. Issue #1057, PRs #1100, #1058.

  • Recursive subtree cycles now detected at parse time. Previously, mutually-recursive subtrees caused a stack overflow at tree instantiation. The parser now tracks an ancestor set and throws a clear RuntimeError when a cycle is detected. Issue #979, PR #1085.

  • Deeply-nested XML no longer causes stack overflow. A depth limit (256) is now enforced during XML parsing and tree instantiation. Issue #672, PR #1091.

  • Script parser left-associativity for arithmetic operators. Expressions like A - B + C were evaluated as A - (B + C) instead of (A - B) + C. Issue #1029, PR #1069.

  • Mock substitution hangs when TestNodeConfigs is absent. An empty TestNodeConfigs object was always created, causing mock nodes to be registered even when no test configuration was intended, which led to infinite loops. Issue #930, PR #1086.

  • Segfault when substituting a SubTree node. When a substitution rule replaced a SubTree with a TestNode, setSubtreeID was called on a null pointer. Issue #934, PR #1083.

  • BehaviorTreeFactory could not be returned by value. Move constructor and move assignment were defaulted in the header where PImpl is an incomplete type, preventing compilation. Issue #937, PR #1082.

  • getLockedPortContent creates entry for default-remapped ports. Issue #942, PR #1078.

  • getInput() failed for plugin custom types. When a node is loaded as a plugin, the convertFromString<T> specialization defined in the plugin is not visible to the main application. getInput<T>() now uses the StringConverter stored in PortInfo instead of calling convertFromString<T>() directly. Issue #953, PR #1104.

  • parseString now supports enums with convertFromString specializations. Issue #948, PR #1075.

  • LoopNode now accepts std::vector<T> in addition to SharedQueue<T>. Issue #969, PR #1074.

  • json: prefix handled in vector convertFromString specializations. When a port of type std::vector<T> had a default empty value {}, toStr() would produce "json:[]" which was not parsed correctly by the explicit specializations. Issue #982, PR #1073.

  • JsonExporter use-after-move in vector converter registration. The addConverter method moved converter before vector_converter captured it, causing std::bad_function_call. Issue #989, PR #1090.

  • debugMessage now shows type info for remapped subtree entries. Issue #408, PR #1079.

  • DelayNode ignoring delay_msec when created from XML. PR #1097.

  • DelayNode missing read_parameter_from_ports_ initialization. PR #1103.

  • Misleading static_assert when extra constructor args have wrong type. The compiler now reports that the extra arguments don't match instead of the misleading "you MUST add a constructor" message. Issue #837, PR #1098.

  • Windows build issues. Removed redundant TINYXML2_DEBUG definition that caused Debug mode crashes on VS 2022 and added MSVC runtime propagation in conanfile.py. Issues #762, #869, #836, PR #1089.

  • std::from_chars compilation failure on older g++ versions. PR #1110.

  • Fix issue #861. Issue #861.

Improvements

  • Removed deprecated std::aligned_storage usage. The type was deprecated in C++23 and could cause warnings in client code. PR #1061.

  • Improved PreCondition documentation. Added clarifying comments about _failureIf, _successIf, _skipIf, and _while evaluation semantics. Issue #917.

  • Generate .clangd in PROJECT_SOURCE_DIR. This allows BT.CPP to be used as a submodule or via FetchContent/CPM without rewriting the parent project's .clangd file. PR #1059.

  • Added vcpkg installation instructions. PR #421.

  • Improved test suite quality and coverage. Added 50+ new tests covering basic types, IfThenElseNode, WhileDoElseNode, loggers, decorators, LoopNode, and reactive nodes. Tests now run faster with reduced sleep durations. PR #1102.

  • Added Doxygen welcome page with organized navigation, quick links to core classes, and complete lists of built-in nodes.

4.8.4: New validation rules (might be a breaking change)

09 Jan 11:38

Choose a tag to compare

What's Changed

  • Added more validation rules to the names of Nodes and Ports.
  • Fix XML validation to prevent two "fullpaths" to be the same. Some users might need to update their XML.
  • More complex Groot2 publisher example to reproduce the issue with arrays in the blackboard.
  • Added a new command line tool to generate the XML model file that Groot2 needs.
  • Some improved documentation

4.8.3: Lint all the things!

30 Dec 09:25

Choose a tag to compare

Highlights

The most notable change, that will also affect future PRs, is the introduction of static analysis through clang-tidy.

This allowed me to improve the consistency and readability of the code and to find some subtle potential bugs.

From now on, contributors will need run clang-tidy locally on their machine using the script run_clang-tidy.sh, before submitting their PR.

What's Changed

New Contributors

Full Changelog: 4.8.2...4.8.3

4.8.2: fix issue with TinyXML2 on ROS2

30 Oct 05:40

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 4.8.1...4.8.2

4.8.0: ASAN + TSAN

14 Oct 18:52

Choose a tag to compare

4.8.0 (2025-10-14)

  • fix memory leak
  • fix thread safety issues
  • Improve error message
  • Add support for sanitizers including some GHAs
  • Remove unused conan.cmake (#1016 <https://github.com/BehaviorTree/BehaviorTree.CPP/issues/1016>_)
  • Improve handling of dependencies (#1012 <https://github.com/BehaviorTree/BehaviorTree.CPP/issues/1012>_)
  • update tinyxml to version 11.0
  • fix potential compilation errors
  • compile for c++ 17 (#1013 <https://github.com/BehaviorTree/BehaviorTree.CPP/issues/1013>_)
  • Contributors: Davide Faconti, Eric Riff

4.7.0

24 Apr 07:37

Choose a tag to compare

Finally!

It was about time to do a new release. Thanks to all the amazing contributors that submitted issues and Pull Requests.

Noteworthy changes

  • From now on, when registering a custom types T to the JSON converter, you will automatically add a converter to/from std::vector<T>. See #965

  • Behavioral change in PreconditionNode. See #904

  • TestNode constructor arguments changes. See #967

What's Changed

New Contributors

Full Changelog: 4.6.2...4.7.0

4.6.2

26 Jun 10:02

Choose a tag to compare

Noteworthy

  1. Re-added support for custom JSOn convertion functions.
  2. Fix in minitrace logger
  3. Removed singleton protection from various Loggers
  4. nonstd::expectedupdated
  5. More checks in VerifyXML to check that Subtree don't use names already recistered and regular Nodes
  6. New callback TickMonitorCallback called at each tick
  7. Fix ament_export_targets

4.6.1: Small bug fix and flatbuffers deprecation

20 May 09:10

Choose a tag to compare

The main change is a bug fix related to #823

Additionally, the old FileLogger and the flatbuffers files have been deprectaed and removed from the public API

4.6: Lot of new features and tutorials

28 Apr 14:17

Choose a tag to compare

This release includes a lot of important changes. This is a non comprehensive list.

With my great surprise, this release seems to be ABI compatible with 4.5.2

Default behavior of ReactiveSequence and ReactiveFallback

ReactiveSequence and ReactiveFallback are unfortunately hard to use correctly.
There was a long discussion about what should happen when one of these nodes has multiple asynchronous children and there is no easy answer.

The default behavior is not more similar to version 3.8, but this also means that users must be very careful.
Read this issue for details: #755

The "global blackboard" idiom

We introduce here a new idiom and syntax: the global blackboard.
Usually each Subtree (including the main tree) has its own blackboard, isolated from the others, unless we do remapping.

We additionally provide a top-level blackboard that can be accessed from everywhere, without any manual remapping, using the prefix "@"

See example: https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/examples/t19_global_blackboard.cpp

Entries of the blackboard are now timestamped!

We added a timestamp and a sequence number to each entry in the blackboard (both updated when we set the value).

This allow use to determine if the value we are reading in the blackboard is "new" (since the last time we accessed it) or "obsolate".

We added the methods Blackboard::getStamped and TreeNode::getInputStamped.

Additionally, we added 3 new builtin nodes that use this functionality:

  • SkipUnlessUpdated: decorator that skip the execution of the children unless an entry was updated, since the last time.
  • WaitValueUpdate: decorator that remains in RUNNING state, unless an entry was updated. Executes the child if it did.
  • WasEntryUpdated: action that returns SUCCESS if an entry was updated, FAILURE otherwise.

String + number concatenation in the scripting language

Details: #802

We use the operator ".." to concatenate strings and numbers (inspired by Lua).
Give this:

prefix := 'value_';
val := 42;
str:= prefix .. val

The variable "str" should contain the string "value_42"

Enhanced SQlite logger

We added a method to send comands directly to the database and to append extra information to a state transition in the Transitions table.

See example https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/examples/t16_sqlite_log.cpp

Refactored API to register JSON convertions.

We simplified the way a custom type can be converted from/to JSON. See the example here:
https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/examples/t11_groot_howto.cpp#L13-L27

Blackup / restore a blackboard state.

Related somehow to the JSON convertion mentioned earlier.
We add some methods to save/load the state of a blackboard. usefull if you want to reset it correctly, withour destrying it and rebuilding it from scratch.

See this tutorial: https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/examples/t17_blackboard_backup.cpp

convertToString

Added more convertToString specializations

4.5.2: Bug fixes

07 Mar 11:53

Choose a tag to compare

Bug fix

This release fix some important bugs in the scripting language, most notably in the equal operators, that now support enums and boolean more correctly.

New features

The way default port values is specified is also being changed, to include default pointers to the blackboard too.

Example of how ports with complex types can be initialized.
Note that the case represented in pointC requires the implementation of convertFromString<Point2D>()

  static PortsList providedPorts()
  {
    return {BT::InputPort<Point2D>("input", "no default value"),
            BT::InputPort<Point2D>("pointA", Point2D{1, 2}, "default value is [1,2]"),
            BT::InputPort<Point2D>("pointB", "{point}", "default value inside blackboard {point}"),
            BT::InputPort<Point2D>("pointC", "5,6", "default value is [5,6]"),
            BT::InputPort<Point2D>("pointD", "{=}", "default value inside blackboard {pointD}")};
  }

But this new syntax is still experimental and will become stable in release 4.6.0