Skip to content

Commit d3ca767

Browse files
authored
Initial implementation (#1)
* Initial implementation pulled out of Polymath core * Apply pre-commit configurations * Migrate to gtest * Add GitHub action CI
1 parent a51c9bc commit d3ca767

26 files changed

+1082
-1
lines changed

.config/clang-format

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
# C++ Formatting rules for Polymath Code Standard
3+
4+
# See https://releases.llvm.org/14.0.0/tools/clang/docs/ClangFormatStyleOptions.html for documentation of these options
5+
BasedOnStyle: Google
6+
IndentWidth: 2
7+
ColumnLimit: 120
8+
9+
AccessModifierOffset: -2
10+
AlignAfterOpenBracket: AlwaysBreak
11+
AlignConsecutiveAssignments: None
12+
AlignConsecutiveDeclarations: None
13+
AlignEscapedNewlines: Left
14+
AlignTrailingComments: false
15+
AllowAllArgumentsOnNextLine: true
16+
AllowAllParametersOfDeclarationOnNextLine: true
17+
AllowShortBlocksOnASingleLine: Empty
18+
AllowShortFunctionsOnASingleLine: false
19+
BinPackArguments: false
20+
BinPackParameters: false
21+
BraceWrapping:
22+
AfterClass: true
23+
AfterControlStatement: MultiLine
24+
AfterEnum: true
25+
AfterFunction: true
26+
AfterNamespace: true
27+
AfterStruct: true
28+
AfterUnion: true
29+
AfterExternBlock: true
30+
BeforeCatch: false
31+
BeforeElse: false
32+
BeforeLambdaBody: false
33+
BeforeWhile: false
34+
IndentBraces: false
35+
SplitEmptyFunction: false
36+
SplitEmptyRecord: false
37+
SplitEmptyNamespace: false
38+
BreakBeforeBraces: Custom
39+
BreakConstructorInitializers: BeforeComma
40+
CompactNamespaces: false
41+
ContinuationIndentWidth: 2
42+
ConstructorInitializerIndentWidth: 0
43+
DerivePointerAlignment: false
44+
EmptyLineAfterAccessModifier: Never
45+
EmptyLineBeforeAccessModifier: LogicalBlock
46+
FixNamespaceComments: true
47+
IncludeBlocks: Regroup
48+
IncludeCategories:
49+
# Headers in <> with .h extension (best guess at C system headers)
50+
- Regex: '<([A-Za-z0-9\Q/-_\E])+\.h>'
51+
Priority: 1
52+
# Headers in <> without extension (C++ system headers)
53+
- Regex: '<([A-Za-z0-9\Q/-_\E])+>'
54+
Priority: 2
55+
# Headers in <> with other extensions.
56+
- Regex: '<([A-Za-z0-9.\Q/-_\E])+>'
57+
Priority: 3
58+
# Headers in ""
59+
- Regex: '"([A-Za-z0-9.\Q/-_\E])+"'
60+
Priority: 4
61+
IndentAccessModifiers: false
62+
IndentPPDirectives: BeforeHash
63+
PackConstructorInitializers: Never
64+
PointerAlignment: Middle
65+
ReferenceAlignment: Middle
66+
ReflowComments: false
67+
SeparateDefinitionBlocks: Always
68+
SortIncludes: CaseInsensitive
69+
SpacesBeforeTrailingComments: 2

.config/copyright.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2025-present Polymath Robotics, Inc.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

.cpplint.cfg

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Because of cpplint's config file assumptions, this can't be contained in .config/ directory
2+
linelength=256
3+
4+
# TODO(emerson) we need to apply a copyright check, maybe not via this tool though
5+
filter=-legal/copyright
6+
# TODO(emerson) we want these, but the style as enforced here is probably not quite right for us
7+
filter=-build/header_guard
8+
filter=-build/c++17
9+
10+
# Per our style guide, we want to allow the use of non-const reference passing for output parameters
11+
filter=-runtime/references
12+
13+
# Disable all formatting checks, this is handled by clang-format
14+
filter=-readability/braces
15+
filter=-whitespace/braces
16+
filter=-whitespace/indent
17+
filter=-whitespace/newline
18+
filter=-whitespace/parens
19+
filter=-whitespace/semicolon

.github/workflows/build.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
name: Build and test
3+
"on":
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
build_and_test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
ros: [humble, jazzy, kilted, rolling]
16+
package: [behaviortree_cpp_pluginlib, behaviortree_cpp_pluginlib_tests]
17+
include:
18+
- ros: humble
19+
ubuntu: jammy
20+
- ros: jazzy
21+
ubuntu: noble
22+
- ros: kilted
23+
ubuntu: noble-testing
24+
- ros: rolling
25+
ubuntu: noble
26+
name: ${{ matrix.ros }} - ${{ matrix.package }}
27+
container:
28+
image: ghcr.io/ros-tooling/setup-ros-docker/setup-ros-docker-ubuntu-${{ matrix.ubuntu }}:latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
- uses: ros-tooling/action-ros-ci@v0.4
32+
with:
33+
target-ros2-distro: ${{ matrix.ros }}
34+
package-name: ${{ matrix.package }}
35+
import-token: ${{ secrets.GITHUB_TOKEN }}
36+
- uses: actions/upload-artifact@v4
37+
with:
38+
name: colcon-logs__${{ matrix.package }}__${{ matrix.ros }}
39+
path: ros_ws/log

.github/workflows/pre-commit.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
name: pre-commit
3+
"on":
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
pre-commit:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
- run: sudo apt-get update && sudo apt-get install libxml2-utils
16+
- uses: pre-commit/action@v3.0.1

.pre-commit-config.yaml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
# See https://pre-commit.com for more information on these settings
3+
repos:
4+
# Generally useful checks provided by pre-commit
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v5.0.0
7+
hooks:
8+
- id: check-added-large-files
9+
- id: check-ast
10+
- id: check-case-conflict
11+
- id: check-merge-conflict
12+
- id: check-shebang-scripts-are-executable
13+
- id: check-symlinks
14+
- id: check-xml
15+
- id: end-of-file-fixer
16+
- id: forbid-submodules
17+
- id: mixed-line-ending
18+
- id: trailing-whitespace
19+
# C++ formatting
20+
- repo: https://github.com/pre-commit/mirrors-clang-format
21+
rev: v19.1.7
22+
hooks:
23+
- id: clang-format
24+
args: ["--style=file:.config/clang-format"]
25+
# C++ linting
26+
- repo: https://github.com/cpplint/cpplint
27+
rev: 2.0.0
28+
hooks:
29+
- id: cpplint
30+
args: ["--config=.cpplint.cfg", --quiet, --output=sed]
31+
# Markdown
32+
- repo: https://github.com/jackdewinter/pymarkdown
33+
rev: v0.9.28
34+
hooks:
35+
- id: pymarkdown
36+
args: [-d, MD013, fix]
37+
# XML
38+
- repo: https://github.com/emersonknapp/ament_xmllint
39+
rev: v0.1
40+
hooks:
41+
- id: ament_xmllint
42+
# CMake
43+
- repo: https://github.com/cmake-lint/cmake-lint
44+
rev: 1.4.3
45+
hooks:
46+
- id: cmakelint
47+
args: [--linelength=140]
48+
# License headers
49+
- repo: https://github.com/Lucas-C/pre-commit-hooks
50+
rev: v1.5.5
51+
hooks:
52+
- id: insert-license
53+
types_or: [cmake]
54+
name: Copyright headers for Python/CMake
55+
args: [
56+
--license-filepath, .config/copyright.txt,
57+
--comment-style, '#',
58+
--allow-past-years,
59+
--no-extra-eol,
60+
]
61+
- id: insert-license
62+
types_or: [c++, c]
63+
name: Copyright headers for C/C++
64+
args: [
65+
--license-filepath, .config/copyright.txt,
66+
--comment-style, '//',
67+
--allow-past-years,
68+
]

.ruff.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Python rules for Polymath Code Standard
2+
3+
line-length = 120
4+
indent-width = 4
5+
6+
[format]
7+
preview = true
8+
quote-style = "single"
9+
indent-style = "space"
10+
skip-magic-trailing-comma = false
11+
line-ending = "lf"
12+
13+
[lint]
14+
select = ["E4", "E7", "E9", "F", "I", "PTH"]
15+
# Rules intended for future application
16+
# select = ["N", "D", "C90", "UP", "PERF", "RUF"]
17+
ignore = []
18+
fixable = ["ALL"]
19+
unfixable = []
20+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
11
# behaviortree_cpp_pluginlib
2-
Pluginlib integration for registering and loading BehaviorTree.CPP extensions automatically
2+
3+
Pluginlib integration for registering and loading BehaviorTree.CPP extensions automatically.
4+
5+
This allows a workflow where any number of BT node plugins can be exposed in a distributed manner, with a single CMake call, so that no centralized plugin-exposure mechanism is needed to be kept updated.
6+
7+
The use of pluginlib enables discovering all these nodes automatic automatically at runtime, without having to provide a list ahead of time to the factory.
8+
9+
The packages in this repository are:
10+
* [behaviortree_cpp_pluginlib](./behaviortree_cpp_pluginlib/) - main implementation, see here for all information
11+
* [behaviortree_cpp_pluginlib_tests](./behaviortree_cpp_pluginlib_tests/) - separated test package to make sure all exposed build-system tools are working as intended for a user
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright (c) 2025-present Polymath Robotics, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
cmake_minimum_required(VERSION 3.22)
16+
project(behaviortree_cpp_pluginlib)
17+
18+
if(NOT CMAKE_C_STANDARD)
19+
set(CMAKE_C_STANDARD 99)
20+
endif()
21+
if(NOT CMAKE_CXX_STANDARD)
22+
set(CMAKE_CXX_STANDARD 17)
23+
endif()
24+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
25+
add_compile_options(-Wall -Wextra -Wpedantic)
26+
add_link_options(-Wl,-no-undefined)
27+
endif()
28+
29+
find_package(ament_cmake_auto REQUIRED)
30+
ament_auto_find_build_dependencies()
31+
32+
# Create library
33+
add_library(${PROJECT_NAME} SHARED
34+
src/factory.cpp
35+
)
36+
target_include_directories(${PROJECT_NAME} PUBLIC
37+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
38+
$<INSTALL_INTERFACE:include>
39+
)
40+
target_link_libraries(${PROJECT_NAME}
41+
PUBLIC
42+
behaviortree_cpp::behaviortree_cpp
43+
pluginlib::pluginlib
44+
PRIVATE
45+
rcutils::rcutils
46+
)
47+
48+
# Install and export resources
49+
install(
50+
TARGETS ${PROJECT_NAME}
51+
EXPORT ${PROJECT_NAME}_TARGETS
52+
ARCHIVE DESTINATION lib
53+
LIBRARY DESTINATION lib
54+
RUNTIME DESTINATION bin
55+
)
56+
install(
57+
EXPORT ${PROJECT_NAME}_TARGETS
58+
NAMESPACE ${PROJECT_NAME}::
59+
DESTINATION share/${PROJECT_NAME}/cmake
60+
)
61+
install(
62+
FILES src/autoregistrar.cpp.in src/plugin_description.xml.in
63+
DESTINATION share/${PROJECT_NAME}
64+
)
65+
install(
66+
DIRECTORY include/
67+
DESTINATION include
68+
)
69+
install(
70+
DIRECTORY cmake
71+
DESTINATION share/${PROJECT_NAME}
72+
)
73+
74+
if(BUILD_TESTING)
75+
ament_auto_find_test_dependencies()
76+
77+
set(arg_TARGET test_register)
78+
configure_file(
79+
src/autoregistrar.cpp.in
80+
${PROJECT_BINARY_DIR}/test/autoregistrar.cpp
81+
@ONLY
82+
)
83+
84+
ament_add_gtest(test_register
85+
test/test_register.cpp
86+
${PROJECT_BINARY_DIR}/test/autoregistrar.cpp
87+
)
88+
target_link_libraries(test_register ${PROJECT_NAME})
89+
endif()
90+
91+
ament_export_targets(${PROJECT_NAME}_TARGETS HAS_LIBRARY_TARGET)
92+
ament_export_dependencies(behaviortree_cpp pluginlib)
93+
ament_package(
94+
CONFIG_EXTRAS "${PROJECT_NAME}-extras.cmake"
95+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Implementation Details
2+
3+
## BT Plugin Base Class
4+
5+
[plugin.hpp](./include/behaviortree_cpp_pluginlib/plugin.hpp) defines the abstract base class `BT::BehaviorTreePlugin` which has a no-argument constructor and so can be exposed to `pluginlib`.
6+
7+
Prerequisites for `pluginlib`:
8+
1. Plugins must derive from a known base class and be able to be used polymorphically
9+
1. Plugins must provide a no-argument constructor
10+
11+
## C++ Registration Macros
12+
13+
In [register_macro.hpp](./include/behaviortree_cpp_pluginlib/register_macro.hpp) we provide the macros needed to register an arbitrary number of plugin entrypoints from a single library.
14+
15+
See the doc comments in that file for the breakdown of the implementation.
16+
17+
## CMake Macro
18+
19+
Follow the logic in [register_behaviortree_cpp_plugin.cmake](./cmake/register_behaviortree_cpp_plugin.cmake) for the implementation details. High level:
20+
1. Add `autoregistrar.cpp` to the library target
21+
1. Create `plugin_description.xml` file and register it with the resource index for `pluginlib` to find

0 commit comments

Comments
 (0)