Skip to content

Port PickNik's fork onto upstream BehaviorTree.CPP 4.9.0 - #29

Draft
dv-picknik wants to merge 162 commits into
mainfrom
port/17640-btcpp-4.9.0
Draft

Port PickNik's fork onto upstream BehaviorTree.CPP 4.9.0#29
dv-picknik wants to merge 162 commits into
mainfrom
port/17640-btcpp-4.9.0

Conversation

@dv-picknik

Copy link
Copy Markdown
Member

Advances the fork from the 4.7.2 line to upstream 4.9.0, which is what nav2's Jazzy debs are built against. This is the fix #20928 concluded was necessary — the full commit-by-commit breakdown is on moveit_pro#17640.

11 commits on top of upstream tag 4.9.0, one per feature. 511/511 tests pass, zero compiler warnings.

Why a replay and not a merge

The fork's history contains duplicate commits — PR #15 rebased main onto the upstream mirror and then merged the pre-rebase line back in, so most features exist twice. A merge produces one unreviewable blob. Replaying commit-by-commit also answers the question that actually matters — is this patch still needed on 4.9.0? — and for 9 of the 22 the answer was no.

What this closes

All three ABI breaks from #20928:

# Break How 4.9.0 closes it
1 NodeConfig::auto_remapped inserted mid-struct, shifting manifest and everything after by 8 bytes Ours to place — appended, offsets verified byte-identical to stock
2 Fork reverted upstream BehaviorTree#965, dropping JsonExporter::from_json_array_converters_ We stop reverting it; the member is upstream's again
3 SimpleString move ctor gained noexcept in 4.9.0, flipping linb::any between heap and inline storage Free — we are 4.9.0

Break #3 is why the layout-patch approach on fix/20928-btcpp-abi was abandoned: sizes, offsets and mangled names are all identical, so no layout diff can see it. That branch is now retired.

ABI break #1, verified by measurement

offsetof against a stock 4.9.0 checkout, same toolchain:

member stock 4.9.0 original fork this branch
other_attributes 144 152 144
manifest 200 208 200
uid 208 216 208
path 216 224 216
pre_conditions 248 256 248
post_conditions 296 304 296

⚠️ git cherry-pick auto-merges tree_node.h with no conflict and silently reinserts the member mid-struct. Resolving conflicts carefully is not enough to avoid reshipping the bug. A one-line offsetof assertion in the suite would have caught #20928 at the commit that introduced it — worth adding separately.

Packaging collision found

4.9.0 adds tools/bt_nodes_model.cpp/opt/ros/*/bin/bt4_nodes_model. Stock ros-jazzy-behaviortree-cpp 4.9.0 installs that exact path, so shipping it unrenamed is a hard dpkg "trying to overwrite" failure — and per the coexistence design's own pitfall section, a path-exclude does not help, because dpkg's ownership check runs before the exclude filter. Renamed to bt4_picknik_nodes_model. This block also auto-merges silently, below the conflict region.

Conversely the LEXY_ENABLE_INSTALL guard is now obsolete — 4.9.0 deleted 3rdparty/lexy outright, and every remaining vendored tree is STATIC/INTERFACE with no install() rule.

Testing

  • pixi run build && pixi run test511/511, zero warnings
  • Library builds as libbehaviortree_cpp_picknik.so.4.9.0 with versioned soname .so.4.9
  • CMake configure yields behaviortree_cpp_picknik, bt4_picknik_plugin_manifest, bt4_picknik_nodes_model
  • NodeConfig offsets measured against a stock 4.9.0 worktree

One upstream test, PortTest.LoopNodeAcceptsVector_Issue969, failed mid-port: the fork's setOutput stores vectors as vector<Any>, which upstream's new LoopNode doesn't recognise. A real fork-vs-upstream collision, not a merge artifact — fixed in its own commit.

Decisions that want a reviewer

  1. JSON primitive wire format. Fork emits {"__type":"double","value":3.14}; stock emits bare 3.14. Kept the fork's toJson (the Pro UI consumes it), made fromJson accept both. The tagged path is gated on __type naming a primitive rather than on a value field merely existing — otherwise a registered custom type with its own value member, or the diagnostic blob the non-registered-type commit emits, imports silently as a std::string.
  2. Vector→string format. Fork gives 1;2;3;4, stock gives json:[1,2,3,4]; empty vector "" vs json:[]. Both round-trip. The fork form additionally covers types with a toStr<T> specialization but no JSON converter (vector<float>), which stock throws on. Easiest thing to drop if nothing downstream needs ;.
  3. '5' .. 3 returns an empty Any — the widened are_numbers guard steals the concat branch. Live in the fork today; the port neither introduces nor fixes it. One-token fix (&& op != concat); left alone to keep the port faithful.

Blocking risk before this ships

4.9.0 rejects . / \ : < > & " ' * ? | in port names and BehaviorTree/SubTree IDs (findForbiddenChar + validateModelName). A port named request.name that works today throws at tree-load time. Needs a sweep of moveit_pro and moveit_pro_example_ws Objective XML — a literal-only grep is not enough, since most Behaviors declare ports via kPortID* constants.

Also outstanding, none blocking review of this branch:

  • Subtree ports now split across input_ports/output_ports; bt_flatbuffer_helper.h iterates only input_ports, so Groot1 serialization omits subtree OUTPUT ports.
  • {=} expansion now applies to every node type, not just subtrees — a deliberate widening.
  • Soname .so.4.7.so.4.9: apt_build_farm needs a git_sha bump with revision reset to 1, Dockerfile pin → 4.9.0-1noble, and every Pro binary rebuilt.
  • 4.9.0's package.xml adds libsqlite3-dev, libzmq3-dev, tinyxml2, tinyxml2_vendor.
  • Re-run the zero-file-intersection deb proof against a 4.9.0-derived build — both sides now derive from the same tree, so any missed scoping is a direct hit.

Refs PickNikRobotics/moveit_pro#17640, PickNikRobotics/moveit_pro#20928

🤖 Generated with Claude Code

https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX

redvinaa and others added 30 commits July 31, 2025 15:18
Signed-off-by: redvinaa <redvinaa@gmail.com>
Signed-off-by: redvinaa <redvinaa@gmail.com>
Signed-off-by: redvinaa <redvinaa@gmail.com>
Co-authored-by: ahuo <ahuo2865189826@gmail.com>
…e#1007)

* fix: use dynamically growing error buffer in ParseScript

* style: format code

* fix: use dynamically growing error buffer in ValidateScript

---------

Co-authored-by: ahuo <ahuo2865189826@gmail.com>
…lite3.h won't be found (BehaviorTree#1002)

Co-authored-by: alejandro.suarez@omron.com <alejandro.suarez@omron.com>
* Refactor VerifyXML to clarify logic

- Reduces duplication in VerifyXML by handling the ID check for built-in
node types up front so they can then be definitively looked up in the
registered nodes.

- Enhances error messaging in VerifyXML by using *either* the node name
  *or* the ID, depending on which is appropriate, instead of leaving
users guessing "which Decorator is wrong"

- Fixes custom Action and Condition nodes using shorthand syntax not
  being properly verified

- Fixes `<Control ID="ReactiveSequence"/>` not being verified with the
  same logic as `<ReactiveSequence/>`

- Fixes `<Action ID="MyAction"/>` not triggering a behavior lookup when
  `<MyAction/>` would.

* fix tests that were failing due to bad assumptions
* Support using minitrace from conan

* Support using tinyxml2 from conan

* Add support for using minicoro from conan

* Add support for using flatbuffers from conan

* Create separate targets for each 3rdparty lib not yet supported by conan so we can avoid exposing the whole 3rdparty folder on target_include_directories
Since this can create some confusion around which headers are actually being included -- the ones from that folder or the ones from conan?
Also fixes the include dirs by using ${CMAKE_CURRENT_SOURCE_DIR} instead of "."

* Fix builds
For whatever reason including zmq.hpp before zmq_addon.hpp (which does include zmq.hpp internally) breaks builds

* Do not include the whole 3rdparty folder, only link in what we need

* Use the regular lexy target

* Do not expose the whole 3rdparty folder as a include_directory

* Add options to opt-out of vendored libraries

* This was shared across both code paths, conan_build.cmake and ament_build.cmake
So it is better to keep this on a single place

* Keep all the find_package calls on the toplevel CMakeLists

* SQLite3 is actually a dependency of cpp-sqlite

* Fix include dirs of the vendored minicoro and flatbuffers

* Define libzmq cmake target on FindZeroMQ to match the conan package

* Improve message. This code path doesn't really mean we're using conan, it just means we're not using ament.

* Use the python version of conanfile.py so we can set the CMake options needed to opt out of vendored dependencies

* Address pre-commit complains

* Use conanfile.py across the board

* Do not look for ZeroMQ directly as it is a dependency of cppzmq
Also only look for cppzmq if BTCPP_GROOT_INTERFACE

* Keep a single copy of zmq.hpp
This header is part of the cppzmq library so it lives on 3rdparty/cppzmq. But for whatever reason there was
another version of this header here. Furthermore it was a differnt version of the library.

* Leave a FIXME for posterity
This target was silently being skiped, not it is explicit

* Leave comment for posterity

* Remove empty line

* Remove unneeded line

* Remove uneeded line

* Remove empty line

* Revert unintentional changes

* Use cmake_layout to support multiconfig

* Update toolchain path on cicd

* Emtpy commit to re-trigger CI

* Use cppzmq from conan

* Use cmake presets on conan builds

* It looks like in windows the preset is called conan-default

* It looks like the preset is only called default for config?

* Fix tests path in windows

* Use lexy from conan

* Force cppstd to 17, conan profile detect uses 14

* Try to fix windows builds

* Remove wildcards cmake options, it has been removed on master

* Update changes after cpp-sqlite removal
this modern approach registers many individual tests instead of a single monolitic test
so if one fails the rest continue running which allows the developer to flag multiple
failing tests on a single run
It also speeds up testing since tests run in parallel
facontidavide and others added 27 commits February 4, 2026 13:24
- Add run_clang_tidy_hook.sh for pre-commit integration
  - Skips if clangd-21 not installed
  - Skips if compile_commands.json not found
  - Runs only on modified files
  - Fails on errors

- Fix clang-tidy warnings in exception tracking code:
  - Use anonymous namespace instead of static for tick_stack_
  - Add deleted move operations to TickStackGuard

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…avior

Demonstrates that regular Sequence does NOT re-evaluate conditions
while a child action is RUNNING, whereas ReactiveSequence DOES.
This is expected behavior - users should use ReactiveSequence when
they need conditions to be re-evaluated every tick.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…-sequence-vs-reactive

Add test for Issue BehaviorTree#819: Sequence vs ReactiveSequence behavior
When a new commit is pushed to a PR, any running jobs for that PR
will be automatically canceled, reducing CI queue time and noise.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…Tree#1109)

* Fix clang-tidy warnings across tests, examples, and samples

- Fix uninitialized std::array counters across test files
- Add default member initializers in test node classes
- Add anonymous namespaces for file-local functions
- Add NOLINT comments for intentional patterns
- Fix implicit bool conversions
- Fix self-assignment in copy assignment operators
- Add Rule of Five compliance to test fixtures
- Exclude optional-dependency files from clang-tidy (gmock, zmq, flatbuffers)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix heap corruption caused by thread_local tick stack

The thread_local std::vector used for exception backtraces caused heap
corruption on Windows DLLs and when running all tests in a single
process. Simplified NodeExecutionError to store only the failing node
info instead of a full tick backtrace, removing the thread_local
entirely.

Also disabled Groot2Publisher tests (to be addressed separately) and
fixed Groot2Publisher destructor cleanup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…sions. (BehaviorTree#1110)

Co-authored-by: Davide Faconti <davide.faconti@gmail.com>
…aviorTree#1107)

Enable passing shared_ptr<Derived> to ports expecting shared_ptr<Base>
without breaking ABI compatibility. Users register inheritance
relationships at runtime via BehaviorTreeFactory::registerPolymorphicCast,
and the system handles upcasting/downcasting transparently.

Key components:
- PolymorphicCastRegistry: thread-safe registry for inheritance
  relationships with transitive cast support (e.g. Sphynx->Cat->Animal)
- BehaviorTreeFactory owns the registry, shares it with Blackboards
- Blackboard::tryCastWithPolymorphicFallback: public Expected-returning
  API used by both Blackboard::get and TreeNode::getInputStamped
- XML parser validates port compatibility including polymorphic types
- Downcasts allowed at parse-time, checked at runtime via
  dynamic_pointer_cast

Design decisions:
- Registry uses shared_mutex for read-heavy workload
- Error propagation via nonstd::expected<T, std::string>
- No circular includes: safe_any.hpp includes registry directly
- All polymorphic tests consolidated in gtest_polymorphic_ports.cpp

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…#1112)

EntryUpdatedDecorator::halt() was missing the call to DecoratorNode::halt(),
which meant the child node was never halted when the decorator was halted.

Fixes BehaviorTree#1111

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
New control node that executes a try-child and, on failure, runs a
catch-child as recovery. Supports configurable catch_on_halt behavior,
async children, and re-entry after RUNNING states.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add null check for subtree_id when <SubTree> in <TreeNodesModel> is
  missing the ID attribute — now throws descriptive RuntimeError instead
  of crashing with UB (null pointer as map key)
- Fix variable name shadowing: rename inner-loop 'name' to 'port_name'
  to avoid shadowing the outer structured binding

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix 6 data races in Blackboard, verified with ThreadSanitizer (clang-21):

- set() new-entry path: wrote value/sequence_id/stamp without
  entry_mutex after createEntryImpl — add scoped_lock on entry_mutex
- set() existing-entry path: held raw reference after unlocking
  storage_mutex_, risking use-after-free if concurrent unset() erases
  the entry — copy shared_ptr before unlocking
- cloneInto(): read/wrote entry members without entry_mutex —
  add scoped_lock on src and dst entry mutexes
- ImportBlackboardFromJSON(): wrote entry->value without any lock —
  add scoped_lock on entry_mutex
- debugMessage(): iterated storage_ without storage_mutex_ —
  add unique_lock
- getKeys(): iterated storage_ without storage_mutex_ —
  add unique_lock

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch storage_mutex_ from std::mutex to std::shared_mutex so that
concurrent readers (getEntry, getKeys, debugMessage, set initial lookup,
cloneInto snapshot) no longer block each other.  Write operations
(createEntryImpl, unset, clear, cloneInto insert/erase) still take
exclusive locks.

Also remove the dead entry_mutex_ recursive_mutex and its deprecated
entryMutex() accessor — no callers exist in the codebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix Blackboard thread-safety bugs and XML null pointer dereference
…ut<T>` to convert `vector<BT::Any>` type to `vector<T>`

* Support vector<Any> -> vector<typename T::value_type> conversion

Don't check port type alignment for vector<Any>

* Convert vector to vector<Any> before placing on the blackboard

Also update checks to allow mismatch when a port was declared as a
vector<T> and we have an input port that takes it in as a vector<Any>

* Update include/behaviortree_cpp/blackboard.h

Co-authored-by: Nathan Brooks <nbbrooks@gmail.com>

* Fix formatting with pre-commit

* Add unit test passing a vector through ports

---------

Co-authored-by: Nathan Brooks <nbbrooks@gmail.com>
(cherry picked from commit 663cfa3)
This aligns with how custom types are represented by the JsonExporter.

* Update both toJson & fromJson functions in the JsonExporter
* Add & update tests

Co-authored by: David Sobek <david.sobek@picknik.ai>

(cherry picked from commit c06e058)
Signed-off-by: Paul Gesel <paul.gesel@picknik.ai>
(cherry picked from commit 79e09ed)
Port-integration fix, no upstream counterpart.

Upstream 4.9.0's LoopNode (issue BehaviorTree#969) accepts SharedQueue<T>, std::vector<T>,
or a string in its 'queue' port. The fork's setOutput<std::vector<T>>() stores
vectors as std::vector<BT::Any>, so none of those casts match and LoopNode
throws "port 'queue' must contain either SharedQueue<T>, std::vector<T>, or a
string". This is a genuine fork-vs-upstream collision, not a merge artifact:
upstream's test PortTest.LoopNodeAcceptsVector_Issue969 fails without this.

Unwrap std::vector<BT::Any> element-by-element back to T, erroring with the
element's own cast failure rather than the generic message when a member does
not fit the loop type.

Refs PickNikRobotics/moveit_pro#17640

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
Use type_ID instead of element->Name() so the error prints the actual
behavior name (e.g. GetEpickObjectDetectionStatus) rather than the
generic XML tag (e.g. Action). Use element->GetLineNum() instead of
att->GetLineNum() for a correct line number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 4d87c12)
Ported from fork commits 2a0f48f + 5596408. Upstream 4.9.0 has not adopted
an equivalent: it still re-parses _autoremap inside recursivelyCreateSubtree,
and still assigns every subtree remapping to config.input_ports regardless of
the direction declared in <TreeNodesModel>.

Deliberate divergence from the original fork commits: NodeConfig::auto_remapped
is APPENDED after post_conditions rather than inserted after output_ports.
The original placement shifted other_attributes/manifest/uid/path/pre_conditions/
post_conditions by 8 bytes, and because TreeNode::getInput<T>() is header-inlined
into callers and dereferences config().manifest, binaries built against stock
headers read that pointer out of the middle of other_attributes and crash. That
was ABI break #1 in moveit_pro#20928. Appending restores every offset:

  member            stock 4.9.0   original fork   this commit
  other_attributes  144           152             144
  manifest          200           208             200
  uid               208           216             208
  path              216           224             216
  pre_conditions    248           256             248
  post_conditions   296           304             296

Verified with offsetof against a stock 4.9.0 checkout, not by inspection.

Dropped from the original commits: the tests/CMakeLists.txt hunk (targeted a
catkin branch and a test-target name 4.9.0 no longer has) and the gmock
dependency it existed to pull in -- the two EXPECT_THAT matchers are rewritten
as plain gtest, so the fork adds no build-time dep upstream lacks.

Refs PickNikRobotics/moveit_pro#17640, PickNikRobotics/moveit_pro#20928

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
Squash of fork commits be74f60 + 19bfaf2. They must land together: without
19bfaf2's empty() guard, `--value.end()` on an empty vector is UB, so
be74f60 alone is a latent crash rather than a separable feature.

Upstream 4.9.0 has no toStr overload for std::vector<T>, but it does stringify
vectors via the toJsonString fallback plus the BehaviorTree#965 JSON vector converters, so
this is a change of output format, not a new capability, for the four
registered element types:

  vector<int>{1,2,3,4}   stock: json:[1,2,3,4]   fork: 1;2;3;4
  vector<string>{}       stock: json:[]          fork: ""
  vector<float>          stock: throws LogicError  fork: 1.000000;2.000000

Both round-trip -- 4.9.0 taught convertFromString<vector<T>> to strip a "json:"
prefix and it still accepts ';'-delimited input. The fork form additionally
covers element types with a toStr<T> specialization but no JSON converter,
which stock 4.9.0 throws on.

Dropped from the original commits: the throw_unspecialized_error lambda. The
compiler cannot see that a lambda call always throws, so it warns
"control reaches end of non-void function" at both call sites and the
fall-through is UB. Upstream's inline throw is kept instead.

Refs PickNikRobotics/moveit_pro#17640

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
Ported from fork commits 8972919 + b8d70d6, rebuilt against 4.9.0's build
system rather than cherry-picked -- upstream moved BTCPP_*_DESTINATION into the
top-level CMakeLists.txt and rewrote tools/CMakeLists.txt, so the original
hunks no longer apply.

Keeps the coexistence invariants from
docs_nonpublic/design/behaviortree-cpp-fork-coexistence.md: scoped ament
package / library / include root, versioned soname (now .so.4.9, was .so.4.7),
disjointly-named bin/ tools, and the BTCPP_PICKNIK_FORK compile-time sentinel.

New in 4.9.0 and therefore NOT covered by the original rename commits:
upstream added tools/bt_nodes_model.cpp, installing /opt/ros/*/bin/bt4_nodes_model.
Stock ros-jazzy-behaviortree-cpp 4.9.0 installs that exact path, so shipping it
unrenamed is a hard dpkg "trying to overwrite" failure -- and a path-exclude
does not help, because dpkg's ownership-conflict check runs before the exclude
filter. Renamed to bt4_picknik_nodes_model. Note git cherry-pick auto-merges
this block below the conflict region, so it survives a careless resolution
silently; moveit_pro's Dockerfile assertion would have caught it only after a
full image build.

Dropped as obsolete on 4.9.0:
- the LEXY_ENABLE_INSTALL block -- 4.9.0 deleted 3rdparty/lexy outright,
  replacing it with a hand-written tokenizer/parser. Every remaining vendored
  tree (tinyxml2, minitrace, minicoro, flatbuffers, cppzmq, doxygen-awesome-css)
  is STATIC or INTERFACE with no install() rule, so none leaks into the export
  set and the collision class does not recur.
- the tests/CMakeLists.txt test-target rename -- the test binary is never
  installed, so it is not collision surface.

Refs PickNikRobotics/moveit_pro#17640, PickNikRobotics/moveit_pro#20928

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
Ported from fork commit f4c4ce8 (test only).

The refactor that shipped with it (cc77236) and its test fixups (ceadf1a)
are dropped: upstream 4.9.0 already contains that refactor essentially
verbatim -- same is_builtin precondition block, same lookup_name dispatch,
same reordered BehaviorTree/SubTree branches -- and goes further with
validateModelName, a TryCatch arity check and a kMaxNestingDepth guard. The
fork's version is a strict subset, so cherry-picking it would regress upstream.

The assertions are rewritten with std::string::find instead of gmock's
HasSubstr, so the fork does not add a gmock build dependency upstream lacks.
That is also why ceadf1a's package.xml and tests/CMakeLists.txt hunks are
dropped -- they existed only to pull gmock in for these two matchers.

Note both fixtures trip on an unregistered node (TriggerServer, IsDoorLocked)
rather than on a structural rule, so this guards recursive line-number
reporting, not decorator arity.

Refs PickNikRobotics/moveit_pro#17640

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 388 files, which is 288 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b7576a76-fa63-460b-97e3-853ebc4fd0da

📥 Commits

Reviewing files that changed from the base of the PR and between 120a665 and e89db2b.

📒 Files selected for processing (388)
  • .clang-format
  • .clang-tidy
  • .github/dependabot.yml
  • .github/pull_request_template.md
  • .github/workflows/cmake_ubuntu.yml
  • .github/workflows/cmake_ubuntu_sanitizers.yml
  • .github/workflows/cmake_windows.yml
  • .github/workflows/doxygen-gh-pages.yml
  • .github/workflows/pixi.yaml
  • .github/workflows/pre-commit.yaml
  • .github/workflows/ros2-rolling.yaml
  • .github/workflows/ros2.yaml
  • .gitignore
  • .pre-commit-config.yaml
  • 3rdparty/cpp-sqlite/README.md
  • 3rdparty/cpp-sqlite/sqlite.hpp
  • 3rdparty/cppzmq/CMakeLists.txt
  • 3rdparty/cppzmq/README.md
  • 3rdparty/cppzmq/zmq.hpp
  • 3rdparty/cppzmq/zmq_addon.hpp
  • 3rdparty/doxygen-awesome-css/LICENSE
  • 3rdparty/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js
  • 3rdparty/doxygen-awesome-css/doxygen-awesome-sidebar-only.css
  • 3rdparty/doxygen-awesome-css/doxygen-awesome.css
  • 3rdparty/flatbuffers/CMakeLists.txt
  • 3rdparty/flatbuffers/flatbuffers/base.h
  • 3rdparty/lexy/CMakeLists.txt
  • 3rdparty/lexy/LICENSE
  • 3rdparty/lexy/README.adoc
  • 3rdparty/lexy/cmake/lexyConfig.cmake.in
  • 3rdparty/lexy/include/lexy/_detail/any_ref.hpp
  • 3rdparty/lexy/include/lexy/_detail/assert.hpp
  • 3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp
  • 3rdparty/lexy/include/lexy/_detail/code_point.hpp
  • 3rdparty/lexy/include/lexy/_detail/config.hpp
  • 3rdparty/lexy/include/lexy/_detail/detect.hpp
  • 3rdparty/lexy/include/lexy/_detail/integer_sequence.hpp
  • 3rdparty/lexy/include/lexy/_detail/invoke.hpp
  • 3rdparty/lexy/include/lexy/_detail/iterator.hpp
  • 3rdparty/lexy/include/lexy/_detail/lazy_init.hpp
  • 3rdparty/lexy/include/lexy/_detail/memory_resource.hpp
  • 3rdparty/lexy/include/lexy/_detail/nttp_string.hpp
  • 3rdparty/lexy/include/lexy/_detail/stateless_lambda.hpp
  • 3rdparty/lexy/include/lexy/_detail/std.hpp
  • 3rdparty/lexy/include/lexy/_detail/string_view.hpp
  • 3rdparty/lexy/include/lexy/_detail/swar.hpp
  • 3rdparty/lexy/include/lexy/_detail/tuple.hpp
  • 3rdparty/lexy/include/lexy/_detail/type_name.hpp
  • 3rdparty/lexy/include/lexy/_detail/unicode_database.hpp
  • 3rdparty/lexy/include/lexy/action/base.hpp
  • 3rdparty/lexy/include/lexy/action/match.hpp
  • 3rdparty/lexy/include/lexy/action/parse.hpp
  • 3rdparty/lexy/include/lexy/action/parse_as_tree.hpp
  • 3rdparty/lexy/include/lexy/action/scan.hpp
  • 3rdparty/lexy/include/lexy/action/trace.hpp
  • 3rdparty/lexy/include/lexy/action/validate.hpp
  • 3rdparty/lexy/include/lexy/callback.hpp
  • 3rdparty/lexy/include/lexy/callback/adapter.hpp
  • 3rdparty/lexy/include/lexy/callback/aggregate.hpp
  • 3rdparty/lexy/include/lexy/callback/base.hpp
  • 3rdparty/lexy/include/lexy/callback/bind.hpp
  • 3rdparty/lexy/include/lexy/callback/bit_cast.hpp
  • 3rdparty/lexy/include/lexy/callback/composition.hpp
  • 3rdparty/lexy/include/lexy/callback/constant.hpp
  • 3rdparty/lexy/include/lexy/callback/container.hpp
  • 3rdparty/lexy/include/lexy/callback/fold.hpp
  • 3rdparty/lexy/include/lexy/callback/forward.hpp
  • 3rdparty/lexy/include/lexy/callback/integer.hpp
  • 3rdparty/lexy/include/lexy/callback/noop.hpp
  • 3rdparty/lexy/include/lexy/callback/object.hpp
  • 3rdparty/lexy/include/lexy/callback/string.hpp
  • 3rdparty/lexy/include/lexy/code_point.hpp
  • 3rdparty/lexy/include/lexy/dsl.hpp
  • 3rdparty/lexy/include/lexy/dsl/any.hpp
  • 3rdparty/lexy/include/lexy/dsl/ascii.hpp
  • 3rdparty/lexy/include/lexy/dsl/base.hpp
  • 3rdparty/lexy/include/lexy/dsl/bits.hpp
  • 3rdparty/lexy/include/lexy/dsl/bom.hpp
  • 3rdparty/lexy/include/lexy/dsl/brackets.hpp
  • 3rdparty/lexy/include/lexy/dsl/branch.hpp
  • 3rdparty/lexy/include/lexy/dsl/byte.hpp
  • 3rdparty/lexy/include/lexy/dsl/capture.hpp
  • 3rdparty/lexy/include/lexy/dsl/case_folding.hpp
  • 3rdparty/lexy/include/lexy/dsl/char_class.hpp
  • 3rdparty/lexy/include/lexy/dsl/choice.hpp
  • 3rdparty/lexy/include/lexy/dsl/code_point.hpp
  • 3rdparty/lexy/include/lexy/dsl/combination.hpp
  • 3rdparty/lexy/include/lexy/dsl/context_counter.hpp
  • 3rdparty/lexy/include/lexy/dsl/context_flag.hpp
  • 3rdparty/lexy/include/lexy/dsl/context_identifier.hpp
  • 3rdparty/lexy/include/lexy/dsl/delimited.hpp
  • 3rdparty/lexy/include/lexy/dsl/digit.hpp
  • 3rdparty/lexy/include/lexy/dsl/effect.hpp
  • 3rdparty/lexy/include/lexy/dsl/eof.hpp
  • 3rdparty/lexy/include/lexy/dsl/error.hpp
  • 3rdparty/lexy/include/lexy/dsl/expression.hpp
  • 3rdparty/lexy/include/lexy/dsl/flags.hpp
  • 3rdparty/lexy/include/lexy/dsl/follow.hpp
  • 3rdparty/lexy/include/lexy/dsl/identifier.hpp
  • 3rdparty/lexy/include/lexy/dsl/if.hpp
  • 3rdparty/lexy/include/lexy/dsl/integer.hpp
  • 3rdparty/lexy/include/lexy/dsl/list.hpp
  • 3rdparty/lexy/include/lexy/dsl/literal.hpp
  • 3rdparty/lexy/include/lexy/dsl/lookahead.hpp
  • 3rdparty/lexy/include/lexy/dsl/loop.hpp
  • 3rdparty/lexy/include/lexy/dsl/member.hpp
  • 3rdparty/lexy/include/lexy/dsl/newline.hpp
  • 3rdparty/lexy/include/lexy/dsl/operator.hpp
  • 3rdparty/lexy/include/lexy/dsl/option.hpp
  • 3rdparty/lexy/include/lexy/dsl/parse_as.hpp
  • 3rdparty/lexy/include/lexy/dsl/parse_tree_node.hpp
  • 3rdparty/lexy/include/lexy/dsl/peek.hpp
  • 3rdparty/lexy/include/lexy/dsl/position.hpp
  • 3rdparty/lexy/include/lexy/dsl/production.hpp
  • 3rdparty/lexy/include/lexy/dsl/punctuator.hpp
  • 3rdparty/lexy/include/lexy/dsl/recover.hpp
  • 3rdparty/lexy/include/lexy/dsl/repeat.hpp
  • 3rdparty/lexy/include/lexy/dsl/return.hpp
  • 3rdparty/lexy/include/lexy/dsl/scan.hpp
  • 3rdparty/lexy/include/lexy/dsl/separator.hpp
  • 3rdparty/lexy/include/lexy/dsl/sequence.hpp
  • 3rdparty/lexy/include/lexy/dsl/sign.hpp
  • 3rdparty/lexy/include/lexy/dsl/subgrammar.hpp
  • 3rdparty/lexy/include/lexy/dsl/symbol.hpp
  • 3rdparty/lexy/include/lexy/dsl/terminator.hpp
  • 3rdparty/lexy/include/lexy/dsl/times.hpp
  • 3rdparty/lexy/include/lexy/dsl/token.hpp
  • 3rdparty/lexy/include/lexy/dsl/unicode.hpp
  • 3rdparty/lexy/include/lexy/dsl/until.hpp
  • 3rdparty/lexy/include/lexy/dsl/whitespace.hpp
  • 3rdparty/lexy/include/lexy/encoding.hpp
  • 3rdparty/lexy/include/lexy/error.hpp
  • 3rdparty/lexy/include/lexy/grammar.hpp
  • 3rdparty/lexy/include/lexy/input/argv_input.hpp
  • 3rdparty/lexy/include/lexy/input/base.hpp
  • 3rdparty/lexy/include/lexy/input/buffer.hpp
  • 3rdparty/lexy/include/lexy/input/file.hpp
  • 3rdparty/lexy/include/lexy/input/lexeme_input.hpp
  • 3rdparty/lexy/include/lexy/input/parse_tree_input.hpp
  • 3rdparty/lexy/include/lexy/input/range_input.hpp
  • 3rdparty/lexy/include/lexy/input/string_input.hpp
  • 3rdparty/lexy/include/lexy/input_location.hpp
  • 3rdparty/lexy/include/lexy/lexeme.hpp
  • 3rdparty/lexy/include/lexy/parse_tree.hpp
  • 3rdparty/lexy/include/lexy/token.hpp
  • 3rdparty/lexy/include/lexy/visualize.hpp
  • 3rdparty/lexy/include/lexy_ext/compiler_explorer.hpp
  • 3rdparty/lexy/include/lexy_ext/parse_tree_algorithm.hpp
  • 3rdparty/lexy/include/lexy_ext/parse_tree_doctest.hpp
  • 3rdparty/lexy/include/lexy_ext/report_error.hpp
  • 3rdparty/lexy/include/lexy_ext/shell.hpp
  • 3rdparty/lexy/src/CMakeLists.txt
  • 3rdparty/lexy/src/input/file.cpp
  • 3rdparty/minicoro/CMakeLists.txt
  • 3rdparty/minitrace/CMakeLists.txt
  • 3rdparty/tinyxml2/CMakeLists.txt
  • 3rdparty/tinyxml2/tinyxml2.cpp
  • 3rdparty/tinyxml2/tinyxml2.h
  • 3rdparty/wildcards/LICENSE_1_0.txt
  • 3rdparty/wildcards/README.md
  • 3rdparty/wildcards/wildcards.hpp
  • CHANGELOG.rst
  • CLAUDE.md
  • CMakeLists.txt
  • CONTRIBUTORS_GUIDE.md
  • Doxyfile
  • README.md
  • cmake/FindZeroMQ.cmake
  • cmake/ament_build.cmake
  • cmake/conan.cmake
  • cmake/conan_build.cmake
  • cmake/sanitizers.cmake
  • codecov.yml
  • conanfile.py
  • conanfile.txt
  • docs/PORT_CONNECTION_RULES.md
  • docs/mainpage.md
  • docs/name_validation_rules.md
  • docs/pre_postconditions.md
  • examples/CMakeLists.txt
  • examples/ex01_wrap_legacy.cpp
  • examples/ex03_ncurses_manual_selector.cpp
  • examples/ex03_sqlite_log.cpp
  • examples/plugin_example/plugin_action.cpp
  • examples/t02_basic_ports.cpp
  • examples/t04_reactive_sequence.cpp
  • examples/t05_crossdoor.cpp
  • examples/t06_subtree_port_remapping.cpp
  • examples/t07_load_multiple_xml.cpp
  • examples/t09_scripting.cpp
  • examples/t11_groot_howto.cpp
  • examples/t14_subtree_model.cpp
  • examples/t15_nodes_mocking.cpp
  • examples/t16_global_blackboard.cpp
  • examples/t17_blackboard_backup.cpp
  • examples/t18_waypoints.cpp
  • examples/t19_polymorphic_ports.cpp
  • fuzzing/bb_fuzzer.cpp
  • fuzzing/bt_fuzzer.cpp
  • fuzzing/script_fuzzer.cpp
  • include/behaviortree_cpp/action_node.h
  • include/behaviortree_cpp/actions/always_failure_node.h
  • include/behaviortree_cpp/actions/always_success_node.h
  • include/behaviortree_cpp/actions/pop_from_queue.hpp
  • include/behaviortree_cpp/actions/script_condition.h
  • include/behaviortree_cpp/actions/script_node.h
  • include/behaviortree_cpp/actions/set_blackboard_node.h
  • include/behaviortree_cpp/actions/sleep_node.h
  • include/behaviortree_cpp/actions/test_node.h
  • include/behaviortree_cpp/actions/unset_blackboard_node.h
  • include/behaviortree_cpp/actions/updated_action.h
  • include/behaviortree_cpp/basic_types.h
  • include/behaviortree_cpp/behavior_tree.h
  • include/behaviortree_cpp/blackboard.h
  • include/behaviortree_cpp/bt_factory.h
  • include/behaviortree_cpp/bt_parser.h
  • include/behaviortree_cpp/condition_node.h
  • include/behaviortree_cpp/contrib/any.hpp
  • include/behaviortree_cpp/control_node.h
  • include/behaviortree_cpp/controls/fallback_node.h
  • include/behaviortree_cpp/controls/if_then_else_node.h
  • include/behaviortree_cpp/controls/manual_node.h
  • include/behaviortree_cpp/controls/parallel_all_node.h
  • include/behaviortree_cpp/controls/parallel_node.h
  • include/behaviortree_cpp/controls/reactive_fallback.h
  • include/behaviortree_cpp/controls/reactive_sequence.h
  • include/behaviortree_cpp/controls/sequence_node.h
  • include/behaviortree_cpp/controls/sequence_with_memory_node.h
  • include/behaviortree_cpp/controls/switch_node.h
  • include/behaviortree_cpp/controls/try_catch_node.h
  • include/behaviortree_cpp/controls/while_do_else_node.h
  • include/behaviortree_cpp/decorator_node.h
  • include/behaviortree_cpp/decorators/consume_queue.h
  • include/behaviortree_cpp/decorators/delay_node.h
  • include/behaviortree_cpp/decorators/force_failure_node.h
  • include/behaviortree_cpp/decorators/force_success_node.h
  • include/behaviortree_cpp/decorators/inverter_node.h
  • include/behaviortree_cpp/decorators/keep_running_until_failure_node.h
  • include/behaviortree_cpp/decorators/loop_node.h
  • include/behaviortree_cpp/decorators/repeat_node.h
  • include/behaviortree_cpp/decorators/retry_node.h
  • include/behaviortree_cpp/decorators/run_once_node.h
  • include/behaviortree_cpp/decorators/script_precondition.h
  • include/behaviortree_cpp/decorators/subtree_node.h
  • include/behaviortree_cpp/decorators/timeout_node.h
  • include/behaviortree_cpp/decorators/updated_decorator.h
  • include/behaviortree_cpp/exceptions.h
  • include/behaviortree_cpp/json_export.h
  • include/behaviortree_cpp/leaf_node.h
  • include/behaviortree_cpp/loggers/abstract_logger.h
  • include/behaviortree_cpp/loggers/bt_cout_logger.h
  • include/behaviortree_cpp/loggers/bt_file_logger_v2.h
  • include/behaviortree_cpp/loggers/bt_minitrace_logger.h
  • include/behaviortree_cpp/loggers/bt_observer.h
  • include/behaviortree_cpp/loggers/bt_sqlite_logger.h
  • include/behaviortree_cpp/loggers/groot2_protocol.h
  • include/behaviortree_cpp/loggers/groot2_publisher.h
  • include/behaviortree_cpp/scripting/any_types.hpp
  • include/behaviortree_cpp/scripting/operators.hpp
  • include/behaviortree_cpp/scripting/script_parser.hpp
  • include/behaviortree_cpp/tree_node.h
  • include/behaviortree_cpp/utils/convert_impl.hpp
  • include/behaviortree_cpp/utils/demangle_util.h
  • include/behaviortree_cpp/utils/locked_reference.hpp
  • include/behaviortree_cpp/utils/polymorphic_cast_registry.hpp
  • include/behaviortree_cpp/utils/safe_any.hpp
  • include/behaviortree_cpp/utils/shared_library.h
  • include/behaviortree_cpp/utils/signal.h
  • include/behaviortree_cpp/utils/simple_string.hpp
  • include/behaviortree_cpp/utils/strcat.hpp
  • include/behaviortree_cpp/utils/timer_queue.h
  • include/behaviortree_cpp/utils/wakeup_signal.hpp
  • include/behaviortree_cpp/utils/wildcards.hpp
  • package.xml
  • run_clang_format.sh
  • run_clang_tidy.sh
  • run_clang_tidy_hook.sh
  • run_coverage.sh
  • sample_nodes/CMakeLists.txt
  • sample_nodes/crossdoor_nodes.cpp
  • sample_nodes/dummy_nodes.cpp
  • sample_nodes/dummy_nodes.h
  • sample_nodes/movebase_node.cpp
  • sample_nodes/movebase_node.h
  • sonar-project.properties
  • src/action_node.cpp
  • src/actions/sleep_node.cpp
  • src/actions/updated_action.cpp
  • src/basic_types.cpp
  • src/behavior_tree.cpp
  • src/blackboard.cpp
  • src/bt_factory.cpp
  • src/condition_node.cpp
  • src/control_node.cpp
  • src/controls/fallback_node.cpp
  • src/controls/if_then_else_node.cpp
  • src/controls/manual_node.cpp
  • src/controls/parallel_all_node.cpp
  • src/controls/parallel_node.cpp
  • src/controls/reactive_fallback.cpp
  • src/controls/reactive_sequence.cpp
  • src/controls/sequence_node.cpp
  • src/controls/sequence_with_memory_node.cpp
  • src/controls/switch_node.cpp
  • src/controls/try_catch_node.cpp
  • src/controls/while_do_else_node.cpp
  • src/decorator_node.cpp
  • src/decorators/delay_node.cpp
  • src/decorators/inverter_node.cpp
  • src/decorators/repeat_node.cpp
  • src/decorators/retry_node.cpp
  • src/decorators/subtree_node.cpp
  • src/decorators/timeout_node.cpp
  • src/decorators/updated_decorator.cpp
  • src/example.cpp
  • src/json_export.cpp
  • src/loggers/bt_cout_logger.cpp
  • src/loggers/bt_file_logger_v2.cpp
  • src/loggers/bt_minitrace_logger.cpp
  • src/loggers/bt_observer.cpp
  • src/loggers/bt_sqlite_logger.cpp
  • src/loggers/groot2_publisher.cpp
  • src/loggers/zmq.hpp
  • src/script_parser.cpp
  • src/script_tokenizer.cpp
  • src/shared_library.cpp
  • src/shared_library_UNIX.cpp
  • src/shared_library_WIN.cpp
  • src/tree_node.cpp
  • src/xml_parsing.cpp
  • tests/CMakeLists.txt
  • tests/gtest_any.cpp
  • tests/gtest_async_action_node.cpp
  • tests/gtest_basic_types.cpp
  • tests/gtest_blackboard.cpp
  • tests/gtest_blackboard_thread_safety.cpp
  • tests/gtest_coroutines.cpp
  • tests/gtest_decorator.cpp
  • tests/gtest_enums.cpp
  • tests/gtest_exception_tracking.cpp
  • tests/gtest_factory.cpp
  • tests/gtest_fallback.cpp
  • tests/gtest_groot2_publisher.cpp
  • tests/gtest_if_then_else.cpp
  • tests/gtest_interface.cpp
  • tests/gtest_json.cpp
  • tests/gtest_logger_zmq.cpp
  • tests/gtest_loggers.cpp
  • tests/gtest_loop.cpp
  • tests/gtest_match.cpp
  • tests/gtest_name_validation.cpp
  • tests/gtest_parallel.cpp
  • tests/gtest_plugin_issue953.cpp
  • tests/gtest_polymorphic_ports.cpp
  • tests/gtest_port_type_rules.cpp
  • tests/gtest_ports.cpp
  • tests/gtest_postconditions.cpp
  • tests/gtest_preconditions.cpp
  • tests/gtest_reactive.cpp
  • tests/gtest_reactive_backchaining.cpp
  • tests/gtest_scripting.cpp
  • tests/gtest_sequence.cpp
  • tests/gtest_simple_string.cpp
  • tests/gtest_skipping.cpp
  • tests/gtest_substitution.cpp
  • tests/gtest_subtree.cpp
  • tests/gtest_switch.cpp
  • tests/gtest_tree.cpp
  • tests/gtest_try_catch.cpp
  • tests/gtest_updates.cpp
  • tests/gtest_wakeup.cpp
  • tests/gtest_while_do_else.cpp
  • tests/gtest_xml_null_subtree_id.cpp
  • tests/include/action_test_node.h
  • tests/include/animal_hierarchy_test.h
  • tests/include/condition_test_node.h
  • tests/include/environment.h
  • tests/navigation_test.cpp
  • tests/plugin_issue953/plugin_issue953.cpp
  • tests/script_parser_test.cpp
  • tests/src/action_test_node.cpp
  • tests/src/condition_test_node.cpp
  • tests/test_helper.hpp
  • tests/tsan_suppressions.txt
  • tools/CMakeLists.txt
  • tools/bt_nodes_model.cpp
  • tools/bt_plugin_manifest.cpp
  • tools/bt_recorder.cpp

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Upstream 4.9.0 added validateModelName, which rejects ' ' in <BehaviorTree ID>,
<SubTree ID>, and custom node type names. MoveIt Pro names every Objective and
SubTree in human-readable form, so this rejects essentially the entire product.

Swept moveit_pro and moveit_pro_example_ws for names that 4.9.0's
findForbiddenChar rejects:

  C++ port names          1226 port-creation sites, 1310 kPortID* constants:  0
  XML tree / subtree IDs                                                   1139
  XML TreeNodesModel node IDs                                               809
                                                                     ----------
  total                                    1948 across 334 files, 276 distinct

1926 of those are in shipped config rather than test fixtures -- core Objectives
like "Close Gripper", "Move to Pose", "Wait for Trajectory Approval if User
Available" -- and customer configs in the field use the same convention.
Renaming them is not an option: Objective IDs are referenced by saved configs.

Every one of the 1948 is the space character. No name in either repo uses any
other forbidden character, so relaxing exactly ' ' clears all of them and
nothing else. Verified by re-running the sweep under the relaxed rule: 0.

'<' '>' '&' '"' '\'' (break XML serialization) and '/' '\\' ':' '*' '?' '|' '.'
are all still rejected, and a new test pins that. Upstream already permits
spaces in instance names for the same human-readability reason, so this narrows
the model/instance gap rather than inventing a rule.

ABI-safe: validateModelName lives in src/xml_parsing.cpp, not a header, so this
changes no struct layout and no header-inlined body.

The two upstream tests asserting spaces are rejected now assert the fork's
behavior instead, renamed to say so.

Refs PickNikRobotics/moveit_pro#17640

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFjW9VieunSxySXNKSFEmX
@dv-picknik
dv-picknik marked this pull request as draft August 5, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.