├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── 0-troubleshooting.yml │ ├── 1-bug.yml │ ├── 2-feature.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── turtlebot4_description ├── CHANGELOG.rst ├── CMakeLists.txt ├── launch │ └── robot_description.launch.py ├── meshes │ ├── camera_bracket.dae │ ├── oakd_lite.dae │ ├── oakd_pro.dae │ ├── rplidar.dae │ ├── shell.dae │ ├── shell_collision.dae │ ├── tower.dae │ ├── tower_sensor_plate.dae │ ├── tower_standoff.dae │ └── weight_block.dae ├── package.xml └── urdf │ ├── lite │ └── turtlebot4.urdf.xacro │ ├── sensors │ ├── camera_bracket.urdf.xacro │ ├── oakd.urdf.xacro │ └── rplidar.urdf.xacro │ └── standard │ ├── tower_sensor_plate.urdf.xacro │ ├── tower_standoff.urdf.xacro │ ├── turtlebot4.urdf.xacro │ └── weight_block.urdf.xacro ├── turtlebot4_msgs ├── CHANGELOG.rst ├── CMakeLists.txt ├── msg │ ├── UserButton.msg │ ├── UserDisplay.msg │ └── UserLed.msg └── package.xml ├── turtlebot4_navigation ├── CHANGELOG.rst ├── CMakeLists.txt ├── config │ ├── localization.yaml │ ├── nav2.yaml │ └── slam.yaml ├── launch │ ├── localization.launch.py │ ├── nav2.launch.py │ └── slam.launch.py ├── maps │ ├── depot.pgm │ ├── depot.yaml │ ├── maze.pgm │ ├── maze.yaml │ ├── warehouse.pgm │ └── warehouse.yaml ├── package.xml └── turtlebot4_navigation │ ├── __init__.py │ └── turtlebot4_navigator.py └── turtlebot4_node ├── CHANGELOG.rst ├── CMakeLists.txt ├── include └── turtlebot4_node │ ├── action.hpp │ ├── buttons.hpp │ ├── display.hpp │ ├── leds.hpp │ ├── service.hpp │ ├── turtlebot4.hpp │ └── utils.hpp ├── package.xml └── src ├── buttons.cpp ├── display.cpp ├── leds.cpp ├── main.cpp └── turtlebot4.cpp /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Default all changes will request review from: 2 | * @roni-kreinin 3 | * @hilary-luo -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/0-troubleshooting.yml: -------------------------------------------------------------------------------- 1 | name: Troubleshooting Help 2 | description: Use this form when you are looking for assistance to understand why the system is not working how you think it should. 3 | labels: ["troubleshooting"] 4 | assignees: 5 | - smatarCPR 6 | - RustyCPR 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: "# System Information" 11 | - type: dropdown 12 | id: model 13 | attributes: 14 | label: Robot Model 15 | description: Standard has a screen, Lite does not. For simulation select the one that you are simulating. 16 | options: 17 | - Select One 18 | - Turtlebot4 Standard 19 | - Turtlebot4 Lite 20 | validations: 21 | required: true 22 | - type: dropdown 23 | id: ros-distro 24 | attributes: 25 | label: ROS distro 26 | description: What ROS distribution are you using (must match on all devices in the system)? 27 | options: 28 | - Select One 29 | - Galactic 30 | - Humble 31 | - Jazzy 32 | validations: 33 | required: true 34 | - type: dropdown 35 | id: networking 36 | attributes: 37 | label: Networking Configuration 38 | options: 39 | - Select One 40 | - Simple Discovery 41 | - Discovery Server 42 | - I do not know 43 | validations: 44 | required: true 45 | - type: dropdown 46 | id: os 47 | attributes: 48 | label: OS 49 | description: What OS are you running on your companion PC (used to interact with the Turtlebot4)? 50 | options: 51 | - Select One 52 | - Ubuntu 20.04 53 | - Ubuntu 22.04 54 | - Ubuntu 24.04 55 | - Other Linux 56 | - Windows / MAC 57 | validations: 58 | required: true 59 | - type: dropdown 60 | id: build-type 61 | attributes: 62 | label: Built from source or installed? 63 | description: Did you build from source (build the packages yourself) or did you install the packages (e.g. `sudo apt install ...`)? 64 | options: 65 | - Select One 66 | - Built from Source 67 | - Installed 68 | validations: 69 | required: true 70 | - type: textarea 71 | id: version 72 | attributes: 73 | label: Package version 74 | description: What version of the package are you running? (if installed run `dpkg -s ros-$ROS_DISTRO-turtlebot4-PACKAGE_WITH_ISSUE`, if from source, give commit hash) 75 | validations: 76 | required: true 77 | 78 | - type: markdown 79 | attributes: 80 | value: "# Problem Description" 81 | - type: dropdown 82 | id: topic-tag 83 | attributes: 84 | label: Type of issue 85 | description: What component or topic do you need help with? 86 | options: 87 | - Select One 88 | - Networking 89 | - Camera 90 | - LIDAR 91 | - Battery 92 | - Navigation (SLAM, Nav2 etc.) 93 | - Other 94 | validations: 95 | required: true 96 | - type: textarea 97 | attributes: 98 | label: Expected behaviour 99 | description: A clear and concise description of what you expected to happen. 100 | validations: 101 | required: true 102 | - type: textarea 103 | attributes: 104 | label: Actual behaviour 105 | description: A clear and concise description of what you encountered. 106 | validations: 107 | required: true 108 | - type: textarea 109 | attributes: 110 | label: Error messages 111 | description: Error messages copied from terminal and/or relevant logs. Copy these directly from the terminal in full. 112 | render: bash 113 | - type: textarea 114 | attributes: 115 | label: To Reproduce 116 | description: Provide the steps to reproduce. 117 | placeholder: | 118 | 1. run something 119 | 2. launch something else 120 | 3. see the error 121 | validations: 122 | required: true 123 | - type: textarea 124 | attributes: 125 | label: Other notes 126 | description: Add anything else you thing is important. 127 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Use this form when you are confident that there is a bug in this particular package. If you are not sure then use the Troubleshooting Form. 3 | labels: ["bug"] 4 | assignees: 5 | - hilary-luo 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: __Only use this form if you are confident that there is a bug in this package and that it is not user error. If you are not sure then please use the troubleshooting form.__ 10 | - type: markdown 11 | attributes: 12 | value: "# System Information" 13 | - type: dropdown 14 | id: model 15 | attributes: 16 | label: Robot Model 17 | description: Standard has a screen, Lite does not. For simulation select the one that you are simulating. 18 | options: 19 | - Select One 20 | - Turtlebot4 Standard 21 | - Turtlebot4 Lite 22 | validations: 23 | required: true 24 | - type: dropdown 25 | id: ros-distro 26 | attributes: 27 | label: ROS distro 28 | description: What ROS distribution are you using (must match on all devices in the system)? 29 | options: 30 | - Select One 31 | - Galactic 32 | - Humble 33 | - Jazzy 34 | validations: 35 | required: true 36 | - type: dropdown 37 | id: networking 38 | attributes: 39 | label: Networking Configuration 40 | options: 41 | - Select One 42 | - Simple Discovery 43 | - Discovery Server 44 | - I do not know 45 | validations: 46 | required: true 47 | - type: dropdown 48 | id: os 49 | attributes: 50 | label: OS 51 | description: What OS are you running on your companion PC (used to interact with the Turtlebot4)? 52 | options: 53 | - Select One 54 | - Ubuntu 20.04 55 | - Ubuntu 22.04 56 | - Ubuntu 24.04 57 | - Other Linux 58 | - Windows / MAC 59 | validations: 60 | required: true 61 | - type: dropdown 62 | id: build-type 63 | attributes: 64 | label: Built from source or installed? 65 | description: Did you build from source (build the packages yourself) or did you install the packages (e.g. `sudo apt install ...`)? 66 | options: 67 | - Select One 68 | - Built from Source 69 | - Installed 70 | validations: 71 | required: true 72 | - type: textarea 73 | id: version 74 | attributes: 75 | label: Package version 76 | description: What version of the package are you running? (if installed run `dpkg -s ros-$ROS_DISTRO-turtlebot4-PACKAGE_WITH_ISSUE`, if from source, give commit hash) 77 | validations: 78 | required: true 79 | 80 | - type: markdown 81 | attributes: 82 | value: "# Problem Description" 83 | - type: textarea 84 | attributes: 85 | label: Expected behaviour 86 | description: A clear and concise description of what you expected to happen. 87 | validations: 88 | required: true 89 | - type: textarea 90 | attributes: 91 | label: Actual behaviour 92 | description: A clear and concise description of what you encountered. 93 | validations: 94 | required: true 95 | - type: textarea 96 | attributes: 97 | label: Error messages 98 | description: Error messages copied from terminal and/or relevant logs. Copy these directly from the terminal in full. 99 | render: bash 100 | - type: textarea 101 | attributes: 102 | label: To Reproduce 103 | description: Provide the steps to reproduce. 104 | placeholder: | 105 | 1. run something 106 | 2. launch something else 107 | 3. see the error 108 | validations: 109 | required: true 110 | - type: textarea 111 | attributes: 112 | label: Other notes 113 | description: Add anything else you thing is important. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Use this form for requesting a feature that current doesn't exist. 3 | labels: ["enhancement"] 4 | assignees: 5 | - smatarCPR 6 | - RustyCPR 7 | body: 8 | - type: textarea 9 | attributes: 10 | label: Describe the the feature you would like 11 | description: A clear and concise description of what you want to happen. 12 | validations: 13 | required: true 14 | - type: textarea 15 | attributes: 16 | label: Motivation and impact 17 | description: Why is this an important feature and who will it impact? 18 | validations: 19 | required: true 20 | - type: textarea 21 | attributes: 22 | label: Other notes 23 | description: Add anything else you thing is important. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please include a summary of the change and which issue is fixed. Also include relevant motivation and context. 4 | 5 | Fixes # (issue). 6 | 7 | ## Type of change 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | 12 | ## How Has This Been Tested? 13 | 14 | Please describe the tests that you ran to verify your changes. 15 | Provide instructions so we can reproduce. Also list any relevant details for your test configuration. 16 | 17 | ```bash 18 | # Run this command 19 | ros2 launch package launch.py 20 | ``` 21 | 22 | ## Checklist 23 | 24 | - [ ] I have performed a self-review of my own code 25 | - [ ] I have commented my code, particularly in hard-to-understand areas 26 | - [ ] I have made corresponding changes to the documentation -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: turtlebot4_ci 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | turtlebot4_jazzy_ci: 7 | name: Jazzy 8 | runs-on: ubuntu-24.04 9 | steps: 10 | - uses: actions/checkout@v2.3.4 11 | - uses: ros-tooling/setup-ros@v0.7 12 | with: 13 | required-ros-distributions: jazzy 14 | use-ros2-testing: true 15 | - uses: ros-tooling/action-ros-ci@v0.3 16 | id: action_ros_ci_step 17 | with: 18 | target-ros2-distro: jazzy 19 | import-token: ${{ secrets.GITHUB_TOKEN }} 20 | package-name: 21 | turtlebot4_description 22 | turtlebot4_msgs 23 | turtlebot4_navigation 24 | turtlebot4_node 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # turtlebot4 2 | Turtlebot4 common packages. 3 | 4 | Visit the [TurtleBot 4 User Manual](https://turtlebot.github.io/turtlebot4-user-manual/software/turtlebot4_common.html) for details. 5 | -------------------------------------------------------------------------------- /turtlebot4_description/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package turtlebot4_description 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 2.1.0 (2025-05-23) 6 | ------------------ 7 | * Remove unnecessary comments 8 | * Fix tag order 9 | * Update package maintainers 10 | * Contributors: Chris Iverach-Brereton 11 | 12 | 2.0.1 (2024-09-25) 13 | ------------------ 14 | 15 | 2.0.0 (2024-08-29) 16 | ------------------ 17 | * Add base_footprint link to URDF 18 | * Contributors: Chris Iverach-Brereton 19 | 20 | 1.0.5 (2024-07-02) 21 | ------------------ 22 | * Fix typo in rplidar.dae (`#320 `) 23 | Co-authored-by: Gaël Écorchard 24 | * Contributors: Gaël Écorchard 25 | 26 | 1.0.4 (2023-11-08) 27 | ------------------ 28 | 29 | 1.0.3 (2023-05-31) 30 | ------------------ 31 | * Added joint_state_publisher dependency 32 | * Contributors: Roni Kreinin 33 | 34 | 1.0.2 (2023-05-15) 35 | ------------------ 36 | * New maps and Improved Nav2 Config 37 | * Added namespace arg to urdf for namespacing support in sim 38 | * Replaced wheel drop static transforms with joint state publisher 39 | * Contributors: Hilary Luo, Roni Kreinin 40 | 41 | 1.0.1 (2023-02-28) 42 | ------------------ 43 | 44 | 1.0.0 (2023-02-17) 45 | ------------------ 46 | * Updates for new DepthAI node. 47 | * Added tf_static remapping to support namespacing 48 | * Updated oakd link names to match new oakd node 49 | * Added fix for wheeldrop frames not found by Rviz 50 | * Namespacing 51 | * Remap tf topics to not use global namespace 52 | * Contributors: Roni Kreinin 53 | 54 | 0.1.2 (2022-09-15) 55 | ------------------ 56 | 57 | 0.1.1 (2022-07-12) 58 | ------------------ 59 | 60 | 0.1.0 (2022-05-03) 61 | ------------------ 62 | * First Galactic release 63 | * Contributors: Roni Kreinin 64 | -------------------------------------------------------------------------------- /turtlebot4_description/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(turtlebot4_description) 3 | 4 | # Default to C99 5 | if(NOT CMAKE_C_STANDARD) 6 | set(CMAKE_C_STANDARD 99) 7 | endif() 8 | 9 | # Default to C++14 10 | if(NOT CMAKE_CXX_STANDARD) 11 | set(CMAKE_CXX_STANDARD 14) 12 | endif() 13 | 14 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | add_compile_options(-Wall -Wextra -Wpedantic) 16 | endif() 17 | 18 | # find dependencies 19 | find_package(ament_cmake REQUIRED) 20 | find_package(urdf REQUIRED) 21 | find_package(irobot_create_description REQUIRED) 22 | 23 | install( 24 | DIRECTORY launch meshes urdf 25 | DESTINATION share/${PROJECT_NAME} 26 | ) 27 | 28 | if(BUILD_TESTING) 29 | find_package(ament_lint_auto REQUIRED) 30 | ament_lint_auto_find_test_dependencies() 31 | endif() 32 | 33 | ament_package() 34 | -------------------------------------------------------------------------------- /turtlebot4_description/launch/robot_description.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Clearpath 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 | # @author Roni Kreinin (rkreinin@clearpathrobotics.com) 16 | 17 | 18 | from ament_index_python.packages import get_package_share_directory 19 | 20 | from launch import LaunchDescription 21 | from launch.actions import DeclareLaunchArgument 22 | from launch.substitutions import Command, PathJoinSubstitution 23 | from launch.substitutions.launch_configuration import LaunchConfiguration 24 | 25 | from launch_ros.actions import Node 26 | 27 | 28 | ARGUMENTS = [ 29 | DeclareLaunchArgument('model', default_value='standard', 30 | choices=['standard', 'lite'], 31 | description='Turtlebot4 Model'), 32 | DeclareLaunchArgument('use_sim_time', default_value='false', 33 | choices=['true', 'false'], 34 | description='use_sim_time'), 35 | DeclareLaunchArgument('robot_name', default_value='turtlebot4', 36 | description='Robot name'), 37 | DeclareLaunchArgument('namespace', default_value=LaunchConfiguration('robot_name'), 38 | description='Robot namespace'), 39 | ] 40 | 41 | 42 | def generate_launch_description(): 43 | pkg_turtlebot4_description = get_package_share_directory('turtlebot4_description') 44 | xacro_file = PathJoinSubstitution([pkg_turtlebot4_description, 45 | 'urdf', 46 | LaunchConfiguration('model'), 47 | 'turtlebot4.urdf.xacro']) 48 | namespace = LaunchConfiguration('namespace') 49 | 50 | robot_state_publisher = Node( 51 | package='robot_state_publisher', 52 | executable='robot_state_publisher', 53 | name='robot_state_publisher', 54 | output='screen', 55 | parameters=[ 56 | {'use_sim_time': LaunchConfiguration('use_sim_time')}, 57 | {'robot_description': Command([ 58 | 'xacro', ' ', xacro_file, ' ', 59 | 'gazebo:=ignition', ' ', 60 | 'namespace:=', namespace])}, 61 | ], 62 | remappings=[ 63 | ('/tf', 'tf'), 64 | ('/tf_static', 'tf_static') 65 | ] 66 | ) 67 | 68 | joint_state_publisher = Node( 69 | package='joint_state_publisher', 70 | executable='joint_state_publisher', 71 | name='joint_state_publisher', 72 | output='screen', 73 | parameters=[{'use_sim_time': LaunchConfiguration('use_sim_time')}], 74 | remappings=[ 75 | ('/tf', 'tf'), 76 | ('/tf_static', 'tf_static') 77 | ] 78 | ) 79 | 80 | # Define LaunchDescription variable 81 | ld = LaunchDescription(ARGUMENTS) 82 | # Add nodes to LaunchDescription 83 | ld.add_action(robot_state_publisher) 84 | ld.add_action(joint_state_publisher) 85 | return ld 86 | -------------------------------------------------------------------------------- /turtlebot4_description/meshes/tower_sensor_plate.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2022-03-23T14:01:05.789524 5 | 2022-03-23T14:01:05.789527 6 | 7 | Z_UP 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 0.0 0.0 0.0 1.0 16 | 17 | 18 | 0.0 0.0 0.0 1.0 19 | 20 | 21 | 0.101 0.101 0.101 1.0 22 | 23 | 24 | 1 1 1 1.0 25 | 26 | 27 | 0.0 28 | 29 | 30 | 0.0 0.0 0.0 1.0 31 | 32 | 33 | 0.0 34 | 35 | 36 | 0.0 0.0 0.0 1.0 37 | 38 | 39 | 1.0 40 | 41 | 42 | 43 | 44 | 45 | 0 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -0.1345843 -0.01058583 0 -0.1345843 -0.01058583 0.003 -0.1345843 0.01058583 0 -0.1345843 0.01058583 0.003 -0.1312742 -0.03149714 0 -0.1312742 -0.03149714 0.003 -0.1312742 0.03149714 0 -0.1312742 0.03149714 0.003 -0.1247355 -0.05163379 0 -0.1247355 -0.05163379 0.003 -0.1247355 0.05163379 0 -0.1247355 0.05163379 0.003 -0.115129 -0.07050051 0 -0.115129 -0.07050051 0.003 -0.115129 0.07050051 0 -0.115129 0.07050051 0.003 -0.1026908 -0.08763329 0 -0.1026908 -0.08763329 0.003 -0.1026908 0.08763329 0 -0.1026908 0.08763329 0.003 -0.08772704 -0.1026107 0 -0.08772704 -0.1026107 0.003 -0.08772704 0.1026107 0 -0.08772704 0.1026107 0.003 -0.07831945 -0.09062618 0 -0.07831945 -0.09062618 0.003 -0.07831945 0.09065604 0 -0.07831945 0.09065604 0.003 -0.07801801 -0.09175118 0 -0.07801801 -0.09175118 0.003 -0.07801801 -0.08950118 0 -0.07801801 -0.08950118 0.003 -0.07801801 0.08953104 0 -0.07801801 0.08953104 0.003 -0.07801801 0.09178104 0 -0.07801801 0.09178104 0.003 -0.07719445 -0.09257474 0 -0.07719445 -0.09257474 0.003 -0.07719445 -0.08867762 0 -0.07719445 -0.08867762 0.003 -0.07719445 0.08870748 0 -0.07719445 0.08870748 0.003 -0.07719445 0.0926046 0 -0.07719445 0.0926046 0.003 -0.07606945 -0.09287618 0 -0.07606945 -0.09287618 0.003 -0.07606945 -0.08837618 0 -0.07606945 -0.08837618 0.003 -0.07606945 0.08840604 0 -0.07606945 0.08840604 0.003 -0.07606945 0.09290604 0 -0.07606945 0.09290604 0.003 -0.07494445 -0.09257474 0 -0.07494445 -0.09257474 0.003 -0.07494445 -0.08867762 0 -0.07494445 -0.08867762 0.003 -0.07494445 0.08870748 0 -0.07494445 0.08870748 0.003 -0.07494445 0.0926046 0 -0.07494445 0.0926046 0.003 -0.0741209 -0.09175118 0 -0.0741209 -0.09175118 0.003 -0.0741209 -0.08950118 0 -0.0741209 -0.08950118 0.003 -0.0741209 0.08953104 0 -0.0741209 0.08953104 0.003 -0.0741209 0.09178104 0 -0.0741209 0.09178104 0.003 -0.07381945 -0.09062618 0 -0.07381945 -0.09062618 0.003 -0.07381945 0.09065604 0 -0.07381945 0.09065604 0.003 -0.07060562 -0.1150645 0 -0.07060562 -0.1150645 0.003 -0.07060562 0.1150645 0 -0.07060562 0.1150645 0.003 -0.05174768 -0.1246883 0 -0.05174768 -0.1246883 0.003 -0.05174768 0.1246883 0 -0.05174768 0.1246883 0.003 -0.03161702 -0.1312454 0 -0.03161702 -0.1312454 0.003 -0.03161702 0.1312454 0 -0.03161702 0.1312454 0.003 -0.01070874 -0.1345746 0 -0.01070874 -0.1345746 0.003 -0.01070874 0.1345746 0 -0.01070874 0.1345746 0.003 0.01046292 -0.1345939 0 0.01046292 -0.1345939 0.003 0.01046292 0.1345939 0 0.01046292 0.1345939 0.003 0.02837944 -0.1142808 0 0.02837944 -0.1142808 0.003 0.02837944 0.1143106 0 0.02837944 0.1143106 0.003 0.02868088 -0.1154058 0 0.02868088 -0.1154058 0.003 0.02868088 -0.1131558 0 0.02868088 -0.1131558 0.003 0.02868088 0.1131856 0 0.02868088 0.1131856 0.003 0.02868088 0.1154356 0 0.02868088 0.1154356 0.003 0.02950444 -0.1162293 0 0.02950444 -0.1162293 0.003 0.02950444 -0.1123322 0 0.02950444 -0.1123322 0.003 0.02950444 0.1123621 0 0.02950444 0.1123621 0.003 0.02950444 0.1162592 0 0.02950444 0.1162592 0.003 0.03062944 -0.1165308 0 0.03062944 -0.1165308 0.003 0.03062944 -0.1120308 0 0.03062944 -0.1120308 0.003 0.03062944 0.1120606 0 0.03062944 0.1120606 0.003 0.03062944 0.1165606 0 0.03062944 0.1165606 0.003 0.03137724 -0.131303 0 0.03137724 -0.131303 0.003 0.03137724 0.131303 0 0.03137724 0.131303 0.003 0.03175444 -0.1162293 0 0.03175444 -0.1162293 0.003 0.03175444 -0.1123322 0 0.03175444 -0.1123322 0.003 0.03175444 0.1123621 0 0.03175444 0.1123621 0.003 0.03175444 0.1162592 0 0.03175444 0.1162592 0.003 0.032578 -0.1154058 0 0.032578 -0.1154058 0.003 0.032578 -0.1131558 0 0.032578 -0.1131558 0.003 0.032578 0.1131856 0 0.032578 0.1131856 0.003 0.032578 0.1154356 0 0.032578 0.1154356 0.003 0.03287944 -0.1142808 0 0.03287944 -0.1142808 0.003 0.03287944 0.1143106 0 0.03287944 0.1143106 0.003 0.05151985 -0.1247826 0 0.05151985 -0.1247826 0.003 0.05151985 0.1247826 0 0.05151985 0.1247826 0.003 0.07039533 -0.1151933 0 0.07039533 -0.1151933 0.003 0.07039533 0.1151933 0 0.07039533 0.1151933 0.003 0.08753947 -0.1027708 0 0.08753947 -0.1027708 0.003 0.08753947 0.1027708 0 0.08753947 0.1027708 0.003 0.1025306 -0.08782071 0 0.1025306 -0.08782071 0.003 0.1025306 0.08782071 0 0.1025306 0.08782071 0.003 0.115 -0.07071068 0 0.115 -0.07071068 0.003 0.115 0.07071068 0 0.115 0.07071068 0.003 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 0.8081572 0.5889668 0 0.8081572 0.5889668 0 0.7061377 0.7080746 0 0.7061377 0.7080746 0 0.58675 0.8097681 0 0.58675 0.8097681 0 0.4529325 0.8915448 0 0.4529325 0.8915448 0 0.3079745 0.9513946 0 0.3079745 0.9513946 0 0.1554422 0.987845 0 0.1554422 0.987845 0 -0.000913149 0.9999996 0 -0.000913149 0.9999996 0 -0.1572462 0.9875594 0 -0.1572462 0.9875594 0 -0.3097121 0.9508304 0 -0.3097121 0.9508304 0 -0.4545599 0.8907162 0 -0.4545599 0.8907162 0 -0.5882285 0.8086948 0 -0.5882285 0.8086948 0 -0.7074294 0.706784 0 -0.7074294 0.706784 0 -0.8092317 0.5874897 0 -0.8092317 0.5874897 0 -0.891131 0.4537461 0 -0.891131 0.4537461 0 -0.951113 0.308843 0 -0.951113 0.308843 0 -0.9877025 0.1563445 0 -0.9877025 0.1563445 0 -1 0 0 -1 0 0 -0.9877025 -0.1563445 0 -0.9877025 -0.1563445 -0 -0.951113 -0.308843 0 -0.951113 -0.308843 -0 -0.891131 -0.4537461 0 -0.891131 -0.4537461 -0 -0.8092317 -0.5874897 0 -0.8092317 -0.5874897 -0 -0.7074294 -0.706784 0 -0.7074294 -0.706784 -0 -0.5882285 -0.8086948 0 -0.5882285 -0.8086948 -0 -0.4545599 -0.8907162 0 -0.4545599 -0.8907162 -0 -0.3097121 -0.9508304 0 -0.3097121 -0.9508304 -0 -0.1572462 -0.9875594 0 -0.1572462 -0.9875594 -0 -0.000913149 -0.9999996 0 -0.000913149 -0.9999996 -0 0.1554422 -0.987845 0 0.1554422 -0.987845 0 0.3079745 -0.9513946 0 0.3079745 -0.9513946 0 0.4529325 -0.8915448 0 0.4529325 -0.8915448 0 0.58675 -0.8097681 0 0.58675 -0.8097681 0 0.7061377 -0.7080746 0 0.7061377 -0.7080746 0 0.8081572 -0.5889668 0 0.8081572 -0.5889668 0 0 0 1 0 0 1 0 -0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0 0 1 -0 0 1 0 0 1 0 -0 1 0 -0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0 0 1 0 0 1 0 0 1 -0 -0 1 -0 0 1 -0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0 0 1 0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 -0 0 1 0 -0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 -0 1 -0 0 1 0 -0 1 -0 0 1 -0 0 1 0 0 1 0 0 1 0 0 1 0 -0 1 0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 -0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0 0 1 -0 0 1 0 0 -1 -0 0 -1 -0 0 -1 0 0 -1 -0 0 -1 0 -0 -1 0 -0 -1 0 0 -1 -0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 0 -1 -0 0 -1 -0 0 -1 -0 0 -1 0 -0 -1 0 -0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 -0 -1 0 -0 -1 0 0 -1 0 -0 -1 0 0 -1 0 0 -1 0 -0 -1 0 -0 -1 0 -0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 0 -1 0 -0 -1 -0 -0 -1 0 -0 -1 -0 -0 -1 -0 -0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 0 -1 -0 0 -1 0 0 -1 -0 0 -1 0 0 -1 0 0 -1 0 -0 -1 0 0 -1 -0 0 -1 0 0 -1 -0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0 0 -1 0 -0 -1 0 0 -1 0 -0 -1 0 0 -1 0 0 -1 -0.9659253 -0.2588208 0 -0.9659253 -0.2588208 -0 -0.7071068 -0.7071068 0 -0.7071068 -0.7071068 -0 -0.2588208 -0.9659253 0 -0.2588208 -0.9659253 -0 0.2588208 -0.9659253 0 0.2588208 -0.9659253 0 0.7071035 -0.70711 0 0.7071035 -0.70711 0 0.965927 -0.2588147 0 0.965927 -0.2588147 0 0.965927 0.2588147 0 0.965927 0.2588147 0 0.7071068 0.7071068 0 0.7071068 0.7071068 0 0.2588147 0.965927 0 0.2588147 0.965927 0 -0.2588147 0.965927 0 -0.2588147 0.965927 0 -0.70711 0.7071035 0 -0.70711 0.7071035 0 -0.9659253 0.2588208 0 -0.9659253 0.2588208 0 -0.9659261 -0.2588177 0 -0.9659261 -0.2588177 -0 -0.707106 -0.7071076 0 -0.707106 -0.7071076 -0 -0.2588204 -0.9659255 0 -0.2588204 -0.9659255 -0 0.2588208 -0.9659253 0 0.2588208 -0.9659253 0 0.707106 -0.7071076 0 0.707106 -0.7071076 0 0.9659258 -0.2588193 0 0.9659258 -0.2588193 0 0.9659258 0.2588193 0 0.9659258 0.2588193 0 0.707106 0.7071076 0 0.707106 0.7071076 0 0.2588208 0.9659253 0 0.2588208 0.9659253 0 -0.2588204 0.9659255 0 -0.2588204 0.9659255 0 -0.707106 0.7071076 0 -0.707106 0.7071076 0 -0.9659261 0.2588177 0 -0.9659261 0.2588177 0 -0.9659261 -0.2588177 0 -0.9659261 -0.2588177 -0 -0.7071092 -0.7071043 0 -0.7071092 -0.7071043 -0 -0.2588081 -0.9659287 0 -0.2588081 -0.9659287 -0 0.2588086 -0.9659286 0 0.2588086 -0.9659286 0 0.7071092 -0.7071043 0 0.7071092 -0.7071043 0 0.9659258 -0.2588193 0 0.9659258 -0.2588193 0 0.9659258 0.2588193 0 0.9659258 0.2588193 0 0.707106 0.7071076 0 0.707106 0.7071076 0 0.2588208 0.9659253 0 0.2588208 0.9659253 0 -0.2588204 0.9659255 0 -0.2588204 0.9659255 0 -0.707106 0.7071076 0 -0.707106 0.7071076 0 -0.9659261 0.2588177 0 -0.9659261 0.2588177 0 -0.9659253 -0.2588208 0 -0.9659253 -0.2588208 -0 -0.70711 -0.7071035 0 -0.70711 -0.7071035 -0 -0.2588147 -0.965927 0 -0.2588147 -0.965927 -0 0.2588147 -0.965927 0 0.2588147 -0.965927 0 0.7071068 -0.7071068 0 0.7071068 -0.7071068 0 0.965927 -0.2588147 0 0.965927 -0.2588147 0 0.965927 0.2588147 0 0.965927 0.2588147 0 0.7071035 0.70711 0 0.7071035 0.70711 0 0.2588208 0.9659253 0 0.2588208 0.9659253 0 -0.2588208 0.9659253 0 -0.2588208 0.9659253 0 -0.7071068 0.7071068 0 -0.7071068 0.7071068 0 -0.9659253 0.2588208 0 -0.9659253 0.2588208 0 1 0 0 1 0 0 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |

158 0 163 0 162 0 159 1 163 1 158 1 154 2 159 2 158 2 155 3 159 3 154 3 150 4 155 4 154 4 151 5 155 5 150 5 146 6 151 6 150 6 147 7 151 7 146 7 122 8 147 8 146 8 123 9 147 9 122 9 90 10 123 10 122 10 91 11 123 11 90 11 86 12 91 12 90 12 87 13 91 13 86 13 82 14 87 14 86 14 83 15 87 15 82 15 78 16 83 16 82 16 79 17 83 17 78 17 74 18 79 18 78 18 75 19 79 19 74 19 22 20 75 20 74 20 23 21 75 21 22 21 18 22 23 22 22 22 19 23 23 23 18 23 14 24 19 24 18 24 15 25 19 25 14 25 10 26 15 26 14 26 11 27 15 27 10 27 6 28 11 28 10 28 7 29 11 29 6 29 2 30 7 30 6 30 3 31 7 31 2 31 0 32 3 32 2 32 1 33 3 33 0 33 4 34 1 34 0 34 5 35 1 35 4 35 8 36 5 36 4 36 9 37 5 37 8 37 12 38 9 38 8 38 13 39 9 39 12 39 16 40 13 40 12 40 17 41 13 41 16 41 20 42 17 42 16 42 21 43 17 43 20 43 72 44 21 44 20 44 73 45 21 45 72 45 76 46 73 46 72 46 77 47 73 47 76 47 80 48 77 48 76 48 81 49 77 49 80 49 84 50 81 50 80 50 85 51 81 51 84 51 88 52 85 52 84 52 89 53 85 53 88 53 120 54 89 54 88 54 121 55 89 55 120 55 144 56 121 56 120 56 145 57 121 57 144 57 148 58 145 58 144 58 149 59 145 59 148 59 152 60 149 60 148 60 153 61 149 61 152 61 156 62 153 62 152 62 157 63 153 63 156 63 160 64 157 64 156 64 161 65 157 65 160 65 57 66 39 66 47 66 163 67 159 67 55 67 63 68 163 68 55 68 133 69 121 69 145 69 155 70 137 70 159 70 57 71 47 71 55 71 159 72 57 72 55 72 65 73 57 73 159 73 71 74 65 74 159 74 127 75 135 75 157 75 115 76 127 76 157 76 57 77 49 77 25 77 31 78 57 78 25 78 39 79 57 79 31 79 141 80 133 80 145 80 149 81 141 81 145 81 135 82 141 82 149 82 153 83 135 83 149 83 157 84 135 84 153 84 43 85 23 85 35 85 69 86 107 86 115 86 157 87 69 87 115 87 63 88 69 88 157 88 161 89 63 89 157 89 163 90 63 90 161 90 73 91 77 91 53 91 45 92 73 92 53 92 21 93 73 93 45 93 75 94 23 94 43 94 95 95 79 95 75 95 69 96 61 96 93 96 99 97 69 97 93 97 107 98 69 98 99 98 121 99 133 99 125 99 113 100 121 100 125 100 89 101 121 101 113 101 105 102 89 102 113 102 85 103 89 103 105 103 97 104 85 104 105 104 81 105 85 105 97 105 93 106 81 106 97 106 77 107 81 107 93 107 61 108 77 108 93 108 53 109 77 109 61 109 143 110 137 110 155 110 151 111 143 111 155 111 139 112 143 112 151 112 147 113 139 113 151 113 131 114 139 114 147 114 123 115 131 115 147 115 119 116 131 116 123 116 159 117 137 117 129 117 117 118 159 118 129 118 71 119 159 119 117 119 27 120 35 120 23 120 19 121 27 121 23 121 33 122 27 122 19 122 15 123 33 123 19 123 41 124 33 124 15 124 11 125 41 125 15 125 7 126 41 126 11 126 111 127 119 127 123 127 91 128 111 128 123 128 103 129 111 129 91 129 87 130 103 130 91 130 95 131 103 131 87 131 83 132 95 132 87 132 79 133 95 133 83 133 41 134 7 134 3 134 1 135 41 135 3 135 49 136 41 136 1 136 5 137 49 137 1 137 71 138 117 138 109 138 101 139 71 139 109 139 67 140 71 140 101 140 95 141 67 141 101 141 59 142 67 142 95 142 75 143 59 143 95 143 51 144 59 144 75 144 43 145 51 145 75 145 21 146 45 146 37 146 29 147 21 147 37 147 17 148 21 148 29 148 25 149 17 149 29 149 13 150 17 150 25 150 49 151 13 151 25 151 9 152 13 152 49 152 5 153 9 153 49 153 92 154 44 154 98 154 106 155 98 155 44 155 36 156 20 156 28 156 72 157 20 157 36 157 114 158 106 158 44 158 52 159 114 159 44 159 60 160 114 160 52 160 72 161 36 161 44 161 92 162 72 162 44 162 76 163 72 163 92 163 80 164 76 164 92 164 48 165 2 165 40 165 50 166 22 166 74 166 84 167 80 167 92 167 96 168 84 168 92 168 88 169 84 169 96 169 104 170 88 170 96 170 120 171 88 171 104 171 160 172 156 172 56 172 64 173 160 173 56 173 70 174 160 174 64 174 90 175 122 175 118 175 110 176 90 176 118 176 86 177 90 177 110 177 102 178 86 178 110 178 82 179 86 179 102 179 94 180 82 180 102 180 78 181 82 181 94 181 74 182 78 182 94 182 56 183 156 183 152 183 148 184 56 184 152 184 144 185 56 185 148 185 120 186 104 186 112 186 124 187 120 187 112 187 144 188 120 188 124 188 132 189 144 189 124 189 94 190 100 190 70 190 66 191 94 191 70 191 74 192 94 192 66 192 58 193 74 193 66 193 50 194 74 194 58 194 150 195 154 195 136 195 142 196 150 196 136 196 146 197 150 197 142 197 138 198 146 198 142 198 122 199 146 199 138 199 130 200 122 200 138 200 118 201 122 201 130 201 70 202 100 202 108 202 116 203 70 203 108 203 160 204 70 204 116 204 128 205 160 205 116 205 162 206 160 206 128 206 136 207 162 207 128 207 158 208 162 208 136 208 154 209 158 209 136 209 134 210 126 210 56 210 144 211 134 211 56 211 140 212 134 212 144 212 132 213 140 213 144 213 114 214 60 214 68 214 62 215 114 215 68 215 54 216 114 216 62 216 22 217 50 217 42 217 34 218 22 218 42 218 18 219 22 219 34 219 26 220 18 220 34 220 14 221 18 221 26 221 32 222 14 222 26 222 10 223 14 223 32 223 40 224 10 224 32 224 6 225 10 225 40 225 2 226 6 226 40 226 24 227 28 227 20 227 16 228 24 228 20 228 30 229 24 229 16 229 12 230 30 230 16 230 38 231 30 231 12 231 8 232 38 232 12 232 4 233 38 233 8 233 38 234 4 234 0 234 2 235 38 235 0 235 46 236 38 236 2 236 48 237 46 237 2 237 54 238 46 238 48 238 56 239 54 239 48 239 114 240 54 240 56 240 126 241 114 241 56 241 66 242 70 242 71 242 67 243 66 243 71 243 58 244 66 244 67 244 59 245 58 245 67 245 50 246 58 246 59 246 51 247 50 247 59 247 42 248 50 248 51 248 43 249 42 249 51 249 34 250 42 250 43 250 35 251 34 251 43 251 26 252 34 252 35 252 27 253 26 253 35 253 32 254 26 254 27 254 33 255 32 255 27 255 40 256 32 256 33 256 41 257 40 257 33 257 48 258 40 258 41 258 49 259 48 259 41 259 56 260 48 260 49 260 57 261 56 261 49 261 64 262 56 262 57 262 65 263 64 263 57 263 70 264 64 264 65 264 71 265 70 265 65 265 138 266 142 266 143 266 139 267 138 267 143 267 130 268 138 268 139 268 131 269 130 269 139 269 118 270 130 270 131 270 119 271 118 271 131 271 110 272 118 272 119 272 111 273 110 273 119 273 102 274 110 274 111 274 103 275 102 275 111 275 94 276 102 276 103 276 95 277 94 277 103 277 100 278 94 278 95 278 101 279 100 279 95 279 108 280 100 280 101 280 109 281 108 281 101 281 116 282 108 282 109 282 117 283 116 283 109 283 128 284 116 284 117 284 129 285 128 285 117 285 136 286 128 286 129 286 137 287 136 287 129 287 142 288 136 288 137 288 143 289 142 289 137 289 134 290 140 290 141 290 135 291 134 291 141 291 126 292 134 292 135 292 127 293 126 293 135 293 114 294 126 294 127 294 115 295 114 295 127 295 106 296 114 296 115 296 107 297 106 297 115 297 98 298 106 298 107 298 99 299 98 299 107 299 92 300 98 300 99 300 93 301 92 301 99 301 96 302 92 302 93 302 97 303 96 303 93 303 104 304 96 304 97 304 105 305 104 305 97 305 112 306 104 306 105 306 113 307 112 307 105 307 124 308 112 308 113 308 125 309 124 309 113 309 132 310 124 310 125 310 133 311 132 311 125 311 140 312 132 312 133 312 141 313 140 313 133 313 62 314 68 314 69 314 63 315 62 315 69 315 54 316 62 316 63 316 55 317 54 317 63 317 46 318 54 318 55 318 47 319 46 319 55 319 38 320 46 320 47 320 39 321 38 321 47 321 30 322 38 322 39 322 31 323 30 323 39 323 24 324 30 324 31 324 25 325 24 325 31 325 28 326 24 326 25 326 29 327 28 327 25 327 36 328 28 328 29 328 37 329 36 329 29 329 44 330 36 330 37 330 45 331 44 331 37 331 52 332 44 332 45 332 53 333 52 333 45 333 60 334 52 334 53 334 61 335 60 335 53 335 68 336 60 336 61 336 69 337 68 337 61 337 161 338 160 338 162 338 163 339 161 339 162 339

81 |
82 |
83 |
84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
107 | -------------------------------------------------------------------------------- /turtlebot4_description/meshes/weight_block.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2022-03-23T14:01:27.861365 5 | 2022-03-23T14:01:27.861370 6 | 7 | Z_UP 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 0.0 0.0 0.0 1.0 16 | 17 | 18 | 0.0 0.0 0.0 1.0 19 | 20 | 21 | 0.753 0.753 0.753 1.0 22 | 23 | 24 | 1 1 1 1.0 25 | 26 | 27 | 0.0 28 | 29 | 30 | 0.0 0.0 0.0 1.0 31 | 32 | 33 | 0.0 34 | 35 | 36 | 0.0 0.0 0.0 1.0 37 | 38 | 39 | 1.0 40 | 41 | 42 | 43 | 44 | 45 | 0 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -0.01775167 0.02120715 -0.004500001 -0.01775167 0.02120715 0.004499999 -0.01770006 0.02073466 -0.0045 -0.01770006 0.02073466 0.004500001 -0.01757933 0.0216501 -0.004500001 -0.01757933 0.0216501 0.004499999 -0.01722195 0.02196345 -0.0045 -0.01722195 0.02196345 0.004500001 -0.01676027 0.0220764 -0.0045 -0.01676027 0.0220764 0.0045 -0.007622411 0.01570014 0.0045 -0.007622411 0.01570014 -0.004499999 -0.007622409 0.01445267 -0.0045 -0.007622409 0.01445267 0.0045 -0.007115019 0.01331305 -0.004499999 -0.007115019 0.01331305 0.0045 -0.007115014 0.01683976 -0.0045 -0.007115014 0.01683976 0.0045 -0.006187963 0.01247833 0.0045 -0.006187963 0.01767448 0.0045 -0.006187963 0.01247833 -0.0045 -0.006187963 0.01767448 -0.004500001 -0.005001549 0.01209284 -0.004500001 -0.005001549 0.01209284 0.0045 -0.005001546 0.01805997 0.0045 -0.005001546 0.01805997 -0.0045 -0.003760915 0.01792957 0.0045 -0.003760915 0.01792957 -0.0045 -0.00376091 0.01222323 0.0045 -0.00376091 0.01222324 -0.0045 -0.002680577 0.01730584 0.0045 -0.002680576 0.01730584 -0.0045 -0.002680574 0.01284697 0.0045 -0.002680574 0.01284697 -0.0045 -0.00264426 -0.00133942 0.0045 -0.002644259 -0.00133942 -0.0045 -0.002590086 -0.0003055647 -0.004499999 -0.002590072 -0.0003055617 0.004499999 -0.002427337 -0.02126534 -0.0045 -0.002427337 -0.02126534 0.004500001 -0.002215045 -0.02160969 0.0045 -0.002215044 -0.02160969 -0.0045 -0.002174262 -0.00226186 -0.004499999 -0.002174248 -0.002261857 0.004499999 -0.002026231 0.0005626921 0.0045 -0.002026231 0.0005626921 -0.0045 -0.001947335 0.01629661 0.004500001 -0.001947335 0.01629661 -0.0045 -0.001947332 0.01385619 0.0045 -0.001947332 0.01385619 -0.0045 -0.001883713 -0.02184177 0.0045 -0.001883713 -0.02184177 -0.004499999 -0.001687971 0.0150764 0.004500001 -0.001687971 0.0150764 -0.0045 -0.001487545 -0.0219236 -0.0045 -0.001487545 -0.0219236 0.004500001 -0.001306003 -0.002825712 -0.0045 -0.001306003 -0.002825712 0.0045 -0.001103783 0.001032699 0.004499999 -0.001103783 0.001032699 -0.004500001 -0.0002721362 -0.002879892 0.004499999 -0.0002721361 -0.002879892 -0.004500001 -6.993057e-05 0.0009785165 0.0045 -6.993032e-05 0.0009785166 -0.0045 0.0006502969 -0.002409887 0.0045 0.0006502972 -0.002409887 -0.0045 0.0007983288 0.0004146651 0.004499999 0.0007983289 0.0004146651 -0.004500002 0.001214152 -0.001541631 0.004499999 0.001214152 -0.00154163 -0.004500002 0.001268326 -0.0005077747 0.0045 0.001268326 -0.0005077747 -0.0045 0.002312033 0.0220764 -0.0045 0.002312033 0.0220764 0.0045 0.002812038 0.02194243 0.004499999 0.002812039 0.02194243 -0.004500001 0.00317806 0.0215764 0.0045 0.00317806 0.0215764 -0.0045 0.003312028 0.0210764 0.004500001 0.003312028 0.0210764 -0.004499999 0.003312041 0.001076404 0.004499999 0.003312041 0.001076404 -0.0045 0.003388155 0.0006937186 0.0045 0.003388155 0.0006937187 -0.004499999 0.00360492 0.0003692954 0.004500001 0.003604921 0.0003692955 -0.004499998 0.003929347 0.0001525225 0.0045 0.003929347 0.0001525225 -0.0045 0.004312036 7.640237e-05 0.0045 0.004312036 7.640238e-05 -0.0045 0.007312036 -0.0219236 -0.004500001 0.007312036 -0.0219236 0.0045 0.007694711 -0.02184748 -0.004499998 0.007694711 -0.02184748 0.004500001 0.008019134 -0.0216307 0.004500001 0.008019135 -0.0216307 -0.004499999 0.00823592 -0.02130628 -0.004500001 0.00823592 -0.02130628 0.004499999 0.008312027 -0.0159236 0.004500001 0.008312028 -0.0159236 -0.0045 0.008312037 -0.0209236 -0.0045 0.008312037 -0.0209236 0.0045 0.00838816 -0.01554091 -0.004500001 0.00838816 -0.01554091 0.004499999 0.008604931 -0.01521649 -0.0045 0.008604931 -0.01521649 0.004499999 0.008929354 -0.01499972 -0.0045 0.008929354 -0.01499972 0.0045 0.009312029 -0.0149236 0.004500001 0.00931203 -0.0149236 -0.004499999 0.01631203 7.640263e-05 0.004500001 0.01631203 7.640268e-05 -0.004499999 0.01631203 -0.0149236 -0.004499999 0.01631203 -0.0149236 0.0045 0.01669472 2.824832e-07 0.0045 0.01669472 2.825201e-07 -0.0045 0.01669472 -0.01484748 -0.0045 0.01669472 -0.01484748 0.0045 0.01701914 -0.0146307 -0.004500001 0.01701914 -0.0146307 0.0045 0.01701914 -0.0002164904 0.0045 0.01701914 -0.0002164904 -0.0045 0.01723591 -0.0005409154 0.0045 0.01723591 -0.0005409154 -0.0045 0.01723592 -0.01430628 -0.0045 0.01723592 -0.01430628 0.0045 0.01731203 -0.0139236 -0.0045 0.01731203 -0.0139236 0.0045 0.01731204 -0.000923596 0.004499999 0.01731204 -0.0009235959 -0.0045 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 0 1 0 0 1 -0 -0.994087 -0.1085859 0 -0.994087 -0.1085859 0 -0.9319413 0.3626093 0 -0.9319413 0.3626093 0 -0.6592722 0.7519043 0 -0.6592722 0.7519043 0 -0.2376481 0.9713513 0 -0.2376481 0.9713513 0 -0.9397935 -0.341743 0 -0.9397935 -0.341743 0 -0.2022724 -0.9793293 0 -0.2022726 -0.9793293 -5.358393e-09 -0.5737084 -0.8190596 -1.432512e-08 -0.5737087 -0.8190594 -3.039618e-08 -0.8512356 -0.5247837 -4.502115e-08 -0.8512352 -0.5247846 0 2.167545e-07 -1 0 2.167545e-07 -1 0 0.9807868 -0.1950824 0 0.9807868 -0.1950824 0 0.8314546 -0.5555927 0 0.8314557 -0.555591 8.810422e-08 0.5555736 -0.8314674 5.940733e-08 0.5555725 -0.8314681 0 0.1950892 -0.9807855 0 0.1950892 -0.9807855 0 1 2.098085e-06 1.059638e-07 1 1.90735e-06 -0 0.1950913 -0.9807851 -8.32779e-08 0.1950895 -0.9807855 0 0.555573 -0.8314677 0 0.555573 -0.8314677 0 0.8314704 -0.5555691 0 0.8314704 -0.5555691 0 0.9807801 -0.1951168 0 0.9807796 -0.1951191 1.039271e-07 1.362392e-07 -1 0 -7.218211e-15 -1 -1.059638e-07 0.9807859 -0.1950871 0 0.9807859 -0.1950871 0 0.8314723 -0.5555663 0 0.8314723 -0.5555663 0 0.5555663 -0.8314722 0 0.5555663 -0.8314723 0 0.1950914 -0.9807851 0 0.1950914 -0.9807851 0 1 -2.934382e-07 -1.943364e-15 1 -2.934382e-07 0 0.195087 0.980786 5.834573e-09 0.1950871 0.980786 4.015278e-09 0.5555666 0.831472 4.243348e-09 0.5555666 0.831472 4.129966e-09 0.8314785 0.555557 2.121702e-09 0.8314785 0.555557 3.679308e-09 0.9807813 0.1951104 1.591273e-09 0.9807813 0.1951103 1.292165e-09 -2.173087e-08 1 1.655685e-09 -2.483528e-08 1 5.794896e-09 0.9807886 0.1950733 2.864276e-08 0.9807886 0.1950733 2.727394e-08 0.8314779 0.5555578 2.546055e-08 0.8314779 0.5555578 2.570595e-08 0.5555667 0.831472 2.121675e-08 0.5555666 0.831472 2.022411e-08 0.1950872 0.9807858 1.166915e-08 0.195087 0.980786 1.623872e-09 1 6.437303e-07 2.649095e-08 1 6.437303e-07 2.649096e-08 0.2588157 0.9659267 0 0.2588156 0.9659268 6.856271e-09 0.7071114 0.7071021 1.599276e-08 0.7071114 0.7071022 1.873205e-08 0.9659291 0.2588069 2.558828e-08 0.9659291 0.2588069 2.558838e-08 0.8910101 0.4539833 4.797816e-08 0.891004 0.4539956 -1.536931e-06 0.5446373 0.8386716 -1.119485e-06 0.5446455 0.8386664 0 0.05233328 0.9986297 0 0.0523333 0.9986297 5.198846e-10 -0.4539914 0.8910061 -6.397103e-09 -0.4539914 0.8910061 -1.503333e-08 -0.8386695 0.5446408 -2.878675e-08 -0.8386693 0.5446409 -3.894546e-09 -0.99863 0.05232789 -1.159472e-08 -0.99863 0.05232789 -1.288078e-08 -0.8910102 -0.4539833 -1.599272e-08 -0.8910102 -0.4539833 -1.330516e-08 -0.5446372 -0.8386717 -6.397057e-09 -0.5446372 -0.8386717 -2.088401e-08 -0.05233689 -0.9986295 -7.99638e-09 -0.05233695 -0.9986295 -6.932278e-10 0.4539881 -0.8910078 6.397015e-09 0.4539881 -0.8910078 1.202658e-08 0.8386694 -0.5446408 2.23897e-08 0.8386748 -0.5446324 -1.130473e-06 0.9986299 -0.05232789 -1.543698e-06 0.9986293 -0.05234174 5.290928e-08 1.080159e-06 -9.088293e-08 1 -4.693647e-07 -1.553398e-07 1 -7.947287e-08 -1.986825e-06 1 7.900258e-08 7.335952e-08 1 7.335047e-07 6.220323e-07 1 6.811955e-08 2.193855e-07 1 3.810506e-07 3.137292e-08 1 -1.223194e-08 -3.764604e-08 1 6.283904e-07 1.266482e-07 1 -1.552684e-06 1.461392e-07 1 2.217315e-06 9.59302e-08 1 2.035195e-07 7.400709e-08 1 -7.460783e-10 -6.53139e-08 1 -9.083137e-07 -1.065373e-06 1 -3.109576e-07 -2.887463e-07 1 5.159401e-07 -1.871924e-06 1 6.916143e-07 -2.78723e-06 1 -1.423147e-05 -6.569252e-06 1 1.409231e-06 -9.062477e-08 1 2.637221e-06 7.298988e-07 1 -6.569309e-07 -2.861038e-07 1 5.644813e-06 3.861122e-06 1 0 0 1 -3.782516e-07 -2.721792e-07 1 -2.059828e-06 -1.316666e-06 1 -2.210515e-06 -1.415757e-06 1 9.222057e-07 -4.361596e-09 1 3.915954e-06 -3.552983e-07 1 -1.308419e-06 1.866444e-07 1 -2.526576e-06 -6.823579e-09 1 -1.531984e-06 -6.515306e-08 1 0.0001504163 -6.961414e-06 1 -1.29606e-06 -3.317649e-09 1 -0 0 1 0 0 1 1.070239e-07 -8.918661e-08 1 1.437542e-07 -9.536736e-08 1 1.818436e-07 -1.411341e-06 1 -1.115353e-06 3.51625e-06 1 -9.093507e-07 1.604393e-06 1 -1.208476e-06 2.132148e-06 1 7.960359e-07 -3.208053e-06 1 2.012113e-06 2.412648e-06 1 -2.694423e-08 4.032531e-08 1 -3.884503e-08 2.595515e-08 1 1.829457e-07 3.369633e-07 1 1.515848e-06 2.247151e-06 1 -2.81787e-06 -4.394976e-06 1 6.549292e-08 2.915922e-08 1 4.731634e-08 9.043187e-14 1 2.716392e-06 5.342716e-06 1 -1.55423e-07 6.047356e-08 1 0 0 1 2.257466e-07 5.42186e-07 1 0 -1.187215e-07 1 -1.064585e-05 1.59325e-05 1 9.709621e-06 -4.423345e-06 1 -6.221837e-06 6.221837e-06 1 -1.790745e-08 1.790744e-08 1 1.625658e-07 8.978108e-08 1 -1.167547e-06 1.746716e-07 1 -1.047365e-08 -9.964992e-08 1 -5.142961e-07 6.381879e-07 1 1.510533e-06 -1.480886e-06 1 -8.578632e-08 4.101511e-07 1 -1.230427e-06 1.375073e-06 1 -1.393981e-06 1.533844e-06 1 0.9135462 0.4067351 0 0.9135462 0.4067351 0 0.6691281 0.7431471 0 0.6691288 0.7431465 1.141984e-07 0.3090178 0.9510563 1.167966e-07 0.309017 0.9510565 0 -0.1045296 0.9945218 0 -0.1045288 0.9945219 1.026143e-07 -0.5000009 0.8660249 7.432541e-08 -0.5000014 0.8660246 -1.324551e-08 -0.8090178 0.5877842 -2.123577e-08 -0.8090178 0.5877842 -2.143165e-08 -0.9781481 0.2079094 -2.654469e-08 -0.978148 0.2079097 2.203091e-08 -0.9781476 -0.2079117 -2.123575e-08 -0.9781477 -0.2079116 -1.295603e-08 -0.8090184 -0.5877833 -1.061788e-08 -0.8090183 -0.5877833 -2.143167e-08 -0.5000011 -0.8660247 -1.061789e-08 -0.500001 -0.8660248 -2.649101e-08 -0.1045287 -0.9945219 -5.308957e-09 -0.1045287 -0.9945219 -5.53813e-09 0.3090171 -0.9510565 1.592677e-08 0.3090171 -0.9510565 1.637231e-08 0.6691298 -0.7431455 3.185363e-08 0.66913 -0.7431454 0 0.9135443 -0.4067393 0 0.9135441 -0.4067396 4.840131e-08 1 1.528975e-06 5.298191e-08 1 1.911219e-06 0 -2.821515e-09 -3.667977e-08 -1 -3.412184e-06 -1.871613e-06 -1 -7.029532e-07 -2.094597e-07 -1 -1.406113e-06 -6.166728e-07 -1 -6.783984e-08 -2.466903e-08 -1 -1.625658e-07 -8.978108e-08 -1 -1.613483e-06 -1.984703e-06 -1 -3.018175e-06 -3.618979e-06 -1 -1.115503e-06 -1.472336e-06 -1 -9.327185e-07 5.203199e-06 -1 7.224036e-07 4.404394e-07 -1 -7.625663e-08 1.3208e-07 -1 7.419686e-06 2.229652e-06 -1 4.272739e-07 1.620472e-07 -1 -1.521308e-07 3.233603e-08 -1 -1.651796e-06 -4.257258e-06 -1 1.430544e-06 8.943985e-07 -1 -9.066462e-07 -2.496573e-07 -1 1.717821e-07 1.807537e-07 -1 -1.573192e-06 -1.175109e-06 -1 1.854517e-06 1.28649e-06 -1 3.062119e-06 9.405066e-09 -1 -2.145605e-06 7.875784e-08 -1 -2.120825e-06 7.725094e-08 -1 -9.214276e-07 1.920671e-08 -1 2.633465e-06 -3.495548e-07 -1 -1.208382e-06 -2.30349e-08 -1 -6.811959e-08 -1.614665e-07 -1 3.305767e-06 2.173868e-06 -1 1.161594e-06 7.638626e-07 -1 1.027451e-06 6.620198e-07 -1 -1.223767e-06 6.376137e-06 -1 5.548261e-09 -2.890784e-08 -1 1.136933e-06 1.324092e-06 -1 9.340058e-07 1.060265e-06 -1 1.58664e-06 1.879429e-06 -1 -1.12746e-07 -8.191435e-08 -1 -1.518227e-05 4.265845e-06 -1 -6.203394e-06 -7.084415e-06 -1 4.210893e-06 3.329778e-06 -1 -2.755619e-06 -1.325136e-06 -1 1.192093e-07 1.549724e-06 -1 -1.629733e-06 1.036016e-06 -1 2.088097e-06 -2.098081e-06 -1 1.519718e-07 3.230259e-08 -1 7.629391e-08 9.53675e-08 -1 -4.135422e-08 5.33502e-08 -1 2.510514e-06 -3.23876e-06 -1 1.697939e-06 -1.80511e-06 -1 2.031887e-07 -4.125541e-07 -1 -1.047365e-08 -9.964992e-08 -1 0 -1.187215e-07 -1 4.317239e-07 1.145216e-06 -1 -5.187649e-07 -1.137617e-06 -1 2.173963e-06 1.487018e-06 -1 -5.64481e-06 -3.86112e-06 -1 4.66366e-07 1.606916e-07 -1 2.861007e-07 1.907355e-07 -1 9.214355e-06 -8.737519e-06 -1 -2.195507e-06 -1.113606e-06 -1 -1.322889e-07 -3.595175e-07 -1 4.292338e-07 7.644881e-07 -1 -7.875328e-07 -1.187465e-06 -1 -4.93069e-06 1.171051e-05 -1 6.428587e-07 1.001951e-06 -1 -2.651583e-07 -9.733299e-07 -1 -1.160695e-06 -3.154384e-06 -1 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |

8 0 9 0 73 0 72 1 8 1 73 1 1 2 2 2 3 2 0 3 2 3 1 3 5 4 0 4 1 4 4 5 0 5 5 5 7 6 4 6 5 6 6 7 4 7 7 7 9 8 6 8 7 8 8 9 6 9 9 9 38 10 39 10 3 10 2 11 38 11 3 11 50 12 54 12 55 12 51 13 54 13 50 13 40 14 51 14 50 14 41 15 51 15 40 15 39 16 41 16 40 16 38 17 41 17 39 17 90 18 91 18 55 18 54 19 90 19 55 19 97 20 100 20 101 20 96 21 100 21 97 21 94 22 96 22 97 22 95 23 96 23 94 23 93 24 95 24 94 24 92 25 95 25 93 25 91 26 92 26 93 26 90 27 92 27 91 27 99 28 98 28 101 28 100 29 99 29 101 29 106 30 109 30 108 30 107 31 106 31 108 31 104 32 106 32 107 32 105 33 104 33 107 33 102 34 104 34 105 34 103 35 102 35 105 35 99 36 102 36 103 36 98 37 99 37 103 37 112 38 113 38 108 38 109 39 112 39 108 39 125 40 126 40 127 40 124 41 126 41 125 41 119 42 124 42 125 42 118 43 124 43 119 43 117 44 118 44 119 44 116 45 118 45 117 45 113 46 116 46 117 46 112 47 116 47 113 47 129 48 128 48 127 48 126 49 129 49 127 49 114 50 111 50 110 50 115 51 111 51 114 51 120 52 115 52 114 52 121 53 115 53 120 53 122 54 121 54 120 54 123 55 121 55 122 55 128 56 123 56 122 56 129 57 123 57 128 57 89 58 88 58 110 58 111 59 89 59 110 59 83 60 81 60 80 60 82 61 83 61 80 61 85 62 83 62 82 62 84 63 85 63 82 63 87 64 85 64 84 64 86 65 87 65 84 65 89 66 87 66 86 66 88 67 89 67 86 67 79 68 78 68 80 68 81 69 79 69 80 69 74 70 72 70 73 70 75 71 72 71 74 71 76 72 75 72 74 72 77 73 75 73 76 73 78 74 77 74 76 74 79 75 77 75 78 75 42 76 35 76 34 76 43 77 42 77 34 77 56 78 42 78 43 78 57 79 56 79 43 79 61 80 56 80 57 80 60 81 61 81 57 81 65 82 61 82 60 82 64 83 65 83 60 83 69 84 65 84 64 84 68 85 69 85 64 85 71 86 69 86 68 86 70 87 71 87 68 87 67 88 71 88 70 88 66 89 67 89 70 89 63 90 67 90 66 90 62 91 63 91 66 91 59 92 63 92 62 92 58 93 59 93 62 93 45 94 59 94 58 94 44 95 45 95 58 95 36 96 45 96 44 96 37 97 36 97 44 97 35 98 36 98 37 98 34 99 35 99 37 99 52 100 44 100 58 100 62 101 52 101 58 101 128 102 110 102 88 102 127 103 128 103 88 103 68 104 64 104 108 104 113 105 68 105 108 105 34 106 28 106 23 106 18 107 34 107 23 107 15 108 34 108 18 108 39 109 57 109 43 109 34 110 39 110 43 110 3 111 39 111 34 111 15 112 3 112 34 112 68 113 125 113 127 113 88 114 68 114 127 114 70 115 68 115 88 115 86 116 70 116 88 116 128 117 122 117 120 117 114 118 128 118 120 118 110 119 128 119 114 119 60 120 101 120 98 120 60 121 98 121 103 121 105 122 60 122 103 122 64 123 60 123 105 123 107 124 64 124 105 124 108 125 64 125 107 125 60 126 57 126 39 126 40 127 60 127 39 127 50 128 60 128 40 128 37 129 44 129 52 129 48 130 37 130 52 130 34 131 37 131 48 131 32 132 34 132 48 132 28 133 34 133 32 133 78 134 46 134 52 134 62 135 78 135 52 135 80 136 78 136 62 136 66 137 80 137 62 137 82 138 80 138 66 138 70 139 82 139 66 139 84 140 82 140 70 140 86 141 84 141 70 141 68 142 113 142 117 142 119 143 68 143 117 143 125 144 68 144 119 144 10 145 17 145 9 145 7 146 10 146 9 146 5 147 10 147 7 147 3 148 15 148 13 148 10 149 3 149 13 149 1 150 3 150 10 150 5 151 1 151 10 151 9 152 17 152 19 152 24 153 9 153 19 153 73 154 9 154 24 154 93 155 94 155 97 155 101 156 93 156 97 156 91 157 93 157 101 157 60 158 91 158 101 158 55 159 91 159 60 159 50 160 55 160 60 160 73 161 24 161 26 161 30 162 73 162 26 162 74 163 73 163 30 163 46 164 74 164 30 164 76 165 74 165 46 165 78 166 76 166 46 166 14 167 12 167 13 167 15 168 14 168 13 168 20 169 14 169 15 169 18 170 20 170 15 170 22 171 20 171 18 171 23 172 22 172 18 172 29 173 22 173 23 173 28 174 29 174 23 174 33 175 29 175 28 175 32 176 33 176 28 176 49 177 33 177 32 177 48 178 49 178 32 178 53 179 49 179 48 179 52 180 53 180 48 180 47 181 53 181 52 181 46 182 47 182 52 182 31 183 47 183 46 183 30 184 31 184 46 184 27 185 31 185 30 185 26 186 27 186 30 186 25 187 27 187 26 187 24 188 25 188 26 188 21 189 25 189 24 189 19 190 21 190 24 190 16 191 21 191 19 191 17 192 16 192 19 192 11 193 16 193 17 193 10 194 11 194 17 194 12 195 11 195 10 195 13 196 12 196 10 196 89 197 129 197 126 197 67 198 63 198 14 198 20 199 67 199 14 199 22 200 67 200 20 200 35 201 38 201 2 201 54 202 61 202 90 202 69 203 118 203 116 203 112 204 69 204 116 204 65 205 69 205 112 205 87 206 71 206 85 206 67 207 22 207 29 207 33 208 67 208 29 208 71 209 67 209 33 209 49 210 71 210 33 210 53 211 71 211 49 211 79 212 75 212 77 212 14 213 63 213 59 213 45 214 14 214 59 214 2 215 14 215 45 215 36 216 2 216 45 216 35 217 2 217 36 217 38 218 35 218 42 218 56 219 38 219 42 219 41 220 38 220 56 220 61 221 41 221 56 221 51 222 41 222 61 222 54 223 51 223 61 223 65 224 112 224 109 224 106 225 65 225 109 225 61 226 65 226 106 226 104 227 61 227 106 227 71 228 87 228 89 228 126 229 71 229 89 229 69 230 71 230 126 230 124 231 69 231 126 231 118 232 69 232 124 232 72 233 47 233 31 233 95 234 100 234 96 234 115 235 121 235 123 235 129 236 115 236 123 236 111 237 115 237 129 237 89 238 111 238 129 238 47 239 72 239 75 239 79 240 47 240 75 240 53 241 47 241 79 241 81 242 53 242 79 242 71 243 53 243 81 243 83 244 71 244 81 244 85 245 71 245 83 245 72 246 31 246 27 246 25 247 72 247 27 247 8 248 72 248 25 248 21 249 8 249 25 249 16 250 8 250 21 250 61 251 104 251 102 251 99 252 61 252 102 252 90 253 61 253 99 253 100 254 90 254 99 254 92 255 90 255 100 255 95 256 92 256 100 256 2 257 16 257 11 257 12 258 2 258 11 258 14 259 2 259 12 259 4 260 6 260 8 260 16 261 4 261 8 261 0 262 4 262 16 262 2 263 0 263 16 263

81 |
82 |
83 |
84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
107 | -------------------------------------------------------------------------------- /turtlebot4_description/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | turtlebot4_description 5 | 2.1.0 6 | Turtlebot4 Description package 7 | Chris Iverach-Brereton 8 | Hilary Luo 9 | 10 | Apache 2.0 11 | 12 | Roni Kreinin 13 | 14 | ament_cmake 15 | 16 | irobot_create_description 17 | joint_state_publisher 18 | robot_state_publisher 19 | urdf 20 | 21 | ament_lint_auto 22 | ament_lint_common 23 | 24 | 25 | ament_cmake 26 | 27 | 28 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/lite/turtlebot4.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/sensors/camera_bracket.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/sensors/oakd.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 1.25 127 | 128 | 320 129 | 240 130 | 131 | 132 | 0.3 133 | 100 134 | 135 | ${name}_rgb_camera_optical_frame 136 | 137 | 1 138 | 30 139 | true 140 | 141 | 142 | 143 | 144 | 145 | true 146 | 147 | 148 | 149 | true 150 | 151 | 152 | 153 | true 154 | 155 | 156 | 157 | true 158 | 159 | 160 | 161 | true 162 | 163 | 164 | 165 | true 166 | 167 | 168 | 169 | true 170 | 171 | 172 | 173 | true 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/sensors/rplidar.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/standard/tower_sensor_plate.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | true 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/standard/tower_standoff.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | true 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/standard/turtlebot4.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /turtlebot4_description/urdf/standard/weight_block.urdf.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /turtlebot4_msgs/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package turtlebot4_msgs 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 2.1.0 (2025-05-23) 6 | ------------------ 7 | * Fix tag order 8 | * Update package maintainers 9 | * Contributors: Chris Iverach-Brereton 10 | 11 | 2.0.1 (2024-09-25) 12 | ------------------ 13 | 14 | 2.0.0 (2024-08-29) 15 | ------------------ 16 | 17 | 1.0.5 (2024-07-02) 18 | ------------------ 19 | 20 | 1.0.4 (2023-11-08) 21 | ------------------ 22 | 23 | 1.0.3 (2023-05-31) 24 | ------------------ 25 | 26 | 1.0.2 (2023-05-15) 27 | ------------------ 28 | 29 | 1.0.1 (2023-02-28) 30 | ------------------ 31 | 32 | 1.0.0 (2023-02-17) 33 | ------------------ 34 | 35 | 0.1.2 (2022-09-15) 36 | ------------------ 37 | 38 | 0.1.1 (2022-07-12) 39 | ------------------ 40 | 41 | 0.1.0 (2022-05-03) 42 | ------------------ 43 | * First Galactic release 44 | * Contributors: Roni Kreinin 45 | -------------------------------------------------------------------------------- /turtlebot4_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(turtlebot4_msgs) 3 | 4 | # Default to C99 5 | if(NOT CMAKE_C_STANDARD) 6 | set(CMAKE_C_STANDARD 99) 7 | endif() 8 | 9 | # Default to C++14 10 | if(NOT CMAKE_CXX_STANDARD) 11 | set(CMAKE_CXX_STANDARD 14) 12 | endif() 13 | 14 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | add_compile_options(-Wall -Wextra -Wpedantic) 16 | endif() 17 | 18 | # find dependencies 19 | find_package(ament_cmake REQUIRED) 20 | 21 | if(BUILD_TESTING) 22 | find_package(ament_lint_auto REQUIRED) 23 | ament_lint_auto_find_test_dependencies() 24 | endif() 25 | 26 | find_package(rosidl_default_generators REQUIRED) 27 | find_package(std_msgs REQUIRED) 28 | 29 | rosidl_generate_interfaces(${PROJECT_NAME} 30 | "msg/UserLed.msg" 31 | "msg/UserButton.msg" 32 | "msg/UserDisplay.msg" 33 | ) 34 | 35 | ament_package() 36 | -------------------------------------------------------------------------------- /turtlebot4_msgs/msg/UserButton.msg: -------------------------------------------------------------------------------- 1 | # This message relays the state of the user buttons 2 | # Each button is represented with a boolean, were True indicates the button is pressed 3 | 4 | bool[4] button -------------------------------------------------------------------------------- /turtlebot4_msgs/msg/UserDisplay.msg: -------------------------------------------------------------------------------- 1 | # This message represents the header and 5 entries 2 | # that are displayed on the Turtlebot4 display 3 | # selected_entry indicates which menu entry is currently selected 4 | 5 | string ip 6 | string battery 7 | string[5] entries 8 | int32 selected_entry -------------------------------------------------------------------------------- /turtlebot4_msgs/msg/UserLed.msg: -------------------------------------------------------------------------------- 1 | # This message sets the state of the user LEDs 2 | # Blink period is the time in milliseconds during which the ON/OFF cycle occurs 3 | # The duty cycle represents the percentage of the blink period that the LED is ON 4 | # A duty cycle of 1.0 would set the LED to always be ON, whereas a duty cycle of 0.0 is always OFF 5 | # A blink period of 1000ms with a duty cycle of 0.6 will have the LED turn ON for 600ms, 6 | # then OFF for 400ms 7 | 8 | # Available LEDs 9 | uint8 USER_LED_1 = 0 10 | uint8 USER_LED_2 = 1 11 | 12 | # Available colors 13 | uint8 COLOR_OFF = 0 14 | uint8 COLOR_GREEN = 1 15 | uint8 COLOR_RED = 2 16 | uint8 COLOR_YELLOW = 3 17 | 18 | 19 | # Which available LED to use 20 | uint8 led 21 | 22 | # Which color to set the LED to 23 | uint8 color 24 | 25 | # Blink period in ms 26 | uint32 blink_period 27 | 28 | # Duty cycle (0.0 to 1.0) 29 | float64 duty_cycle -------------------------------------------------------------------------------- /turtlebot4_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | turtlebot4_msgs 5 | 2.1.0 6 | Turtlebot4 Messages 7 | Chris Iverach-Brereton 8 | Hilary Luo 9 | 10 | Apache 2.0 11 | 12 | Roni Kreinin 13 | 14 | ament_cmake 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | std_msgs 20 | 21 | rosidl_default_generators 22 | rosidl_default_runtime 23 | rosidl_interface_packages 24 | 25 | 26 | ament_cmake 27 | 28 | 29 | -------------------------------------------------------------------------------- /turtlebot4_navigation/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package turtlebot4_navigation 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 2.1.0 (2025-05-23) 6 | ------------------ 7 | * Change footprint from radius to octagon of similar size (`#592 `_) 8 | * Nav2 changed how use_sim_time is set, should not be in yaml (`#564 `_) 9 | * Fix tag order 10 | * Update package maintainers 11 | * Adds support for namespaces to TurtleBot4Navigator. 12 | * Contributors: Chris Iverach-Brereton, Hilary Luo, Pbopbo, Pradyum Aadith 13 | 14 | 2.0.1 (2024-09-25) 15 | ------------------ 16 | * Revert to using base_link for navigation; the create3 uses that for odom, and using a different link appears to break slam_toolbox. Update the SLAM launch parameters 17 | * Contributors: Chris Iverach-Brereton 18 | 19 | 2.0.0 (2024-08-29) 20 | ------------------ 21 | * Update the SLAM launch file so it works with the latest version of slam_toolbox. Rather than re-impementing all of the launch file, just include the online_sync or online_async launch files as appropriate 22 | * Update nav2 launch configuration to work with the latest jazzy: syntax changes (/ -> ::) 23 | * Use TwistStamped messages for velocity controllers 24 | * Use MPPIController for path follower plugin instead of DWMLocalPlanner 25 | * Assorted minor yaml formatting fixes (e.g. consistent caps for true & false) 26 | * Use base_footprint link as the tf base for slam & localization 27 | * Contributors: Chris Iverach-Brereton 28 | 29 | 1.0.5 (2024-07-02) 30 | ------------------ 31 | 32 | 1.0.4 (2023-11-08) 33 | ------------------ 34 | * Use opaque function to allow for remapping of scan topics () 35 | * Contributors: Hilary Luo 36 | 37 | 1.0.3 (2023-05-31) 38 | ------------------ 39 | 40 | 1.0.2 (2023-05-15) 41 | ------------------ 42 | * Added namespacing support in sim 43 | * Set warehouse map as default 44 | * New map files for new and modified worlds 45 | * Updating robot radius to max radius and increasing inflation 46 | * Added missing Nav2 plugin 47 | * Contributors: Hilary Luo, Roni Kreinin 48 | 49 | 1.0.1 (2023-02-28) 50 | ------------------ 51 | * Navigator fixes 52 | * Contributors: Roni Kreinin 53 | 54 | 1.0.0 (2023-02-17) 55 | ------------------ 56 | * Namespacing 57 | * Linter fixes 58 | * Nav2, localization, and slam launch and config files 59 | * Contributors: Roni Kreinin 60 | 61 | 0.1.2 (2022-09-15) 62 | ------------------ 63 | * ci: Fixed flake8 lint 64 | * Contributors: Daisuke Nishimatsu, Roni Kreinin 65 | 66 | 0.1.1 (2022-07-12) 67 | ------------------ 68 | * Install turtlebot4_navigation module 69 | * Added turtlebot4 navigator 70 | * Fixed AMCL robot_model_type parameter 71 | * Contributors: Roni Kreinin, roni-kreinin 72 | 73 | 0.1.0 (2022-05-03) 74 | ------------------ 75 | * First Galactic release 76 | * Contributors: Roni Kreinin 77 | -------------------------------------------------------------------------------- /turtlebot4_navigation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(turtlebot4_navigation) 3 | 4 | # Default to C99 5 | if(NOT CMAKE_C_STANDARD) 6 | set(CMAKE_C_STANDARD 99) 7 | endif() 8 | 9 | # Default to C++14 10 | if(NOT CMAKE_CXX_STANDARD) 11 | set(CMAKE_CXX_STANDARD 14) 12 | endif() 13 | 14 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | add_compile_options(-Wall -Wextra -Wpedantic) 16 | endif() 17 | 18 | # find dependencies 19 | find_package(ament_cmake REQUIRED) 20 | find_package(ament_cmake_python REQUIRED) 21 | 22 | install( 23 | DIRECTORY config launch maps 24 | DESTINATION share/${PROJECT_NAME} 25 | ) 26 | 27 | ament_python_install_package(${PROJECT_NAME}) 28 | ament_python_install_module(${PROJECT_NAME}/turtlebot4_navigator.py) 29 | 30 | if(BUILD_TESTING) 31 | find_package(ament_lint_auto REQUIRED) 32 | ament_lint_auto_find_test_dependencies() 33 | endif() 34 | 35 | ament_package() 36 | -------------------------------------------------------------------------------- /turtlebot4_navigation/config/localization.yaml: -------------------------------------------------------------------------------- 1 | amcl: 2 | ros__parameters: 3 | alpha1: 0.2 4 | alpha2: 0.2 5 | alpha3: 0.2 6 | alpha4: 0.2 7 | alpha5: 0.2 8 | base_frame_id: "base_link" 9 | beam_skip_distance: 0.5 10 | beam_skip_error_threshold: 0.9 11 | beam_skip_threshold: 0.3 12 | do_beamskip: false 13 | global_frame_id: "map" 14 | lambda_short: 0.1 15 | laser_likelihood_max_dist: 2.0 16 | laser_max_range: 100.0 17 | laser_min_range: -1.0 18 | laser_model_type: "likelihood_field" 19 | max_beams: 60 20 | max_particles: 2000 21 | min_particles: 500 22 | odom_frame_id: "odom" 23 | pf_err: 0.05 24 | pf_z: 0.99 25 | recovery_alpha_fast: 0.0 26 | recovery_alpha_slow: 0.0 27 | resample_interval: 1 28 | robot_model_type: "nav2_amcl::DifferentialMotionModel" 29 | save_pose_rate: 0.5 30 | sigma_hit: 0.2 31 | tf_broadcast: true 32 | transform_tolerance: 1.0 33 | update_min_a: 0.2 34 | update_min_d: 0.25 35 | z_hit: 0.5 36 | z_max: 0.05 37 | z_rand: 0.5 38 | z_short: 0.05 39 | scan_topic: scan 40 | 41 | map_saver: 42 | ros__parameters: 43 | save_map_timeout: 5.0 44 | free_thresh_default: 0.25 45 | occupied_thresh_default: 0.65 46 | map_subscribe_transient_local: true 47 | -------------------------------------------------------------------------------- /turtlebot4_navigation/config/nav2.yaml: -------------------------------------------------------------------------------- 1 | bt_navigator: 2 | ros__parameters: 3 | enable_stamped_cmd_vel: true 4 | global_frame: map 5 | robot_base_frame: base_link 6 | odom_topic: odom 7 | bt_loop_duration: 10 8 | default_server_timeout: 20 9 | wait_for_service_timeout: 1000 10 | action_server_result_timeout: 900.0 11 | navigators: ["navigate_to_pose", "navigate_through_poses"] 12 | navigate_to_pose: 13 | plugin: "nav2_bt_navigator::NavigateToPoseNavigator" 14 | navigate_through_poses: 15 | plugin: "nav2_bt_navigator::NavigateThroughPosesNavigator" 16 | error_code_names: 17 | - compute_path_error_code 18 | - follow_path_error_code 19 | 20 | controller_server: 21 | ros__parameters: 22 | enable_stamped_cmd_vel: true 23 | controller_frequency: 20.0 24 | min_x_velocity_threshold: 0.001 25 | min_y_velocity_threshold: 0.5 26 | min_theta_velocity_threshold: 0.001 27 | failure_tolerance: 0.3 28 | progress_checker_plugins: ["progress_checker"] 29 | goal_checker_plugins: ["general_goal_checker"] 30 | controller_plugins: ["FollowPath"] 31 | use_realtime_priority: false 32 | progress_checker: 33 | plugin: "nav2_controller::SimpleProgressChecker" 34 | required_movement_radius: 0.5 35 | movement_time_allowance: 10.0 36 | general_goal_checker: 37 | stateful: true 38 | plugin: "nav2_controller::SimpleGoalChecker" 39 | xy_goal_tolerance: 0.25 40 | yaw_goal_tolerance: 0.25 41 | FollowPath: 42 | plugin: "nav2_mppi_controller::MPPIController" 43 | time_steps: 56 44 | model_dt: 0.05 45 | batch_size: 2000 46 | ax_max: 3.0 47 | ax_min: -3.0 48 | ay_max: 3.0 49 | az_max: 3.5 50 | vx_std: 0.2 51 | vy_std: 0.2 52 | wz_std: 0.4 53 | vx_max: 0.5 54 | vx_min: -0.35 55 | vy_max: 0.5 56 | wz_max: 1.9 57 | iteration_count: 1 58 | prune_distance: 1.7 59 | transform_tolerance: 0.1 60 | temperature: 0.3 61 | gamma: 0.015 62 | motion_model: "DiffDrive" 63 | visualize: true 64 | regenerate_noises: true 65 | TrajectoryVisualizer: 66 | trajectory_step: 5 67 | time_step: 3 68 | AckermannConstraints: 69 | min_turning_r: 0.2 70 | critics: [ 71 | "ConstraintCritic", "CostCritic", "GoalCritic", 72 | "GoalAngleCritic", "PathAlignCritic", "PathFollowCritic", 73 | "PathAngleCritic", "PreferForwardCritic"] 74 | ConstraintCritic: 75 | enabled: true 76 | cost_power: 1 77 | cost_weight: 4.0 78 | GoalCritic: 79 | enabled: true 80 | cost_power: 1 81 | cost_weight: 5.0 82 | threshold_to_consider: 1.4 83 | GoalAngleCritic: 84 | enabled: true 85 | cost_power: 1 86 | cost_weight: 3.0 87 | threshold_to_consider: 0.5 88 | PreferForwardCritic: 89 | enabled: true 90 | cost_power: 1 91 | cost_weight: 5.0 92 | threshold_to_consider: 0.5 93 | CostCritic: 94 | enabled: true 95 | cost_power: 1 96 | cost_weight: 3.81 97 | critical_cost: 300.0 98 | consider_footprint: true 99 | collision_cost: 1000000.0 100 | near_goal_distance: 1.0 101 | trajectory_point_step: 2 102 | PathAlignCritic: 103 | enabled: true 104 | cost_power: 1 105 | cost_weight: 14.0 106 | max_path_occupancy_ratio: 0.05 107 | trajectory_point_step: 4 108 | threshold_to_consider: 0.5 109 | offset_from_furthest: 20 110 | use_path_orientations: false 111 | PathFollowCritic: 112 | enabled: true 113 | cost_power: 1 114 | cost_weight: 5.0 115 | offset_from_furthest: 5 116 | threshold_to_consider: 1.4 117 | PathAngleCritic: 118 | enabled: true 119 | cost_power: 1 120 | cost_weight: 2.0 121 | offset_from_furthest: 4 122 | threshold_to_consider: 0.5 123 | max_angle_to_furthest: 1.0 124 | mode: 0 125 | 126 | local_costmap: 127 | local_costmap: 128 | ros__parameters: 129 | enable_stamped_cmd_vel: true 130 | update_frequency: 5.0 131 | publish_frequency: 2.0 132 | global_frame: odom 133 | robot_base_frame: base_link 134 | rolling_window: true 135 | width: 3 136 | height: 3 137 | resolution: 0.06 138 | footprint: "[[ 0.189, 0.000], 139 | [ 0.134, -0.134], 140 | [ 0.000, -0.189], 141 | [-0.134, -0.134], 142 | [-0.189, 0.000], 143 | [-0.134, 0.134], 144 | [ 0.000, 0.189], 145 | [ 0.134, 0.134]]" 146 | plugins: ["static_layer", "voxel_layer", "inflation_layer"] 147 | inflation_layer: 148 | plugin: "nav2_costmap_2d::InflationLayer" 149 | cost_scaling_factor: 4.0 150 | inflation_radius: 0.45 151 | voxel_layer: 152 | plugin: "nav2_costmap_2d::VoxelLayer" 153 | enabled: true 154 | publish_voxel_map: true 155 | origin_z: 0.0 156 | z_resolution: 0.05 157 | z_voxels: 16 158 | max_obstacle_height: 2.0 159 | mark_threshold: 0 160 | observation_sources: scan 161 | scan: 162 | topic: scan 163 | max_obstacle_height: 2.0 164 | clearing: true 165 | marking: true 166 | data_type: "LaserScan" 167 | raytrace_max_range: 3.0 168 | raytrace_min_range: 0.0 169 | obstacle_max_range: 2.5 170 | obstacle_min_range: 0.0 171 | static_layer: 172 | plugin: "nav2_costmap_2d::StaticLayer" 173 | map_subscribe_transient_local: true 174 | always_send_full_costmap: true 175 | 176 | global_costmap: 177 | global_costmap: 178 | ros__parameters: 179 | enable_stamped_cmd_vel: true 180 | update_frequency: 1.0 181 | publish_frequency: 1.0 182 | global_frame: map 183 | robot_base_frame: base_link 184 | footprint: "[[ 0.189, 0.000], 185 | [ 0.134, -0.134], 186 | [ 0.000, -0.189], 187 | [-0.134, -0.134], 188 | [-0.189, 0.000], 189 | [-0.134, 0.134], 190 | [ 0.000, 0.189], 191 | [ 0.134, 0.134]]" 192 | resolution: 0.06 193 | track_unknown_space: true 194 | plugins: ["static_layer", "obstacle_layer", "inflation_layer"] 195 | obstacle_layer: 196 | plugin: "nav2_costmap_2d::ObstacleLayer" 197 | enabled: true 198 | observation_sources: scan 199 | scan: 200 | topic: scan 201 | max_obstacle_height: 2.0 202 | clearing: true 203 | marking: true 204 | data_type: "LaserScan" 205 | raytrace_max_range: 3.0 206 | raytrace_min_range: 0.0 207 | obstacle_max_range: 2.5 208 | obstacle_min_range: 0.0 209 | static_layer: 210 | plugin: "nav2_costmap_2d::StaticLayer" 211 | map_subscribe_transient_local: true 212 | inflation_layer: 213 | plugin: "nav2_costmap_2d::InflationLayer" 214 | cost_scaling_factor: 4.0 215 | inflation_radius: 0.45 216 | always_send_full_costmap: true 217 | 218 | planner_server: 219 | ros__parameters: 220 | enable_stamped_cmd_vel: true 221 | #expected_planner_frequency: 20.0 222 | planner_plugins: ["GridBased"] 223 | GridBased: 224 | plugin: "nav2_navfn_planner::NavfnPlanner" 225 | tolerance: 0.5 226 | use_astar: false 227 | allow_unknown: true 228 | 229 | smoother_server: 230 | ros__parameters: 231 | enable_stamped_cmd_vel: true 232 | smoother_plugins: ["simple_smoother"] 233 | simple_smoother: 234 | plugin: "nav2_smoother::SimpleSmoother" 235 | tolerance: 1.0e-10 236 | max_its: 1000 237 | do_refinement: true 238 | 239 | behavior_server: 240 | ros__parameters: 241 | enable_stamped_cmd_vel: true 242 | local_costmap_topic: local_costmap/costmap_raw 243 | global_costmap_topic: global_costmap/costmap_raw 244 | local_footprint_topic: local_costmap/published_footprint 245 | global_footprint_topic: global_costmap/published_footprint 246 | cycle_frequency: 10.0 247 | behavior_plugins: ["spin", "backup", "drive_on_heading", "assisted_teleop", "wait"] 248 | spin: 249 | plugin: "nav2_behaviors::Spin" 250 | backup: 251 | plugin: "nav2_behaviors::BackUp" 252 | drive_on_heading: 253 | plugin: "nav2_behaviors::DriveOnHeading" 254 | wait: 255 | plugin: "nav2_behaviors::Wait" 256 | assisted_teleop: 257 | plugin: "nav2_behaviors::AssistedTeleop" 258 | global_frame: map 259 | local_frame: odom 260 | robot_base_frame: base_link 261 | transform_tolerance: 0.1 262 | simulate_ahead_time: 2.0 263 | max_rotational_vel: 1.0 264 | min_rotational_vel: 0.4 265 | rotational_acc_lim: 3.2 266 | 267 | waypoint_follower: 268 | ros__parameters: 269 | enable_stamped_cmd_vel: true 270 | loop_rate: 20 271 | stop_on_failure: false 272 | action_server_result_timeout: 900.0 273 | waypoint_task_executor_plugin: "wait_at_waypoint" 274 | wait_at_waypoint: 275 | plugin: "nav2_waypoint_follower::WaitAtWaypoint" 276 | enabled: true 277 | waypoint_pause_duration: 200 278 | 279 | velocity_smoother: 280 | ros__parameters: 281 | enable_stamped_cmd_vel: true 282 | smoothing_frequency: 20.0 283 | scale_velocities: False 284 | feedback: "OPEN_LOOP" 285 | max_velocity: [0.26, 0.0, 1.0] 286 | min_velocity: [-0.26, 0.0, -1.0] 287 | max_accel: [2.5, 0.0, 3.2] 288 | max_decel: [-2.5, 0.0, -3.2] 289 | odom_topic: "odom" 290 | odom_duration: 0.1 291 | deadband_velocity: [0.0, 0.0, 0.0] 292 | velocity_timeout: 1.0 293 | 294 | collision_monitor: 295 | ros__parameters: 296 | enable_stamped_cmd_vel: true 297 | base_frame_id: "base_link" 298 | odom_frame_id: "odom" 299 | cmd_vel_in_topic: "cmd_vel_smoothed" 300 | cmd_vel_out_topic: "cmd_vel" 301 | state_topic: "collision_monitor_state" 302 | transform_tolerance: 0.2 303 | source_timeout: 1.0 304 | base_shift_correction: True 305 | stop_pub_timeout: 2.0 306 | # Polygons represent zone around the robot for "stop", "slowdown" and "limit" action types, 307 | # and robot footprint for "approach" action type. 308 | polygons: ["FootprintApproach"] 309 | FootprintApproach: 310 | type: "polygon" 311 | action_type: "approach" 312 | footprint_topic: "/local_costmap/published_footprint" 313 | time_before_collision: 1.2 314 | simulation_time_step: 0.1 315 | min_points: 6 316 | visualize: False 317 | enabled: True 318 | observation_sources: ["scan"] 319 | scan: 320 | type: "scan" 321 | topic: "scan" 322 | min_height: 0.15 323 | max_height: 2.0 324 | enabled: True 325 | 326 | docking_server: 327 | ros__parameters: 328 | enable_stamped_cmd_vel: true 329 | controller_frequency: 50.0 330 | initial_perception_timeout: 5.0 331 | wait_charge_timeout: 5.0 332 | dock_approach_timeout: 30.0 333 | undock_linear_tolerance: 0.05 334 | undock_angular_tolerance: 0.1 335 | max_retries: 3 336 | base_frame: "base_link" 337 | fixed_frame: "odom" 338 | dock_backwards: false 339 | dock_prestaging_tolerance: 0.5 340 | 341 | # Types of docks 342 | dock_plugins: ['simple_charging_dock'] 343 | simple_charging_dock: 344 | plugin: 'opennav_docking::SimpleChargingDock' 345 | docking_threshold: 0.05 346 | staging_x_offset: -0.7 347 | use_external_detection_pose: true 348 | use_battery_status: false # true 349 | use_stall_detection: false # true 350 | 351 | external_detection_timeout: 1.0 352 | external_detection_translation_x: -0.18 353 | external_detection_translation_y: 0.0 354 | external_detection_rotation_roll: -1.57 355 | external_detection_rotation_pitch: -1.57 356 | external_detection_rotation_yaw: 0.0 357 | filter_coef: 0.1 358 | 359 | # Dock instances 360 | # The following example illustrates configuring dock instances. 361 | # docks: ['home_dock'] # Input your docks here 362 | # home_dock: 363 | # type: 'simple_charging_dock' 364 | # frame: map 365 | # pose: [0.0, 0.0, 0.0] 366 | 367 | controller: 368 | k_phi: 3.0 369 | k_delta: 2.0 370 | v_linear_min: 0.15 371 | v_linear_max: 0.15 -------------------------------------------------------------------------------- /turtlebot4_navigation/config/slam.yaml: -------------------------------------------------------------------------------- 1 | slam_toolbox: 2 | ros__parameters: 3 | 4 | # Plugin params 5 | solver_plugin: solver_plugins::CeresSolver 6 | ceres_linear_solver: SPARSE_NORMAL_CHOLESKY 7 | ceres_preconditioner: SCHUR_JACOBI 8 | ceres_trust_strategy: LEVENBERG_MARQUARDT 9 | ceres_dogleg_type: TRADITIONAL_DOGLEG 10 | ceres_loss_function: None 11 | 12 | # ROS Parameters 13 | odom_frame: odom 14 | map_frame: map 15 | base_frame: base_link 16 | scan_topic: /scan 17 | use_map_saver: true 18 | mode: mapping 19 | 20 | debug_logging: false 21 | throttle_scans: 1 22 | transform_publish_period: 0.02 #if 0 never publishes odometry 23 | map_update_interval: 1.0 24 | resolution: 0.05 25 | max_laser_range: 12.0 26 | minimum_time_interval: 0.5 27 | transform_timeout: 0.2 28 | tf_buffer_duration: 30. 29 | stack_size_to_use: 40000000 30 | enable_interactive_mode: true 31 | 32 | # General Parameters 33 | use_scan_matching: true 34 | use_scan_barycenter: true 35 | minimum_travel_distance: 0.1 36 | minimum_travel_heading: 0.1 37 | scan_buffer_size: 10 38 | scan_buffer_maximum_scan_distance: 10.0 39 | link_match_minimum_response_fine: 0.1 40 | link_scan_maximum_distance: 1.5 41 | loop_search_maximum_distance: 3.0 42 | do_loop_closing: true 43 | loop_match_minimum_chain_size: 10 44 | loop_match_maximum_variance_coarse: 3.0 45 | loop_match_minimum_response_coarse: 0.35 46 | loop_match_minimum_response_fine: 0.45 47 | 48 | # Correlation Parameters - Correlation Parameters 49 | correlation_search_space_dimension: 0.5 50 | correlation_search_space_resolution: 0.01 51 | correlation_search_space_smear_deviation: 0.1 52 | 53 | # Correlation Parameters - Loop Closure Parameters 54 | loop_search_space_dimension: 8.0 55 | loop_search_space_resolution: 0.05 56 | loop_search_space_smear_deviation: 0.03 57 | 58 | # Scan Matcher Parameters 59 | distance_variance_penalty: 0.5 60 | angle_variance_penalty: 1.0 61 | 62 | fine_search_angle_offset: 0.00349 63 | coarse_search_angle_offset: 0.349 64 | coarse_angle_resolution: 0.0349 65 | minimum_angle_penalty: 0.9 66 | minimum_distance_penalty: 0.5 67 | use_response_expansion: true -------------------------------------------------------------------------------- /turtlebot4_navigation/launch/localization.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Clearpath 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 | # @author Roni Kreinin (rkreinin@clearpathrobotics.com) 16 | 17 | 18 | from ament_index_python.packages import get_package_share_directory 19 | 20 | from launch import LaunchDescription 21 | from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription 22 | from launch.launch_description_sources import PythonLaunchDescriptionSource 23 | from launch.substitutions import LaunchConfiguration, PathJoinSubstitution 24 | 25 | from launch_ros.actions import PushRosNamespace 26 | 27 | 28 | ARGUMENTS = [ 29 | DeclareLaunchArgument('use_sim_time', default_value='false', 30 | choices=['true', 'false'], 31 | description='Use sim time'), 32 | DeclareLaunchArgument('namespace', default_value='', 33 | description='Robot namespace') 34 | ] 35 | 36 | 37 | def generate_launch_description(): 38 | pkg_turtlebot4_navigation = get_package_share_directory('turtlebot4_navigation') 39 | pkg_nav2_bringup = get_package_share_directory('nav2_bringup') 40 | 41 | localization_params_arg = DeclareLaunchArgument( 42 | 'params', 43 | default_value=PathJoinSubstitution( 44 | [pkg_turtlebot4_navigation, 'config', 'localization.yaml']), 45 | description='Localization parameters') 46 | 47 | map_arg = DeclareLaunchArgument( 48 | 'map', 49 | default_value=PathJoinSubstitution( 50 | [pkg_turtlebot4_navigation, 'maps', 'warehouse.yaml']), 51 | description='Full path to map yaml file to load') 52 | 53 | namespace = LaunchConfiguration('namespace') 54 | use_sim_time = LaunchConfiguration('use_sim_time') 55 | 56 | localization = GroupAction([ 57 | PushRosNamespace(namespace), 58 | 59 | IncludeLaunchDescription( 60 | PythonLaunchDescriptionSource( 61 | PathJoinSubstitution( 62 | [pkg_nav2_bringup, 'launch', 'localization_launch.py'])), 63 | launch_arguments={'namespace': namespace, 64 | 'map': LaunchConfiguration('map'), 65 | 'use_sim_time': use_sim_time, 66 | 'params_file': LaunchConfiguration('params')}.items()), 67 | ]) 68 | 69 | ld = LaunchDescription(ARGUMENTS) 70 | ld.add_action(localization_params_arg) 71 | ld.add_action(map_arg) 72 | ld.add_action(localization) 73 | return ld 74 | -------------------------------------------------------------------------------- /turtlebot4_navigation/launch/nav2.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Clearpath 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 | # @author Roni Kreinin (rkreinin@clearpathrobotics.com) 16 | 17 | 18 | from ament_index_python.packages import get_package_share_directory 19 | 20 | from launch import LaunchDescription 21 | from launch.actions import ( 22 | DeclareLaunchArgument, 23 | GroupAction, 24 | IncludeLaunchDescription, 25 | OpaqueFunction 26 | ) 27 | from launch.launch_description_sources import PythonLaunchDescriptionSource 28 | from launch.substitutions import LaunchConfiguration, PathJoinSubstitution 29 | 30 | from launch_ros.actions import PushRosNamespace, SetRemap 31 | 32 | 33 | ARGUMENTS = [ 34 | DeclareLaunchArgument('use_sim_time', default_value='false', 35 | choices=['true', 'false'], 36 | description='Use sim time'), 37 | DeclareLaunchArgument('params_file', 38 | default_value=PathJoinSubstitution([ 39 | get_package_share_directory('turtlebot4_navigation'), 40 | 'config', 41 | 'nav2.yaml' 42 | ]), 43 | description='Nav2 parameters'), 44 | DeclareLaunchArgument('namespace', default_value='', 45 | description='Robot namespace') 46 | ] 47 | 48 | 49 | def launch_setup(context, *args, **kwargs): 50 | pkg_nav2_bringup = get_package_share_directory('nav2_bringup') 51 | 52 | nav2_params = LaunchConfiguration('params_file') 53 | namespace = LaunchConfiguration('namespace') 54 | use_sim_time = LaunchConfiguration('use_sim_time') 55 | 56 | namespace_str = namespace.perform(context) 57 | if (namespace_str and not namespace_str.startswith('/')): 58 | namespace_str = '/' + namespace_str 59 | 60 | launch_nav2 = PathJoinSubstitution( 61 | [pkg_nav2_bringup, 'launch', 'navigation_launch.py']) 62 | 63 | nav2 = GroupAction([ 64 | PushRosNamespace(namespace), 65 | SetRemap(namespace_str + '/global_costmap/scan', namespace_str + '/scan'), 66 | SetRemap(namespace_str + '/local_costmap/scan', namespace_str + '/scan'), 67 | 68 | IncludeLaunchDescription( 69 | PythonLaunchDescriptionSource(launch_nav2), 70 | launch_arguments=[ 71 | ('use_sim_time', use_sim_time), 72 | ('params_file', nav2_params.perform(context)), 73 | ('use_composition', 'False'), 74 | ('namespace', namespace_str) 75 | ] 76 | ), 77 | ]) 78 | 79 | return [nav2] 80 | 81 | 82 | def generate_launch_description(): 83 | ld = LaunchDescription(ARGUMENTS) 84 | ld.add_action(OpaqueFunction(function=launch_setup)) 85 | return ld 86 | -------------------------------------------------------------------------------- /turtlebot4_navigation/launch/slam.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Clearpath 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 | # @author Roni Kreinin (rkreinin@clearpathrobotics.com) 16 | 17 | 18 | from ament_index_python.packages import get_package_share_directory 19 | 20 | from launch import LaunchDescription 21 | from launch.actions import ( 22 | DeclareLaunchArgument, 23 | GroupAction, 24 | IncludeLaunchDescription, 25 | OpaqueFunction 26 | ) 27 | from launch.conditions import IfCondition, UnlessCondition 28 | from launch.launch_description_sources import PythonLaunchDescriptionSource 29 | from launch.substitutions import LaunchConfiguration, PathJoinSubstitution 30 | from launch_ros.actions import PushRosNamespace, SetRemap 31 | 32 | pkg_turtlebot4_navigation = get_package_share_directory('turtlebot4_navigation') 33 | pkg_slam_toolbox = get_package_share_directory('slam_toolbox') 34 | 35 | ARGUMENTS = [ 36 | DeclareLaunchArgument('use_sim_time', default_value='false', 37 | choices=['true', 'false'], 38 | description='Use sim time'), 39 | DeclareLaunchArgument('sync', default_value='true', 40 | choices=['true', 'false'], 41 | description='Use synchronous SLAM'), 42 | DeclareLaunchArgument('namespace', default_value='', 43 | description='Robot namespace'), 44 | DeclareLaunchArgument('autostart', default_value='true', 45 | choices=['true', 'false'], 46 | description='Automatically startup the slamtoolbox. Ignored when use_lifecycle_manager is true.'), # noqa: E501 47 | DeclareLaunchArgument('use_lifecycle_manager', default_value='false', 48 | choices=['true', 'false'], 49 | description='Enable bond connection during node activation'), 50 | DeclareLaunchArgument('params', 51 | default_value=PathJoinSubstitution([pkg_turtlebot4_navigation, 'config', 'slam.yaml']), # noqa: E501 52 | description='Path to the SLAM Toolbox configuration file') 53 | ] 54 | 55 | 56 | def launch_setup(context, *args, **kwargs): 57 | namespace = LaunchConfiguration('namespace') 58 | sync = LaunchConfiguration('sync') 59 | use_sim_time = LaunchConfiguration('use_sim_time') 60 | autostart = LaunchConfiguration('autostart') 61 | use_lifecycle_manager = LaunchConfiguration('use_lifecycle_manager') 62 | slam_params = LaunchConfiguration('params') 63 | 64 | namespace_str = namespace.perform(context) 65 | if (namespace_str and not namespace_str.startswith('/')): 66 | namespace_str = '/' + namespace_str 67 | 68 | launch_slam_sync = PathJoinSubstitution( 69 | [pkg_slam_toolbox, 'launch', 'online_sync_launch.py']) 70 | 71 | launch_slam_async = PathJoinSubstitution( 72 | [pkg_slam_toolbox, 'launch', 'online_async_launch.py']) 73 | 74 | slam = GroupAction([ 75 | PushRosNamespace(namespace), 76 | 77 | SetRemap('/tf', namespace_str + '/tf'), 78 | SetRemap('/tf_static', namespace_str + '/tf_static'), 79 | SetRemap('/scan', namespace_str + '/scan'), 80 | SetRemap('/map', namespace_str + '/map'), 81 | SetRemap('/map_metadata', namespace_str + '/map_metadata'), 82 | 83 | IncludeLaunchDescription( 84 | PythonLaunchDescriptionSource(launch_slam_sync), 85 | launch_arguments=[ 86 | ('use_sim_time', use_sim_time), 87 | ('autostart', autostart), 88 | ('use_lifecycle_manager', use_lifecycle_manager), 89 | ('slam_params_file', slam_params) 90 | ], 91 | condition=IfCondition(sync) 92 | ), 93 | 94 | IncludeLaunchDescription( 95 | PythonLaunchDescriptionSource(launch_slam_async), 96 | launch_arguments=[ 97 | ('use_sim_time', use_sim_time), 98 | ('autostart', autostart), 99 | ('use_lifecycle_manager', use_lifecycle_manager), 100 | ('slam_params_file', slam_params) 101 | ], 102 | condition=UnlessCondition(sync) 103 | ) 104 | ]) 105 | 106 | return [slam] 107 | 108 | 109 | def generate_launch_description(): 110 | ld = LaunchDescription(ARGUMENTS) 111 | ld.add_action(OpaqueFunction(function=launch_setup)) 112 | return ld 113 | -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/depot.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turtlebot/turtlebot4/91100467a1f9d440e7614ca6be69d6df3b073662/turtlebot4_navigation/maps/depot.pgm -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/depot.yaml: -------------------------------------------------------------------------------- 1 | image: depot.pgm 2 | mode: trinary 3 | resolution: 0.04 4 | origin: [-15.1, -7.74, 0] 5 | negate: 0 6 | occupied_thresh: 0.65 7 | free_thresh: 0.196 -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/maze.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turtlebot/turtlebot4/91100467a1f9d440e7614ca6be69d6df3b073662/turtlebot4_navigation/maps/maze.pgm -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/maze.yaml: -------------------------------------------------------------------------------- 1 | image: maze.pgm 2 | mode: trinary 3 | resolution: 0.03 4 | origin: [-10.1, -10, 0] 5 | negate: 0 6 | occupied_thresh: 0.65 7 | free_thresh: 0.1 8 | -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/warehouse.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turtlebot/turtlebot4/91100467a1f9d440e7614ca6be69d6df3b073662/turtlebot4_navigation/maps/warehouse.pgm -------------------------------------------------------------------------------- /turtlebot4_navigation/maps/warehouse.yaml: -------------------------------------------------------------------------------- 1 | image: warehouse.pgm 2 | mode: trinary 3 | resolution: 0.03 4 | origin: [-15.1, -25, 0] 5 | negate: 0 6 | occupied_thresh: 0.65 7 | free_thresh: 0.1 8 | -------------------------------------------------------------------------------- /turtlebot4_navigation/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | turtlebot4_navigation 5 | 2.1.0 6 | Turtlebot4 Navigation 7 | Chris Iverach-Brereton 8 | Hilary Luo 9 | 10 | Apache 2.0 11 | 12 | Roni Kreinin 13 | 14 | ament_cmake 15 | ament_cmake_python 16 | 17 | slam_toolbox 18 | nav2_bringup 19 | nav2_simple_commander 20 | 21 | ament_lint_auto 22 | ament_lint_common 23 | 24 | 25 | ament_cmake 26 | 27 | 28 | -------------------------------------------------------------------------------- /turtlebot4_navigation/turtlebot4_navigation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turtlebot/turtlebot4/91100467a1f9d440e7614ca6be69d6df3b073662/turtlebot4_navigation/turtlebot4_navigation/__init__.py -------------------------------------------------------------------------------- /turtlebot4_navigation/turtlebot4_navigation/turtlebot4_navigator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2022 Clearpath Robotics, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # @author Roni Kreinin (rkreinin@clearpathrobotics.com) 18 | 19 | 20 | from enum import IntEnum 21 | import math 22 | from threading import Thread 23 | import time 24 | 25 | from action_msgs.msg import GoalStatus 26 | 27 | from geometry_msgs.msg import PoseStamped, PoseWithCovarianceStamped 28 | 29 | from irobot_create_msgs.action import Dock, Undock 30 | from irobot_create_msgs.msg import DockStatus 31 | 32 | from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult 33 | 34 | import rclpy 35 | from rclpy.action import ActionClient 36 | from rclpy.duration import Duration 37 | from rclpy.qos import qos_profile_sensor_data, qos_profile_system_default 38 | 39 | 40 | class TurtleBot4Directions(IntEnum): 41 | NORTH = 0 42 | NORTH_WEST = 45 43 | WEST = 90 44 | SOUTH_WEST = 135 45 | SOUTH = 180 46 | SOUTH_EAST = 225 47 | EAST = 270 48 | NORTH_EAST = 315 49 | 50 | 51 | class TurtleBot4Navigator(BasicNavigator): 52 | is_docked = None 53 | creating_path = False 54 | 55 | def __init__(self, namespace=''): 56 | super().__init__(namespace=namespace) 57 | 58 | self.create_subscription(DockStatus, 59 | 'dock_status', 60 | self._dockCallback, 61 | qos_profile_sensor_data) 62 | 63 | self.create_subscription(PoseWithCovarianceStamped, 64 | 'initialpose', 65 | self._poseEstimateCallback, 66 | qos_profile_system_default) 67 | 68 | self.undock_action_client = ActionClient(self, Undock, 'undock') 69 | self.dock_action_client = ActionClient(self, Dock, 'dock') 70 | 71 | self.undock_result_future = None 72 | self.dock_result_future = None 73 | 74 | def getPoseStamped(self, position, rotation): 75 | """ 76 | Fill and return a PoseStamped message. 77 | 78 | :param position: A list consisting of the x and y positions for the Pose. e.g [0.5, 1.2] 79 | :param rotation: Rotation of the pose about the Z axis in degrees. 80 | :return: PoseStamped message 81 | """ 82 | pose = PoseStamped() 83 | 84 | pose.header.frame_id = 'map' 85 | pose.header.stamp = self.get_clock().now().to_msg() 86 | 87 | pose.pose.position.x = position[0] 88 | pose.pose.position.y = position[1] 89 | 90 | # Convert Z rotation to quaternion 91 | pose.pose.orientation.z = math.sin(math.radians(rotation) / 2) 92 | pose.pose.orientation.w = math.cos(math.radians(rotation) / 2) 93 | 94 | return pose 95 | 96 | def stampPose(self, pose): 97 | """ 98 | Stamp a Pose message and return a PoseStamped message. 99 | 100 | :param pose: Pose message 101 | :return: PoseStamped message 102 | """ 103 | poseStamped = PoseStamped() 104 | 105 | poseStamped.header.frame_id = 'map' 106 | poseStamped.header.stamp = self.get_clock().now().to_msg() 107 | 108 | poseStamped.pose = pose 109 | 110 | return poseStamped 111 | 112 | def createPath(self): 113 | """ 114 | Create a path using the '2D Pose Estimate' tool in Rviz. 115 | 116 | :return: List of PoseStamped poses 117 | """ 118 | poses = [] 119 | self.new_pose = None 120 | self.creating_path = True 121 | 122 | self.info('Creating a path. Press Enter to finish.') 123 | self.info('Use the "2D Pose Estimate" tool in Rviz to add a pose to the path.') 124 | 125 | def wait_for_key(): 126 | input() 127 | 128 | input_thread = Thread(target=wait_for_key, daemon=True) 129 | input_thread.start() 130 | 131 | while self.creating_path: 132 | while self.new_pose is None: 133 | if input_thread.is_alive(): 134 | rclpy.spin_once(self, timeout_sec=0.1) 135 | else: 136 | self.creating_path = False 137 | break 138 | if self.new_pose: 139 | self.info('Pose added.') 140 | poses.append(self.stampPose(self.new_pose)) 141 | self.new_pose = None 142 | self.clearAllCostmaps() 143 | if len(poses) > 0: 144 | self.info('Path created.') 145 | for i, p in enumerate(poses): 146 | self.info('Pose {0} [x,y]=[{1:.3f},{2:.3f}]'.format( 147 | i, p.pose.position.x, p.pose.position.y) + 148 | '[x,y,z,w]=[{0:.3f},{1:.3f},{2:.3f},{3:.3f}]'.format( 149 | p.pose.orientation.x, p.pose.orientation.y, 150 | p.pose.orientation.z, p.pose.orientation.w)) 151 | return poses 152 | 153 | # 2D Pose Estimate callback 154 | def _poseEstimateCallback(self, msg: PoseWithCovarianceStamped): 155 | if self.creating_path: 156 | self.new_pose = msg.pose.pose 157 | 158 | # DockStatus subscription callback 159 | def _dockCallback(self, msg: DockStatus): 160 | self.is_docked = msg.is_docked 161 | 162 | def getDockedStatus(self): 163 | """ 164 | Get current docked status. 165 | 166 | :return: ``True`` if docked, ``False`` otherwise. 167 | """ 168 | # Spin to get latest dock status 169 | rclpy.spin_once(self, timeout_sec=0.1) 170 | # If dock status hasn't been published yet, spin until it is 171 | while self.is_docked is None: 172 | rclpy.spin_once(self, timeout_sec=0.1) 173 | 174 | return self.is_docked 175 | 176 | def undock(self): 177 | """Perform Undock action.""" 178 | self.info('Undocking...') 179 | self.undock_send_goal() 180 | 181 | while not self.isUndockComplete(): 182 | time.sleep(0.1) 183 | 184 | def undock_send_goal(self): 185 | goal_msg = Undock.Goal() 186 | self.undock_action_client.wait_for_server() 187 | goal_future = self.undock_action_client.send_goal_async(goal_msg) 188 | 189 | rclpy.spin_until_future_complete(self, goal_future) 190 | 191 | self.undock_goal_handle = goal_future.result() 192 | 193 | if not self.undock_goal_handle.accepted: 194 | self.error('Undock goal rejected') 195 | return 196 | 197 | self.undock_result_future = self.undock_goal_handle.get_result_async() 198 | 199 | def isUndockComplete(self): 200 | """ 201 | Get status of Undock action. 202 | 203 | :return: ``True`` if undocked, ``False`` otherwise. 204 | """ 205 | if self.undock_result_future is None or not self.undock_result_future: 206 | return True 207 | 208 | rclpy.spin_until_future_complete(self, self.undock_result_future, timeout_sec=0.1) 209 | 210 | if self.undock_result_future.result(): 211 | self.undock_status = self.undock_result_future.result().status 212 | if self.undock_status != GoalStatus.STATUS_SUCCEEDED: 213 | self.info(f'Goal with failed with status code: {self.status}') 214 | return True 215 | else: 216 | return False 217 | 218 | self.info('Undock succeeded') 219 | return True 220 | 221 | def dock(self): 222 | """Perform Undock action.""" 223 | self.info('Docking...') 224 | self.dock_send_goal() 225 | 226 | while not self.isDockComplete(): 227 | time.sleep(0.1) 228 | 229 | def dock_send_goal(self): 230 | goal_msg = Dock.Goal() 231 | self.dock_action_client.wait_for_server() 232 | goal_future = self.dock_action_client.send_goal_async(goal_msg) 233 | 234 | rclpy.spin_until_future_complete(self, goal_future) 235 | 236 | self.dock_goal_handle = goal_future.result() 237 | 238 | if not self.dock_goal_handle.accepted: 239 | self.error('Dock goal rejected') 240 | return 241 | 242 | self.dock_result_future = self.dock_goal_handle.get_result_async() 243 | 244 | def isDockComplete(self): 245 | """ 246 | Get status of Dock action. 247 | 248 | :return: ``True`` if docked, ``False`` otherwise. 249 | """ 250 | if self.dock_result_future is None or not self.dock_result_future: 251 | return True 252 | 253 | rclpy.spin_until_future_complete(self, self.dock_result_future, timeout_sec=0.1) 254 | 255 | if self.dock_result_future.result(): 256 | self.dock_status = self.dock_result_future.result().status 257 | if self.dock_status != GoalStatus.STATUS_SUCCEEDED: 258 | self.info(f'Goal with failed with status code: {self.status}') 259 | return True 260 | else: 261 | return False 262 | 263 | self.info('Dock succeeded') 264 | return True 265 | 266 | def startToPose(self, pose: PoseStamped): 267 | """ 268 | Perform goToPose action and print feedback. 269 | 270 | :param pose: Goal pose. 271 | """ 272 | i = 0 273 | self.goToPose(pose) 274 | 275 | while not self.isTaskComplete(): 276 | feedback = self.getFeedback() 277 | i = i + 1 278 | if feedback and i % 5 == 0: 279 | print('Estimated time of arrival: ' + '{0:.0f}'.format( 280 | Duration.from_msg(feedback.estimated_time_remaining).nanoseconds / 1e9) 281 | + '{0: <20}'.format('seconds.'), end='\r') 282 | 283 | # Some navigation timeout to demo cancellation 284 | if Duration.from_msg(feedback.navigation_time) > Duration(seconds=600.0): 285 | self.cancelTask() 286 | 287 | result = self.getResult() 288 | if result == TaskResult.SUCCEEDED: 289 | self.info('Goal succeeded!') 290 | elif result == TaskResult.CANCELED: 291 | self.info('Goal was canceled!') 292 | elif result == TaskResult.FAILED: 293 | self.info('Goal failed!') 294 | else: 295 | self.info('Goal has an invalid return status!') 296 | 297 | def startThroughPoses(self, poses): 298 | """ 299 | Perform goThroughPoses action and print feedback. 300 | 301 | :param poses: List of goal poses. 302 | """ 303 | i = 0 304 | self.goThroughPoses(poses) 305 | 306 | while not self.isTaskComplete(): 307 | feedback = self.getFeedback() 308 | i = i + 1 309 | if feedback and i % 5 == 0: 310 | print('Estimated time of arrival: ' + '{0:.0f}'.format( 311 | Duration.from_msg(feedback.estimated_time_remaining).nanoseconds / 1e9) 312 | + '{0: <20}'.format(' seconds.'), end='\r') 313 | 314 | # Some navigation timeout to demo cancellation 315 | if Duration.from_msg(feedback.navigation_time) > Duration(seconds=600.0): 316 | self.cancelTask() 317 | 318 | result = self.getResult() 319 | if result == TaskResult.SUCCEEDED: 320 | self.info('Goal succeeded!') 321 | elif result == TaskResult.CANCELED: 322 | self.info('Goal was canceled!') 323 | elif result == TaskResult.FAILED: 324 | self.info('Goal failed!') 325 | else: 326 | self.info('Goal has an invalid return status!') 327 | 328 | def startFollowWaypoints(self, poses): 329 | """ 330 | Perform followWaypoint action and print feedback. 331 | 332 | :param poses: List of goal poses. 333 | """ 334 | i = 0 335 | self.followWaypoints(poses) 336 | 337 | while not self.isTaskComplete(): 338 | i = i + 1 339 | feedback = self.getFeedback() 340 | if feedback and i % 5 == 0: 341 | print('Executing current waypoint: {0}/{1: <5}'.format( 342 | str(feedback.current_waypoint + 1), str(len(poses))), end='\r') 343 | -------------------------------------------------------------------------------- /turtlebot4_node/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package turtlebot4_node 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 2.1.0 (2025-05-23) 6 | ------------------ 7 | * Fix tag order 8 | * Update package maintainers 9 | * Contributors: Chris Iverach-Brereton 10 | 11 | 2.0.1 (2024-09-25) 12 | ------------------ 13 | * Block the wall-follow callbacks from running if the robot is presently docked 14 | * Contributors: Chris Iverach-Brereton 15 | 16 | 2.0.0 (2024-08-29) 17 | ------------------ 18 | 19 | 1.0.5 (2024-07-02) 20 | ------------------ 21 | 22 | 1.0.4 (2023-11-08) 23 | ------------------ 24 | 25 | 1.0.3 (2023-05-31) 26 | ------------------ 27 | 28 | 1.0.2 (2023-05-15) 29 | ------------------ 30 | 31 | 1.0.1 (2023-02-28) 32 | ------------------ 33 | * Force 1HZ update on display 34 | * Contributors: Roni Kreinin 35 | 36 | 1.0.0 (2023-02-17) 37 | ------------------ 38 | * Updates for new DepthAI node. 39 | * Linter fixes 40 | * Separated RPLIDAR Motor function into stop/start 41 | * Added OAKD stop/start function 42 | * Added power saver option 43 | * Update display only when something has changed 44 | * Function calls 45 | * Namespacing 46 | * Flash Comms LED based on high frequency wheel status feedback instead of low frequency battery state 47 | * Move comms_timer() from battery_callback() to wheel_status_callback() 48 | * Updated dock action 49 | * Contributors: Joey Yang, Roni Kreinin 50 | 51 | 0.1.2 (2022-09-15) 52 | ------------------ 53 | * Added support for Empty service 54 | * Added RPLIDAR motor stop service as a function option 55 | * Added timeouts to services (defaults to 30s) 56 | * Updated rclcpp action api 57 | * Contributors: Daisuke Nishimatsu, Roni Kreinin 58 | 59 | 0.1.1 (2022-07-12) 60 | ------------------ 61 | * Merge pull request `#7 `_ from turtlebot/roni-kreinin/linters 62 | Fixed linter errors 63 | * Fixed linter errors 64 | * Contributors: Roni Kreinin, roni-kreinin 65 | 66 | 0.1.0 (2022-05-03) 67 | ------------------ 68 | * First Galactic release 69 | * Contributors: Roni Kreinin, ahcorde 70 | -------------------------------------------------------------------------------- /turtlebot4_node/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(turtlebot4_node) 3 | 4 | # Default to C99 5 | if(NOT CMAKE_C_STANDARD) 6 | set(CMAKE_C_STANDARD 99) 7 | endif() 8 | 9 | # Default to C++14 10 | if(NOT CMAKE_CXX_STANDARD) 11 | set(CMAKE_CXX_STANDARD 14) 12 | endif() 13 | 14 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | add_compile_options(-Wall -Wextra -Wpedantic) 16 | endif() 17 | 18 | # find dependencies 19 | find_package(ament_cmake REQUIRED) 20 | find_package(rclcpp REQUIRED) 21 | find_package(rclcpp_action REQUIRED) 22 | find_package(rcutils REQUIRED) 23 | find_package(std_msgs REQUIRED) 24 | find_package(std_srvs REQUIRED) 25 | find_package(sensor_msgs REQUIRED) 26 | find_package(irobot_create_msgs REQUIRED) 27 | find_package(turtlebot4_msgs REQUIRED) 28 | 29 | #Build 30 | 31 | include_directories( 32 | include 33 | ) 34 | 35 | add_library(${PROJECT_NAME}_lib 36 | "src/main.cpp" 37 | "src/turtlebot4.cpp" 38 | "src/display.cpp" 39 | "src/buttons.cpp" 40 | "src/leds.cpp" 41 | ) 42 | 43 | set(DEPENDENCIES 44 | "rclcpp" 45 | "rclcpp_action" 46 | "rcutils" 47 | "std_msgs" 48 | "std_srvs" 49 | "sensor_msgs" 50 | "irobot_create_msgs" 51 | "turtlebot4_msgs" 52 | ) 53 | 54 | ament_target_dependencies(${PROJECT_NAME}_lib ${DEPENDENCIES}) 55 | 56 | set(EXECUTABLE_NAME "turtlebot4_node") 57 | 58 | add_executable(${EXECUTABLE_NAME} src/main.cpp) 59 | target_link_libraries(${EXECUTABLE_NAME} ${PROJECT_NAME}_lib) 60 | ament_target_dependencies(${EXECUTABLE_NAME} ${DEPENDENCIES}) 61 | 62 | install(TARGETS ${EXECUTABLE_NAME} 63 | DESTINATION lib/${PROJECT_NAME} 64 | ) 65 | 66 | install( 67 | DIRECTORY include/ 68 | DESTINATION include 69 | ) 70 | 71 | if(BUILD_TESTING) 72 | find_package(ament_lint_auto REQUIRED) 73 | list(APPEND AMENT_LINT_AUTO_EXCLUDE 74 | ament_cmake_copyright 75 | ) 76 | ament_lint_auto_find_test_dependencies() 77 | endif() 78 | 79 | 80 | ament_export_include_directories(include) 81 | ament_package() 82 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/action.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__ACTION_HPP_ 20 | #define TURTLEBOT4_NODE__ACTION_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "rclcpp_action/rclcpp_action.hpp" 26 | 27 | 28 | namespace turtlebot4 29 | { 30 | // Templated Action class to allow any ROS actions to be used 31 | template 32 | class Turtlebot4Action 33 | { 34 | public: 35 | // Constructor and Destructor 36 | explicit Turtlebot4Action(std::shared_ptr & nh, std::string action) 37 | : nh_(nh), action_(action) 38 | { 39 | // Create action client 40 | client_ = rclcpp_action::create_client(nh_, action); 41 | } 42 | virtual ~Turtlebot4Action() {} 43 | 44 | void send_goal() 45 | { 46 | RCLCPP_INFO(nh_->get_logger(), "Waiting for %s action server", action_.c_str()); 47 | 48 | // Cancel existing timers 49 | if (timer_ != nullptr) { 50 | timer_->cancel(); 51 | } 52 | 53 | // Create timer to check for service without blocking 54 | timer_ = nh_->create_wall_timer( 55 | std::chrono::milliseconds(1000), 56 | [this]() -> void 57 | { 58 | // Wait for action server 59 | if (client_->wait_for_action_server(std::chrono::milliseconds(10))) { 60 | RCLCPP_INFO( 61 | nh_->get_logger(), "%s action server available, sending goal", 62 | action_.c_str()); 63 | timer_->cancel(); 64 | 65 | // Create goal 66 | auto goal_msg = typename ActionT::Goal(); 67 | 68 | // Set goal callbacks 69 | auto send_goal_options = typename rclcpp_action::Client::SendGoalOptions(); 70 | send_goal_options.goal_response_callback = 71 | std::bind(&Turtlebot4Action::goal_response_callback, this, std::placeholders::_1); 72 | send_goal_options.feedback_callback = 73 | std::bind( 74 | &Turtlebot4Action::feedback_callback, this, std::placeholders::_1, 75 | std::placeholders::_2); 76 | send_goal_options.result_callback = 77 | std::bind(&Turtlebot4Action::result_callback, this, std::placeholders::_1); 78 | 79 | // Send goal 80 | this->client_->async_send_goal(goal_msg, send_goal_options); 81 | } else { 82 | // TODO(roni-kreinin): Add timeout 83 | } 84 | }); 85 | } 86 | 87 | void send_goal(std::shared_ptr goal_msg) 88 | { 89 | RCLCPP_INFO(nh_->get_logger(), "Waiting for %s action server", action_.c_str()); 90 | 91 | // Cancel existing timers 92 | if (timer_ != nullptr) { 93 | timer_->cancel(); 94 | } 95 | 96 | // Create timer to check for service without blocking 97 | timer_ = nh_->create_wall_timer( 98 | std::chrono::milliseconds(1000), 99 | [this, goal_msg]() -> void 100 | { 101 | // Wait for action server 102 | if (client_->wait_for_action_server(std::chrono::milliseconds(10))) { 103 | RCLCPP_INFO( 104 | nh_->get_logger(), "%s action server available, sending goal", 105 | action_.c_str()); 106 | timer_->cancel(); 107 | 108 | // Set goal callbacks 109 | auto send_goal_options = typename rclcpp_action::Client::SendGoalOptions(); 110 | send_goal_options.goal_response_callback = 111 | std::bind(&Turtlebot4Action::goal_response_callback, this, std::placeholders::_1); 112 | send_goal_options.feedback_callback = 113 | std::bind( 114 | &Turtlebot4Action::feedback_callback, this, std::placeholders::_1, 115 | std::placeholders::_2); 116 | send_goal_options.result_callback = 117 | std::bind(&Turtlebot4Action::result_callback, this, std::placeholders::_1); 118 | 119 | // Send goal 120 | this->client_->async_send_goal(*goal_msg, send_goal_options); 121 | } else { 122 | // TODO(roni-kreinin): Add timeout 123 | } 124 | }); 125 | } 126 | 127 | private: 128 | // Node handle 129 | std::shared_ptr nh_; 130 | // Action 131 | std::string action_; 132 | // Timer 133 | rclcpp::TimerBase::SharedPtr timer_; 134 | // Action client 135 | typename rclcpp_action::Client::SharedPtr client_; 136 | 137 | // TODO(roni-kreinin): Virtual callbacks? 138 | 139 | /** 140 | * @brief Goal response callback 141 | * @input future - Shared future with goal response 142 | */ 143 | void goal_response_callback( 144 | typename rclcpp_action::ClientGoalHandle::SharedPtr goal_handle) 145 | { 146 | if (!goal_handle) { 147 | RCLCPP_ERROR(nh_->get_logger(), "%s goal was rejected by server", action_.c_str()); 148 | } else { 149 | RCLCPP_INFO( 150 | nh_->get_logger(), "%s goal accepted by server, waiting for result", 151 | action_.c_str()); 152 | } 153 | } 154 | 155 | /** 156 | * @brief Feedback callback 157 | * @input ptr - Unused 158 | * @input feedback - Action feedback 159 | */ 160 | void feedback_callback( 161 | typename rclcpp_action::ClientGoalHandle::SharedPtr ptr, 162 | const std::shared_ptr feedback) 163 | { 164 | (void)ptr; 165 | (void)feedback; 166 | } 167 | 168 | /** 169 | * @brief Result callback 170 | * @input result - Action result 171 | */ 172 | void result_callback( 173 | const typename rclcpp_action::ClientGoalHandle::WrappedResult & result) 174 | { 175 | switch (result.code) { 176 | case rclcpp_action::ResultCode::SUCCEEDED: 177 | RCLCPP_INFO(nh_->get_logger(), "%s goal succeeded", action_.c_str()); 178 | break; 179 | case rclcpp_action::ResultCode::ABORTED: 180 | RCLCPP_ERROR(nh_->get_logger(), "%s goal was aborted", action_.c_str()); 181 | return; 182 | case rclcpp_action::ResultCode::CANCELED: 183 | RCLCPP_ERROR(nh_->get_logger(), "%s goal was canceled", action_.c_str()); 184 | return; 185 | default: 186 | RCLCPP_ERROR(nh_->get_logger(), "%s Unknown result code", action_.c_str()); 187 | return; 188 | } 189 | } 190 | }; 191 | 192 | } // namespace turtlebot4 193 | 194 | #endif // TURTLEBOT4_NODE__ACTION_HPP_ 195 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/buttons.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__BUTTONS_HPP_ 20 | #define TURTLEBOT4_NODE__BUTTONS_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "irobot_create_msgs/msg/interface_buttons.hpp" 31 | #include "turtlebot4_msgs/msg/user_button.hpp" 32 | #include "turtlebot4_node/utils.hpp" 33 | 34 | 35 | namespace turtlebot4 36 | { 37 | 38 | enum Turtlebot4ButtonEnum : uint8_t 39 | { 40 | CREATE3_1, 41 | CREATE3_POWER, 42 | CREATE3_2, 43 | CONTROLLER_A, 44 | CONTROLLER_B, 45 | CONTROLLER_X, 46 | CONTROLLER_Y, 47 | CONTROLLER_UP, 48 | CONTROLLER_DOWN, 49 | CONTROLLER_LEFT, 50 | CONTROLLER_RIGHT, 51 | CONTROLLER_L1, 52 | CONTROLLER_L2, 53 | CONTROLLER_L3, 54 | CONTROLLER_R1, 55 | CONTROLLER_R2, 56 | CONTROLLER_R3, 57 | CONTROLLER_SHARE, 58 | CONTROLLER_OPTIONS, 59 | CONTROLLER_HOME, 60 | HMI_1, 61 | HMI_2, 62 | HMI_3, 63 | HMI_4, 64 | }; 65 | 66 | enum Turtlebot4ButtonState 67 | { 68 | RELEASED = 0, 69 | PRESSED = 1, 70 | WAIT_FOR_RELEASE 71 | }; 72 | 73 | struct Turtlebot4Button 74 | { 75 | std::string short_function_; 76 | std::string long_function_; 77 | turtlebot4_function_callback_t short_cb_; 78 | turtlebot4_function_callback_t long_cb_; 79 | turtlebot4_function_call_callback_t function_call_cb_; 80 | 81 | int long_press_duration_ms_; 82 | std::chrono::time_point last_start_pressed_time_; 83 | 84 | Turtlebot4ButtonState current_state_; 85 | Turtlebot4ButtonState next_state_; 86 | 87 | explicit Turtlebot4Button(std::vector params) 88 | : long_press_duration_ms_(0), 89 | current_state_(RELEASED), 90 | next_state_(RELEASED) 91 | { 92 | // Short press function only 93 | if (params.size() == 1) { 94 | short_function_ = params.at(0); 95 | } else if (params.size() == 2) { 96 | // Long press and Long press duration 97 | long_function_ = params.at(0); 98 | long_press_duration_ms_ = params.at(1).empty() ? 0 : std::stoi(params.at(1)); 99 | } else if (params.size() == 3) { 100 | // Short press, Long press, and Long press duration 101 | short_function_ = params.at(0); 102 | long_function_ = params.at(1); 103 | long_press_duration_ms_ = params.at(2).empty() ? 0 : std::stoi(params.at(2)); 104 | } 105 | } 106 | 107 | void set_state(Turtlebot4ButtonState state) 108 | { 109 | next_state_ = state; 110 | } 111 | 112 | void spin_once() 113 | { 114 | switch (current_state_) { 115 | case RELEASED: 116 | { 117 | if (next_state_ == PRESSED) { 118 | // Start timer 119 | last_start_pressed_time_ = std::chrono::steady_clock::now(); 120 | current_state_ = PRESSED; 121 | } 122 | break; 123 | } 124 | 125 | case PRESSED: 126 | { 127 | if (next_state_ == PRESSED) { 128 | // Long press implemented 129 | if (long_press_duration_ms_ > 0) { 130 | if (std::chrono::steady_clock::now() > 131 | last_start_pressed_time_ + std::chrono::milliseconds(long_press_duration_ms_)) 132 | { 133 | long_press(); 134 | current_state_ = WAIT_FOR_RELEASE; 135 | } 136 | } else { 137 | // Long press not implemented, do short press function and wait for release 138 | short_press(); 139 | current_state_ = WAIT_FOR_RELEASE; 140 | } 141 | } else if (next_state_ == RELEASED) { 142 | short_press(); 143 | current_state_ = RELEASED; 144 | } 145 | break; 146 | } 147 | 148 | case WAIT_FOR_RELEASE: 149 | { 150 | if (next_state_ == RELEASED) { 151 | current_state_ = RELEASED; 152 | } 153 | break; 154 | } 155 | 156 | default: 157 | break; 158 | } 159 | } 160 | 161 | void short_press() 162 | { 163 | if (short_cb_ != nullptr) { 164 | if (function_call_cb_ != nullptr) { 165 | function_call_cb_(short_function_); 166 | } 167 | short_cb_(); 168 | } 169 | } 170 | 171 | void long_press() 172 | { 173 | if (long_cb_ != nullptr) { 174 | if (function_call_cb_ != nullptr) { 175 | function_call_cb_(long_function_); 176 | } 177 | long_cb_(); 178 | } 179 | } 180 | }; 181 | 182 | class Buttons 183 | { 184 | public: 185 | Buttons( 186 | Turtlebot4Model model, 187 | std::vector buttons, 188 | std::shared_ptr & nh); 189 | 190 | void spin_once(); 191 | 192 | private: 193 | void create3_buttons_callback( 194 | const irobot_create_msgs::msg::InterfaceButtons::SharedPtr create3_buttons_msg); 195 | void hmi_buttons_callback(const turtlebot4_msgs::msg::UserButton::SharedPtr hmi_buttons_msg); 196 | void joy_callback(const sensor_msgs::msg::Joy::SharedPtr joy_msg); 197 | 198 | Turtlebot4Model model_; 199 | 200 | std::vector buttons_; 201 | 202 | std::shared_ptr nh_; 203 | rclcpp::Subscription::SharedPtr create3_buttons_sub_; 204 | rclcpp::Subscription::SharedPtr hmi_buttons_sub_; 205 | rclcpp::Subscription::SharedPtr joy_sub_; 206 | }; 207 | 208 | } // namespace turtlebot4 209 | 210 | #endif // TURTLEBOT4_NODE__BUTTONS_HPP_ 211 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/display.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__DISPLAY_HPP_ 20 | #define TURTLEBOT4_NODE__DISPLAY_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | #include "turtlebot4_node/utils.hpp" 33 | #include "turtlebot4_msgs/msg/user_display.hpp" 34 | 35 | 36 | namespace turtlebot4 37 | { 38 | 39 | static constexpr auto DISPLAY_NUM_LINES = 5; 40 | static constexpr auto DISPLAY_CHAR_PER_LINE = 18; 41 | static constexpr auto DISPLAY_CHAR_PER_LINE_HEADER = 21; 42 | 43 | struct Turtlebot4MenuEntry 44 | { 45 | std::string name_, function_; 46 | turtlebot4_function_callback_t cb_; 47 | turtlebot4_function_call_callback_t function_call_cb_; 48 | 49 | explicit Turtlebot4MenuEntry(std::string name) 50 | : name_(name), 51 | function_(name) 52 | {} 53 | 54 | /** 55 | * @brief Call menu function 56 | * 57 | */ 58 | void function_call() 59 | { 60 | if (function_call_cb_ != nullptr) { 61 | function_call_cb_(function_); 62 | } 63 | 64 | if (cb_ != nullptr) { 65 | cb_(); 66 | } 67 | } 68 | }; 69 | 70 | class Display 71 | { 72 | public: 73 | // Constructor and Destructor 74 | explicit Display( 75 | std::vector entries, 76 | std::shared_ptr & nh); 77 | virtual ~Display() {} 78 | 79 | // Setters 80 | void set_battery(const sensor_msgs::msg::BatteryState::SharedPtr & battery_state_msg); 81 | void set_ip(std::string ip); 82 | 83 | // Menu Navigation 84 | void scroll_up(); 85 | void scroll_down(); 86 | void select(); 87 | void back(); 88 | void show_message(std::vector message); 89 | void show_message(std::string message); 90 | 91 | // Spin Once 92 | void spin_once(); 93 | 94 | // Request display update 95 | void request_update(); 96 | 97 | private: 98 | // Update display 99 | void update(); 100 | void update_header(); 101 | void set_menu_entries(); 102 | void pad_line(std::string & line); 103 | std::vector get_visible_entries(); 104 | 105 | void display_message_callback(const std_msgs::msg::String::SharedPtr display_msg); 106 | 107 | // Node handle 108 | std::shared_ptr nh_; 109 | rclcpp::Publisher::SharedPtr display_pub_; 110 | rclcpp::Subscription::SharedPtr display_message_sub_; 111 | bool update_required_; 112 | 113 | // Menu 114 | std::vector menu_entries_; 115 | std::vector visible_entries_; 116 | std::vector display_lines_; 117 | bool menu_override_; 118 | uint8_t scroll_position_; 119 | uint8_t selected_line_; 120 | 121 | // Header 122 | std::string ip_; 123 | int battery_percentage_; 124 | std::string header_; 125 | }; 126 | 127 | } // namespace turtlebot4 128 | 129 | #endif // TURTLEBOT4_NODE__DISPLAY_HPP_ 130 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/leds.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__LEDS_HPP_ 20 | #define TURTLEBOT4_NODE__LEDS_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include "std_msgs/msg/int32.hpp" 29 | 30 | #include "turtlebot4_msgs/msg/user_led.hpp" 31 | #include "turtlebot4_node/utils.hpp" 32 | 33 | namespace turtlebot4 34 | { 35 | 36 | struct Turtlebot4Led 37 | { 38 | Turtlebot4LedType type_; 39 | uint32_t on_period_ms_, off_period_ms_; 40 | std::chrono::time_point last_on_time_, last_off_time_; 41 | Turtlebot4LedColor current_color_, next_color_, blink_color_; 42 | rclcpp::Publisher::SharedPtr led_pub_; 43 | 44 | explicit Turtlebot4Led(Turtlebot4LedType type) 45 | : type_(type), 46 | on_period_ms_(0), 47 | off_period_ms_(1000), 48 | current_color_(Turtlebot4LedColor::OFF), 49 | next_color_(Turtlebot4LedColor::OFF), 50 | blink_color_(Turtlebot4LedColor::OFF) 51 | {} 52 | 53 | void create_publisher(rclcpp::Node::SharedPtr nh, std::string topic) 54 | { 55 | led_pub_ = nh->create_publisher(topic, rclcpp::QoS(rclcpp::KeepLast(10))); 56 | } 57 | 58 | void spin_once() 59 | { 60 | switch (current_color_) { 61 | case Turtlebot4LedColor::OFF: 62 | { 63 | // Duty cycle > 0 64 | if (on_period_ms_ > 0) { 65 | // Time to turn on 66 | if (std::chrono::steady_clock::now() > 67 | last_off_time_ + std::chrono::milliseconds(off_period_ms_)) 68 | { 69 | last_on_time_ = std::chrono::steady_clock::now(); 70 | current_color_ = blink_color_; 71 | } 72 | } 73 | break; 74 | } 75 | 76 | case Turtlebot4LedColor::GREEN: 77 | case Turtlebot4LedColor::RED: 78 | case Turtlebot4LedColor::YELLOW: 79 | { 80 | // Duty cycle < 1.0 or blink color is OFF 81 | if (off_period_ms_ > 0 || blink_color_ != current_color_) { 82 | // Time to blink off 83 | if (std::chrono::steady_clock::now() > 84 | last_on_time_ + std::chrono::milliseconds(on_period_ms_)) 85 | { 86 | last_off_time_ = std::chrono::steady_clock::now(); 87 | current_color_ = Turtlebot4LedColor::OFF; 88 | } 89 | } 90 | break; 91 | } 92 | 93 | default: 94 | { 95 | return; 96 | } 97 | } 98 | 99 | auto msg = std_msgs::msg::Int32(); 100 | msg.data = static_cast(current_color_); 101 | led_pub_->publish(msg); 102 | } 103 | }; 104 | 105 | class Leds 106 | { 107 | public: 108 | Leds( 109 | std::shared_ptr & nh); 110 | 111 | void spin_once(); 112 | void set_led(Turtlebot4LedEnum led, Turtlebot4LedColor color); 113 | void blink( 114 | Turtlebot4LedEnum led, uint32_t blink_period_ms, double duty_cycle, 115 | Turtlebot4LedColor color); 116 | 117 | private: 118 | void user_led_callback(const turtlebot4_msgs::msg::UserLed user_led_msg); 119 | 120 | std::shared_ptr nh_; 121 | 122 | rclcpp::Subscription::SharedPtr user_led_sub_; 123 | 124 | std::map> leds_; 125 | }; 126 | 127 | } // namespace turtlebot4 128 | 129 | #endif // TURTLEBOT4_NODE__LEDS_HPP_ 130 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/service.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__SERVICE_HPP_ 20 | #define TURTLEBOT4_NODE__SERVICE_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | namespace turtlebot4 29 | { 30 | 31 | // Base templated service class 32 | template 33 | class Turtlebot4BaseService 34 | { 35 | public: 36 | // Constructor and Destructor 37 | explicit Turtlebot4BaseService( 38 | std::shared_ptr & nh, std::string service, 39 | uint32_t timeout) 40 | : nh_(nh), service_(service), timeout_(timeout) 41 | { 42 | // Create service client 43 | client_ = nh_->create_client(service); 44 | } 45 | virtual ~Turtlebot4BaseService() {} 46 | 47 | virtual void make_request(std::shared_ptr request) = 0; 48 | 49 | protected: 50 | // Node handle 51 | std::shared_ptr nh_; 52 | // Service 53 | std::string service_; 54 | // Timer 55 | rclcpp::TimerBase::SharedPtr timer_; 56 | uint32_t timeout_; 57 | // Service client 58 | typename rclcpp::Client::SharedPtr client_; 59 | 60 | // Service response callback 61 | virtual void response_callback(typename rclcpp::Client::SharedFuture future) = 0; 62 | }; 63 | 64 | // Templated service class for services with a success and message response 65 | template 66 | class Turtlebot4Service : public Turtlebot4BaseService 67 | { 68 | public: 69 | // Constructor and Destructor 70 | explicit Turtlebot4Service( 71 | std::shared_ptr & nh, std::string service, 72 | uint32_t timeout = 30) 73 | : Turtlebot4BaseService(nh, service, timeout) 74 | {} 75 | 76 | virtual ~Turtlebot4Service() {} 77 | 78 | void make_request(std::shared_ptr request) override 79 | { 80 | // Cancel existing timers 81 | if (this->timer_ != nullptr) { 82 | this->timer_->cancel(); 83 | } 84 | 85 | auto timeout = rclcpp::Clock().now().seconds() + this->timeout_; 86 | 87 | // Create timer to check for service without blocking 88 | this->timer_ = this->nh_->create_wall_timer( 89 | std::chrono::milliseconds(1000), 90 | [this, request, timeout]() -> void 91 | { 92 | // Check for service 93 | if (this->client_->wait_for_service(std::chrono::milliseconds(10))) { 94 | RCLCPP_INFO( 95 | this->nh_->get_logger(), "%s service available, sending request", 96 | this->service_.c_str()); 97 | this->timer_->cancel(); 98 | 99 | // Send request 100 | auto future_result = this->client_->async_send_request( 101 | request, 102 | std::bind(&Turtlebot4Service::response_callback, this, std::placeholders::_1)); 103 | } else if (!rclcpp::ok()) { 104 | RCLCPP_ERROR( 105 | this->nh_->get_logger(), "Interrupted while waiting for the service %s.", 106 | this->service_.c_str()); 107 | this->timer_->cancel(); 108 | } else if (rclcpp::Clock().now().seconds() > timeout) { // Timed out 109 | RCLCPP_ERROR( 110 | this->nh_->get_logger(), "Service %s unavailable.", 111 | this->service_.c_str()); 112 | this->timer_->cancel(); 113 | } 114 | }); 115 | } 116 | 117 | private: 118 | // Service response callback 119 | void response_callback(typename rclcpp::Client::SharedFuture future) override 120 | { 121 | auto result = future.get(); 122 | RCLCPP_INFO( 123 | this->nh_->get_logger(), "%s service got results: %s", 124 | this->service_.c_str(), result->success ? "Success" : "Failed"); 125 | RCLCPP_INFO(this->nh_->get_logger(), result->message.c_str()); 126 | } 127 | }; 128 | 129 | // Templated service class for services with an empty response 130 | template 131 | class Turtlebot4EmptyService : public Turtlebot4BaseService 132 | { 133 | public: 134 | // Constructor and Destructor 135 | explicit Turtlebot4EmptyService( 136 | std::shared_ptr & nh, std::string service, 137 | uint32_t timeout = 30) 138 | : Turtlebot4BaseService(nh, service, timeout) 139 | {} 140 | 141 | virtual ~Turtlebot4EmptyService() {} 142 | 143 | void make_request(std::shared_ptr request) override 144 | { 145 | // Cancel existing timers 146 | if (this->timer_ != nullptr) { 147 | this->timer_->cancel(); 148 | } 149 | 150 | auto timeout = rclcpp::Clock().now().seconds() + this->timeout_; 151 | 152 | // Create timer to check for service without blocking 153 | this->timer_ = this->nh_->create_wall_timer( 154 | std::chrono::milliseconds(1000), 155 | [this, request, timeout]() -> void 156 | { 157 | // Check for service 158 | if (this->client_->wait_for_service(std::chrono::milliseconds(10))) { 159 | RCLCPP_INFO( 160 | this->nh_->get_logger(), "%s service available, sending request", 161 | this->service_.c_str()); 162 | this->timer_->cancel(); 163 | 164 | // Send request 165 | auto future_result = this->client_->async_send_request( 166 | request, 167 | std::bind(&Turtlebot4EmptyService::response_callback, this, std::placeholders::_1)); 168 | } else if (!rclcpp::ok()) { 169 | RCLCPP_ERROR( 170 | this->nh_->get_logger(), "Interrupted while waiting for the service %s.", 171 | this->service_.c_str()); 172 | this->timer_->cancel(); 173 | } else if (rclcpp::Clock().now().seconds() > timeout) { // Timed out 174 | RCLCPP_ERROR( 175 | this->nh_->get_logger(), "Service %s unavailable.", 176 | this->service_.c_str()); 177 | this->timer_->cancel(); 178 | } 179 | }); 180 | } 181 | 182 | private: 183 | // Service response callback 184 | void response_callback(typename rclcpp::Client::SharedFuture future) override 185 | { 186 | (void)future; 187 | RCLCPP_INFO( 188 | this->nh_->get_logger(), "%s service completed.", this->service_.c_str()); 189 | } 190 | }; 191 | 192 | } // namespace turtlebot4 193 | 194 | #endif // TURTLEBOT4_NODE__SERVICE_HPP_ 195 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/turtlebot4.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__TURTLEBOT4_HPP_ 20 | #define TURTLEBOT4_NODE__TURTLEBOT4_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "turtlebot4_node/action.hpp" 35 | #include "turtlebot4_node/service.hpp" 36 | #include "turtlebot4_node/display.hpp" 37 | #include "turtlebot4_node/buttons.hpp" 38 | #include "turtlebot4_node/leds.hpp" 39 | #include "turtlebot4_node/utils.hpp" 40 | 41 | #include "irobot_create_msgs/msg/wheel_status.hpp" 42 | #include "irobot_create_msgs/msg/lightring_leds.hpp" 43 | #include "irobot_create_msgs/msg/dock_status.hpp" 44 | #include "irobot_create_msgs/action/undock.hpp" 45 | #include "irobot_create_msgs/action/dock.hpp" 46 | #include "irobot_create_msgs/action/wall_follow.hpp" 47 | #include "irobot_create_msgs/action/led_animation.hpp" 48 | #include "irobot_create_msgs/srv/e_stop.hpp" 49 | #include "irobot_create_msgs/srv/robot_power.hpp" 50 | 51 | 52 | /** Supported functions 53 | * Dock 54 | * Undock 55 | * Follow 56 | * Power off 57 | * EStop 58 | */ 59 | 60 | namespace turtlebot4 61 | { 62 | 63 | // Timer Periods 64 | static constexpr auto BUTTONS_TIMER_PERIOD = 10; 65 | static constexpr auto COMMS_TIMER_PERIOD = 30000; 66 | static constexpr auto DISPLAY_TIMER_PERIOD = 50; 67 | static constexpr auto LEDS_TIMER_PERIOD = 50; 68 | static constexpr auto POWER_OFF_TIMER_PERIOD = 60000; 69 | static constexpr auto WIFI_TIMER_PERIOD = 5000; 70 | 71 | class Turtlebot4 : public rclcpp::Node 72 | { 73 | public: 74 | // Type alias for actions and services 75 | using Dock = irobot_create_msgs::action::Dock; 76 | using Undock = irobot_create_msgs::action::Undock; 77 | using WallFollow = irobot_create_msgs::action::WallFollow; 78 | using LedAnimation = irobot_create_msgs::action::LedAnimation; 79 | using EStop = irobot_create_msgs::srv::EStop; 80 | using Power = irobot_create_msgs::srv::RobotPower; 81 | using EmptySrv = std_srvs::srv::Empty; 82 | using TriggerSrv = std_srvs::srv::Trigger; 83 | 84 | // Constructor and Destructor 85 | Turtlebot4(); 86 | virtual ~Turtlebot4() {} 87 | 88 | private: 89 | void run(); 90 | 91 | // Subscription callbacks 92 | void battery_callback(const sensor_msgs::msg::BatteryState::SharedPtr battery_state_msg); 93 | void dock_status_callback( 94 | const irobot_create_msgs::msg::DockStatus::SharedPtr dock_status_msg); 95 | void wheel_status_callback( 96 | const irobot_create_msgs::msg::WheelStatus::SharedPtr wheel_status_msg); 97 | void joy_callback( 98 | const sensor_msgs::msg::Joy::SharedPtr joy_msg); 99 | 100 | // Function callbacks 101 | void dock_function_callback(); 102 | void undock_function_callback(); 103 | void wall_follow_left_function_callback(); 104 | void wall_follow_right_function_callback(); 105 | void estop_function_callback(); 106 | void power_function_callback(); 107 | void rplidar_start_function_callback(); 108 | void rplidar_stop_function_callback(); 109 | void oakd_start_function_callback(); 110 | void oakd_stop_function_callback(); 111 | void scroll_up_function_callback(); 112 | void scroll_down_function_callback(); 113 | void select_function_callback(); 114 | void back_function_callback(); 115 | void help_function_callback(); 116 | void unused_function_callback(); 117 | void function_call_callback(std::string function_name); 118 | 119 | void add_button_function_callbacks(); 120 | void add_menu_function_callbacks(); 121 | 122 | void low_battery_animation(); 123 | 124 | // Run display timer 125 | void display_timer(const std::chrono::milliseconds timeout); 126 | 127 | // Run buttons timer 128 | void buttons_timer(const std::chrono::milliseconds timeout); 129 | 130 | // Run leds timer 131 | void leds_timer(const std::chrono::milliseconds timeout); 132 | 133 | // Run wifi timer 134 | void wifi_timer(const std::chrono::milliseconds timeout); 135 | 136 | // Run comms timer 137 | void comms_timer(const std::chrono::milliseconds timeout); 138 | 139 | // Run power off timer 140 | void power_off_timer(const std::chrono::milliseconds timeout); 141 | 142 | // IP 143 | std::string get_ip(); 144 | std::string wifi_interface_; 145 | 146 | // Node 147 | rclcpp::Node::SharedPtr node_handle_; 148 | 149 | // Turtlebot4 Functions 150 | std::vector turtlebot4_buttons_; 151 | std::vector turtlebot4_menu_entries_; 152 | std::map function_callbacks_; 153 | std::map button_parameters_; 154 | 155 | // Display 156 | std::unique_ptr display_; 157 | 158 | // Buttons 159 | std::unique_ptr buttons_; 160 | 161 | // Leds 162 | std::unique_ptr leds_; 163 | 164 | // Actions 165 | std::unique_ptr> dock_client_; 166 | std::unique_ptr> undock_client_; 167 | std::unique_ptr> wall_follow_client_; 168 | std::unique_ptr> led_animation_client_; 169 | 170 | // Services 171 | std::unique_ptr> estop_client_; 172 | std::unique_ptr> power_client_; 173 | std::unique_ptr> rplidar_start_client_; 174 | std::unique_ptr> rplidar_stop_client_; 175 | std::unique_ptr> oakd_start_client_; 176 | std::unique_ptr> oakd_stop_client_; 177 | 178 | // Timers 179 | rclcpp::TimerBase::SharedPtr display_timer_; 180 | rclcpp::TimerBase::SharedPtr buttons_timer_; 181 | rclcpp::TimerBase::SharedPtr leds_timer_; 182 | rclcpp::TimerBase::SharedPtr wifi_timer_; 183 | rclcpp::TimerBase::SharedPtr comms_timer_; 184 | rclcpp::TimerBase::SharedPtr power_off_timer_; 185 | 186 | // Subscribers 187 | rclcpp::Subscription::SharedPtr battery_sub_; 188 | rclcpp::Subscription::SharedPtr dock_status_sub_; 189 | rclcpp::Subscription::SharedPtr wheel_status_sub_; 190 | 191 | // Publishers 192 | rclcpp::Publisher::SharedPtr ip_pub_; 193 | rclcpp::Publisher::SharedPtr function_call_pub_; 194 | 195 | // Store current wheels state 196 | bool wheels_enabled_; 197 | 198 | // Store current dock state 199 | bool is_docked_; 200 | 201 | // Store power saver mode 202 | bool power_saver_; 203 | 204 | // Turtlebot4 Model 205 | Turtlebot4Model model_; 206 | }; 207 | 208 | } // namespace turtlebot4 209 | 210 | #endif // TURTLEBOT4_NODE__TURTLEBOT4_HPP_ 211 | -------------------------------------------------------------------------------- /turtlebot4_node/include/turtlebot4_node/utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #ifndef TURTLEBOT4_NODE__UTILS_HPP_ 20 | #define TURTLEBOT4_NODE__UTILS_HPP_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace turtlebot4 29 | { 30 | 31 | static constexpr auto CREATE3_BUTTON_COUNT = 3; 32 | static constexpr auto HMI_BUTTON_COUNT = 4; 33 | static constexpr auto TOTAL_BUTTON_COUNT = 7; 34 | 35 | static constexpr auto UNKNOWN_IP = "UNKNOWN"; 36 | 37 | enum Turtlebot4LedEnum 38 | { 39 | POWER, 40 | MOTORS, 41 | COMMS, 42 | WIFI, 43 | BATTERY, 44 | USER_1, 45 | USER_2, 46 | COUNT 47 | }; 48 | 49 | enum Turtlebot4LedType 50 | { 51 | GREEN_ONLY, 52 | RED_GREEN 53 | }; 54 | 55 | enum Turtlebot4LedColor 56 | { 57 | OFF = 0, 58 | GREEN = 1, 59 | RED = 2, 60 | YELLOW = 3 61 | }; 62 | 63 | enum class Turtlebot4Model 64 | { 65 | LITE, 66 | STANDARD 67 | }; 68 | 69 | static std::map Turtlebot4ModelName 70 | { 71 | {Turtlebot4Model::LITE, "lite"}, 72 | {Turtlebot4Model::STANDARD, "standard"} 73 | }; 74 | 75 | typedef std::function turtlebot4_function_callback_t; 76 | typedef std::function turtlebot4_function_call_callback_t; 77 | 78 | } // namespace turtlebot4 79 | 80 | #endif // TURTLEBOT4_NODE__UTILS_HPP_ 81 | -------------------------------------------------------------------------------- /turtlebot4_node/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | turtlebot4_node 5 | 2.1.0 6 | Turtlebot4 Node 7 | Chris Iverach-Brereton 8 | Hilary Luo 9 | 10 | Apache 2.0 11 | 12 | Roni Kreinin 13 | 14 | ament_cmake 15 | 16 | rclcpp 17 | rclcpp_action 18 | rcutils 19 | std_msgs 20 | std_srvs 21 | sensor_msgs 22 | turtlebot4_msgs 23 | irobot_create_msgs 24 | 25 | ament_lint_auto 26 | ament_lint_common 27 | 28 | 29 | ament_cmake 30 | 31 | 32 | -------------------------------------------------------------------------------- /turtlebot4_node/src/buttons.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #include "turtlebot4_node/buttons.hpp" 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using turtlebot4::Buttons; 26 | 27 | Buttons::Buttons( 28 | Turtlebot4Model model, 29 | std::vector buttons, 30 | std::shared_ptr & nh) 31 | : model_(model), 32 | buttons_(buttons), 33 | nh_(nh) 34 | { 35 | RCLCPP_INFO(nh_->get_logger(), "Buttons Init"); 36 | 37 | create3_buttons_sub_ = nh_->create_subscription( 38 | "interface_buttons", 39 | rclcpp::SensorDataQoS(), 40 | std::bind(&Buttons::create3_buttons_callback, this, std::placeholders::_1)); 41 | 42 | joy_sub_ = nh_->create_subscription( 43 | "joy", 44 | rclcpp::QoS(10), 45 | std::bind(&Buttons::joy_callback, this, std::placeholders::_1)); 46 | 47 | if (model_ == Turtlebot4Model::STANDARD) { 48 | hmi_buttons_sub_ = nh_->create_subscription( 49 | "hmi/buttons", 50 | rclcpp::SensorDataQoS(), 51 | std::bind(&Buttons::hmi_buttons_callback, this, std::placeholders::_1)); 52 | } 53 | } 54 | 55 | /** 56 | * @brief Poll buttons, call callbacks if pressed 57 | */ 58 | void Buttons::spin_once() 59 | { 60 | // Spin buttons 61 | for (size_t i = 0; i < buttons_.size(); i++) { 62 | buttons_.at(i).spin_once(); 63 | } 64 | } 65 | 66 | void Buttons::hmi_buttons_callback( 67 | const turtlebot4_msgs::msg::UserButton::SharedPtr hmi_buttons_msg) 68 | { 69 | for (uint8_t i = 0; i < HMI_BUTTON_COUNT; i++) { 70 | buttons_.at(HMI_1 + i).set_state( 71 | static_cast(hmi_buttons_msg->button[i])); 72 | } 73 | } 74 | 75 | void Buttons::create3_buttons_callback( 76 | const irobot_create_msgs::msg::InterfaceButtons::SharedPtr create3_buttons_msg) 77 | { 78 | buttons_.at(CREATE3_1).set_state( 79 | static_cast(create3_buttons_msg->button_1. 80 | is_pressed)); 81 | buttons_.at(CREATE3_POWER).set_state( 82 | static_cast(create3_buttons_msg-> 83 | button_power.is_pressed)); 84 | buttons_.at(CREATE3_2).set_state( 85 | static_cast(create3_buttons_msg->button_2. 86 | is_pressed)); 87 | } 88 | 89 | void Buttons::joy_callback(const sensor_msgs::msg::Joy::SharedPtr joy_msg) 90 | { 91 | buttons_.at(CONTROLLER_A).set_state( 92 | static_cast(joy_msg->buttons[0])); 93 | buttons_.at(CONTROLLER_B).set_state( 94 | static_cast(joy_msg->buttons[1])); 95 | buttons_.at(CONTROLLER_X).set_state( 96 | static_cast(joy_msg->buttons[3])); 97 | buttons_.at(CONTROLLER_Y).set_state( 98 | static_cast(joy_msg->buttons[2])); 99 | 100 | buttons_.at(CONTROLLER_UP).set_state( 101 | static_cast(joy_msg->axes[7] == 1.0f)); 102 | buttons_.at(CONTROLLER_DOWN).set_state( 103 | static_cast(joy_msg->axes[7] == -1.0f)); 104 | buttons_.at(CONTROLLER_LEFT).set_state( 105 | static_cast(joy_msg->axes[6] == 1.0f)); 106 | buttons_.at(CONTROLLER_RIGHT).set_state( 107 | static_cast(joy_msg->axes[6] == -1.0f)); 108 | 109 | buttons_.at(CONTROLLER_L1).set_state( 110 | static_cast(joy_msg->buttons[4])); 111 | buttons_.at(CONTROLLER_L2).set_state( 112 | static_cast(joy_msg->buttons[6])); 113 | buttons_.at(CONTROLLER_L3).set_state( 114 | static_cast(joy_msg->buttons[11])); 115 | buttons_.at(CONTROLLER_R1).set_state( 116 | static_cast(joy_msg->buttons[5])); 117 | buttons_.at(CONTROLLER_R2).set_state( 118 | static_cast(joy_msg->buttons[7])); 119 | buttons_.at(CONTROLLER_R3).set_state( 120 | static_cast(joy_msg->buttons[12])); 121 | 122 | buttons_.at(CONTROLLER_SHARE).set_state( 123 | static_cast(joy_msg->buttons[8])); 124 | buttons_.at(CONTROLLER_OPTIONS).set_state( 125 | static_cast(joy_msg->buttons[9])); 126 | buttons_.at(CONTROLLER_HOME).set_state( 127 | static_cast(joy_msg->buttons[10])); 128 | } 129 | -------------------------------------------------------------------------------- /turtlebot4_node/src/display.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #include "turtlebot4_node/display.hpp" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using turtlebot4::Display; 27 | using turtlebot4::Turtlebot4MenuEntry; 28 | 29 | /** 30 | * @brief Display constructor 31 | * @input nh - Turtlebot4 Node Handle 32 | */ 33 | Display::Display( 34 | std::vector entries, 35 | std::shared_ptr & nh) 36 | : nh_(nh), 37 | update_required_(true), 38 | menu_entries_(entries), 39 | menu_override_(false), 40 | scroll_position_(0), 41 | selected_line_(0), 42 | ip_(std::string(UNKNOWN_IP)), 43 | battery_percentage_(0) 44 | { 45 | RCLCPP_INFO(nh_->get_logger(), "Init Display"); 46 | 47 | display_pub_ = 48 | nh_->create_publisher( 49 | "hmi/display", 50 | rclcpp::SensorDataQoS()); 51 | display_message_sub_ = nh_->create_subscription( 52 | "hmi/display/message", 53 | rclcpp::SensorDataQoS(), 54 | std::bind(&Display::display_message_callback, this, std::placeholders::_1)); 55 | 56 | // Initialize menu entries 57 | set_menu_entries(); 58 | visible_entries_ = get_visible_entries(); 59 | } 60 | 61 | /** 62 | * @brief Set IP address 63 | * @input ip - IP address as std::string 64 | */ 65 | void Display::set_ip(std::string ip) 66 | { 67 | if (ip_ != ip) { 68 | ip_ = ip; 69 | request_update(); 70 | } 71 | } 72 | 73 | /** 74 | * @brief Set battery percentage 75 | * @input battery_state_msg - Battery state message from Create3 76 | */ 77 | void Display::set_battery(const sensor_msgs::msg::BatteryState::SharedPtr & battery_state_msg) 78 | { 79 | if (battery_percentage_ != static_cast(battery_state_msg->percentage * 100)) { 80 | battery_percentage_ = static_cast(battery_state_msg->percentage * 100); 81 | request_update(); 82 | } 83 | } 84 | 85 | void Display::scroll_down() 86 | { 87 | if (menu_override_) { 88 | return; 89 | } 90 | // Last possible scroll position, last line selected 91 | if (static_cast(scroll_position_ + DISPLAY_NUM_LINES) == menu_entries_.size() && 92 | selected_line_ == DISPLAY_NUM_LINES - 1) 93 | { 94 | return; 95 | } 96 | 97 | if (selected_line_ == DISPLAY_NUM_LINES - 1) { 98 | if (menu_entries_.size() > static_cast(scroll_position_ + DISPLAY_NUM_LINES)) { 99 | scroll_position_++; 100 | } 101 | } else { 102 | selected_line_++; 103 | } 104 | request_update(); 105 | } 106 | 107 | void Display::scroll_up() 108 | { 109 | if (menu_override_) { 110 | return; 111 | } 112 | // First scroll position, first line selected 113 | if (scroll_position_ == 0 && selected_line_ == 0) { 114 | return; 115 | } 116 | 117 | if (selected_line_ == 0) { 118 | scroll_position_--; 119 | } else { 120 | selected_line_--; 121 | } 122 | request_update(); 123 | } 124 | 125 | void Display::select() 126 | { 127 | if (menu_override_) { 128 | return; 129 | } 130 | 131 | visible_entries_[selected_line_].function_call(); 132 | request_update(); 133 | } 134 | 135 | void Display::back() 136 | { 137 | if (menu_override_) { 138 | menu_override_ = false; 139 | } else { 140 | scroll_position_ = 0; 141 | selected_line_ = 0; 142 | } 143 | request_update(); 144 | } 145 | 146 | /** 147 | * @brief Format and return default display message 148 | */ 149 | void Display::set_menu_entries() 150 | { 151 | for (auto & entry : menu_entries_) { 152 | pad_line(entry.name_); 153 | } 154 | } 155 | 156 | void Display::pad_line(std::string & line) 157 | { 158 | // Pad string 159 | if (line.length() < DISPLAY_CHAR_PER_LINE) { 160 | line.insert(line.length(), DISPLAY_CHAR_PER_LINE - line.length(), ' '); 161 | } else if (line.length() > DISPLAY_CHAR_PER_LINE) { 162 | // Remove excess characters 163 | line = line.substr(0, DISPLAY_CHAR_PER_LINE); 164 | } 165 | } 166 | 167 | std::vector Display::get_visible_entries() 168 | { 169 | std::vector::const_iterator first = menu_entries_.begin() + scroll_position_; 170 | std::vector::const_iterator last; 171 | 172 | if (menu_entries_.size() > static_cast(scroll_position_ + DISPLAY_NUM_LINES)) { 173 | last = menu_entries_.begin() + scroll_position_ + DISPLAY_NUM_LINES; 174 | } else { 175 | last = menu_entries_.end(); 176 | } 177 | return std::vector(first, last); 178 | } 179 | 180 | void Display::show_message(std::vector message) 181 | { 182 | std::vector::const_iterator first = message.begin(); 183 | std::vector::const_iterator last; 184 | 185 | if (message.size() > static_cast(DISPLAY_NUM_LINES)) { 186 | last = message.begin() + DISPLAY_NUM_LINES; 187 | } else { 188 | last = message.end(); 189 | } 190 | display_lines_ = std::vector(first, last); 191 | 192 | for (auto & line : display_lines_) { 193 | pad_line(line); 194 | } 195 | 196 | menu_override_ = true; 197 | request_update(); 198 | } 199 | 200 | void Display::show_message(std::string message) 201 | { 202 | display_lines_ = std::vector(DISPLAY_NUM_LINES); 203 | 204 | for (int i = 0; i < DISPLAY_NUM_LINES; i++) { 205 | if (message.length() < static_cast(DISPLAY_CHAR_PER_LINE * i)) { 206 | display_lines_[i] = ""; 207 | } else if (message.length() < static_cast(DISPLAY_CHAR_PER_LINE * (i + 1))) { 208 | display_lines_[i] = 209 | message.substr(DISPLAY_CHAR_PER_LINE * i, message.length() - (DISPLAY_CHAR_PER_LINE * i)); 210 | } else { 211 | display_lines_[i] = message.substr(DISPLAY_CHAR_PER_LINE * i, DISPLAY_CHAR_PER_LINE); 212 | } 213 | } 214 | 215 | for (auto & line : display_lines_) { 216 | pad_line(line); 217 | } 218 | 219 | menu_override_ = true; 220 | request_update(); 221 | } 222 | 223 | /** 224 | * @brief Update display 225 | */ 226 | void Display::update() 227 | { 228 | visible_entries_ = get_visible_entries(); 229 | 230 | auto display_msg = std::make_unique(); 231 | 232 | display_msg->ip = ip_; 233 | display_msg->battery = std::to_string(battery_percentage_); 234 | 235 | if (menu_override_) { 236 | display_msg->selected_entry = -1; 237 | for (size_t i = 0; i < display_lines_.size(); i++) { 238 | display_msg->entries[i] = display_lines_.at(i); 239 | } 240 | } else { 241 | display_msg->selected_entry = selected_line_; 242 | for (size_t i = 0; i < visible_entries_.size(); i++) { 243 | display_msg->entries[i] = visible_entries_.at(i).name_; 244 | } 245 | } 246 | 247 | display_pub_->publish(std::move(display_msg)); 248 | } 249 | 250 | /** 251 | * @brief Spin Once 252 | */ 253 | void Display::spin_once() 254 | { 255 | if (update_required_) { 256 | update(); 257 | update_required_ = false; 258 | } 259 | } 260 | 261 | void Display::request_update() 262 | { 263 | update_required_ = true; 264 | } 265 | 266 | void Display::display_message_callback(const std_msgs::msg::String::SharedPtr display_msg) 267 | { 268 | show_message(display_msg->data); 269 | } 270 | -------------------------------------------------------------------------------- /turtlebot4_node/src/leds.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #include "turtlebot4_node/leds.hpp" 20 | 21 | #include 22 | 23 | using turtlebot4::Leds; 24 | 25 | Leds::Leds( 26 | std::shared_ptr & nh) 27 | : nh_(nh) 28 | { 29 | RCLCPP_INFO(nh_->get_logger(), "Leds Init"); 30 | 31 | // Power 32 | leds_ = { 33 | {Turtlebot4LedEnum::POWER, std::make_shared(Turtlebot4LedType::GREEN_ONLY)}, 34 | {Turtlebot4LedEnum::MOTORS, std::make_shared(Turtlebot4LedType::GREEN_ONLY)}, 35 | {Turtlebot4LedEnum::COMMS, std::make_shared(Turtlebot4LedType::GREEN_ONLY)}, 36 | {Turtlebot4LedEnum::WIFI, std::make_shared(Turtlebot4LedType::GREEN_ONLY)}, 37 | {Turtlebot4LedEnum::BATTERY, std::make_shared(Turtlebot4LedType::RED_GREEN)}, 38 | {Turtlebot4LedEnum::USER_1, std::make_shared(Turtlebot4LedType::GREEN_ONLY)}, 39 | {Turtlebot4LedEnum::USER_2, std::make_shared(Turtlebot4LedType::RED_GREEN)}, 40 | }; 41 | 42 | user_led_sub_ = nh_->create_subscription( 43 | "hmi/led", 44 | rclcpp::SensorDataQoS(), 45 | std::bind(&Leds::user_led_callback, this, std::placeholders::_1)); 46 | 47 | leds_[Turtlebot4LedEnum::POWER]->create_publisher(nh_, "hmi/led/_power"); 48 | leds_[Turtlebot4LedEnum::MOTORS]->create_publisher(nh_, "hmi/led/_motors"); 49 | leds_[Turtlebot4LedEnum::COMMS]->create_publisher(nh_, "hmi/led/_comms"); 50 | leds_[Turtlebot4LedEnum::WIFI]->create_publisher(nh_, "hmi/led/_wifi"); 51 | leds_[Turtlebot4LedEnum::BATTERY]->create_publisher(nh_, "hmi/led/_battery"); 52 | leds_[Turtlebot4LedEnum::USER_1]->create_publisher(nh_, "hmi/led/_user1"); 53 | leds_[Turtlebot4LedEnum::USER_2]->create_publisher(nh_, "hmi/led/_user2"); 54 | } 55 | 56 | void Leds::spin_once() 57 | { 58 | for (uint8_t i = 0; i < Turtlebot4LedEnum::COUNT; i++) { 59 | leds_[static_cast(i)]->spin_once(); 60 | } 61 | } 62 | 63 | void Leds::user_led_callback(const turtlebot4_msgs::msg::UserLed user_led_msg) 64 | { 65 | Turtlebot4LedEnum led = user_led_msg.led == 0 ? USER_1 : USER_2; 66 | blink( 67 | led, user_led_msg.blink_period, user_led_msg.duty_cycle, 68 | static_cast(user_led_msg.color)); 69 | } 70 | 71 | void Leds::set_led(Turtlebot4LedEnum led, Turtlebot4LedColor color) 72 | { 73 | if (color == Turtlebot4LedColor::OFF) { 74 | blink(led, 1000, 0.0, color); 75 | } else { 76 | blink(led, 1000, 1.0, color); 77 | } 78 | } 79 | 80 | void Leds::blink( 81 | Turtlebot4LedEnum led, uint32_t blink_period_ms, double duty_cycle, 82 | Turtlebot4LedColor color) 83 | { 84 | // Invalid duty cycle 85 | if (duty_cycle > 1.0 || duty_cycle < 0.0) { 86 | RCLCPP_ERROR(nh_->get_logger(), "Invalid duty cycle %f", duty_cycle); 87 | return; 88 | } 89 | 90 | if (color > Turtlebot4LedColor::GREEN && leds_[led]->type_ == Turtlebot4LedType::GREEN_ONLY) { 91 | RCLCPP_ERROR(nh_->get_logger(), "Invalid color %d for led %d", color, led); 92 | return; 93 | } 94 | 95 | leds_[led]->on_period_ms_ = blink_period_ms * duty_cycle; 96 | leds_[led]->off_period_ms_ = blink_period_ms * (1 - duty_cycle); 97 | leds_[led]->blink_color_ = color; 98 | } 99 | -------------------------------------------------------------------------------- /turtlebot4_node/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Clearpath Robotics, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * @author Roni Kreinin (rkreinin@clearpathrobotics.com) 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include "turtlebot4_node/turtlebot4.hpp" 28 | #include "turtlebot4_node/utils.hpp" 29 | 30 | 31 | int main(int argc, char * argv[]) 32 | { 33 | rclcpp::init(argc, argv); 34 | 35 | rclcpp::executors::SingleThreadedExecutor executor; 36 | 37 | auto turtlebot4 = std::make_shared(); 38 | 39 | executor.add_node(turtlebot4); 40 | executor.spin(); 41 | 42 | rclcpp::shutdown(); 43 | 44 | return 0; 45 | } 46 | --------------------------------------------------------------------------------