├── LICENSE ├── README.md ├── cookiecutter.json └── {{ cookiecutter.project_name | snakecase }} ├── .clang-format ├── .clang-tidy ├── .github └── workflows │ └── build_and_test.yaml ├── .pre-commit-config.yaml ├── CMakeLists.txt ├── README.md ├── include └── {{ cookiecutter.project_name | snakecase }} │ └── {{ cookiecutter.class_name | snakecase }}.hpp ├── package.xml ├── src ├── main.cpp └── {{ cookiecutter.class_name | snakecase }}.cpp ├── test └── {{ cookiecutter.class_name | snakecase }}_test.cpp └── {{ cookiecutter.project_name | snakecase }}.repos /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, PickNik Robotics 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cookiecutter ROS2 Package 2 | 3 | [Cookiecutter](https://github.com/cookiecutter/cookiecutter) template for a ROS2 package. 4 | 5 | ### Quickstart 6 | 7 | Install the latest Cookiecutter if you haven't installed it yet: 8 | 9 | ```bash 10 | pip install -U cookiecutter 11 | pip install -U jinja2_stringcase 12 | ``` 13 | 14 | Generate a ROS2 package project 15 | 16 | ```bash 17 | cookiecutter https://github.com/PickNikRobotics/ros2_package_template 18 | 19 | ``` 20 | -------------------------------------------------------------------------------- /cookiecutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_name": "my_project", 3 | "class_name": "MyClass", 4 | "ros2_version": "rolling", 5 | "project_short_description": "TODO: Project Short Description", 6 | "author": "John Doe", 7 | "author_email": "john@doe.com", 8 | "ci_docker_image": "", 9 | "ci_underlay_path": "", 10 | "_extensions": [ 11 | "jinja2_stringcase.StringCaseExtension" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | ColumnLimit: 120 4 | MaxEmptyLinesToKeep: 1 5 | 6 | SortIncludes: true 7 | IncludeBlocks: Regroup 8 | IncludeCategories: 9 | - Regex: '^\"(gmock|gtest)' 10 | Priority: 8 11 | - Regex: '^\"' 12 | Priority: 7 13 | - Regex: '^\<.*msgs' 14 | Priority: 4 15 | - Regex: '^\' 22 | Priority: 1 23 | - Regex: '^<.*/.*' 24 | Priority: 3 25 | 26 | Standard: Auto 27 | IndentWidth: 2 28 | TabWidth: 2 29 | UseTab: Never 30 | AccessModifierOffset: -2 31 | ConstructorInitializerIndentWidth: 2 32 | NamespaceIndentation: None 33 | ContinuationIndentWidth: 4 34 | IndentCaseLabels: true 35 | IndentFunctionDeclarationAfterType: false 36 | 37 | AlignEscapedNewlinesLeft: false 38 | AlignTrailingComments: true 39 | 40 | AllowAllParametersOfDeclarationOnNextLine: false 41 | ExperimentalAutoDetectBinPacking: false 42 | ObjCSpaceBeforeProtocolList: true 43 | Cpp11BracedListStyle: false 44 | 45 | AllowShortBlocksOnASingleLine: true 46 | AllowShortIfStatementsOnASingleLine: false 47 | AllowShortLoopsOnASingleLine: false 48 | AllowShortFunctionsOnASingleLine: None 49 | AllowShortCaseLabelsOnASingleLine: false 50 | 51 | AlwaysBreakTemplateDeclarations: true 52 | AlwaysBreakBeforeMultilineStrings: false 53 | BreakBeforeBinaryOperators: false 54 | BreakBeforeTernaryOperators: false 55 | BreakConstructorInitializersBeforeComma: true 56 | 57 | BinPackParameters: true 58 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 59 | DerivePointerBinding: false 60 | PointerBindsToType: true 61 | 62 | PenaltyExcessCharacter: 50 63 | PenaltyBreakBeforeFirstCallParameter: 30 64 | PenaltyBreakComment: 1000 65 | PenaltyBreakFirstLessLess: 10 66 | PenaltyBreakString: 100 67 | PenaltyReturnTypeOnItsOwnLine: 50 68 | 69 | SpacesBeforeTrailingComments: 2 70 | SpacesInParentheses: false 71 | SpacesInAngles: false 72 | SpaceInEmptyParentheses: false 73 | SpacesInCStyleCastParentheses: false 74 | SpaceAfterCStyleCast: false 75 | SpaceAfterControlStatementKeyword: true 76 | SpaceBeforeAssignmentOperators: true 77 | 78 | # Configure each individual brace in BraceWrapping 79 | BreakBeforeBraces: Custom 80 | 81 | # Control of individual brace wrapping cases 82 | BraceWrapping: 83 | AfterCaseLabel: true 84 | AfterClass: true 85 | AfterControlStatement: true 86 | AfterEnum: true 87 | AfterFunction: true 88 | AfterNamespace: true 89 | AfterStruct: true 90 | AfterUnion: true 91 | BeforeCatch: true 92 | BeforeElse: true 93 | IndentBraces: false 94 | ... 95 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | # TODO(henningkayser): Re-enable performance-unnecessary-value-param once #214 is resolved 3 | Checks: '-*, 4 | performance-*, 5 | -performance-unnecessary-value-param, 6 | llvm-namespace-comment, 7 | modernize-redundant-void-arg, 8 | modernize-use-nullptr, 9 | modernize-use-default, 10 | modernize-use-override, 11 | modernize-loop-convert, 12 | readability-named-parameter, 13 | readability-redundant-smartptr-get, 14 | readability-redundant-string-cstr, 15 | readability-simplify-boolean-expr, 16 | readability-container-size-empty, 17 | readability-identifier-naming, 18 | ' 19 | HeaderFilterRegex: '' 20 | AnalyzeTemporaryDtors: false 21 | CheckOptions: 22 | - key: llvm-namespace-comment.ShortNamespaceLines 23 | value: '10' 24 | - key: llvm-namespace-comment.SpacesBeforeComments 25 | value: '2' 26 | - key: readability-braces-around-statements.ShortStatementLines 27 | value: '2' 28 | # type names 29 | - key: readability-identifier-naming.ClassCase 30 | value: CamelCase 31 | - key: readability-identifier-naming.EnumCase 32 | value: CamelCase 33 | - key: readability-identifier-naming.UnionCase 34 | value: CamelCase 35 | # method names 36 | - key: readability-identifier-naming.MethodCase 37 | value: camelBack 38 | # variable names 39 | - key: readability-identifier-naming.VariableCase 40 | value: lower_case 41 | - key: readability-identifier-naming.ClassMemberSuffix 42 | value: '_' 43 | # const static or global variables are UPPER_CASE 44 | - key: readability-identifier-naming.EnumConstantCase 45 | value: UPPER_CASE 46 | - key: readability-identifier-naming.StaticConstantCase 47 | value: UPPER_CASE 48 | - key: readability-identifier-naming.ClassConstantCase 49 | value: UPPER_CASE 50 | - key: readability-identifier-naming.GlobalVariableCase 51 | value: UPPER_CASE 52 | ... 53 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/.github/workflows/build_and_test.yaml: -------------------------------------------------------------------------------- 1 | # This config uses industrial_ci (https://github.com/ros-industrial/industrial_ci.git). 2 | # For troubleshooting, see readme (https://github.com/ros-industrial/industrial_ci/blob/master/README.rst) 3 | 4 | name: Build and Test ({{ cookiecutter.ros2_version }}) 5 | 6 | # This determines when this workflow is run 7 | on: 8 | workflow_dispatch: 9 | pull_request: 10 | push: 11 | branches: 12 | - main 13 | 14 | jobs: 15 | industrial_ci: 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | env: 20 | - CI_NAME: clang-format 21 | CLANG_FORMAT_CHECK: file 22 | CLANG_FORMAT_VERSION: 10 23 | - CI_NAME: build-and-test 24 | - CI_NAME: clang-tidy 25 | CLANG_TIDY: true 26 | 27 | env: 28 | CCACHE_DIR: /github/home/.ccache 29 | CXXFLAGS: "-Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls" 30 | {% if cookiecutter.ci_docker_image != "" %} cookiecutter.ci_docker_image : {{ cookiecutter.ci_docker_image }}{% endif %} 31 | ROS_DISTRO: {{ cookiecutter.ros2_version }} 32 | ROS_REPO: main 33 | {% if cookiecutter.ci_underlay_path != "" %}UNDERLAY: {{ cookiecutter.ci_underlay_path }}{% endif %} 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v2 37 | # This step will fetch/store the directory used by ccache before/after the ci run 38 | - uses: actions/cache@v2 39 | with: 40 | path: {{ "${{ env.CCACHE_DIR }}" }} 41 | key: ccache-{{ "{{ matrix.env.ROS_DISTRO }}" }}-{{ "{{ matrix.env.ROS_REPO }}" }} 42 | # Run industrial_ci 43 | - uses: 'ros-industrial/industrial_ci@master' 44 | env: {{ "${{ matrix.env }}" }} 45 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # To use: 2 | # 3 | # pre-commit run -a 4 | # 5 | # Or: 6 | # 7 | # pre-commit install # (runs every time you commit in git) 8 | # 9 | # To update this file: 10 | # 11 | # pre-commit autoupdate 12 | # 13 | # See https://github.com/pre-commit/pre-commit 14 | 15 | repos: 16 | # Standard hooks 17 | - repo: https://github.com/pre-commit/pre-commit-hooks 18 | rev: v3.4.0 19 | hooks: 20 | - id: check-added-large-files 21 | - id: check-ast 22 | - id: check-case-conflict 23 | - id: check-docstring-first 24 | - id: check-merge-conflict 25 | - id: check-symlinks 26 | - id: check-yaml 27 | - id: debug-statements 28 | - id: end-of-file-fixer 29 | - id: mixed-line-ending 30 | - id: trailing-whitespace 31 | - id: fix-byte-order-marker 32 | 33 | - repo: https://github.com/psf/black 34 | rev: 20.8b1 35 | hooks: 36 | - id: black 37 | 38 | - repo: local 39 | hooks: 40 | - id: ament_copyright 41 | name: ament_copyright 42 | language: system 43 | entry: ament_copyright 44 | args: ['--add-missing', 'picknik', 'picknik_proprietary', '.'] 45 | 46 | # Cmake hooks 47 | - repo: local 48 | hooks: 49 | - id: ament_lint_cmake 50 | name: ament_lint_cmake 51 | description: Check format of CMakeLists.txt files. 52 | stages: [commit] 53 | entry: ament_lint_cmake 54 | language: system 55 | files: CMakeLists\.txt$ 56 | 57 | - repo: https://github.com/codespell-project/codespell 58 | rev: v2.0.0 59 | hooks: 60 | - id: codespell 61 | args: ['--write-changes'] 62 | exclude: \.(svg|pyc)$ 63 | 64 | - repo: local 65 | hooks: 66 | - id: clang-format 67 | name: clang-format 68 | description: Format files with ClangFormat. 69 | entry: clang-format-10 70 | language: system 71 | files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ 72 | args: ['-fallback-style=none', '-i'] 73 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project({{ cookiecutter.project_name | snakecase }} CXX) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Werror -Wall -Wextra -Wpedantic -Wshadow 6 | -Wsign-conversion -Winit-self -Wredundant-decls) 7 | endif() 8 | 9 | option(BUILD_SHARED_LIBS "Build shared libraries" ON) 10 | 11 | set(THIS_PACKAGE_INCLUDE_DEPENDS 12 | rclcpp 13 | eigen3_cmake_module 14 | Eigen3 15 | ) 16 | 17 | find_package(ament_cmake REQUIRED) 18 | foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) 19 | find_package(${Dependency} REQUIRED) 20 | endforeach() 21 | 22 | ########### 23 | ## Build ## 24 | ########### 25 | 26 | # Declare a C++ library 27 | add_library( 28 | ${PROJECT_NAME} 29 | src/{{ cookiecutter.class_name | snakecase }}.cpp 30 | ) 31 | ament_target_dependencies(${PROJECT_NAME} ${THIS_PACKAGE_INCLUDE_DEPENDS}) 32 | target_include_directories(${PROJECT_NAME} 33 | PUBLIC $ 34 | $) 35 | target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) 36 | 37 | # Declare a C++ executable 38 | add_executable( 39 | ${PROJECT_NAME}_node 40 | src/main.cpp 41 | ) 42 | target_link_libraries(${PROJECT_NAME}_node ${PROJECT_NAME}) 43 | ament_target_dependencies(${PROJECT_NAME}_node ${THIS_PACKAGE_INCLUDE_DEPENDS}) 44 | 45 | ############# 46 | ## Install ## 47 | ############# 48 | 49 | install( 50 | TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node 51 | EXPORT ${PROJECT_NAME}Targets 52 | ARCHIVE DESTINATION lib 53 | LIBRARY DESTINATION lib 54 | RUNTIME DESTINATION lib/${PROJECT_NAME} 55 | ) 56 | 57 | ############# 58 | ## Testing ## 59 | ############# 60 | 61 | if(BUILD_TESTING) 62 | find_package(ament_cmake_gtest REQUIRED) 63 | find_package(ament_lint_auto REQUIRED) 64 | find_package(ament_cmake_pytest REQUIRED) 65 | 66 | # ROS2 linters, but disable copyright test. PickNik's copyright's may not conform 67 | # to this test 68 | # set(ament_cmake_copyright_FOUND TRUE) 69 | # ament_lint_auto_find_test_dependencies() 70 | 71 | # GTests 72 | ament_add_gtest({{ cookiecutter.class_name | snakecase }}_test test/{{ cookiecutter.class_name | snakecase }}_test.cpp) 73 | target_link_libraries({{ cookiecutter.class_name | snakecase }}_test 74 | ${PROJECT_NAME}) 75 | ament_target_dependencies({{ cookiecutter.class_name | snakecase }}_test ${THIS_PACKAGE_INCLUDE_DEPENDS}) 76 | endif() 77 | 78 | ament_export_targets(${PROJECT_NAME}Targets HAS_LIBRARY_TARGET) 79 | ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) 80 | ament_package() 81 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/README.md: -------------------------------------------------------------------------------- 1 | # {{ cookiecutter.project_name | titlecase }} 2 | 3 | Description: TODO(GITHUB_NAME): 4 | 5 | 6 | 7 | 8 | [![Build Status](https://github.com/PickNikRobotics/{{ cookiecutter.project_name | snakecase }}/actions/workflows/build_and_test.yaml/badge.svg)](https://github.com/PickNikRobotics/{{ cookiecutter.project_name | snakecase }}/actions/workflows/build_and_test.yaml) 9 | 10 | ## Installation 11 | 12 | ### Build from Source 13 | 14 | These instructions assume you are running on Ubuntu 20.04: 15 | 16 | 1. [Install ROS2 {{ cookiecutter.ros2_version }}](https://docs.ros.org/en/{{ cookiecutter.ros2_version }}/Installation/Ubuntu-Install-Debians.html). You can stop following along with the tutorial after you complete the section titled: [Environment setup](https://docs.ros.org/en/{{ cookiecutter.ros2_version }}/Installation/Ubuntu-Install-Debians.html#environment-setup). Make sure you setup your environment with: 17 | 18 | source /opt/ros/{{ cookiecutter.ros2_version }}/setup.bash 19 | 20 | > *NOTE:* You may want to add that line to your `~/.bashrc` 21 | 22 | 2. [Install ROS2 Build Tools](https://docs.ros.org/en/{{ cookiecutter.ros2_version }}/Installation/Ubuntu-Development-Setup.html#install-development-tools-and-ros-tools) 23 | 24 | > *NOTE:* If installing on a fresh OS, run `sudo rosdep init` and `rosdep update` before the install script 25 | 26 | 3. Create a colcon workspace (*Note:* Feel free to change `~/ws_ros2` to whatever absolute path you want): 27 | 28 | export COLCON_WS=~/ws_ros2/ 29 | mkdir -p $COLCON_WS/src 30 | 31 | 4. Get the repo: 32 | 33 | cd $COLCON_WS/src 34 | git clone git@github.com:PickNikRobotics/{{ cookiecutter.project_name | snakecase }}.git 35 | 36 | 5. Download the required repositories and install any dependencies: 37 | 38 | cd $COLCON_WS/src 39 | vcs import < {{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.project_name | snakecase }}.repos 40 | rosdep install --ignore-src --from-paths . -y 41 | 42 | # Pick a ROS_DOMAIN_ID that doesn't clash with others 43 | echo 'export ROS_DOMAIN_ID=' >> ~/.bashrc 44 | 45 | 7. Configure and build the workspace: 46 | 47 | cd $COLCON_WS 48 | colcon build --symlink-install --event-handlers log- 49 | 50 | 8. Source the workspace. 51 | 52 | source $COLCON_WS/install/setup.bash 53 | 54 | > *Note*: Whenever you open a new terminal be sure to run `source /opt/ros/{{ cookiecutter.ros2_version }}/setup.bash`, `export COLCON_WS=~/ws_ros2`, and `source $COLCON_WS/install/setup.bash`. You may want to add those commands to your `~/.bashrc` 55 | 56 | ## For Developers 57 | 58 | ### Quickly update code repositories 59 | 60 | To make sure you have the latest repos: 61 | 62 | cd $COLCON_WS/src/{{ cookiecutter.project_name | snakecase }} 63 | git checkout main 64 | git pull origin main 65 | cd $COLCON_WS/src 66 | vcs import < {{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.project_name | snakecase }}.repos 67 | rosdep install --from-paths . --ignore-src -y 68 | 69 | ### Setup pre-commit 70 | 71 | pre-commit is a tool to automatically run formatting checks on each commit, which saves you from manually running clang-format (or, crucially, from forgetting to run them!). 72 | 73 | Install pre-commit like this: 74 | 75 | ``` 76 | pip3 install pre-commit 77 | ``` 78 | 79 | Run this in the top directory of the repo to set up the git hooks: 80 | 81 | ``` 82 | pre-commit install 83 | ``` 84 | 85 | ### Testing and Linting 86 | 87 | To test the pacakges in {{ cookiecutter.project_name | snakecase }}, use the following command with [colcon](https://colcon.readthedocs.io/en/released/). 88 | 89 | export TEST_PACKAGES="PROJECT_PACKAGE_NAMES" 90 | colcon build --packages-up-to ${TEST_PACKAGES} 91 | colcon test --packages-select ${TEST_PACKAGES} 92 | colcon test-result 93 | 94 | ### Using ccache 95 | 96 | ccache is a useful tool to speed up compilation times with GCC or any other sufficiently similar compiler. 97 | 98 | To install ccache on Linux: 99 | 100 | sudo apt-get install ccache 101 | 102 | For other OS, search the package manager or software store for ccache, or refer to the [ccache website](https://ccache.dev/) 103 | 104 | #### Setup 105 | 106 | To use ccache after installing it there are two methods. you can add it to your PATH or you can configure it for more specific uses. 107 | 108 | ccache must be in front of your regular compiler or it won't be called. It is recommended that you add this line to your `.bashrc`: 109 | 110 | export PATH=/usr/lib/ccache:$PATH 111 | 112 | To configure ccache for more particular uses, set the CC and CXX environment variables before invoking make, cmake, catkin_make or catkin build. 113 | 114 | For more information visit the [ccache website](https://ccache.dev/). 115 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/include/{{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.class_name | snakecase }}.hpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) {% now 'utc', '%Y' %}, PickNik Inc 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of PickNik Inc nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | /* Author: {{ cookiecutter.author }} 36 | Desc: TODO(GITHUB_NAME): 37 | */ 38 | 39 | #pragma once 40 | 41 | // C++ 42 | #include 43 | #include 44 | 45 | // ROS 46 | #include 47 | #include 48 | 49 | namespace {{ cookiecutter.project_name | snakecase }} 50 | { 51 | class {{ cookiecutter.class_name}} : public rclcpp::Node 52 | { 53 | public: 54 | /** \brief Constructor */ 55 | {{ cookiecutter.class_name}}(); 56 | 57 | private: 58 | }; // end class {{ cookiecutter.class_name}} 59 | 60 | // Create std pointers for this class 61 | typedef std::shared_ptr<{{ cookiecutter.class_name}}> {{ cookiecutter.class_name}}Ptr; 62 | typedef std::shared_ptr {{ cookiecutter.class_name}}ConstPtr; 63 | 64 | } // namespace {{ cookiecutter.project_name | snakecase }} 65 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ cookiecutter.project_name | snakecase }} 4 | 0.0.1 5 | {{ cookiecutter.project_short_description }} 6 | 7 | {{ cookiecutter.author }} 8 | {{ cookiecutter.author }} 9 | 10 | BSD 11 | 12 | https://github.com/PickNikRobotics/{{ cookiecutter.project_name | snakecase }} 13 | https://github.com/PickNikRobotics/{{ cookiecutter.project_name | snakecase }}/issues 14 | https://github.com/PickNikRobotics/{{ cookiecutter.project_name | snakecase }}/ 15 | 16 | ament_cmakes 17 | eigen3_cmake_module 18 | eigen3_cmake_module 19 | 20 | eigen 21 | rclcpp 22 | 23 | ament_lint_auto 24 | ament_lint_common 25 | 26 | 27 | ament_cmake 28 | 29 | 30 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/src/main.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) {% now 'utc', '%Y' %}, PickNik Inc 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of PickNik Inc nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | /* Author: {{ cookiecutter.author }} 36 | Desc: TODO(GITHUB_NAME): 37 | */ 38 | 39 | // ROS 40 | #include 41 | #include 42 | #include 43 | 44 | #include <{{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.class_name | snakecase }}.hpp> 45 | 46 | int main(int argc, char ** argv) 47 | { 48 | // Initialize ROS 49 | rclcpp::init(argc, argv); 50 | rclcpp::Logger logger = rclcpp::get_logger("{{ cookiecutter.class_name | snakecase }}"); 51 | RCLCPP_INFO(logger, "Starting {{ cookiecutter.class_name}}..."); 52 | 53 | // Create a node. 54 | auto node = std::make_shared<{{ cookiecutter.project_name | snakecase }}::{{ cookiecutter.class_name}}>(); 55 | 56 | /* Create an executor that will be responsible for execution of callbacks for 57 | * a set of nodes. With this version, all callbacks will be called from within 58 | * this thread (the main one). */ 59 | rclcpp::executors::SingleThreadedExecutor exec; 60 | exec.add_node(node); 61 | 62 | /* spin will block until work comes in, execute work as it becomes available, 63 | * and keep blocking. It will only be interrupted by Ctrl-C. */ 64 | exec.spin(); 65 | rclcpp::shutdown(); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/src/{{ cookiecutter.class_name | snakecase }}.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) {% now 'utc', '%Y' %}, PickNik Inc 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of PickNik Inc nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | /* Author: {{ cookiecutter.author }} 36 | Desc: TODO(GITHUB_NAME): 37 | */ 38 | #include <{{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.class_name | snakecase }}.hpp> 39 | 40 | namespace {{ cookiecutter.project_name | snakecase }} 41 | { 42 | {{ cookiecutter.class_name}}::{{ cookiecutter.class_name}}() : Node("{{ cookiecutter.class_name}}") 43 | { 44 | RCLCPP_INFO(get_logger(), "Initializing {{ cookiecutter.class_name}}..."); 45 | } 46 | 47 | } // end namespace {{ cookiecutter.project_name | snakecase }} 48 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/test/{{ cookiecutter.class_name | snakecase }}_test.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Software License Agreement (BSD License) 3 | * 4 | * Copyright (c) {% now 'utc', '%Y' %}, PickNik Inc 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * * Neither the name of PickNik Inc nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | *********************************************************************/ 34 | 35 | /* Author: {{ cookiecutter.author }} 36 | Desc: TODO(GITHUB_NAME): 37 | */ 38 | 39 | /** EXAMPLES: 40 | EXPECT_FALSE(robot_state.hasFixedLinks()); 41 | EXPECT_EQ(robot_state.getFixedLinksCount(), 0); 42 | EXPECT_TRUE(robot_state.getPrimaryFixedLink() == NULL); 43 | EXPECT_GT(robot_state.getFixedLinksMode(), 0); 44 | EXPECT_LT( fabs(vars[0] - 0), EPSILON) << "Virtual joint in wrong position " 45 | << vars[0]; 46 | */ 47 | 48 | // C++ 49 | #include 50 | 51 | // Testing 52 | #include 53 | 54 | // ROS 55 | #include 56 | #include 57 | 58 | // Include class 59 | #include <{{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.class_name | snakecase }}.hpp> 60 | 61 | class {{ cookiecutter.class_name}}Test : public ::testing::Test 62 | { 63 | public: 64 | {{ cookiecutter.class_name}}Test() { node_ = std::make_shared<{{ cookiecutter.project_name | snakecase }}::{{ cookiecutter.class_name}}>(); } 65 | 66 | protected: 67 | rclcpp::Node::SharedPtr node_; 68 | }; // class {{ cookiecutter.class_name}}Test 69 | 70 | TEST_F({{ cookiecutter.class_name}}Test, NameOfTest) 71 | { 72 | bool test = true; 73 | EXPECT_TRUE(test); 74 | } 75 | 76 | TEST_F({{ cookiecutter.class_name}}Test, SpinOnce) 77 | { 78 | rclcpp::executors::SingleThreadedExecutor exec; 79 | exec.add_node(node_); 80 | exec.spin_some(std::chrono::nanoseconds(100)); 81 | bool test = true; 82 | EXPECT_TRUE(test); 83 | } 84 | 85 | int main(int argc, char ** argv) 86 | { 87 | // Initialize ROS 88 | rclcpp::init(argc, argv); 89 | testing::InitGoogleTest(&argc, argv); 90 | 91 | int result = RUN_ALL_TESTS(); 92 | RCLCPP_INFO(rclcpp::get_logger("Test result"), "%d", result); 93 | 94 | rclcpp::shutdown(); 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /{{ cookiecutter.project_name | snakecase }}/{{ cookiecutter.project_name | snakecase }}.repos: -------------------------------------------------------------------------------- 1 | # Used with vcstool, users can download and source of all packages in this. 2 | repositories: 3 | {{ cookiecutter.project_name | snakecase }}: 4 | type: git 5 | url: git@github.com:PickNikRobotics/{{ cookiecutter.project_name | snakecase }}.git 6 | version: main 7 | --------------------------------------------------------------------------------