Skip to content

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

Latest

Choose a tag to compare

@facontidavide facontidavide released this 11 Feb 10:02

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.