├── .gitignore ├── .gitmodules ├── Catkin └── 01 Catkin Reference.md ├── LICENSE ├── README.md ├── ROS 2 ├── 01 ROS 2 - Introduction.md └── assets │ ├── 15281053255360859.png │ ├── 1563875407348.png │ ├── 1563942689701.png │ ├── 2-Figure1-1.png │ ├── 3-Figure3-1.png │ ├── api_levels.png │ ├── ros_client_library_api_stack.png │ ├── ros_idl_api_stack_dynamic.png │ ├── ros_idl_api_stack_static.png │ └── tumblr_inline_ork4205Z761qal0f2_540.jpg ├── ROS ├── 01 ROS - Introduction.md ├── 02 ROS - Nodes and Parameters.md ├── 02 ROS - ROS Nodes and Parameters.md ├── 03 ROS - Messages, Services, and Actions.md ├── 04 ROS - Nodelets.md ├── 05 ROS - Tips and Tricks.md ├── Starter Code and Resources │ └── ROS_Minimal_Projects │ │ ├── Note.txt │ │ ├── roscpp_minimal_packages │ │ ├── CMakeLists.txt │ │ ├── basic_pub_sub │ │ │ ├── CMakeLists.txt │ │ │ ├── launch │ │ │ │ └── basic_pub_sub_init.launch │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ ├── basic_pub.cpp │ │ │ │ ├── basic_sub.cpp │ │ │ │ └── hello_world.cpp │ │ ├── class_pub_sub │ │ │ ├── CMakeLists.txt │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ └── class_pub_sub.cpp │ │ ├── dynamic_configure_example │ │ │ ├── CMakeLists.txt │ │ │ ├── cfg │ │ │ │ └── Example.cfg │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ ├── dynamic_reconfigure_client.cpp │ │ │ │ └── dynamic_reconfigure_example.cpp │ │ ├── modular_pub_sub │ │ │ ├── CMakeLists.txt │ │ │ ├── config │ │ │ │ └── default.yaml │ │ │ ├── include │ │ │ │ └── PACKAGE_HEADERS │ │ │ │ │ ├── algorithm.hpp │ │ │ │ │ └── nodeClassInterface.hpp │ │ │ ├── launch │ │ │ │ └── launch_Node.launch │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ ├── Node.cpp │ │ │ │ ├── algorithm.cpp │ │ │ │ └── nodeClassInterface.cpp │ │ ├── msg_example │ │ │ ├── CMakeLists.txt │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ └── msg_example.cpp │ │ ├── msg_example_msgs │ │ │ ├── CMakeLists.txt │ │ │ ├── msg │ │ │ │ └── My_msg.msg │ │ │ └── package.xml │ │ ├── param_example │ │ │ ├── CMakeLists.txt │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ └── param_example.cpp │ │ ├── pub_sub_nodelet_example │ │ │ ├── CMakeLists.txt │ │ │ ├── include │ │ │ │ └── pub_sub_nodelet_example │ │ │ │ │ └── PubSubNodelet.h │ │ │ ├── launch │ │ │ │ └── nodelet.launch │ │ │ ├── nodelet_plugins.xml │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ └── PubSubNodelet.cpp │ │ ├── simple_action_example │ │ │ ├── CMakeLists.txt │ │ │ ├── action │ │ │ │ └── Fibonacci.action │ │ │ ├── package.xml │ │ │ └── src │ │ │ │ ├── fibonacci_client.cpp │ │ │ │ └── fibonacci_server.cpp │ │ └── srv_example │ │ │ ├── CMakeLists.txt │ │ │ ├── package.xml │ │ │ ├── src │ │ │ ├── srv_example_client.cpp │ │ │ └── srv_example_server.cpp │ │ │ └── srv │ │ │ └── AddTwoInts.srv │ │ └── rospy_minimal_packages │ │ ├── CMakeLists.txt │ │ ├── Reminder.txt │ │ ├── basic_pub_sub │ │ ├── CMakeLists.txt │ │ ├── launch │ │ │ └── basic_pub_sub_init.launch │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ ├── basic_pub │ │ │ ├── basic_sub │ │ │ └── hello_world │ │ ├── class_pub_sub │ │ ├── CMakeLists.txt │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ └── class_pub_sub │ │ ├── dynamic_configure_example │ │ ├── CMakeLists.txt │ │ ├── cfg │ │ │ └── Example.cfg │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ ├── dynamic_reconfigure_client │ │ │ └── dynamic_reconfigure_example │ │ ├── modular_pub_sub │ │ ├── CMakeLists.txt │ │ ├── config │ │ │ └── default.yaml │ │ ├── launch │ │ │ ├── launch_Node.launch │ │ │ └── modular_pub_sub_init.launch │ │ ├── nodes │ │ │ ├── modular_pub │ │ │ └── modular_sub │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ └── modular_pub_sub │ │ │ ├── __init__.py │ │ │ ├── pub_source.py │ │ │ ├── rawr_package │ │ │ ├── __init__.py │ │ │ └── rawr_source.py │ │ │ └── sub_source.py │ │ ├── msg_example │ │ ├── CMakeLists.txt │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ └── msg_example │ │ ├── msg_example_msgs │ │ ├── CMakeLists.txt │ │ ├── msg │ │ │ └── My_msg.msg │ │ └── package.xml │ │ ├── param_example │ │ ├── CMakeLists.txt │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ └── param_example │ │ ├── simple_action_example │ │ ├── CMakeLists.txt │ │ ├── action │ │ │ └── Fibonacci.action │ │ ├── package.xml │ │ ├── setup.py │ │ └── src │ │ │ ├── fibonacci_client │ │ │ └── fibonacci_server │ │ └── srv_example │ │ ├── CMakeLists.txt │ │ ├── package.xml │ │ ├── setup.py │ │ ├── src │ │ ├── srv_example_client │ │ └── srv_example_server │ │ └── srv │ │ └── AddTwoInts.srv └── assets │ ├── 1.1.png │ ├── 1.2.png │ ├── 14599315912601528.png │ ├── 2.1.png │ ├── 2.2.png │ ├── 3.1.png │ ├── 3.2.png │ ├── 3.3.png │ ├── 3.4.png │ ├── 7580OS_09_16.jpg │ ├── 8ros-lt-nodelet-4-638.jpg │ └── Screenshot-Reconfigure.png └── assets ├── 1563793456590.png ├── COFFEE BUTTON ヾ(°∇°^).png ├── CylinderSegmentationFast.gif └── youtube_thumbnail.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swap 3 | *.save 4 | *.bak 5 | *.pyc 6 | 7 | *.no_toc 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Starter Code and Resources/ROS_2_Minimal_Projects"] 2 | path = ROS 2/Starter Code and Resources/ROS_2_Minimal_Projects 3 | url = https://github.com/ros2/examples.git 4 | -------------------------------------------------------------------------------- /Catkin/01 Catkin Reference.md: -------------------------------------------------------------------------------- 1 | ## Catkin Reference 2 | 3 | Author: methylDragon 4 | Reference notes for the CMake-based build system for ROS! I'm using ROS Kinetic at the moment, but these notes should apply for any ROS version Indigo onwards! 5 | Most of the notes will be adapted from: http://wiki.ros.org/catkin/Tutorials 6 | 7 | --- 8 | 9 | ## Pre-Requisites 10 | 11 | - You need to have Catkin installed! Luckily it comes pre-installed with ROS 12 | - Otherwise... http://wiki.ros.org/catkin/Tutorials/create_a_workspace 13 | - !!! **I'll presume you know your way around the Linux Terminal** !!! 14 | - If not... play http://web.mit.edu/mprat/Public/web/Terminus/Web/main.html for a start! 15 | - Make sure you've sourced your ROS environment! 16 | - `source /opt/ros//setup.bash` 17 | - In the case of Kinetic, `source /opt/ros/kinetic/setup.bash` 18 | - It would be good to append said line to your .bashrc file! Access said file using `sudo nano ~/.bashrc` 19 | 20 | 21 | 22 | ## Table Of Contents 23 | 24 | 1. [Introduction](#1) 25 | 2. [Basic Catkin Workflow](#2) 26 | 2.1 [Workflow Introduction](#2.1) 27 | 2.2 [Making a Workspace](#2.2) 28 | 2.3 [Sourcing the Workspace](#2.3) 29 | 2.4 [Catkin Packages](#2.4) 30 | 2.5 [Creating a catkin Package](#2.5) 31 | 2.6 [Building the Workspace](#2.6) 32 | 2.7 [More about catkin_make](#2.7) 33 | 2.8 [Installing Dependencies](#2.8) 34 | 3. [Customising your packages: Package.xml](#3) 35 | 3.1 [package.xml](#3.1) 36 | 3.2 [Example package.xml](#3.2) 37 | 3.3 [Description](#3.3) 38 | 3.4 [Maintainers](#3.4) 39 | 3.5 [License](#3.5) 40 | 3.6 [Author Info](#3.6) 41 | 3.7 [Dependencies](#3.7) 42 | 4. [Customising your packages: CMakeLists.txt](#4) 43 | 4.1 [CMakeLists.txt](#4.1) 44 | 4.2 [Required CMake Version](#4.2) 45 | 4.3 [Package Name](#4.3) 46 | 4.4 [Declare catkin Dependencies](#4.4) 47 | 4.5 [Enable Python module support](#4.5) 48 | 4.6 [Add Messages, Services, and Actions](#4.6) 49 | 4.7 [Generate Messages, Services, and Actions](#4.7) 50 | 4.8 [Specify Package Build-info](#4.8) 51 | 4.9 [Declare Other Dependencies](#4.9) 52 | 4.10 [Specify Build Targets (and more!)](#4.10) 53 | 4.11 [Add Unit Test Handlers (Optional)](#4.11) 54 | 4.12 [Specify Installable Targets (and Python Scripts!)](#4.12) 55 | 4.13 [Use a Custom Compiler Version)](#4.13) 56 | 57 | 58 | 59 | 60 | ## 1. Introduction 61 | 62 | Long story short, when you're making packages for a huge ecosystem such as ROS, you're bound to end up with a lot of problems managing nested dependencies in its many packages. 63 | 64 | Catkin is the next generation of the original answer to that problem (rosbuild.) It helps you manage dependencies, manage workspaces (environments), build ROS packages, and more! 65 | 66 | 67 | 68 | ## 2. Basic Workflow 69 | 70 | ### 2.1 Workflow Introduction 71 | 72 | [go to top](#top) 73 | 74 | Now that we're ready to go, let's get some context! 75 | 76 | The steps you'll generally go through when developing for ROS will go roughly as such 77 | 78 | 1. Make a catkin workspace (and overlaying it into your environment) 79 | - `catkin_make` 80 | 2. Create catkin packages (ROS packages) 81 | - `catkin_create_pkg` 82 | 3. Build the catkin workspace and its packages (and overlay them into your environment) 83 | - `catkin_make` again 84 | 4. Install the catkin workspace and its packages 85 | - `catkin_make install` 86 | 87 | 88 | 89 | ### 2.2 Making a Workspace 90 | 91 | [go to top](#top) 92 | 93 | Before we can do anything with Catkin, we need to make a workspace for it. A workspace is a handy way to partition all your required packages, perfect for neatly packaging individual projects together! 94 | 95 | Ok. So if you want to make a workspace, navigate to whatever directory you want to make it in using `cd`. Then, 96 | 97 | ```shell 98 | $ mkdir -p catkin_ws/src # Create a catkin_ws folder with a src folder in it 99 | $ cd catkin_ws # Navigate into the folder's root 100 | $ catkin_make # Build the required files 101 | ``` 102 | 103 | 104 | 105 | ### 2.3 Sourcing the workspace 106 | 107 | [go to top](#top) 108 | 109 | Great! Now **source** into it to allow you to run commands from the workspace in your Terminal. (You're overlaying the workspace's commands into your environment.) 110 | 111 | ```shell 112 | $ source devel/setup.bash # Make sure you run this from your workspace's root! 113 | 114 | # It would be good to also append this source command to your .bashrc so you don't have to keep doing it everytime you open a terminal 115 | 116 | # Append source /devel/setup.bash 117 | ``` 118 | 119 | To check if you've sourced into it properly, run 120 | 121 | ```shell 122 | $ echo $ROS_PACKAGE_PATH 123 | 124 | # Ensure your workspace's directory appears in here 125 | ``` 126 | 127 | 128 | 129 | ### 2.4 Catkin Packages 130 | 131 | [go to top](#top) 132 | 133 | **ROS packages are catkin packages!** 134 | 135 | Every catkin package requires you to have the following files and folders: 136 | 137 | - package.xml 138 | - Provides metadata about the package (maintainer, description, etc.) 139 | - CMakeLists.txt 140 | - Describes how to build the code and where to install it 141 | - http://wiki.ros.org/catkin/CMakeLists.txt 142 | - The individual package folders 143 | 144 | The simplest package folder structure structure looks like this: 145 | 146 | ``` 147 | my_package/ 148 | CMakeLists.txt 149 | package.xml 150 | ``` 151 | 152 | So the corresponding workspace folder will look like this 153 | 154 | ``` 155 | workspace_folder/ -- WORKSPACE 156 | src/ -- SOURCE SPACE 157 | CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin 158 | package_1/ 159 | CMakeLists.txt -- CMakeLists.txt file for package_1 160 | package.xml -- Package manifest for package_1 161 | ... 162 | package_n/ 163 | CMakeLists.txt -- CMakeLists.txt file for package_n 164 | package.xml -- Package manifest for package_n 165 | ``` 166 | 167 | 168 | 169 | ### 2.5 Creating a catkin Package 170 | 171 | [go to top](#top) 172 | 173 | Go into the **src** directory of the catkin workspace you want to create a package in 174 | 175 | ```shell 176 | $ cd /catkin_ws/src 177 | ``` 178 | 179 | Run the **catkin_create_pkg** script to create your package! The command works like this 180 | 181 | ```shell 182 | $ catkin_create_package [depend1] [depend2] ... 183 | ``` 184 | 185 | This will create a package folder with its respective package.xml and CMakeLists.txt, filled somewhat with the information you gave the script. 186 | 187 | 188 | 189 | #### **Finding Package Dependencies via rospack** 190 | 191 | First-order package dependencies are stored in the package.xml file. 192 | 193 | You can also see them using 194 | 195 | ```shell 196 | $ rospack depends1 197 | ``` 198 | 199 | If you want to see ALL the nested dependencies, use 200 | 201 | ```shell 202 | $ rospack depends 203 | ``` 204 | 205 | > Note: You can make catkin_make ignore your package by leaving an empty file with the name **CATKIN_IGNORE** in the package's directory! 206 | 207 | 208 | 209 | ### 2.6 Building the Workspace 210 | 211 | [go to top](#top) 212 | 213 | Now all you need to do is build the packages in your workspace! 214 | 215 | ```shell 216 | $ cd /catkin_ws 217 | $ catkin_make 218 | ``` 219 | 220 | catkin_make will now do certain things to certain files: 221 | 222 | - **Packages in the source space (src)** will be built into the **build space (/build)** 223 | - **Source files, scripts, and other static files** will remain in the **source space (/src)** 224 | - **Generated files (libraries, executables, etc.)** will be placed in the **devel space (/devel)** 225 | 226 | 227 | 228 | #### **Devel and Install spaces** 229 | 230 | > CHOOSE BETWEEN USING THE INSTALL OR DEVEL SPACE 231 | > 232 | > DON'T USE MORE THAN ONE 233 | 234 | The development space (devel) is useful for, guess what, developing. When you're using `catkin_make` you don't need to invoke the `install` argument each time. 235 | 236 | The install space (install) is there for when you're ready to distribute. 237 | 238 | 239 | 240 | #### **Sourcing the built workspace** 241 | 242 | You know the drill. Find the setup.bash, and source it. Appending it to .bashrc will be useful. 243 | 244 | ```shell 245 | $ source //setup.bash 246 | ``` 247 | 248 | 249 | 250 | ### 2.7 More about catkin_make 251 | 252 | [go to top](#top) 253 | 254 | > This section will talk about customising the behaviour of catkin_make! 255 | > 256 | > Though, there's another tool that's helpful if you want to trudge through the documentation for that! I'm just going to be (mostly) writing for the official catkin_make tool though! The extra tool I'm talking about is here: http://catkin-tools.readthedocs.io/en/latest/index.html 257 | 258 | Sometimes your build might fail at a certain package (eg, at package 100 out of 150). 259 | 260 | If you just ran catkin_make again, it'll rebuild everything starting from package 1. How do you fix stuff like that? Turns out there are more parameters you can use for catkin_make! (Actually you can customise it even more by changing your CMakeLists.txt, but if you don't want to do that, there's a lot you can do from the terminal!) 261 | 262 | 263 | 264 | #### **Build specific packages** 265 | 266 | ```shell 267 | $ catkin_make --pkg 268 | ``` 269 | 270 | 271 | 272 | #### **Build starting from a specific package** 273 | 274 | ```shell 275 | $ catkin_make --from-pkg 276 | ``` 277 | 278 | 279 | 280 | #### **Previewing the build order (catkin tools preview!)** 281 | 282 | Now we'll talk about a handy command we can use from the third-party catkin tools!: http://catkin-tools.readthedocs.io/en/latest/verbs/catkin_build.html 283 | 284 | This command lets you preview the build order. Very useful for saving time if you know what you want to build or where you had an error! 285 | 286 | ```shell 287 | $ catkin build --dry-run 288 | ``` 289 | 290 | 291 | 292 | ### 2.8 Installing Dependencies 293 | 294 | [go to top](#top) 295 | 296 | Sometimes you might find that you don't have dependencies installed from a package you downloaded online. No issues! Use **rosdep** to install all the dependences! 297 | 298 | ```shell 299 | # I'm assuming you're going to be using ROS Kinetic 300 | 301 | # Navigate to your workspace's root and run: 302 | $ rosdep install —from-paths src —ignore-src —rosdistro=kinetic -y 303 | ``` 304 | 305 | 306 | 307 | ## 3. Customising your packages: Package.xml 308 | 309 | ### 3.1 package.xml 310 | 311 | [go to top](#top) 312 | 313 | package.xml contains metadata about your package! It's written in **XML**, so it shouldn't be that hard to understand. 314 | 315 | It contains the following data: (Order matters! Play it safe!) 316 | 317 | - Description 318 | - Maintainers 319 | - License 320 | - Author Info 321 | - Dependencies 322 | - ... 323 | 324 | 325 | 326 | ### 3.2 Example package.xml 327 | 328 | [go to top](#top) 329 | 330 | From the catkin tutorials 331 | 332 | ```xml 333 | 334 | 335 | beginner_tutorials 336 | 0.1.0 337 | The beginner_tutorials package 338 | 339 | Your Name 340 | BSD 341 | http://wiki.ros.org/beginner_tutorials 342 | Jane Doe 343 | 344 | catkin 345 | 346 | roscpp 347 | rospy 348 | std_msgs 349 | 350 | roscpp 351 | rospy 352 | std_msgs 353 | 354 | 355 | 356 | ``` 357 | 358 | 359 | 360 | ### 3.3 Description 361 | 362 | [go to top](#top) 363 | 364 | The description tag can be anything you'd like. But the convention is that the very first sentence should be able to summarise the point of the package. 365 | 366 | ```xml 367 | The beginner_tutorials package 368 | ``` 369 | 370 | 371 | 372 | ### 3.4 Maintainers 373 | 374 | [go to top](#top) 375 | 376 | You can mention more than one maintainer. One per line. Make sure you have the email and the name! 377 | 378 | ```xml 379 | methylDragon 380 | ``` 381 | 382 | 383 | 384 | ### 3.5 License 385 | 386 | [go to top](#top) 387 | 388 | Licenses are required, one per line also. 389 | 390 | Common licenses are: BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3. 391 | 392 | Don't know what license to use? No worries! https://choosealicense.com/ 393 | 394 | ```xml 395 | MIT 396 | ``` 397 | 398 | 399 | 400 | ### 3.6 Author Info 401 | 402 | [go to top](#top) 403 | 404 | Not required, but handy 405 | 406 | ```xml 407 | http://github.com/methylDragon 408 | methylDragon 409 | ``` 410 | 411 | 412 | 413 | ### 3.7 Dependencies 414 | 415 | [go to top](#top) 416 | 417 | REQUIRED. Arguably the most important of them all. 418 | 419 | State your dependencies here! For either catkin or system dependencies, there are a couple of ways to state them: 420 | 421 | **For packages you need at compile time** 422 | 423 | ```xml 424 | roscpp 425 | rospy 426 | std_msgs 427 | ``` 428 | 429 | **For build tool packages** 430 | 431 | ```xml 432 | catkin 433 | ``` 434 | 435 | **For dependencies you need at runtime** 436 | 437 | ```xml 438 | roscpp 439 | rospy 440 | std_msgs 441 | ``` 442 | 443 | **For dependencies you need for testing only** 444 | 445 | ```xml 446 | roscpp 447 | rospy 448 | std_msgs 449 | ``` 450 | 451 | 452 | 453 | ## 4. Customising your packages: CMakeLists.txt 454 | 455 | ### 4.1 CMakeLists.txt 456 | 457 | [go to top](#top) 458 | 459 | CMakeLists.txt is what gets passed into the CMake build system when you run catkin_make. It describes where and how to build the code, and where to install the code to. 460 | 461 | > Your CMakeLists.txt file **MUST** follow this format otherwise your packages will not build correctly. The order in the configuration **DOES** count. 462 | > 463 | > 1. **Required CMake Version** (`cmake_minimum_required`) 464 | > 2. **Package Name** (`project()`) 465 | > 3. **Declare catkin Dependencies** (`find_package()`) 466 | > 4. **Enable Python module support** (`catkin_python_setup()`) 467 | > 5. **Add Messages, Services, and Actions** (`add_message_files(), add_service_files(), add_action_files()`) 468 | > 6. **Generate Messages, Services, and Actions** (`generate_messages()`) 469 | > 7. **Specify Package Build-Info** (`catkin_package()`) 470 | > 8. **Declare other dependencies** (`add_executable()`, `add_dependencies()`, `add_action_files()`) 471 | > 9. **Specify Build Targets (and more!)**(`add_library()/add_executable()/target_link_libraries()`) 472 | > 10. **Add Unit Test Handlers (Optional) ** (`catkin_add_gtest()`) 473 | > 11. **Specify Installable Targets** (`install()`) 474 | > 475 | > (http://wiki.ros.org/catkin/CMakeLists.txt) 476 | 477 | 478 | 479 | > **Handy tip:** 480 | > 481 | > If you want to set 'variables' for the names or paths of install targets, use `set` 482 | > 483 | > ```python 484 | > # Set the name to use for the executable. 485 | > set (BINNAME1 pid_configure) 486 | > set (BINNAME2 pid_listen) 487 | > 488 | > # Set the source files to use with the executable. 489 | > set (SRCS1 ${SRCS1} src/lino_pid_core.cpp) 490 | > set (SRCS1 ${SRCS1} src/pid_configure.cpp) 491 | > set (SRCS2 ${SRCS2} src/lino_pid_core.cpp) 492 | > set (SRCS2 ${SRCS2} src/pid_listen.cpp) 493 | > 494 | > # Build the executable that will be used to run this node. 495 | > add_executable (${BINNAME1} ${SRCS1}) 496 | > target_link_libraries(${BINNAME1} ${catkin_LIBRARIES}) 497 | > add_dependencies(${BINNAME1} ${PROJECT_NAME}_gencfg) 498 | > add_executable (${BINNAME2} ${SRCS2}) 499 | > target_link_libraries(${BINNAME2} ${catkin_LIBRARIES}) 500 | > add_dependencies(${BINNAME2} ${PROJECT_NAME}_gencfg) 501 | > ``` 502 | > 503 | > 504 | 505 | 506 | 507 | ### 4.2 Required CMake Version (`cmake_minimum_required`) 508 | 509 | [go to top](#top) 510 | 511 | Requires version 2.8.3 or higher 512 | 513 | ```python 514 | cmake_minimum_required(VERSION 2.8.3) 515 | ``` 516 | 517 | 518 | 519 | ### 4.3 Package Name (`project()`) 520 | 521 | [go to top](#top) 522 | 523 | Self-Explanatory 524 | 525 | ```python 526 | project(package_name) 527 | ``` 528 | 529 | 530 | 531 | ### 4.4 Declare catkin Dependencies (`find_package()`) 532 | 533 | [go to top](#top) 534 | 535 | This is where you state what other CMake packages you need to use to build your project. 536 | 537 | There is always at least this dependency though! (Since you require catkin in order to build your project) 538 | 539 | ```python 540 | # This is if you have no dependencies other than catkin 541 | find_package(catkin REQUIRED) 542 | 543 | # But if you have more... 544 | # State them as components! 545 | find_package(catkin REQUIRED COMPONENTS package1 package2 package3) 546 | ``` 547 | 548 | find_package() creates some environment variables once catkin finds the package. These variables tell CMake where the relevant components of the package are (header files, source, libraries, dependencies, paths, etc.) 549 | 550 | > _FOUND - Set to true if the library is found, otherwise false 551 | > 552 | > _INCLUDE_DIRS or \_INCLUDES - The include paths exported by the package 553 | > 554 | > _LIBRARIES or \_LIBS - The libraries exported by the package 555 | > 556 | > _DEFINITIONS - ? 557 | 558 | If you don't state the component as a component, the paths, libraries, etc. stated in the quoted block above won't get added. So please **add them as components**. 559 | 560 | 561 | 562 | ### 4.5 Enable Python module support (`catkin_python_setup()`) 563 | 564 | [go to top](#top) 565 | 566 | Use this if your ROS package uses python. 567 | 568 | Create a setup.py file, and add 569 | 570 | ```python 571 | catkin_python_setup() 572 | ``` 573 | 574 | **DO NOT USE THIS ALONE TO INSTALL PYTHON SCRIPTS YOU WANT TO USE AS A PACKAGE IN THE INSTALL SPACE.** There's a section for that later on! 575 | 576 | 577 | 578 | ### 4.6 Add Messages, Services, and Actions (`add_message_files(), add_service_files(), add_action_files()`) 579 | 580 | [go to top](#top) 581 | 582 | Messages, Services, and Actions files are hugely important in ROS. Catkin has to prepare them before they can be used by ROS though! 583 | 584 | So add them! 585 | 586 | ```python 587 | # Declare the message files to be built 588 | add_message_files(FILES 589 | MyMessage1.msg 590 | MyMessage2.msg 591 | ) 592 | 593 | # Declare the service files to be built 594 | add_service_files(FILES 595 | MyService.srv 596 | ) 597 | 598 | # Declare the action files to be built 599 | add_action_files( FILES 600 | File1 601 | File2 602 | ) 603 | ``` 604 | 605 | 606 | 607 | ### 4.7 Generate Messages, Services, and Actions (`generate_messages()`) 608 | 609 | [go to top](#top) 610 | 611 | Simple enough 612 | 613 | ```python 614 | generate_messages() 615 | ``` 616 | 617 | 618 | 619 | ### 4.8 Specify Package Build-Info (`catkin_package()`, `include_directories`) 620 | 621 | [go to top](#top) 622 | 623 | (OPTIONAL) But you **MUST** have this included before you can add_library() or add_executable() 624 | 625 | This is if you need to import modules 626 | 627 | > CATKIN_DEPENDS are catkin packages 628 | > 629 | > DEPENDS are system dependencies 630 | > 631 | > $(PROJECT_NAME) evaluates to whatever you passed project() 632 | 633 | ```python 634 | catkin_package( 635 | INCLUDE_DIRS include 636 | LIBRARIES ${PROJECT_NAME} 637 | CATKIN_DEPENDS roscpp nodelet 638 | DEPENDS eigen opencv) 639 | 640 | include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) 641 | link_directories(~/some_lib_dirs) 642 | ``` 643 | 644 | `include_directories`: For C++ library paths (since you include them) 645 | 646 | `link_directories`: Used to add additional library paths (not recommended) 647 | 648 | 649 | 650 | ### 4.9 Declare Other Dependencies (`add_executable()`, `add_dependencies()`, `add_action_files()`) 651 | 652 | [go to top](#top) 653 | 654 | ```python 655 | # define executable to be built using messages etc. 656 | # and the dependencies it needs 657 | add_executable(message_program src/main.cpp) 658 | add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) 659 | 660 | # define executable not using any messages/services provided by this package 661 | # and the dependencies it needs 662 | add_executable(does_not_use_local_messages_program src/main.cpp) 663 | add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS}) 664 | ``` 665 | 666 | 667 | 668 | ### 4.10 Specify Build Targets (and more!) (`add_library(), add_executable(), target_link_libraries()`) 669 | 670 | [go to top](#top) 671 | 672 | There are generally two ways to specify a build target 673 | 674 | - Executable: Something you run 675 | - Library: Something that is used by executable targets 676 | 677 | 678 | 679 | #### **Name your targets!** They have to be unique! You can rename stuff though! 680 | 681 | ```python 682 | set_target_properties(rviz_image_view 683 | PROPERTIES OUTPUT_NAME image_view 684 | PREFIX "") 685 | ``` 686 | 687 | 688 | 689 | #### **Specify a custom output directory** 690 | 691 | Sometimes you might want a different directory to install to for certain packages (like python module installs) 692 | 693 | ```python 694 | set_target_properties(python_module_library 695 | PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}) 696 | ``` 697 | 698 | 699 | 700 | #### **Include Paths and Library Paths** 701 | 702 | You need to specify the locations of your resources before specifying your targets 703 | 704 | - Include paths: Header files, and the like 705 | - Library paths: Libraries, of course 706 | 707 | ```python 708 | include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS}) 709 | ``` 710 | 711 | 712 | 713 | #### **Specify your targets** 714 | 715 | Executable target 716 | 717 | ```python 718 | # This will build a program called myProgram from the three source files stated 719 | add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp) 720 | ``` 721 | 722 | Library Target 723 | 724 | ```python 725 | add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS}) 726 | ``` 727 | 728 | 729 | 730 | #### **Link Libraries** 731 | 732 | Then you link your libraries to your executables! 733 | 734 | ```python 735 | target_link_libraries( ... ) 736 | ``` 737 | 738 | 739 | 740 | ### 4.11 Add Unit Test Handlers (Optional) (`catkin_add_gtest()`) 741 | 742 | [go to top](#top) 743 | 744 | ```python 745 | catkin_add_gtest(myUnitTest test/utest.cpp) 746 | ``` 747 | 748 | 749 | 750 | ### 4.12 Specify Installable Targets (and Python Scripts!) (`install()`, `catkin_install_python()`) 751 | 752 | [go to top](#top) 753 | 754 | > Make sure catkin_package() is called BEFORE install()! 755 | 756 | Normally, `catkin_make` places built targets into the **devel space (/devel)**. But if you want to do a proper release where users build using `catkin_make install`, use install() to place built targets into the **install space (/install)**. 757 | 758 | install() takes the following arguments: 759 | 760 | - `TARGETS` - which targets to install 761 | - `ARCHIVE DESTINATION` - Static libraries and DLL (Windows) .lib stubs 762 | - `LIBRARY DESTINATION` - Non-DLL shared libraries and modules 763 | - `RUNTIME DESTINATION` - Executable targets and DLL (Windows) style shared libraries 764 | 765 | **For example:** 766 | 767 | ```python 768 | install(TARGETS ${PROJECT_NAME} 769 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 770 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 771 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 772 | ) 773 | ``` 774 | 775 | **Or if you want to install to a specific folder:** (In this case, a Python library folder) 776 | 777 | ```python 778 | install(TARGETS python_module_library 779 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION} 780 | LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION} 781 | ) 782 | ``` 783 | 784 | **Or if you want to install python scripts** 785 | 786 | ```python 787 | catkin_install_python(PROGRAMS scripts/myscript 788 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 789 | ``` 790 | 791 | **Or if you want to install header files** 792 | 793 | ```python 794 | install(DIRECTORY include/${PROJECT_NAME}/ 795 | DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 796 | PATTERN ".svn" EXCLUDE 797 | ) 798 | ``` 799 | 800 | **Or if you want to install roslaunch files, or other resources** 801 | 802 | ```python 803 | install(DIRECTORY launch/ 804 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch 805 | PATTERN ".svn" EXCLUDE) 806 | ``` 807 | 808 | ​ 809 | 810 | ### 4.13 Use a Custom Compiler Version 811 | 812 | [go to top](#top) 813 | 814 | Sometimes you might want ROS to compile with a different compiler version to leverage certain features of that compiler. 815 | 816 | This one sets the compiler to use to C++11! (Which allows one to use list initialisation! Super useful for making maps.) 817 | 818 | ```python 819 | set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") 820 | ``` 821 | 822 | 823 | 824 | ------ 825 | 826 | [![Yeah! Buy the DRAGON a COFFEE!](../assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019, methylDragon 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ROS Tutorials 2 | 3 | I've compiled a whole bunch of comprehensive tutorials and starter code templates for the **Robot Operating System** (ROS), for both **ROS 1** and **ROS 2**! 4 | 5 | Most of these can be read through in under an hour, and they're pitched at the beginner to intermediate level. But most importantly, they're **designed to be CTRL-F-able!** 6 | 7 | 8 | 9 | ## Pre-Requisites 10 | 11 | It will definitely help to brush up on [Python](https://github.com/methylDragon/coding-notes/tree/master/Python%203) and [C++](). 12 | 13 | As well as [Linux]() to be able to follow along with the tutorial. 14 | 15 | 16 | 17 | ## Support my efforts! 18 | 19 | [![Yeah! Buy the DRAGON a COFFEE!](./assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) 20 | 21 | [Or leave a tip! ヾ(°∇°*)](https://www.paypal.me/methylDragon) 22 | 23 | 24 | 25 | ## Further Reading 26 | 27 | After reading up on the ROS tutorials, you can do some further reading! 28 | 29 | ### Robotic Manipulator Planning with MoveIt! 30 | 31 | ![1563793456590](assets/1563793456590.png) 32 | 33 | > The MoveIt! project is a ROS package that helps with motion planning for robotic manipulators. As such, it is especially useful for working with and planning for arms! 34 | 35 | 36 | 37 | 38 | 39 | ### Point Cloud Library Integration with ROS 40 | 41 | ![CylinderSegmentation.gif](assets/CylinderSegmentationFast.gif) 42 | 43 | > The **Point Cloud Library** (or **PCL**) is a **large scale, open project [1]** for 2D/3D image and point cloud processing. The PCL framework contains numerous state-of-the art algorithms including filtering, feature estimation, surface reconstruction, registration, model fitting and segmentation. These algorithms can be used, for example, to filter outliers from noisy data, stitch 3D point clouds together, segment relevant parts of a scene, extract keypoints and compute descriptors to recognize objects in the world based on their geometric appearance, and create surfaces from point clouds and visualize them -- to name a few. 44 | 45 | 46 | 47 | 48 | 49 | ### Sensor Fusion with ROS 50 | 51 | [![Click to watch video!](assets/youtube_thumbnail.png)](https://youtu.be/5vZOvISwT94) 52 | 53 | > The robot_localisation package in ROS is a very useful package for fusing any number of sensors using various flavours of Kalman Filters! 54 | 55 | 56 | 57 | 58 | 59 | ## Credits 60 | 61 | All credits and sources are listed inside the tutorials and references themselves. 62 | 63 | 64 | 65 | ``` 66 | . . 67 | . |\-^-/| . 68 | /| } O.=.O { |\ 69 | ``` 70 | -------------------------------------------------------------------------------- /ROS 2/assets/15281053255360859.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/15281053255360859.png -------------------------------------------------------------------------------- /ROS 2/assets/1563875407348.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/1563875407348.png -------------------------------------------------------------------------------- /ROS 2/assets/1563942689701.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/1563942689701.png -------------------------------------------------------------------------------- /ROS 2/assets/2-Figure1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/2-Figure1-1.png -------------------------------------------------------------------------------- /ROS 2/assets/3-Figure3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/3-Figure3-1.png -------------------------------------------------------------------------------- /ROS 2/assets/api_levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/api_levels.png -------------------------------------------------------------------------------- /ROS 2/assets/ros_client_library_api_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/ros_client_library_api_stack.png -------------------------------------------------------------------------------- /ROS 2/assets/ros_idl_api_stack_dynamic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/ros_idl_api_stack_dynamic.png -------------------------------------------------------------------------------- /ROS 2/assets/ros_idl_api_stack_static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/ros_idl_api_stack_static.png -------------------------------------------------------------------------------- /ROS 2/assets/tumblr_inline_ork4205Z761qal0f2_540.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS 2/assets/tumblr_inline_ork4205Z761qal0f2_540.jpg -------------------------------------------------------------------------------- /ROS/01 ROS - Introduction.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ROS Crash Course 4 | 5 | Author: methylDragon 6 | Fairly comprehensive ROS crash course! 7 | I'll be adapting it from the ROS Tutorials: http://wiki.ros.org/ROS/Tutorials 8 | and ETHz: http://www.rsl.ethz.ch/education-students/lectures/ros.html 9 | 10 | ------ 11 | 12 | ## Pre-Requisites 13 | 14 | - A system with a ROS compatible Ubuntu system installed 15 | - Linux 16 | - Python 3 and/or C++ 17 | 18 | 19 | 20 | ## Table Of Contents 21 | 22 | 1. [Introduction](#1) 23 | 2. [Setup and Basic Concepts](#2) 24 | 2.1 [Installing ROS](#2.1) 25 | 2.2 [ROS Architecture](#2.2) 26 | 2.3 [Installing Packages](#2.3) 27 | 2.4 [Convenience Tools](#2.4) 28 | 3. [ROS Crash Course](#3) 29 | 3.1 [ROS Workspaces](#3.1) 30 | 3.2 [rosbash](#3.2) 31 | 3.3 [roscore (ROS Master)](#3.3) 32 | 3.4 [Using ROS](#3.4) 33 | 3.5 [A Simple ROS Example](#3.5) 34 | 3.6 [Visualising the ROS Graph](#3.6) 35 | 3.7 [roslaunch](#3.7) 36 | 3.8 [Launch Files](#3.8) 37 | 3.9 [RViz](#3.9) 38 | 3.10 [Gazebo (Simulation)](#3.10) 39 | 40 | 41 | 42 | ## 1. Introduction 43 | 44 | ROS stands for Robot Operating System. And true to its name, it's for working with robots! 45 | 46 | ROS: 47 | 48 | - Is a **publisher-subscriber framework** (pub-sub) for running independent programs on robots (across different system architectures) 49 | - Has a **rich ecosystem of open-source packages and tools** written by its active community 50 | - Is one of the **go-to frameworks for robotics research and prototyping!** 51 | 52 | You have enough in the ecosystem to create a fairly robust autonomous system, and there are many tutorials for applications like robotic arms, autonomous ground vehicles, SLAM, and more! 53 | 54 | > ROS is an open-source, meta-operating system for your robot. It provides the services you would expect from an operating system, including hardware abstraction, low-level device control, implementation of commonly-used functionality, message-passing between processes, and package management. It also provides tools and libraries for obtaining, building, writing, and running code across multiple computers. ROS is similar in some respects to 'robot frameworks,' such as [Player](http://playerstage.sf.net/), [YARP](http://eris.liralab.it/yarp/), [Orocos](http://www.orocos.org/), [CARMEN](http://carmen.sourceforge.net/), [Orca](http://orca-robotics.sourceforge.net/), [MOOS](http://www.robots.ox.ac.uk/~pnewman/TheMOOS/index.html), and [Microsoft Robotics Studio](http://msdn.microsoft.com/en-us/robotics/default.aspx). 55 | > 56 | > The ROS runtime "graph" is a peer-to-peer network of processes (potentially distributed across machines) that are loosely coupled using the ROS communication infrastructure. ROS implements several different styles of communication, including synchronous RPC-style communication over [services](http://wiki.ros.org/Services), asynchronous streaming of data over [topics](http://wiki.ros.org/Topics), and storage of data on a [Parameter Server](http://wiki.ros.org/Parameter%20Server). These are explained in greater detail in our [Conceptual Overview](http://wiki.ros.org/ROS/Concepts). 57 | > 58 | > (http://wiki.ros.org/ROS/Introduction) 59 | 60 | 61 | 62 | ## 2. Setup and Basic Concepts 63 | 64 | ### 2.1 Installing ROS 65 | 66 | [go to top](#top) 67 | 68 | For this crash course, I'll be assuming that we'll be using ROS Kinetic for Ubuntu 16.04. Make sure you install the correct version of Ubuntu, otherwise it might be troublesome to install ROS (since it's officially supported on only specific distributions!) 69 | 70 | You may choose to install a more recent distribution though! 71 | 72 | Make sure you **read** the tutorials! Don't just blindly copy terminal commands! 73 | 74 | Dualbooting Ubuntu 16.04: https://www.tecmint.com/install-ubuntu-16-04-alongside-with-windows-10-or-8-in-dual-boot/ 75 | 76 | Installing ROS: http://wiki.ros.org/kinetic/Installation/Ubuntu 77 | 78 | 79 | 80 | > Here's a handy set of quick install scripts to get ROS set up! 81 | > 82 | > https://github.com/methylDragon/quick-install-scripts 83 | 84 | 85 | 86 | ### 2.2 ROS Architecture 87 | 88 | [go to top](#top) 89 | 90 | As you know, ROS is a **publisher-subscriber** framework for facilitating robotics applications. What does this mean, even? 91 | 92 | > Imagine you're on an internet forum, with individuals publishing posts into and subscribing to (and reading from) from the forum topics, and you should get a pretty good idea of what's going on. 93 | 94 | The ROS communication graph is made of ROS nodes (which can run robotics applications) communicating with each other: 95 | 96 | - **ROS nodes** can be distributed across different systems, communicating via wired connections, wireless or the internet! 97 | - **ROS nodes** can act as **Publishers** and/or **Subscribers**, and run programs that can react to messages set through ROS 98 | - **Publishers** post **messages** onto **topics** 99 | - **Subscribers** subscribe to **topics**, and receive **messages** as they are published 100 | - All this activity is facilitated by the **ROS Master** (in the analogy, treat it as the forum site itself that hosts the nodes and topics, and mediates the messages!) 101 | 102 | ![1.1](./assets/1.1.png) 103 | 104 | (Image source: clearpathrobotics.com) 105 | 106 | So for a practical example. Consider a simple image processing system implemented in ROS. 107 | 108 | You have a camera node that **publishes** to an image_data **topic**, which is **subscribed** to by an image processing node and image display node. 109 | 110 | ![1.2](./assets/1.2.png) 111 | 112 | (Image source: clearpathrobotics.com) 113 | 114 | That's really the gist of what ROS is! It's a really powerful concept that allows for ease in creating distributed systems (or hooking additional nodes into existing systems written by other people, or hooking nodes written by other people into your own system!) 115 | 116 | The rest of it is just learning how to route the publishers and subscribers, debug code, write new nodes, and interface them with hardware! 117 | 118 | 119 | 120 | ### 2.3 Installing Packages 121 | 122 | When you first install ROS, it installs the base workspace for it (think of it as a working folder, or environment for working with ROS.) **It is in ROS workspaces do we install ROS packages, which define ROS nodes!** 123 | 124 | After which, it is as simple as either using 125 | 126 | ```shell 127 | $ sudo apt-get install 128 | ``` 129 | 130 | Or, building from source otherwise 131 | 132 | ```shell 133 | # With the package files in the correct locations (for more details, check out my catkin tutorial) 134 | 135 | $ cd /catkin_ws 136 | $ catkin_make 137 | ``` 138 | 139 | > Please go ahead and install the tutorials package! 140 | > 141 | > ```bash 142 | > # Replace with your ROS distribution (it should be kinetic) 143 | > $ sudo apt-get install ros--ros-tutorials 144 | > ``` 145 | > 146 | 147 | 148 | 149 | ### 2.4 Convenience Tools 150 | 151 | [go to top](#top) 152 | 153 | A lot of your ROS use will involve heavy use of the Terminal, so it doesn't hurt to install convenience tools! 154 | 155 | One tool I like a lot is Terminator. It lets you split your terminal panes and set default profiles for the terminal! 156 | 157 | ```shell 158 | $ sudo apt-get update 159 | $ sudo apt-get install terminator 160 | ``` 161 | 162 | 163 | 164 | ## 3. ROS Crash Course 165 | 166 | ### 3.1 ROS Workspaces 167 | 168 | [go to top](#top) 169 | 170 | When you first start using ROS, it's most likely going to involve playing around with nodes other people have written, and running them with Terminal! 171 | 172 | ROS comes with a whole bunch of command line tools that let you mess around with nodes and packages inside your ROS workspace! But in order to be able to use them, you must first **source** them from the ROS workspaces you want to use! 173 | 174 | The ROS installation tutorial should have already gotten you set up with sourcing the base workspace for ROS. 175 | 176 | ```shell 177 | $ echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc 178 | $ source ~/.bashrc 179 | ``` 180 | 181 | 182 | 183 | #### **Making your own workspace** 184 | 185 | But what if we wanted to create our own workspace for our own robotics project? 186 | 187 | (It's generally recommended to do this so that you can port your project over to other systems instead of having to port the whole of ROS) 188 | 189 | Then, we need to make our workspace 190 | 191 | ```shell 192 | $ mkdir -p workspace_name/src # Create a catkin_ws folder with a src folder in it 193 | $ cd workspace_name # Navigate into the folder's root 194 | $ catkin_make # Build the required files 195 | ``` 196 | 197 | Then source it 198 | 199 | ```shell 200 | $ source devel/setup.bash # Make sure you run this from your workspace's root! 201 | 202 | # It would be good to also append this source command to your .bashrc so you don't have to keep doing it everytime you open a terminal 203 | 204 | # Append source /devel/setup.bash 205 | ``` 206 | 207 | To check if you've sourced into it properly, run 208 | 209 | ```shell 210 | $ echo $ROS_PACKAGE_PATH 211 | 212 | # Ensure your workspace's directory appears in here 213 | ``` 214 | 215 | > For more in-depth information on ROS workspaces and building packages, check out my catkin tutorial! 216 | 217 | 218 | 219 | ### 3.2 rosbash 220 | 221 | [go to top](#top) 222 | 223 | Further reading: http://wiki.ros.org/rosbash 224 | 225 | Now that we've sourced our workspaces, we can use the command line utilities ROS provides to us! 226 | 227 | These are mostly shortcuts for the common terminal commands, but can be used without specifying the explicit paths of the ROS packages and nodes! 228 | 229 | - [roscd](http://wiki.ros.org/rosbash#roscd) - shortcut for `cd` , change to the directory of a ros package or node 230 | - [rospd](http://wiki.ros.org/rosbash#rospd) - `pushd` equivalent of `roscd` 231 | - [rosd](http://wiki.ros.org/rosbash#rosd) - lists directories in the directory-stack (for use with `rospd`) 232 | - [rosls](http://wiki.ros.org/rosbash#rosls) - list files of a ros package 233 | - [rosed](http://wiki.ros.org/rosbash#rosed) - edit a file in a package 234 | - [roscp](http://wiki.ros.org/rosbash#roscp) - copy a file from a package 235 | - [rosrun](http://wiki.ros.org/rosbash#rosrun) - run executables of a ros package (run a node) 236 | 237 | Just try them out! Tab completion is your friend! 238 | 239 | Example: 240 | 241 | ```shell 242 | $ roscd [/subdir] 243 | $ rosrun 244 | 245 | # Read the next section before running this! :) 246 | $ rosrun roscpp_tutorials talker 247 | ``` 248 | 249 | 250 | 251 | ### 3.3 roscore (ROS Master) 252 | 253 | [go to top](#top) 254 | 255 | Ok! Now we're ready to really dive in deep! 256 | 257 | As mentioned before, the **ROS master** facilitates messaging between nodes, and is what keep tracks of what nodes exist (nodes have to register with it whenever they initialise.) 258 | 259 | 260 | 261 | #### **ROS Communication Setup** 262 | 263 | In order to help it along, you **MUST** specify the IP address of the ROS master to each machine in the network that you want to communicate via ROS with! 264 | 265 | ```shell 266 | # On the machine with the ROS master 267 | $ export ROS_HOSTNAME=localhost 268 | $ export ROS_MASTER_URI=http://localhost:11311 269 | ``` 270 | 271 | ```shell 272 | # On any other machine 273 | $ export ROS_HOSTNAME= 274 | $ export ROS_MASTER_URI= 275 | ``` 276 | 277 | I'd highly suggest you append these commands into ~/.bashrc so you don't have to keep typing it! 278 | 279 | 280 | 281 | #### **Starting the ROS Master** 282 | 283 | Then, you can go ahead and start the ROS master. Pretty simple. 284 | 285 | ```shell 286 | $ roscore 287 | ``` 288 | 289 | 290 | 291 | ### 3.4 Using ROS 292 | 293 | [go to top](#top) 294 | 295 | #### **Nodes** 296 | 297 | Further reading: http://wiki.ros.org/rosnode 298 | 299 | Now that our ROS master is up, we can get to running **ROS nodes**! 300 | 301 | Remember that nodes are run from **packages**, and are essentially programs that can run independently, but which communicate via ROS' pub-sub architecture 302 | 303 | Here are the relevant commands for starting nodes and getting information about them! 304 | 305 | ```shell 306 | # Run nodes 307 | $ rosrun package_name node_name 308 | 309 | # See what nodes are running 310 | $ rosnode list 311 | 312 | # Get node info 313 | $ rosnode info node_name 314 | 315 | # Kill a node 316 | $ rosnode kill node_name 317 | ``` 318 | 319 | 320 | 321 | #### **Topics** 322 | 323 | Further reading: http://wiki.ros.org/rostopic 324 | 325 | With the nodes up, topics should be listed if there are publishers or subscribers! 326 | 327 | Note: Topics can only take a single type of message, even though messages themselves can consist of elements of multiple types! 328 | 329 | ```shell 330 | # List current topics 331 | $ rostopic list 332 | 333 | # Subscribe to a topic and print messages as they are published to said topic 334 | $ rostopic echo /topic_name 335 | 336 | # Get topic information (like what messages it takes) 337 | $ rostopic info /topic_name 338 | ``` 339 | 340 | 341 | 342 | #### **Messages** 343 | 344 | Messages are the things that are sent to and read from the topics! 345 | 346 | They define the type of the topic, and consist of different C++ types! 347 | 348 | (Eg. A velocity message might consist of several floats x, y, and z.) A message designed for a specific topic can never have more or less arguments, and must be structured as defined! (They're more or less C++ structs -- a group of data elements grouped under a single name.) 349 | 350 | (You define them in .msg files) 351 | 352 | ```shell 353 | # Use this to see what message elements/messages a topic takes 354 | $ rostopic type /topic_name 355 | 356 | # You can publish a single message to a topic as follows! 357 | $ rostopic pub /topic_name 358 | $ rostopic pub /my_topic std_msgs/String "Rawr" 359 | 360 | # Or do it repeatedly! (this one does it 10 times per second) 361 | $ rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}' 362 | ``` 363 | 364 | 365 | 366 | ### 3.5 A Simple ROS Example 367 | 368 | [go to top](#top) 369 | 370 | Ok! Now let's put what we've learnt to practice! 371 | 372 | **Start the ROS master** 373 | 374 | ```shell 375 | # In terminal 1 376 | $ roscore 377 | ``` 378 | **Run the tutorial publisher node** in a **NEW TERMINAL** (if you close the ROS master's terminal, you stop it!!) 379 | 380 | ```shell 381 | # In terminal 2 382 | $ rosrun roscpp_tutorials talker 383 | ``` 384 | **Verify that the new node has been activated** in a **NEW TERMINAL** 385 | 386 | ```shell 387 | # In terminal 3 388 | $ rosnode list 389 | $ rosnode info /talker 390 | ``` 391 | **Noticing that it publishes to a topic, let's check it out!** 392 | 393 | ```shell 394 | $ rostopic info /chatter 395 | $ rostopic type /chatter 396 | ``` 397 | 398 | **Cool! Now let's try subscribing to it** 399 | 400 | ```shell 401 | # In terminal 4 402 | $ rostopic echo /chatter 403 | 404 | # We can also analyse the frequency! (In a NEW TERMINAL) 405 | $ rostopic hz /chatter 406 | ``` 407 | 408 | Running echo should let you see what's being published to the topic, as it'll be displayed on the screen! 409 | 410 | **Run the tutorial subscriber node** in a **NEW TERMINAL** 411 | 412 | ```shell 413 | # In terminal 5 414 | $ rosrun roscpp_tutorials listener 415 | ``` 416 | 417 | You should see the listener node start displaying messages that it sees on the screen, just like when you were echoing 418 | 419 | **Close the tutorial publisher node** and try publishing your own message! 420 | 421 | ```shell 422 | # In terminal 2, press Ctrl-C 423 | $ rostopic pub /chatter std_msgs/String "data: 'Rawr'" 424 | ``` 425 | 426 | 427 | 428 | Now you know how publishers and subscribers work, and how to mess around with them! 429 | 430 | For an interactive example that features keyboard input into a running node in a terminal, check out: 431 | http://wiki.ros.org/ROS/Tutorials/UnderstandingTopics 432 | 433 | Or run these commands! 434 | 435 | ```shell 436 | $ roscore 437 | $ rosrun turtlesim turtlesim_node 438 | $ rosrun turtlesim turtle_teleop_key 439 | 440 | # Pause and play wth the turtle_teleop_key console 441 | 442 | $ rosrun turtlesim draw_square 443 | $ rosrun rqt_graph rqt_graph 444 | ``` 445 | 446 | 447 | 448 | ### 3.6 Visualising the ROS Graph 449 | 450 | [go to top](#top) 451 | 452 | Before you close everything from the previous section, try visualising the ROS computation graph! 453 | 454 | ```shell 455 | # In a NEW terminal 456 | $ rosrun rqt_graph rqt_graph 457 | ``` 458 | 459 | Then go to the dropdown menu, and select nodes/topics (all), then refresh the graph. 460 | 461 | You should see a pretty good representation of the ROS system you've built, with nodes being represented as elipses, and topic as rectangles! It's good for debugging, or looking cool! 462 | 463 | 464 | 465 | ### 3.7 roslaunch 466 | 467 | [go to top](#top) 468 | 469 | Ok. In the previous few examples, you had to manually write out the nodes you wanted to launch. What if you were lazy and wanted to do it in a single terminal with a single command? 470 | 471 | Hmm... 472 | 473 | Well we can use launch files! We can launch nodes with parameters using them! (It even starts a ROS master if you don't have one running!) 474 | 475 | Use `roslaunch` to launch from a launch file! 476 | 477 | ```shell 478 | # Using a launch file 479 | $ roslaunch package_name launchfile_name.launch 480 | ``` 481 | 482 | 483 | 484 | ### 3.8 Launch Files 485 | 486 | [go to top](#top) 487 | 488 | Further reading: http://wiki.ros.org/roslaunch/XML 489 | 490 | Launch files are written in XML. So get to learning it! It's not that hard! 491 | 492 | ```xml 493 | 494 | ``` 495 | 496 | #### **Minimal launch file** 497 | 498 | ```xml 499 | 500 | 501 | 502 | 503 | ``` 504 | 505 | > **PLEASE NOTE:** 506 | > 507 | > The `type` argument in the node specification refers to the type of node that is being launched. 508 | > 509 | > So for example, if you run the node using rosrun, it goes like this: 510 | > 511 | > ```shell 512 | > rosrun PKG TYPE 513 | > ``` 514 | > 515 | > The name of the node is merely what it looks like on the rosgraph, which you can see using `rosnode list` or `rosrun rqt_graph rqt_graph` 516 | 517 | 518 | 519 | #### **Setting parameters** 520 | 521 | Certain nodes might have certain parameters that can be tweaked! (Eg. a laser node's max range) 522 | 523 | Launch files can set them too! 524 | 525 | ```xml 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | ``` 548 | 549 | 550 | 551 | #### **Taking arguments** 552 | 553 | Now you can write your launch file to take arguments! You can write placeholder 'variables' that get filled when you run the launch file as such 554 | 555 | ```shell 556 | $ roslaunch launch_file_name.launch arg_name:=value 557 | ``` 558 | 559 | ```xml 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | ``` 568 | 569 | 570 | 571 | #### **Conditionals** 572 | 573 | ```xml 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 594 | 595 | 596 | ``` 597 | 598 | 599 | 600 | #### **Calling other launch files or importing files** 601 | 602 | ```xml 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | ``` 613 | 614 | 615 | 616 | #### **Remapping nodes** 617 | 618 | This means changing the **name** of the topic that a node is configured to subscribe or publish to! 619 | 620 | ```xml 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | ``` 634 | 635 | Hooray we've remapped the topics!! 636 | 637 | 638 | 639 | ### 3.9 RViz 640 | 641 | [go to top](#top) 642 | 643 | Read more: http://wiki.ros.org/rviz/Tutorials 644 | 645 | RViz is a **3D visualisation tool for ROS** with many different camera views. 646 | 647 | It subscribes to topics, and you can choose to visualise the data! 648 | 649 | You can save and load configurations in RViz! And it can take plugins! There's a lot to go through, so it probably warrants its own tutorial... 650 | 651 | But some uses for it are: 652 | 653 | - Just pure visualisation 654 | - Mapping 655 | - Navigation 'GUI' (You can send commands to the robot via RViz using the interface) 656 | - Finding map points (Clicking on the Publish Point button publishes the coordinate to the topic /clicked_point) 657 | 658 | 659 | 660 | ### 3.10 Gazebo (Simulation) 661 | 662 | [go to top](#top) 663 | 664 | Gazebo is one of the more popular simulation suites that is used with ROS. We're going to try using it with the Turtlebot3 simulator so we can get started writing code without having a hardware robot to play with! This way we can learn and practice the software side of things even without a huge budget! 665 | 666 | Because the Turtlebot3 simulator is finicky, we're going to install the Linorobot simulator! 667 | 668 | > **Please follow these steps!** 669 | > 670 | > - Install the desktop version of the Linorobot using the [ros_lino_base_install script](https://github.com/methylDragon/quick-install-scripts/blob/master/Linux/ros_lino_base_install) (Courtesy of [Linorobot.org](http://linorobot.org)) 671 | > - And the Linorobot [simulator](https://github.com/grassjelly/robot_playground)! (Follow the instructions on the repo!) 672 | 673 | 674 | 675 | Ok! Let's try simulating the Linorobot! Run these commands in **SEPARATE TERMINALS.** 676 | 677 | Ensure that running `$ echo $ROS_PACKAGE_PATH` displays a linorobot_ws and a catkin_ws! 678 | 679 | ```shell 680 | # Start the Gazebo simulation of the Linorobot 681 | # (The first run will take awhile, be patient) 682 | $ roslaunch robot_playground bringup_sim.launch 683 | 684 | # Run this in a separate terminal, you know the drill 685 | # teleop_twist_keyboard lets you move the robot around! 686 | $ rosrun teleop_twist_keyboard teleop_twist_keyboard 687 | 688 | # If that doesn't work, use 689 | $ rosrun teleop_twist_keyboard teleop_twist_keyboard.py 690 | ``` 691 | 692 | Let's try autonomous navigation! 693 | 694 | ```shell 695 | # Start the navigation stack 696 | $ roslaunch linorobot navigate.launch 697 | 698 | # Aaaand start RViz with the navigation configurations! 699 | $ roscd linorobot/rviz 700 | $ rviz -d navigate.rviz 701 | 702 | # Play around with it by using the 2D Pose Estimate and 2D Goal! 703 | ``` 704 | 705 | 706 | 707 | 708 | ``` 709 | . . 710 | . |\-^-/| . 711 | /| } O.=.O { |\ 712 | ``` 713 | 714 | ​ 715 | 716 | ------ 717 | 718 | [![Yeah! Buy the DRAGON a COFFEE!](../assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /ROS/03 ROS - Messages, Services, and Actions.md: -------------------------------------------------------------------------------- 1 | # ROS Messages, Services, and Actions 2 | 3 | Author: methylDragon 4 | Fairly comprehensive ROS crash course! 5 | I'll be adapting code and tutorial content from the ROS Tutorials: http://wiki.ros.org/ROS/Tutorials 6 | and ETHz http://www.rsl.ethz.ch/education-students/lectures/ros.html 7 | 8 | ------ 9 | 10 | ## Pre-Requisites 11 | 12 | - A system with ROS installed 13 | - Linux 14 | - Python 3 and/or C++ 15 | 16 | 17 | 18 | ## Table Of Contents 19 | 20 | 1. [Introduction](#1) 21 | 2. [Messages](#2) 22 | 2.1 [Introduction](#2.1) 23 | 2.2 [Message Files](#2.2) 24 | 2.3 [rosmsg](#2.3) 25 | 2.4 [Creating Message Files](#2.4) 26 | 2.5 [Using Custom Messages](#2.5) ([rospy](#2.5.1)) ([roscpp](#2.5.2)) ([Nested Messages](#2.5.3)) 27 | 3. [Services](#3) 28 | 3.1 [Introduction](#3.1) 29 | 3.2 [Service Files](#3.2) 30 | 3.3 [rosservice](#3.3) 31 | 3.4 [Creating Service Files](#3.4) 32 | 3.5 [Writing Service Nodes](#3.5) ([rospy](#3.5.1)) ([roscpp](#3.5.2)) 33 | 4. [Actions](#4) 34 | 4.1 [Introduction](#4.1) 35 | 4.2 [Action Files](#4.2) 36 | 4.3 [rostopic for Actions](#4.3) 37 | 4.4 [Creating Action Files](#4.4) 38 | 4.5 [Writing Action Nodes](#4.5) ([rospy](#4.5.1)) ([roscpp](#4.5.2)) 39 | 5. [Concluding Comparison](#5) 40 | 41 | ## 1. Introduction 42 | 43 | So now you know how to write nodes. Ever wondered if you could do more? Of course you can! 44 | 45 | You can create **custom messages**, create **nodes just for serving requests**, or nodes that **carry out actions, and provide feedback.** 46 | 47 | We're going to talk about **messages, services, and actions!** 48 | 49 | 50 | 51 | ## 2. Messages 52 | 53 | ### 2.1. Introduction 54 | 55 | [go to top](#top) 56 | 57 | Messages are what are sent to ROS nodes via topics! They are the subject that is published and sent to subscribers! 58 | 59 | You can create messages very easily, because ROS has a couple of macros that dynamically generate the language-specific message related code for you! All you need to do, is create the **.msg file**. 60 | 61 | > [msg](http://wiki.ros.org/msg): msg files are simple text files that describe the fields of a ROS message. They are used to generate source code for messages in different languages. 62 | > 63 | > (http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv) 64 | 65 | 66 | 67 | ### 2.2. Message Files 68 | 69 | [go to top](#top) 70 | 71 | #### **Eligible Message Field Types** 72 | 73 | Msg files are text files that consist of a single field per line. These are the eligible types: 74 | 75 | - int8, int16, int32, int64 (plus uint*) 76 | - float32, float64 77 | - string 78 | - time, duration 79 | - other msg files 80 | - variable-length array[] and fixed-length array[C] 81 | - the special Header type 82 | 83 | > The **Header** type consists of a **timestamp** and **coordinate frame.** A lot of packages use them, and it normally appears as the first line of a .msg file. 84 | 85 | 86 | 87 | #### **Example .msg file** 88 | 89 | ``` 90 | Header header 91 | string child_frame_id 92 | geometry_msgs/PoseWithCovariance pose 93 | geometry_msgs/TwistWithCovariance twist 94 | ``` 95 | 96 | 97 | 98 | ### 2.3 rosmsg 99 | 100 | [go to top](#top) 101 | 102 | ROS has a bunch of command line tools to help with messages as well! 103 | 104 | ```shell 105 | # Show displays the contents of the corresponding message file 106 | $ rosmsg show package_name message_name 107 | 108 | # If you don't know the package, rosmsg will search for a matching message file! 109 | $ rosmsg show message_name 110 | 111 | # You can even use it in combination with rostopic to display type info about the topic! 112 | $ rostopic type /topic_name | rosmsg show 113 | 114 | 115 | # List displays a list of all messages 116 | $ rosmsg list 117 | 118 | # Package displays a list of all messages in a package 119 | $ rosmsg package package_name 120 | 121 | # Packages displays a list of all packages with messages 122 | $ rosmsg packages 123 | 124 | ``` 125 | 126 | 127 | 128 | ### 2.4 Creating Message Files 129 | 130 | [go to top](#top) 131 | 132 | Let's try making some custom message files! 133 | 134 | > Reminder: To create a new package, 135 | > 136 | > ```shell 137 | > $ cd /src 138 | > $ catkin_create_pkg package_name rospy 139 | > 140 | > # Eg. catkin_create_pkg basic_pub_sub rospy std_msgs 141 | > ``` 142 | 143 | **1. Go to your package directory** 144 | 145 | ```shell 146 | $ roscd msg_example_msgs # Using a message-only package is good practice! 147 | $ mkdir msg # Make a msg folder to keep your message files 148 | 149 | $ cd msg 150 | $ touch My_msg.msg # Capitalising the first letter is the convention! 151 | ``` 152 | 153 | **2. Then open that .msg file in your favourite text editor** and HAVE AT IT! (Write your data types and names) 154 | 155 | ``` 156 | Header header 157 | string name 158 | uint8 dragon_rating 159 | ``` 160 | 161 | **3. Then go to package.xml** and **append these two lines** 162 | 163 | ```xml 164 | message_generation 165 | message_runtime 166 | ``` 167 | 168 | **4. Then say hello to our ~~nemesis~~ good old friend CMakeLists.txt** 169 | 170 | Ensure these lines are present 171 | 172 | ```cmake 173 | cmake_minimum_required(VERSION 2.8.3) 174 | project(msg_example_msgs) 175 | 176 | # Standard dependencies 177 | find_package(catkin REQUIRED COMPONENTS 178 | roscpp 179 | rospy 180 | std_msgs 181 | message_generation 182 | ) 183 | 184 | # Your message files! 185 | add_message_files( 186 | FILES 187 | My_msg.msg # <-- Like this one! 188 | ) 189 | 190 | # You need to include this in as well 191 | # Call it BEFORE catkin_package 192 | generate_messages( 193 | DEPENDENCIES 194 | std_msgs # You might have additional message files from other packages 195 | ) 196 | 197 | # Additional catkin dependencies 198 | catkin_package(CATKIN_DEPENDS 199 | message_runtime 200 | ) 201 | ``` 202 | 203 | > NOTE: 204 | > 205 | > When you are compiling a package that requires message files from a separate message package, be sure to add 206 | > 207 | > ```cmake 208 | > add_dependencies(EXECUTABLE_NAME MESSAGE_PACKAGE_generate_messages_cpp) 209 | > ``` 210 | > 211 | > Otherwise it **will** fail! 212 | 213 | **5. Then go back to your workspace root, and rebuild!** 214 | 215 | ```shell 216 | $ roscd msg_example_msgs 217 | $ cd ../.. 218 | $ catkin_make # or catkin_make install, see what works 219 | ``` 220 | 221 | 222 | 223 | ### 2.5 Using Custom Messages 224 | 225 | [go to top](#top) 226 | 227 | In the last tutorial part, we learnt how to use the **rospy** and **roscpp** client libraries to write nodes that use in-built messages! 228 | 229 | Now I'll show you how to use them to include/import custom messages! 230 | 231 | > Our message file is structured as such 232 | > 233 | > ``` 234 | > Header header 235 | > string name 236 | > uint8 dragon_rating 237 | > ``` 238 | 239 | #### **rospy** 240 | 241 | Including the message 242 | 243 | ```python 244 | #!/usr/bin/env python 245 | # -*- coding: utf-8 -*- 246 | 247 | # ^^^ The encoding line is just because I want to have a cute emoticon ヾ(°∇°*) 248 | 249 | import rospy 250 | from msg_example_msgs.msg import My_msg 251 | 252 | # Create the message object to publish 253 | msg = My_msg() 254 | ``` 255 | 256 | Testing it with a publisher 257 | 258 | ```python 259 | # Then to use it~ 260 | def talker(): 261 | # My_msg is the topic type (aka the message file the topic takes) 262 | pub = rospy.Publisher("msg_example", My_msg, queue_size = 10) 263 | 264 | rospy.init_node("msg_example_node", anonymous = True) 265 | rate = rospy.Rate(10) 266 | 267 | while not rospy.is_shutdown(): 268 | msg.header.stamp = rospy.Time.now() # Since our message has a header 269 | # The header sequence value will increase once a subscriber is connected 270 | 271 | msg.name = "methylDragon" 272 | msg.dragon_rating = 10 273 | 274 | rospy.loginfo("FIND MY OUTPUT ON /msg_example ! ヾ(°∇°*)") 275 | 276 | pub.publish(msg) 277 | rate.sleep() 278 | 279 | if __name__ == '__main__': 280 | try: 281 | talker() 282 | except rospy.ROSInterruptException: 283 | pass 284 | ``` 285 | 286 | 287 | 288 | #### **roscpp** 289 | 290 | Including the message 291 | 292 | ```c++ 293 | #include 294 | #include 295 | 296 | msg_example_msgs::My_msg msg; 297 | ``` 298 | 299 | Testing it with a publisher 300 | 301 | ```c++ 302 | int main(int argc, char **argv) 303 | { 304 | ros::init(argc, argv, "msg_example_node"); 305 | ros::NodeHandle nh; 306 | 307 | ros::Publisher chatter_publisher = nh.advertise("msg_example", 1); 308 | 309 | ros::Rate loopRate(10); 310 | 311 | unsigned int count = 0; 312 | 313 | while (ros::ok()) 314 | { 315 | msg_example_msgs::My_msg msg; // Make a new message object 316 | msg.header.stamp = ros::Time::now(); 317 | 318 | msg.name = "methylDragon"; 319 | msg.dragon_rating = 10; 320 | 321 | ROS_INFO_STREAM(" . .\n" 322 | " . |\\-^-/| .\n" 323 | "FIND MY OUTPUT ON /msg_example ! /| } O.=.O { |\\ \n"); 324 | 325 | chatter_publisher.publish(msg); 326 | 327 | ros::spinOnce(); 328 | loopRate.sleep(); 329 | } 330 | 331 | return 0; 332 | } 333 | ``` 334 | 335 | 336 | 337 | > Note: If you're importing messages from other packages, append these lines to **package.xml** 338 | > 339 | > ```xml 340 | > name_of_package_containing_custom_msg 341 | > name_of_package_containing_custom_msg 342 | > ``` 343 | > 344 | > And this line to **CMakeLists.txt** 345 | > 346 | > ```cmake 347 | > add_dependencies(your_program ${catkin_EXPORTED_TARGETS}) 348 | > 349 | > # And then add these lines if you're using roscpp 350 | > find_package(catkin REQUIRED COMPONENTS std_msgs sensor_msgs) 351 | > include_directories(include ${catkin_INCLUDE_DIRS}) 352 | > 353 | > add_dependencies(your_program ${catkin_EXPORTED_TARGETS}) 354 | > add_dependencies(your_library ${catkin_EXPORTED_TARGETS}) 355 | > ``` 356 | > 357 | > 358 | > If you're confused, just check the minimal msg_example package in resources and starter code. 359 | 360 | 361 | 362 | #### **Nested Messages** 363 | 364 | Sometimes you might come across nested messages. 365 | 366 | For example, the very common geometry_msgs/Twist message (http://docs.ros.org/api/geometry_msgs/html/msg/Twist.html) 367 | 368 | The message definition is structured as such 369 | 370 | ``` 371 | # Twist 372 | 373 | Vector3 linear 374 | Vector3 angular 375 | ``` 376 | 377 | But you notice, that the data type is actually a geometry_msgs/Vector3 message! Which is structured as such 378 | 379 | ``` 380 | # Vector3 381 | 382 | float64 x 383 | float64 y 384 | float64 z 385 | ``` 386 | 387 | Ok! Cool, we have a **nested message**. If we want to go ahead and construct a Twist message, we could either: 388 | 389 | 1. Make two Vector3 messages, and pass it in to the original message (the stupid way to do it) 390 | 2. Or access the class members directly! (THE SMART WAY.) 391 | 392 | ```python 393 | # Let's say we have a twist message called twist_msg 394 | 395 | twist_msg.linear.x = # HERE WE GO! 396 | ``` 397 | 398 | This should be fairly self explanatory. 399 | 400 | 401 | 402 | ## 3. Services 403 | 404 | ### 3.1 Introduction 405 | 406 | [go to top](#top) 407 | 408 | A ROS service is a special kind of topic that allows for two-way communication between nodes. (Specifically, request-response communication.) 409 | 410 | ![3.1](assets/3.1.png) 411 | 412 | (Image source: ETHz) 413 | 414 | 415 | 416 | #### **Service Servers and Clients** 417 | 418 | A service is facillitated by two types of nodes: 419 | 420 | - The service **server** advertises the service, and listens for messages sent to the service 421 | - It then computes the response (*carrying out any required tasks along the way*), and publishes its response to the service! 422 | - The service **client** publishes to the service, calling it 423 | - Then, it subscribes to the service and waits for the response, **stopping you from doing anything else on the terminal the service is called with.** (Services are synchronous! As opposed to actions, which are asynchronous and allow you to execute more instructions while the action is running.) 424 | 425 | 426 | 427 | ### 3.2 Service Files 428 | 429 | [go to top](#top) 430 | 431 | The message types available for use with services are based off of the eligible .msg types, as shown in the previous section of this tutorial. 432 | 433 | But the service messages are defined in a special type of file called a .srv file. 434 | 435 | 436 | 437 | #### **Eligible Service Field Types** 438 | 439 | Exactly the same as messages! 440 | 441 | Service files are just two message files 'smushed' into one! 442 | 443 | > Eligible message field types 444 | > 445 | > - int8, int16, int32, int64 (plus uint*) 446 | > - float32, float64 447 | > - string 448 | > - time, duration 449 | > - other msg files 450 | > - variable-length array[] and fixed-length array[C] 451 | > - the special Header type 452 | 453 | 454 | 455 | #### **Example .srv file** 456 | 457 | Recall the example .msg file: 458 | 459 | ``` 460 | Header header 461 | string child_frame_id 462 | geometry_msgs/PoseWithCovariance pose 463 | geometry_msgs/TwistWithCovariance twist 464 | ``` 465 | 466 | A .srv file is **similar** (it's just two message files smushed into one, one request, one response.) 467 | 468 | The sections are separated by three dashes. It has to be done this way. 469 | 470 | ``` 471 | request 472 | --- 473 | response 474 | ``` 475 | 476 | Eg: 477 | 478 | ``` 479 | int64 A 480 | int64 B 481 | --- 482 | int64 Sum 483 | ``` 484 | 485 | 486 | 487 | ### 3.3 rosservice 488 | 489 | [go to top](#top) 490 | 491 | > NOTE: `rosservice` is **different** from `rossrv`, which does the same thing that `rosmsg` does for .srv files. 492 | 493 | You can use `rosservice` in the same way `rostopic` is used to publish and subscribe to topics, except now you're **calling the service.** 494 | 495 | ```shell 496 | # List available services 497 | $ rosservice list 498 | 499 | # Show the type of the service (what messages it takes) 500 | $ rosservice type /service_name 501 | 502 | # Call a service 503 | $ rosservice call /service_name ... 504 | ``` 505 | 506 | 507 | 508 | ### 3.4 Creating Service Files 509 | 510 | [go to top](#top) 511 | 512 | Okay. Let's make a service file! 513 | 514 | > Reminder: To create a new package, 515 | > 516 | > ```shell 517 | > $ cd /src 518 | > $ catkin_create_pkg package_name rospy 519 | > 520 | > # Eg. catkin_create_pkg basic_pub_sub rospy std_msgs 521 | > ``` 522 | 523 | **1. Go to your package directory** 524 | 525 | ```shell 526 | $ roscd srv_example 527 | $ mkdir srv # Make a srv folder to keep your service files 528 | 529 | $ cd srv 530 | $ touch AddTwoInts.srv # Capitalising the first letter is the convention! 531 | ``` 532 | 533 | **2. Then open that .msg file in your favourite text editor** and HAVE AT IT! (Write your data types and names) 534 | 535 | ``` 536 | int64 A 537 | int64 B 538 | --- 539 | int64 Sum 540 | ``` 541 | 542 | **3. Then go to package.xml** and **append these two lines** 543 | 544 | ```xml 545 | message_generation 546 | message_runtime 547 | ``` 548 | 549 | **4. Then say hello to our ~~nemesis~~ good old friend CMakeLists.txt** 550 | 551 | Ensure these lines are present (**IN ORDER!**) 552 | 553 | ```cmake 554 | find_package(catkin REQUIRED COMPONENTS 555 | roscpp 556 | rospy 557 | std_msgs # <-- Add these 558 | message_generation # <-- Add these (even though you're generating services) 559 | ) 560 | 561 | # Uncomment this block 562 | add_service_files( 563 | FILES 564 | AddTwoInts.srv # <-- Add your srv files 565 | ) 566 | 567 | # Uncomment this block (even though you're generating services) 568 | generate_messages( 569 | DEPENDENCIES 570 | std_msgs 571 | ) 572 | 573 | catkin_package( 574 | CATKIN_DEPENDS message_runtime # <-- Add this 575 | ) 576 | ``` 577 | 578 | **5. Then go back to your workspace root, and rebuild!** 579 | 580 | ```shell 581 | $ roscd srv_example 582 | $ cd ../.. 583 | $ catkin_make # or catkin_make install, see what works 584 | ``` 585 | 586 | 587 | 588 | ### 3.5 Writing Service Nodes 589 | 590 | [go to top](#top) 591 | 592 | Source: http://wiki.ros.org/actionlib_tutorials/Tutorials 593 | 594 | This one is a little more involved than just including the messages like we did in the previous part. 595 | 596 | Let's use this service 597 | 598 | AddTwoInts.srv 599 | 600 | ``` 601 | int64 A 602 | int64 B 603 | --- 604 | int64 Sum 605 | ``` 606 | 607 | Which should have generated a header file called AddTwoInts.h on build. 608 | 609 | 610 | 611 | #### **rospy server** 612 | 613 | > Note: You import from your PACKAGE_NAME.srv ! 614 | 615 | ```python 616 | #!/usr/bin/env python 617 | 618 | from srv_example.srv import * 619 | import rospy 620 | 621 | # Here's your service callback function 622 | def handle_add_two_ints(req): 623 | print("Returning [%s + %s = %s]" % (req.A, req.B, (req.A + req.B))) 624 | return AddTwoIntsResponse(req.A + req.B) 625 | 626 | def add_two_ints_server(): 627 | rospy.init_node('add_two_ints_server') 628 | 629 | # Here's your service hook (AddTwoInts is the service type/file) 630 | s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints) 631 | print("Ready to add two ints.") 632 | rospy.spin() 633 | 634 | if __name__ == "__main__": 635 | add_two_ints_server() 636 | ``` 637 | 638 | #### **rospy client** 639 | 640 | ```python 641 | #!/usr/bin/env python 642 | 643 | import sys 644 | import rospy 645 | from srv_example.srv import * 646 | 647 | # Service call handler (arguments are request.A, request.B, as x and y) 648 | def add_two_ints_client(x, y): 649 | # Wait for service to become available 650 | rospy.wait_for_service('add_two_ints') 651 | 652 | try: 653 | # The service proxy handles the service call, like a temporary node! 654 | # add_two_ints is the service name 655 | # AddTwoInts is the service type/file 656 | add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts) 657 | resp1 = add_two_ints(x, y) 658 | return resp1.sum 659 | 660 | except rospy.ServiceException, e: 661 | print("Service call failed: %s" % e) 662 | 663 | # Invalid call reminder 664 | def usage(): 665 | return "Usage: %s [x y]" % sys.argv[0] 666 | 667 | if __name__ == "__main__": 668 | 669 | # If the service call was properly formatted, proceed 670 | if len(sys.argv) == 3: 671 | x = int(sys.argv[1]) 672 | y = int(sys.argv[2]) 673 | 674 | # Else, remind the user of the proper usage 675 | else: 676 | print(usage()) 677 | sys.exit(1) # Terminate the script 678 | 679 | print("Requesting %s+%s" % (x, y)) 680 | print("%s + %s = %s" % (x, y, add_two_ints_client(x, y))) 681 | ``` 682 | 683 | > Remember to `chmod +x scripts/service_node_file.py` ! 684 | 685 | 686 | 687 | #### **roscpp server** 688 | 689 | ```c++ 690 | #include 691 | #include 692 | 693 | // Callback function 694 | bool add(srv_example::AddTwoInts::Request &request, 695 | srv_example::AddTwoInts::Response &response) 696 | { 697 | response.Sum = request.A + request.B; 698 | 699 | ROS_INFO("request: x=%ld, y=%ld", (long int)request.A, (long int)request.B); 700 | 701 | ROS_INFO(" sending back response: [%ld]", (long int)response.Sum); 702 | 703 | return true; 704 | } 705 | 706 | int main(int argc, char **argv) 707 | { 708 | // Start the node 709 | ros::init(argc, argv, "add_two_ints_server"); 710 | ros::NodeHandle nh; 711 | 712 | // Advertise the service 713 | ros::ServiceServer service = nh.advertiseService("add_two_ints", add); 714 | ROS_INFO("Ready to add two ints."); 715 | 716 | // Spin up 717 | ros::spin(); 718 | 719 | return 0; 720 | } 721 | ``` 722 | 723 | #### **roscpp client** 724 | 725 | ```c++ 726 | #include 727 | #include 728 | #include 729 | 730 | int main(int argc, char **argv) 731 | { 732 | ros::init(argc, argv, "add_two_ints_client"); 733 | 734 | if (argc != 3) 735 | { 736 | ROS_INFO("Usage: %s [x y]", argv[0]); 737 | return 1; 738 | } 739 | 740 | ros::NodeHandle nh; 741 | ros::ServiceClient client = nh.serviceClient("add_two_ints"); 742 | 743 | srv_example::AddTwoInts service; 744 | service.request.A = atoi(argv[1]); 745 | service.request.B = atoi(argv[2]); 746 | 747 | // Service callback function 748 | // client.call(service) calls the client! 749 | if (client.call(service)) 750 | { 751 | ROS_INFO("Sum: %ld", (long int)service.response.Sum); 752 | } 753 | else 754 | { 755 | ROS_ERROR("Failed to call service add_two_ints"); 756 | return 1; 757 | } 758 | 759 | return 0; 760 | } 761 | ``` 762 | 763 | 764 | 765 | #### **Testing your service** 766 | 767 | ```shell 768 | # Terminal 1 769 | $ roscore 770 | 771 | # Terminal 2 772 | $ rosrun srv_example srv_example_server 773 | 774 | # Terminal 3 775 | $ rosservice call /add_two_ints 1 3 776 | 777 | # Expected outputs 778 | # Terminal 2: Returning [1 + 3 = 4] (Or something along those lines) 779 | # Terminal 3: Sum: 4 780 | 781 | # NOTE: Remember to catkin_make and source your devel/setup.bash ! 782 | ``` 783 | 784 | 785 | 786 | #### **argv refresher** 787 | 788 | `sys.argv` is a list that contains the arguments passed to the script using the command line. It comes from the argc argv (argument count, argument vector) concept in C++. 789 | 790 | Basically, the elements of sys.argv are as such. 791 | 792 | The **first** element is the name of the script being called 793 | 794 | The elements **beyond** the first are the arguments passed to the script in order. 795 | 796 | SO. This is why you see calls to sys.argv[1], sys.argv[2] for the 2 argument service call in the rospy service example. 797 | 798 | 799 | 800 | ## 4. Actions 801 | 802 | ### 4.1 Introduction 803 | 804 | [go to top](#top) 805 | 806 | A ROS action is just like a ROS service, a special kind of topic that allows for two-way communication between nodes. But with some valuable, and notable differences. 807 | 808 | If services have request-response behaviour, actions have **goal, result, feedback** behaviour. This behaviour is non-blocking, as opposed to services. Which means that the program continues to flow as the action is being executed! 809 | 810 | ![3.2](assets/3.2.png) 811 | 812 | (Image source: ETHz) 813 | 814 | 815 | 816 | #### **Action Topics** 817 | 818 | The Action topic is special, because it consists of 5 topics under its namespace: 819 | 820 | - **/goal** 821 | - You send the desired goal to trigger the action here 822 | - **/cancel** 823 | - You send a cancel signal to stop the action execution 824 | - **/status** 825 | - Shows the status of the action server 826 | - **/result** 827 | - Shows any end state messages from action execution 828 | - **/feedback** 829 | - Shows any running messages during action execution 830 | 831 | 832 | 833 | #### **Action Servers and Clients** 834 | 835 | An action is facillitated by two types of nodes: 836 | 837 | - The action **server** advertises the action topic, and listens for messages sent to the /goal or /cancel 838 | - When a valid goal is sent to /goal, it triggers the action server to execute the action it is programmed to carry out, changing its status 839 | - In the midst of executing that action, it constantly publishes to /feedback, giving information of the proceedings 840 | - Upon completion, error, or a stop command (pre-empt) (eg. a command sent to /cancel, which clears the goal on /goal), the action concludes, and publishes to /result the appropriate result message 841 | - The action **client** publishes to the action topic 842 | - Then, it can poll the /feedback, /status, and /goal topics to get information of the proceedings of the action execution. 843 | - The client is able to continue with its program flow because action calls are not blocking (action calls are asynchronous), as opposed to service calls which are blocking. 844 | 845 | 846 | 847 | #### **Goal, Feedback, and Result** 848 | 849 | ![3.3.png](assets/3.3.png) 850 | 851 | > **Goal** 852 | > To accomplish tasks using actions, we introduce the notion of a goal that can be sent to an ActionServer by an ActionClient. In the case of moving the base, the goal would be a PoseStamped message that contains information about where the robot should move to in the world. For controlling the tilting laser scanner, the goal would contain the scan parameters (min angle, max angle, speed, etc). 853 | > 854 | > **Feedback** 855 | > Feedback provides server implementers a way to tell an ActionClient about the incremental progress of a goal. For moving the base, this might be the robot's current pose along the path. For controlling the tilting laser scanner, this might be the time left until the scan completes. 856 | > 857 | > **Result** 858 | > A result is sent from the ActionServer to the ActionClient upon completion of the goal. This is different than feedback, since it is sent exactly once. This is extremely useful when the purpose of the action is to provide some sort of information. For move base, the result isn't very important, but it might contain the final pose of the robot. For controlling the tilting laser scanner, the result might contain a point cloud generated from the requested scan. 859 | > 860 | > (Source: http://wiki.ros.org/actionlib) 861 | 862 | 863 | 864 | ### 4.2 Action Files 865 | 866 | [go to top](#top) 867 | 868 | The message types available for use with actions are based off of the eligible .msg types, just like servces are. 869 | 870 | But the action messages are defined in a special type of file called a .action file. 871 | 872 | 873 | 874 | #### **Eligible Action Field Types** 875 | 876 | Exactly the same as messages! 877 | 878 | Action files are just three message files 'smushed' into one! (As opposed to service files' two.) 879 | 880 | > Eligible message field types 881 | > 882 | > - int8, int16, int32, int64 (plus uint*) 883 | > - float32, float64 884 | > - string 885 | > - time, duration 886 | > - other msg files 887 | > - variable-length array[] and fixed-length array[C] 888 | > - the special Header type 889 | 890 | 891 | 892 | #### **Example .action file** 893 | 894 | Recall the example .msg file: 895 | 896 | ``` 897 | Header header 898 | string child_frame_id 899 | geometry_msgs/PoseWithCovariance pose 900 | geometry_msgs/TwistWithCovariance twist 901 | ``` 902 | 903 | An .action file is **similar** (it's just three message files smushed into one, goal, result, feedback) 904 | 905 | Again, the sections are separated by three dashes! 906 | 907 | ``` 908 | goal 909 | --- 910 | result 911 | --- 912 | feedback 913 | ``` 914 | 915 | Eg: 916 | 917 | ``` 918 | #goal definition 919 | int32 order 920 | --- 921 | #result definition 922 | int32[] sequence 923 | --- 924 | #feedback 925 | int32[] sequence 926 | ``` 927 | 928 | 929 | 930 | ### 4.3 rostopic for Actions 931 | 932 | [go to top](#top) 933 | 934 | ROS has no special command line interface for interacting with actions. Do it via `rostopic` 935 | 936 | ```shell 937 | # List available actions 938 | # Look for the /goal, /cancel, /status, /result, /feedback pattern 939 | $ rostopic list 940 | 941 | # Show the type of the service (what messages it takes) 942 | $ rostopic type /action_topic 943 | 944 | # Call a service 945 | # Just publish the goal! 946 | $ rostopic pub /action_topic/goal goal_msg_type [CONTENT] 947 | ``` 948 | 949 | 950 | 951 | #### **Actionlib Ax GUI Tools** 952 | 953 | There's a handy GUI client if you really want to use it. But using rostopic is probably better... 954 | 955 | ```shell 956 | # Client 957 | $ rosrun actionlib axclient.py 958 | 959 | # Server 960 | $ rosrun actionlib axserver.py 961 | ``` 962 | 963 | 964 | 965 | ### 4.4 Creating Action Files 966 | 967 | [go to top](#top) 968 | 969 | Source: http://wiki.ros.org/actionlib_tutorials/Tutorials 970 | 971 | Ok, you know the drill. Let's get to writing an action file. 972 | 973 | Create a package called `simple_action_example`. We'll make more later on, but for now let's just run this through for the simple example! We're going to do a fibonacci number calculator! 974 | 975 | **1. Go to your package directory** 976 | 977 | ```shell 978 | $ roscd simple_action_example 979 | $ mkdir action # Make a srv folder to keep your service files 980 | 981 | $ cd action 982 | $ touch Fibonacci.action # Capitalising the first letter is the convention! 983 | ``` 984 | 985 | **2. Then open that .msg file in your favourite text editor** and HAVE AT IT! (Write your data types and names) 986 | 987 | Make the Fibonacci action! 988 | 989 | ``` 990 | #goal definition 991 | int32 order 992 | --- 993 | #result definition 994 | int32[] sequence 995 | --- 996 | #feedback 997 | int32[] sequence 998 | ``` 999 | 1000 | **3. Then go to package.xml** and **append these two lines** 1001 | 1002 | ```xml 1003 | message_generation 1004 | message_runtime 1005 | ``` 1006 | 1007 | **4. Then say hello to our ~~nemesis~~ good old friend CMakeLists.txt** 1008 | 1009 | Ensure these lines are present (**IN ORDER!**) 1010 | 1011 | > Note: This is if you want to generate action messages. But if you want to use actionlib, check the appropriate section in 4.5 1012 | 1013 | ```cmake 1014 | find_package(catkin REQUIRED COMPONENTS 1015 | roscpp 1016 | rospy 1017 | actionlib_msgs # <-- Add this 1018 | # Notice there's no message_generation, this is because it's implied by actionlib_msgs 1019 | ) 1020 | 1021 | # Uncomment this block 1022 | add_action_files( 1023 | DIRECTORY action 1024 | FILES Fibonacci.action 1025 | ) 1026 | 1027 | # Uncomment this block (even though you're generating services) 1028 | generate_messages( 1029 | DEPENDENCIES 1030 | actionlib_msgs 1031 | std_msgs # And any other message packages you're using 1032 | ) 1033 | 1034 | catkin_package( 1035 | CATKIN_DEPENDS roscpp actionlib_msgs # <-- Add this 1036 | ) 1037 | ``` 1038 | 1039 | **5. Then go back to your workspace root, and rebuild!** 1040 | 1041 | ```shell 1042 | $ roscd simple_action_example 1043 | $ cd ../.. 1044 | $ catkin_make # or catkin_make install, see what works 1045 | ``` 1046 | 1047 | If you built this, you should find that in devel/include/simple_action_example, that there are 10 files that were created. 1048 | 1049 | ``` 1050 | FibonacciActionFeedback.h FibonacciAction.h FibonacciFeedback.h FibonacciResult.h 1051 | FibonacciActionGoal.h FibonacciActionResult.h FibonacciGoal.h 1052 | ``` 1053 | 1054 | Pretty cool eh! 1055 | 1056 | 1057 | 1058 | ### 4.5 Writing Simple Action Nodes 1059 | 1060 | [go to top](#top) 1061 | 1062 | Source: http://wiki.ros.org/actionlib_tutorials/Tutorials (With some additions from me) 1063 | 1064 | Check the minimal packages for implementation. 1065 | 1066 | #### **rospy server** 1067 | 1068 | ```python 1069 | #! /usr/bin/env python 1070 | 1071 | import rospy 1072 | import actionlib 1073 | import simple_action_example.msg 1074 | 1075 | # Create the action server as a class 1076 | # The object is just in-case Python 2 is being used to interpret this 1077 | # https://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python 1078 | class FibonacciAction(object): 1079 | # Create the Feedback and Result messages 1080 | _feedback = simple_action_example.msg.FibonacciFeedback() 1081 | _result = simple_action_example.msg.FibonacciResult() 1082 | 1083 | # Constructor 1084 | def __init__(self, name): 1085 | self._action_name = name 1086 | 1087 | # Hook callbacks 1088 | self._as = actionlib.SimpleActionServer(self._action_name, 1089 | simple_action_example.msg.FibonacciAction, 1090 | execute_cb=self.execute_cb, 1091 | auto_start = False) 1092 | 1093 | # Start the action server 1094 | self._as.start() 1095 | 1096 | # Goal execution callback 1097 | def execute_cb(self, goal): 1098 | # helper variables 1099 | r = rospy.Rate(1) 1100 | success = True 1101 | 1102 | # append the seeds for the fibonacci sequence 1103 | self._feedback.sequence = [] 1104 | self._feedback.sequence.append(0) 1105 | self._feedback.sequence.append(1) 1106 | 1107 | # Publish info 1108 | rospy.loginfo('%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i' % (self._action_name, goal.order, self._feedback.sequence[0], self._feedback.sequence[1])) 1109 | 1110 | # Execute the action 1111 | for i in range(1, goal.order): 1112 | # Check that preempt has not been requested by the client 1113 | # If yes, kill the action 1114 | if self._as.is_preempt_requested(): 1115 | rospy.loginfo('%s: Preempted' % self._action_name) 1116 | self._as.set_preempted() 1117 | success = False 1118 | break 1119 | 1120 | self._feedback.sequence.append(self._feedback.sequence[i] + self._feedback.sequence[i-1]) 1121 | 1122 | # publish the feedback 1123 | self._as.publish_feedback(self._feedback) 1124 | 1125 | # this step is not necessary, the sequence is computed at 1 Hz for demonstration purposes 1126 | r.sleep() 1127 | 1128 | if success: 1129 | self._result.sequence = self._feedback.sequence 1130 | rospy.loginfo('%s: Succeeded' % self._action_name) 1131 | self._as.set_succeeded(self._result) 1132 | 1133 | if __name__ == '__main__': 1134 | rospy.init_node('fibonacci') 1135 | server = FibonacciAction(rospy.get_name()) 1136 | rospy.spin() 1137 | ``` 1138 | 1139 | #### **rospy client** 1140 | 1141 | ```python 1142 | #! /usr/bin/env python 1143 | 1144 | from __future__ import print_function # Lets you print like Python 3 1145 | import rospy 1146 | import actionlib 1147 | import simple_action_example.msg 1148 | 1149 | def fibonacci_client(): 1150 | # SimpleActionClient construction, targeting the fibonacci topic of type Fibonacci 1151 | client = actionlib.SimpleActionClient('fibonacci', 1152 | simple_action_example.msg.FibonacciAction) 1153 | 1154 | # Waits until the action server has started up and started 1155 | # listening for goals. (So the goals aren't ignored.) 1156 | client.wait_for_server() 1157 | 1158 | # Creates a goal to send to the action server. 1159 | goal = simple_action_example.msg.FibonacciGoal(order=20) 1160 | 1161 | # Sends the goal to the action server. 1162 | client.send_goal(goal) 1163 | 1164 | # Waits for the server to finish performing the action. 1165 | client.wait_for_result() 1166 | 1167 | # Prints out the result of executing the action 1168 | return client.get_result() # A FibonacciResult 1169 | 1170 | if __name__ == '__main__': 1171 | try: 1172 | # Initializes a rospy node so that the SimpleActionClient can 1173 | # publish and subscribe over ROS. 1174 | rospy.init_node('fibonacci_client_py') 1175 | result = fibonacci_client() 1176 | 1177 | print("Result:", ', '.join([str(n) for n in result.sequence])) 1178 | except rospy.ROSInterruptException: 1179 | print("program interrupted before completion", file=sys.stderr) 1180 | ``` 1181 | 1182 | 1183 | 1184 | #### **roscpp server** 1185 | 1186 | ```c++ 1187 | #include 1188 | #include 1189 | #include 1190 | 1191 | class FibonacciAction 1192 | { 1193 | protected: 1194 | 1195 | ros::NodeHandle nh_; 1196 | 1197 | // NodeHandle instance must be created before this line. Otherwise strange error occurs. 1198 | actionlib::SimpleActionServer as_; 1199 | std::string action_name_; 1200 | 1201 | // create messages that are used to published feedback/result 1202 | simple_action_example::FibonacciFeedback feedback_; 1203 | simple_action_example::FibonacciResult result_; 1204 | 1205 | public: 1206 | 1207 | // Our constructor (with a cool initialisation list!) 1208 | // https://stackoverflow.com/questions/2785612/c-what-does-the-colon-after-a-constructor-mean 1209 | FibonacciAction(std::string name) : 1210 | // Bind the callback to the action server. False is for thread spinning 1211 | as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false), 1212 | action_name_(name) 1213 | { 1214 | // Start the action server 1215 | as_.start(); 1216 | } 1217 | 1218 | // Destructor 1219 | ~FibonacciAction(void) 1220 | { 1221 | } 1222 | 1223 | // Execute action callback (passing the goal via reference) 1224 | void executeCB(const simple_action_example::FibonacciGoalConstPtr &goal) 1225 | { 1226 | // helper variables 1227 | ros::Rate r(1); 1228 | bool success = true; 1229 | 1230 | // push_back the seeds for the fibonacci sequence 1231 | feedback_.sequence.clear(); 1232 | feedback_.sequence.push_back(0); 1233 | feedback_.sequence.push_back(1); 1234 | 1235 | // publish info to the console for the user 1236 | ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]); 1237 | 1238 | // start executing the action (i <= goal->order, as goal is a pointer) 1239 | for(int i=1; i<=goal->order; i++) 1240 | { 1241 | // check that preempt has not been requested by the client 1242 | if (as_.isPreemptRequested() || !ros::ok()) 1243 | { 1244 | ROS_INFO("%s: Preempted", action_name_.c_str()); 1245 | // set the action state to preempted 1246 | as_.setPreempted(); 1247 | success = false; 1248 | break; 1249 | } 1250 | 1251 | // Add the number to the feedback to be fed back 1252 | feedback_.sequence.push_back(feedback_.sequence[i] + feedback_.sequence[i-1]); 1253 | // publish the feedback 1254 | as_.publishFeedback(feedback_); 1255 | // this sleep is not necessary, the sequence is computed at 1 Hz for demonstration purposes 1256 | r.sleep(); 1257 | } 1258 | 1259 | if(success) 1260 | { 1261 | result_.sequence = feedback_.sequence; 1262 | ROS_INFO("%s: Succeeded", action_name_.c_str()); 1263 | // set the action state to succeeded 1264 | as_.setSucceeded(result_); 1265 | } 1266 | } 1267 | }; 1268 | 1269 | 1270 | int main(int argc, char** argv) 1271 | { 1272 | ros::init(argc, argv, "fibonacci"); 1273 | 1274 | // Create an action server object and spin ROS 1275 | FibonacciAction fibonacci("fibonacci"); 1276 | ros::spin(); 1277 | 1278 | return 0; 1279 | } 1280 | ``` 1281 | 1282 | #### **roscpp client** 1283 | 1284 | ```c++ 1285 | #include 1286 | #include 1287 | #include 1288 | #include 1289 | 1290 | int main (int argc, char **argv) 1291 | { 1292 | // Init ROS node called test_fibonacci 1293 | ros::init(argc, argv, "test_fibonacci"); 1294 | 1295 | // create the action client 1296 | // true causes the client to spin its own thread 1297 | actionlib::SimpleActionClient ac("fibonacci", true); 1298 | 1299 | ROS_INFO("Waiting for action server to start."); 1300 | // wait for the action server to start 1301 | ac.waitForServer(); //will wait for infinite time 1302 | 1303 | ROS_INFO("Action server started, sending goal."); 1304 | // send a goal to the action 1305 | simple_action_example::FibonacciGoal goal; 1306 | goal.order = 20; 1307 | ac.sendGoal(goal); 1308 | 1309 | //wait for the action to return 1310 | bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0)); 1311 | 1312 | if (finished_before_timeout) 1313 | { 1314 | actionlib::SimpleClientGoalState state = ac.getState(); 1315 | ROS_INFO("Action finished: %s",state.toString().c_str()); 1316 | } 1317 | else 1318 | ROS_INFO("Action did not finish before the time out."); 1319 | 1320 | //exit 1321 | return 0; 1322 | } 1323 | ``` 1324 | 1325 | 1326 | 1327 | #### **roscpp CMakelists setup** 1328 | 1329 | Example minimal file from the tutorials: 1330 | 1331 | ```python 1332 | cmake_minimum_required(VERSION 2.8.3) 1333 | project(simple_action_example) 1334 | 1335 | find_package(catkin REQUIRED COMPONENTS roscpp actionlib actionlib_msgs) 1336 | 1337 | # Since we added Boost 1338 | find_package(Boost REQUIRED COMPONENTS system) 1339 | 1340 | add_action_files( 1341 | DIRECTORY action 1342 | FILES Fibonacci.action 1343 | ) 1344 | 1345 | generate_messages( 1346 | DEPENDENCIES actionlib_msgs std_msgs 1347 | ) 1348 | 1349 | catkin_package( 1350 | CATKIN_DEPENDS actionlib_msgs 1351 | ) 1352 | 1353 | include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) 1354 | 1355 | # Link the node 1356 | add_executable(fibonacci_server src/fibonacci_server.cpp) 1357 | 1358 | target_link_libraries( 1359 | fibonacci_server 1360 | ${catkin_LIBRARIES} 1361 | ) 1362 | 1363 | add_dependencies( 1364 | fibonacci_server 1365 | # The one below is the name of your package!! 1366 | ${simple_action_example_EXPORTED_TARGETS} 1367 | ) 1368 | 1369 | # Link the node 1370 | add_executable(fibonacci_client src/fibonacci_client.cpp) 1371 | 1372 | target_link_libraries( 1373 | fibonacci_client 1374 | ${catkin_LIBRARIES} 1375 | ) 1376 | 1377 | add_dependencies( 1378 | fibonacci_client 1379 | # The one below is the name of your package!! 1380 | ${simple_action_example_EXPORTED_TARGETS} 1381 | ) 1382 | ``` 1383 | 1384 | 1385 | 1386 | #### **Testing your action** 1387 | 1388 | Easy! But remember that **you will need to echo the /feedback topic to see anything worthwhile!** 1389 | 1390 | If you want to self-publish a goal, remember to send it with a header and goal ID! 1391 | 1392 | ```bash 1393 | # Terminal 1 1394 | $ roscore 1395 | 1396 | # Terminal 2 1397 | $ rosrun simple_action_example fibonacci_server 1398 | 1399 | # Terminal 3 1400 | $ rosrun simple_action_example fibonacci_client 1401 | 1402 | # Then just echo the topics using rostopic echo /fibonacci/??? 1403 | # And view the graph (using rqt_graph) if you want to! 1404 | ``` 1405 | 1406 | 1407 | 1408 | ### 4.6 Writing an Action Server with a Goal Callback 1409 | 1410 | [go to top](#top) 1411 | 1412 | Source: http://wiki.ros.org/actionlib_tutorials/Tutorials (With some additions from me) 1413 | 1414 | 1415 | 1416 | ### 4.7 Writing a Goal Callback 1417 | 1418 | [go to top](#top) 1419 | 1420 | Source: http://wiki.ros.org/actionlib_tutorials/Tutorials (With some additions from me) 1421 | 1422 | 1423 | 1424 | ## 5. Concluding Comparison 1425 | 1426 | [go to top](#top) 1427 | 1428 | ![3.4](assets/3.4.png) 1429 | 1430 | (Image source: ETHz) 1431 | 1432 | 1433 | 1434 | 1435 | ``` 1436 | . . 1437 | . |\-^-/| . 1438 | /| } O.=.O { |\ 1439 | ``` 1440 | 1441 | ​ 1442 | 1443 | ------ 1444 | 1445 | [![Yeah! Buy the DRAGON a COFFEE!](../assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /ROS/04 ROS - Nodelets.md: -------------------------------------------------------------------------------- 1 | # ROS Nodelets 2 | 3 | Author: methylDragon 4 | Fairly comprehensive ROS crash course! 5 | I'll be adapting code and tutorial content from the ROS Tutorials: http://wiki.ros.org/ROS/Tutorials 6 | and ETHz http://www.rsl.ethz.ch/education-students/lectures/ros.html 7 | 8 | ------ 9 | 10 | ## Pre-Requisites 11 | 12 | - A system with Ubuntu 16.04 installed (no other versions!) 13 | - Linux 14 | - C++ 15 | - You should at least know classes and pointers 16 | - Sadly there is no Python nodelet implementation 17 | 18 | 19 | 20 | ## Table Of Contents 21 | 22 | 1. [Introduction](#1) 23 | 2. [Nodelets](#2) 24 | 2.1 [Introduction](#2.1) 25 | 2.2 [Running Nodelets from Launchfiles](#2.2) 26 | 2.3 [Nodelet Managers](#2.3) 27 | 2.4 [Writing Nodelets](#2.4) 28 | 2.5 [Augment the CMakeLists.txt file](#2.5) 29 | 2.6 [Augment the package.xml File](#2.6) 30 | 2.7 [Create nodelet_plugins.xml](#2.7) 31 | 2.8 [Create Your Nodelet!](#2.8) 32 | 2.9 [Nodelet Caveats](#2.9) 33 | 34 | 35 | 36 | 37 | ## 1. Introduction 38 | 39 | > The nodelet package is designed to provide a way to run multiple algorithms in the same process with zero copy transport between algorithms. This package provides both the nodelet base class needed for implementing a nodelet, as well as the NodeletLoader class used for instantiating nodelets. 40 | > 41 | > 42 | 43 | ![img](assets/8ros-lt-nodelet-4-638.jpg) 44 | 45 | [Image Source]() 46 | 47 | They're an optimisation detail (albeit a pretty significant one!) Sometimes widely used especially in applications that deal with computer vision or point clouds in ROS. 48 | 49 | Messages sent from nodelet to nodelet **within a nodelet manager** are instead sent by just passing the message pointer. So no actual transfer of the data pointed to by the pointer happens. This is particularly significant for message data that's huge, like videos, images, or point clouds. 50 | 51 | You basically host multiple ROS node-like processes under a single process, saving time because you skip copying, and saving network bandwidth because no large messages are flying through your ROS network. 52 | 53 | ![image description](assets/14599315912601528.png) 54 | 55 | [Image Source]() 56 | 57 | 58 | 59 | ## 2. Nodelets 60 | 61 | ### 2.1 Introduction 62 | [go to top](#top) 63 | 64 | 65 | - Nodelets within a single nodelet manager process communicate with each other via the use of a shared pointer 66 | - Nodelet managers are ROS nodes on their own! 67 | - In contrast, nodes communicate between themselves via TCP connections in ROS! 68 | 69 | All topics that are subscribed or published are done through the nodelet manager as an interface. 70 | 71 | Additionally, each nodelet is [bonded]() to their nodelet manager, so that the nodelet manager can keep track of whether nodelets are alive or not, and vice versa! 72 | 73 | 74 | 75 | ### 2.2 Running Nodelets from Launchfiles 76 | [go to top](#top) 77 | 78 | 79 | | Nodelet Launch Arg | Description | 80 | | -------------------------------------- | ------------------------------------------------------------ | 81 | | load \/\ | Launch a nodelet on the nodelet manager named | 82 | | standalone \/\ | Launch a nodelet in a standalone node | 83 | | unload | Unload a nodelet named on the nodelet manager named | 84 | | manager | Launch a nodelet manager node | 85 | 86 | > The nodelet names are defined by the `name=""` attribute in the `` tag in the launch XML. 87 | 88 | **Example**: 89 | 90 | ```xml 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | filter_field_name: z 100 | filter_limit_min: 0.01 101 | filter_limit_max: 1.5 102 | filter_limit_negative: False 103 | leaf_size: 0.01 104 | 105 | 106 | 107 | ``` 108 | 109 | So we can see from here that we are loading a pcl/VoxelGrid nodelet in the process that the pcl_manager nodelet manager is running on. 110 | 111 | If we wanted to run it standalone, or kill the nodelet, we just use the corresponding launch argument. 112 | 113 | 114 | 115 | ### 2.3 Nodelet Managers 116 | [go to top](#top) 117 | 118 | 119 | Nodelet managers are nodes that host nodelets on them. They facilitate the transfer of messages into and out of the nodelets if such connections need to be made on the ROS graph. 120 | 121 | Since it's actually one process, if you want to run the nodelets in parallel, you have to set the `num_worker_threads` parameter like so: 122 | 123 | ```xml 124 | 125 | 126 | 127 | 128 | ``` 129 | 130 | This way, the nodelet manager will have a **thread pool** that will be shared across all nodelets hosted by the manager. 131 | 132 | > **Note**: Do also take note that as the nodelet managers host the nodelets on shared thread pool, nodelets that are blocking might cause issues with message transfer between nodelets and callback running. So **do ensure that the nodelet manager has enough threads to prevent this**. 133 | 134 | 135 | 136 | ### 2.4 Writing Nodelets 137 | [go to top](#top) 138 | 139 | 140 | Nodelets work almost like normal ROS nodes in terms of what you can do with them in the code. **Except you should be writing them as a child class of the nodelet class**. 141 | 142 | As such, you can use the publisher and subscriber interfaces (like the one in the `class_pub_sub` package, in the minimal projects directory) in nodelets, in much the same way! 143 | 144 | You just need to settle some boilerplate, that we'll adapt from [this tutorial](http://wiki.ros.org/nodelet/Tutorials/Porting%20nodes%20to%20nodelets). 145 | 146 | 147 | 148 | ### 2.5 Augment the CMakeLists.txt file 149 | [go to top](#top) 150 | 151 | 152 | Add `nodelet` as a dependency, and compile your nodelet as a library 153 | 154 | ```cmake 155 | cmake_minimum_required(VERSION 2.8.3) 156 | project(pub_sub_nodelet_example) 157 | 158 | find_package(catkin REQUIRED COMPONENTS 159 | roscpp 160 | std_msgs 161 | nodelet # Here 162 | ) 163 | 164 | catkin_package( 165 | INCLUDE_DIRS src 166 | CATKIN_DEPENDS roscpp std_msgs nodelet # And here 167 | DEPENDS system_lib 168 | ) 169 | 170 | include_directories( 171 | ${catkin_INCLUDE_DIRS} 172 | ) 173 | 174 | # Library addition here! 175 | # In this case, I'm just calling my nodelet the name of the package 176 | add_library(${PROJECT_NAME} src/PubSubNodelet.cpp) 177 | target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES}) 178 | ``` 179 | 180 | You may also specify install targets 181 | 182 | ```cmake 183 | install(FILES nodelet_plugins.xml 184 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 185 | ) 186 | 187 | install(DIRECTORY launch 188 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/ 189 | ) 190 | 191 | install(DIRECTORY include/${PROJECT_NAME}/ 192 | DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 193 | ) 194 | ``` 195 | 196 | 197 | 198 | ### 2.6 Augment the package.xml File 199 | [go to top](#top) 200 | 201 | 202 | Add these lines, which will add the `nodelet` package as a dependency, as well as export the `nodelet_plugins.xml` you'll add next. 203 | 204 | ```xml 205 | nodelet 206 | nodelet 207 | 208 | 209 | 210 | 211 | ``` 212 | 213 | 214 | 215 | ### 2.7 Create nodelet_plugins.xml 216 | [go to top](#top) 217 | 218 | 219 | In this case, my nodelet is called `PubSubNodelet`, from the example package `pub_sub_nodelet_example`. Find and replace those strings for your own nodelets. 220 | 221 | The `nodelet_plugins.xml` file will help let ROS know that your nodelet is an executable plugin, which is important for exposing it to the nodelet manager interfaces. 222 | 223 | ```xml 224 | 225 | 226 | 227 | Example nodelet that features publisher and subscriber capabilities. 228 | 229 | 230 | 231 | ``` 232 | 233 | 234 | 235 | ### 2.8 Create Your Nodelet! 236 | [go to top](#top) 237 | 238 | 239 | We're going to make an example pub-sub nodelet! 240 | 241 | First we made a header file. **We'll place it in the `include/package_name` directory**. 242 | 243 | In the case of the example, we'll call it `PubSubNodelet.h`, but you can use any name you want. 244 | 245 | ```c++ 246 | #include 247 | #include 248 | #include 249 | 250 | namespace pub_sub_nodelet_example 251 | { 252 | class PubSubNodelet : public nodelet::Nodelet 253 | { 254 | protected: 255 | // Here's our node handle! 256 | ros::NodeHandle nh; 257 | 258 | // Init publisher and subscribers here 259 | ros::Publisher pub; 260 | ros::Subscriber sub; 261 | 262 | // These will be useful in the class implementation 263 | std_msgs::String message; 264 | unsigned int count = 0; 265 | 266 | public: 267 | virtual void onInit(); 268 | void msgCB(const std_msgs::StringConstPtr& msg); 269 | }; 270 | } 271 | ``` 272 | 273 | **Notice that there is an onInit() method** that will get overwritten with your class implementation in the .cpp file you'll write. This onInit() method is called on initialisation of the nodelet! 274 | 275 | So now, we'll create a corresponding `PubSubNodelet.cpp` in the `src` directory! 276 | 277 | Some more important stuff are here. 278 | 279 | > Notably, we need to interface with `pluginlib`. 280 | > 281 | > So we import it here 282 | > 283 | > ```c++ 284 | > #include 285 | > ``` 286 | > 287 | > And we export the nodelet class at the end as a plugin 288 | > 289 | > ```c++ 290 | > PLUGINLIB_EXPORT_CLASS(pub_sub_nodelet_example::PubSubNodelet, nodelet::Nodelet) 291 | > ``` 292 | 293 | ```c++ 294 | #include 295 | #include "pub_sub_nodelet_example/PubSubNodelet.h" 296 | 297 | ros::Rate r = ros::Rate(25); 298 | 299 | namespace pub_sub_nodelet_example 300 | { 301 | void PubSubNodelet::onInit() 302 | { 303 | // Init nodehandle 304 | nh = getNodeHandle(); 305 | 306 | // Bind subscription topic 307 | sub = nh.subscribe("chatter", 1, &PubSubNodelet::msgCB, this); 308 | pub = nh.advertise("chatter", 1); 309 | 310 | NODELET_INFO("NODELET READY!"); 311 | 312 | while (ros::ok()) 313 | { 314 | std::ostringstream string_count; 315 | string_count << count; 316 | message.data = "Rawr " + string_count.str(); 317 | 318 | pub.publish(message); 319 | ros::spinOnce(); 320 | r.sleep(); 321 | 322 | count++; 323 | } 324 | } 325 | 326 | void PubSubNodelet::msgCB(const std_msgs::StringConstPtr& msg) 327 | { 328 | NODELET_INFO_STREAM(msg->data); 329 | } 330 | } 331 | 332 | // Export the nodelet as a plugin 333 | PLUGINLIB_EXPORT_CLASS(pub_sub_nodelet_example::PubSubNodelet, nodelet::Nodelet) 334 | ``` 335 | 336 | Additionally! Notice that we didn't put the rate inside the class. There's a bunch of caveats with nodelets that you should be aware of, that we'll talk about in the next section. 337 | 338 | > **Also note**: Notice how there isn't a `main()` function! This is because the main function will run within the nodelet manager instead, and the nodelet class will hitchhike on that host process instead! 339 | 340 | 341 | 342 | ### 2.9 Nodelet Caveats 343 | [go to top](#top) 344 | 345 | 346 | **ROS Console Output** 347 | 348 | You won't be able to use the normal `ROS_INFO()` type rosconsole methods! Instead, use the nodelet aware methods like `NODELET_INFO()`. 349 | 350 | 351 | 352 | **Nodelet Constructor Overriding** 353 | 354 | Any objects that require the class to have a non-empty constructor will stop the pluginlib export processes, since pluginlib needs to override the class constructor. So this includes stuff like **ROS Rate** objects. Including them in the nodelet class will cause issues. That's why in the example above, we put the ROS Rate on the outside of the class. 355 | 356 | 357 | 358 | **A Warning for Nodelet Messages** 359 | 360 | Remember again that nodelets pass messages within a nodelet manager via the use of shared pointers. As such, these two things must be respected: 361 | 362 | - Message callbacks should be using the ptr type. (Though, whether you want to use a const ptr or not is up to you) 363 | - Messages should **not** be edited on the publishing end after the messages have been published, as that will cause the message that is received on the subscribing end to also be changed, since the only thing that is actually passed is the message pointer, not the value! 364 | 365 | 366 | 367 | **Outputting to Screen For Launchfiles** 368 | 369 | When you want the nodelet to output stuff to screen, **set `output="screen"` on the manager, not the nodelet**. This is because the manager is the actual process that is wrapping the nodelet processes! 370 | 371 | ```xml 372 | 373 | 374 | 375 | 376 | ``` 377 | 378 | 379 | 380 | 381 | ``` 382 | . . 383 | . |\-^-/| . 384 | /| } O.=.O { |\ 385 | ``` 386 | 387 | ​ 388 | 389 | ------ 390 | 391 | [![Yeah! Buy the DRAGON a COFFEE!](../assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /ROS/05 ROS - Tips and Tricks.md: -------------------------------------------------------------------------------- 1 | # ROS Tips and Tricks 2 | 3 | Author: methylDragon 4 | Just a collection of useful things I've found 5 | 6 | ------ 7 | 8 | ## Pre-Requisites 9 | 10 | - A system with Ubuntu 16.04 installed (no other versions!) 11 | - Linux 12 | - Python 3 and/or C++ 13 | 14 | 15 | 16 | ## Table Of Contents 17 | 18 | 1. [Introduction](#1) 19 | 2. [Convenience Tips](#2) 20 | 2.1 [Linux Aliases](#2.1) 21 | 22 | 23 | 24 | ## 1. Introduction 25 | 26 | Everyone loves being ~~lazy~~ efficient! 27 | 28 | 29 | 30 | ## 2. Convenience Tips 31 | 32 | ### 2.1 Linux Aliases 33 | 34 | [go to top](#top) 35 | 36 | Ever wish you could just swap your stated ROS_MASTER_URIs and ROS_HOSTNAMEs **without** having to go `$ sudo nano ~/.bashrc` or typing out the entire line? 37 | 38 | **Aliases** have you covered! (For more than just those purposes!) 39 | 40 | Inside ~/.bashrc: 41 | 42 | ```bash 43 | alias command_name="" 44 | # Don't add spaces between the = sign and the words, it'll break it 45 | 46 | # So for the IP change example: 47 | alias rosinit_local="export ROS_HOSTNAME = localhost && export ROS_MASTER_URI = http://localhost:11311" 48 | ``` 49 | 50 | Now, you can do this! 51 | 52 | ```shell 53 | $ rosinit_local 54 | 55 | # Is equivalent to running 56 | $ export ROS_HOSTNAME = localhost && export ROS_MASTER_URI = http://localhost:11311 57 | ``` 58 | 59 | And your IPs will be set accordingly! Easy! 60 | 61 | 62 | 63 | 64 | ``` 65 | . . 66 | . |\-^-/| . 67 | /| } O.=.O { |\ 68 | ``` 69 | 70 | ​ 71 | 72 | ------ 73 | 74 | [![Yeah! Buy the DRAGON a COFFEE!](../assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/Note.txt: -------------------------------------------------------------------------------- 1 | To use these, put the package you want to test in the /src of a workspace, then run catkin_make in the root of that workspace! 2 | 3 | Then, make sure you source the setup.bash in the /devel space of that workspace 4 | And then run rospack profile to make sure that ROS has captured the package in its tree 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # toplevel CMakeLists.txt for a catkin workspace 2 | # catkin/cmake/toplevel.cmake 3 | 4 | cmake_minimum_required(VERSION 2.8.3) 5 | 6 | set(CATKIN_TOPLEVEL TRUE) 7 | 8 | # search for catkin within the workspace 9 | set(_cmd "catkin_find_pkg" "catkin" "${CMAKE_SOURCE_DIR}") 10 | execute_process(COMMAND ${_cmd} 11 | RESULT_VARIABLE _res 12 | OUTPUT_VARIABLE _out 13 | ERROR_VARIABLE _err 14 | OUTPUT_STRIP_TRAILING_WHITESPACE 15 | ERROR_STRIP_TRAILING_WHITESPACE 16 | ) 17 | if(NOT _res EQUAL 0 AND NOT _res EQUAL 2) 18 | # searching fot catkin resulted in an error 19 | string(REPLACE ";" " " _cmd_str "${_cmd}") 20 | message(FATAL_ERROR "Search for 'catkin' in workspace failed (${_cmd_str}): ${_err}") 21 | endif() 22 | 23 | # include catkin from workspace or via find_package() 24 | if(_res EQUAL 0) 25 | set(catkin_EXTRAS_DIR "${CMAKE_SOURCE_DIR}/${_out}/cmake") 26 | # include all.cmake without add_subdirectory to let it operate in same scope 27 | include(${catkin_EXTRAS_DIR}/all.cmake NO_POLICY_SCOPE) 28 | add_subdirectory("${_out}") 29 | 30 | else() 31 | # use either CMAKE_PREFIX_PATH explicitly passed to CMake as a command line argument 32 | # or CMAKE_PREFIX_PATH from the environment 33 | if(NOT DEFINED CMAKE_PREFIX_PATH) 34 | if(NOT "$ENV{CMAKE_PREFIX_PATH}" STREQUAL "") 35 | string(REPLACE ":" ";" CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH}) 36 | endif() 37 | endif() 38 | 39 | # list of catkin workspaces 40 | set(catkin_search_path "") 41 | foreach(path ${CMAKE_PREFIX_PATH}) 42 | if(EXISTS "${path}/.catkin") 43 | list(FIND catkin_search_path ${path} _index) 44 | if(_index EQUAL -1) 45 | list(APPEND catkin_search_path ${path}) 46 | endif() 47 | endif() 48 | endforeach() 49 | 50 | # search for catkin in all workspaces 51 | set(CATKIN_TOPLEVEL_FIND_PACKAGE TRUE) 52 | find_package(catkin QUIET 53 | NO_POLICY_SCOPE 54 | PATHS ${catkin_search_path} 55 | NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) 56 | unset(CATKIN_TOPLEVEL_FIND_PACKAGE) 57 | 58 | if(NOT catkin_FOUND) 59 | message(FATAL_ERROR "find_package(catkin) failed. catkin was neither found in the workspace nor in the CMAKE_PREFIX_PATH. One reason may be that no ROS setup.sh was sourced before.") 60 | endif() 61 | endif() 62 | 63 | catkin_workspace() 64 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(basic_pub_sub) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | std_msgs 7 | ) 8 | 9 | # Initialise the export variables 10 | catkin_package( 11 | INCLUDE_DIRS src 12 | CATKIN_DEPENDS roscpp std_msgs 13 | DEPENDS system_lib 14 | ) 15 | 16 | include_directories( 17 | ${catkin_INCLUDE_DIRS} 18 | ) 19 | 20 | # One per executable! 21 | add_executable(basic_pub src/basic_pub.cpp) 22 | target_link_libraries(basic_pub ${catkin_LIBRARIES}) 23 | 24 | add_executable(basic_sub src/basic_sub.cpp) 25 | target_link_libraries(basic_sub ${catkin_LIBRARIES}) 26 | 27 | add_executable(hello_world src/hello_world.cpp) 28 | target_link_libraries(hello_world ${catkin_LIBRARIES}) 29 | 30 | 31 | install(DIRECTORY launch 32 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 33 | ) 34 | 35 | #install(DIRECTORY param 36 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 37 | #) 38 | 39 | #install(DIRECTORY maps 40 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 41 | #) 42 | 43 | #install(DIRECTORY rviz 44 | # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 45 | #) 46 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/launch/basic_pub_sub_init.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | basic_pub_sub 4 | 0.0.0 5 | A minimal roscpp basic pub-sub package! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | std_msgs 17 | 18 | roscpp 19 | std_msgs 20 | 21 | roscpp 22 | std_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/src/basic_pub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | // New node called talker 8 | ros::init(argc, argv, "talker"); 9 | ros::NodeHandle nh; 10 | 11 | // Publish onto the "chatter" topic with a queue size of 1 12 | ros::Publisher chatter_publisher = nh.advertise("chatter", 1); 13 | 14 | ros::Rate loopRate(10); 15 | 16 | unsigned int count = 0; 17 | 18 | while (ros::ok()) 19 | { 20 | std_msgs::String message; // Make a new message object 21 | std::ostringstream string_count; 22 | string_count << count; 23 | 24 | message.data = "Rawr " + string_count.str(); // Write to it 25 | ROS_INFO_STREAM(message.data); 26 | 27 | chatter_publisher.publish(message); 28 | 29 | ros::spinOnce(); 30 | loopRate.sleep(); 31 | count++; 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/src/basic_sub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void chatter_callback(const std_msgs::String& msg) 5 | { 6 | ROS_INFO("I heard: [%s]", msg.data.c_str()); 7 | } 8 | 9 | int main(int argc, char **argv) 10 | { 11 | // New node called listener 12 | ros::init(argc, argv, "listener"); 13 | ros::NodeHandle nh; 14 | 15 | // Subscribe to chatter with a queue size of 10 and callback 16 | ros::Subscriber chatter_subscriber = nh.subscribe("chatter", 10, chatter_callback); 17 | ros::spin(); // Keep running until the node is killed 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/basic_pub_sub/src/hello_world.cpp: -------------------------------------------------------------------------------- 1 | #include // Include the ROS main header file 2 | 3 | int main(int argc, char** argv) 4 | { 5 | ros::init(argc, argv, "rawrer", ros::init_options::AnonymousName); 6 | // Initialise a node named rawrer, make it anonymous 7 | // Check the rospy hello_world for what anonymous means 8 | 9 | ros::NodeHandle node_handle; // This HANDLES all communications with ROS 10 | // Topics, services, parameters, etc 11 | 12 | ros::Rate loopRate(10); // Hz 13 | 14 | // Let's just have a nice incrementer here 15 | unsigned int count = 0; 16 | 17 | // As long as ROS is running, keep running 18 | while (ros::ok()) 19 | { // ros::ok() checks for the status of ROS 20 | ROS_INFO_STREAM("Rawr " << count); // Log it! 21 | // Notice how we aren't using cout here! Use ROS_INFO and ROS_INFO_STREAM! 22 | 23 | ros::spinOnce(); // Calls all callbacks waiting to be called-back 24 | loopRate.sleep(); // Sleep according to the loopRate 25 | count++; // Aaaand increment our counter 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/class_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(class_pub_sub) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | std_msgs 7 | ) 8 | 9 | catkin_package( 10 | INCLUDE_DIRS src 11 | CATKIN_DEPENDS roscpp std_msgs 12 | DEPENDS system_lib 13 | ) 14 | 15 | include_directories( 16 | ${catkin_INCLUDE_DIRS} 17 | ) 18 | 19 | add_executable(class_pub_sub src/class_pub_sub.cpp) 20 | target_link_libraries(class_pub_sub ${catkin_LIBRARIES}) 21 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/class_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | class_pub_sub 4 | 0.0.0 5 | A minimal roscpp basic pub-sub package, implemented as a class! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | std_msgs 17 | 18 | roscpp 19 | std_msgs 20 | 21 | roscpp 22 | std_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/class_pub_sub/src/class_pub_sub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class ClassPubSub 6 | { 7 | protected: 8 | ros::NodeHandle nh; 9 | ros::Publisher pub; 10 | ros::Subscriber sub; 11 | ros::Rate r; 12 | 13 | std_msgs::String message; 14 | unsigned int count = 0; 15 | 16 | public: 17 | // Constructor 18 | ClassPubSub() 19 | : r(25) 20 | { 21 | sub = nh.subscribe("chatter", 1, &ClassPubSub::msgCB, this); 22 | pub = nh.advertise("chatter", 1); 23 | 24 | while (ros::ok()) 25 | { 26 | std::ostringstream string_count; 27 | string_count << count; 28 | message.data = "Rawr " + string_count.str(); 29 | 30 | pub.publish(message); 31 | ros::spinOnce(); 32 | r.sleep(); 33 | 34 | count++; 35 | } 36 | } 37 | 38 | // We pass a pointer here to prevent copying 39 | // The access operator has to change, of course 40 | void msgCB(const std_msgs::StringConstPtr& msg) 41 | { 42 | ROS_INFO_STREAM(msg->data); 43 | } 44 | }; 45 | 46 | int main(int argc, char** argv) 47 | { 48 | ros::init(argc, argv, "class_pub_sub"); 49 | ClassPubSub(); 50 | } 51 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/dynamic_configure_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(dynamic_reconfigure_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | std_msgs 7 | dynamic_reconfigure 8 | ) 9 | 10 | generate_dynamic_reconfigure_options( 11 | cfg/Example.cfg 12 | ) 13 | 14 | catkin_package( 15 | INCLUDE_DIRS src 16 | CATKIN_DEPENDS roscpp std_msgs 17 | DEPENDS 18 | ) 19 | 20 | include_directories( 21 | ${catkin_INCLUDE_DIRS} 22 | ) 23 | 24 | add_executable(dynamic_reconfigure_example src/dynamic_reconfigure_example.cpp) 25 | target_link_libraries(dynamic_reconfigure_example ${catkin_LIBRARIES}) 26 | add_dependencies(dynamic_reconfigure_example ${PROJECT_NAME}_gencfg) 27 | 28 | add_executable(dynamic_reconfigure_client src/dynamic_reconfigure_client.cpp) 29 | target_link_libraries(dynamic_reconfigure_client ${catkin_LIBRARIES}) 30 | add_dependencies(dynamic_reconfigure_client ${PROJECT_NAME}_gencfg) 31 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/dynamic_configure_example/cfg/Example.cfg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | PACKAGE = "dynamic_reconfigure_example" 3 | 4 | from dynamic_reconfigure.parameter_generator_catkin import * 5 | 6 | gen = ParameterGenerator() 7 | 8 | # Add parameters 9 | gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100) 10 | gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1) 11 | gen.add("str_param", str_t, 0, "A string parameter", "Hello World") 12 | gen.add("bool_param", bool_t, 0, "A Boolean parameter", True) 13 | 14 | # Create an enum mapping (Small is 0, Medium is 1, ...) 15 | size_enum = gen.enum([gen.const("Small", int_t, 0, "A small constant"), 16 | gen.const("Medium", int_t, 1, "A medium constant"), 17 | gen.const("Large", int_t, 2, "A large constant"), 18 | gen.const("ExtraLarge", int_t, 3, "An extra large constant")], 19 | "An enum to set size") 20 | 21 | # Add enum parameter 22 | gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum) 23 | 24 | exit(gen.generate(PACKAGE, "dynamic_reconfigure_example", "Example")) 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/dynamic_configure_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | dynamic_reconfigure_example 4 | 0.0.0 5 | A minimal roscpp dynamically reconfigurable package! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | std_msgs 17 | dynamic_reconfigure 18 | 19 | roscpp 20 | std_msgs 21 | 22 | roscpp 23 | std_msgs 24 | dynamic_reconfigure 25 | 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/dynamic_configure_example/src/dynamic_reconfigure_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | ros::init(argc, argv, "dynamic_reconfigure_client"); 9 | 10 | ros::NodeHandle nh; 11 | 12 | // Remember to input the name of the server that the 13 | // dynamically reconfigurable node is hosting! 14 | ros::ServiceClient client = nh.serviceClient("/dynamic_reconfigure_example/set_parameters"); 15 | 16 | // Create service message 17 | dynamic_reconfigure::Reconfigure service; 18 | 19 | // Create dependent messages 20 | dynamic_reconfigure::IntParameter int_param; 21 | int_param.name = "int_param"; 22 | int_param.value = 0; 23 | 24 | dynamic_reconfigure::DoubleParameter double_param; 25 | double_param.name = "double_param"; 26 | double_param.value = 1.0; 27 | 28 | dynamic_reconfigure::StrParameter str_param; 29 | str_param.name = "str_param"; 30 | str_param.value = "Rawr"; 31 | 32 | dynamic_reconfigure::BoolParameter bool_param; 33 | bool_param.name = "bool_param"; 34 | bool_param.value = true; 35 | 36 | dynamic_reconfigure::IntParameter size; 37 | size.name = "size"; 38 | size.value = 0; 39 | 40 | // Populate request 41 | service.request.config.ints.push_back(int_param); 42 | service.request.config.doubles.push_back(double_param); 43 | service.request.config.strs.push_back(str_param); 44 | service.request.config.bools.push_back(bool_param); 45 | service.request.config.ints.push_back(size); 46 | 47 | // Service callback function 48 | // client.call(service) calls the client! 49 | if (client.call(service)) 50 | { 51 | ROS_INFO("Reconfigure call succeeded!"); 52 | } 53 | else 54 | { 55 | ROS_INFO("Reconfigure call failed!"); 56 | return 1; 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/dynamic_configure_example/src/dynamic_reconfigure_example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | void callback(dynamic_reconfigure_example::ExampleConfig &config, uint32_t level) 7 | { 8 | ROS_INFO("Reconfigure Request: %d %f %s %s %d", 9 | config.int_param, 10 | config.double_param, 11 | config.str_param.c_str(), 12 | config.bool_param ? "True" : "False", 13 | config.size); 14 | } 15 | 16 | int main(int argc, char **argv) 17 | { 18 | ros::init(argc, argv, "dynamic_reconfigure_example"); 19 | 20 | dynamic_reconfigure::Server server; 21 | dynamic_reconfigure::Server::CallbackType f; 22 | 23 | f = boost::bind(&callback, _1, _2); 24 | server.setCallback(f); 25 | 26 | ROS_INFO("Spinning node"); 27 | ros::spin(); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(modular_pub_sub) 3 | 4 | ## Use C++11 5 | add_definitions(-std=c++11) 6 | ## By adding -Wall and -Werror, the compiler does not ignore warnings anymore, 7 | ## enforcing cleaner code. 8 | #add_definitions(-std=c++11 -Wall -Werror) 9 | 10 | ## Find catkin macros and libraries 11 | find_package(catkin REQUIRED 12 | COMPONENTS 13 | roscpp 14 | std_msgs 15 | std_srvs 16 | ) 17 | 18 | ## Find system libraries 19 | #find_package(Eigen3 REQUIRED) 20 | #find_package(Boost REQUIRED) 21 | 22 | ################################### 23 | ## catkin specific configuration ## 24 | ################################### 25 | ## The catkin_package macro generates cmake config files for your package 26 | ## Declare things to be passed to dependent projects 27 | ## INCLUDE_DIRS: uncomment this if your package contains header files 28 | ## LIBRARIES: libraries you create in this project that dependent projects also need 29 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need 30 | ## DEPENDS: system dependencies of this project that dependent projects also need 31 | catkin_package( 32 | INCLUDE_DIRS 33 | include 34 | # ${EIGEN3_INCLUDE_DIR} 35 | LIBRARIES 36 | ${PROJECT_NAME}_core 37 | CATKIN_DEPENDS 38 | roscpp 39 | std_msgs 40 | std_srvs 41 | # DEPENDS 42 | # Boost 43 | ) 44 | 45 | ########### 46 | ## Build ## 47 | ########### 48 | 49 | ## Specify additional locations of header files 50 | ## Your package locations should be listed before other locations 51 | include_directories( 52 | include 53 | ${catkin_INCLUDE_DIRS} 54 | # ${EIGEN3_INCLUDE_DIR} 55 | # ${Boost_INCLUDE_DIRS} 56 | ) 57 | 58 | ## Declare a cpp library 59 | add_library(${PROJECT_NAME}_core 60 | src/algorithm.cpp 61 | ) 62 | 63 | ## Declare cpp executables 64 | add_executable(${PROJECT_NAME} 65 | src/Node.cpp 66 | src/nodeClassInterface.cpp 67 | ) 68 | 69 | ## Add dependencies to exported targets, like ROS msgs or srvs 70 | add_dependencies(${PROJECT_NAME}_core 71 | ${catkin_EXPORTED_TARGETS} 72 | ) 73 | 74 | add_dependencies(${PROJECT_NAME} 75 | ${catkin_EXPORTED_TARGETS} 76 | ) 77 | 78 | ## Specify libraries to link executable targets against 79 | target_link_libraries(${PROJECT_NAME}_core 80 | ${catkin_LIBRARIES} 81 | ) 82 | 83 | target_link_libraries(${PROJECT_NAME} 84 | ${PROJECT_NAME}_core 85 | ${catkin_LIBRARIES} 86 | ) 87 | 88 | ############# 89 | ## Install ## 90 | ############# 91 | 92 | # Mark executables and/or libraries for installation 93 | install( 94 | TARGETS ${PROJECT_NAME} 95 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 96 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 97 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 98 | ) 99 | 100 | # Mark cpp header files for installation 101 | install( 102 | DIRECTORY include/PACKAGE_HEADERS/ 103 | DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 104 | FILES_MATCHING PATTERN "*.hpp" 105 | ) 106 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/config/default.yaml: -------------------------------------------------------------------------------- 1 | subscriber_topic: /some_topic 2 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/include/PACKAGE_HEADERS/algorithm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace node_class_interface { 4 | 5 | /*! 6 | * Class containing the algorithmic part of the package. 7 | */ 8 | class Algorithm 9 | { 10 | public: 11 | /*! 12 | * Constructor. 13 | */ 14 | Algorithm(); 15 | 16 | /*! 17 | * Destructor. 18 | */ 19 | virtual ~Algorithm(); 20 | 21 | /*! 22 | * Add new measurement data. 23 | * @param data the new data. 24 | */ 25 | void addData(const double data); 26 | 27 | /*! 28 | * Get the computed average of the data. 29 | * @return the average of the data. 30 | */ 31 | double getAverage() const; 32 | 33 | private: 34 | 35 | //! Internal variable to hold the current average. 36 | double average_; 37 | 38 | //! Number of measurements taken. 39 | unsigned int nMeasurements_; 40 | }; 41 | 42 | } /* namespace */ 43 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/include/PACKAGE_HEADERS/nodeClassInterface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PACKAGE_HEADERS/algorithm.hpp" 4 | 5 | // ROS 6 | #include 7 | #include 8 | #include 9 | 10 | namespace node_class_interface { 11 | 12 | /*! 13 | * Main class for the node to handle the ROS interfacing. 14 | */ 15 | class RosNodeTemplate 16 | { 17 | public: 18 | /*! 19 | * Constructor. 20 | * @param nodeHandle the ROS node handle. 21 | */ 22 | RosNodeTemplate(ros::NodeHandle& nodeHandle); 23 | 24 | /*! 25 | * Destructor. 26 | */ 27 | virtual ~RosNodeTemplate(); 28 | 29 | private: 30 | /*! 31 | * Reads and verifies the ROS parameters. 32 | * @return true if successful. 33 | */ 34 | bool readParameters(); 35 | 36 | /*! 37 | * ROS topic callback method. 38 | * @param message the received message. 39 | */ 40 | void topicCallback(const std_msgs::Int32& message); 41 | 42 | /*! 43 | * ROS service server callback. 44 | * @param request the request of the service. 45 | * @param response the provided response. 46 | * @return true if successful, false otherwise. 47 | */ 48 | bool serviceCallback(std_srvs::Trigger::Request& request, 49 | std_srvs::Trigger::Response& response); 50 | 51 | //! ROS node handle. 52 | ros::NodeHandle& nodeHandle_; 53 | 54 | //! ROS topic subscriber. 55 | ros::Subscriber subscriber_; 56 | 57 | //! ROS topic name to subscribe to. 58 | std::string subscriberTopic_; 59 | 60 | //! ROS service server. 61 | ros::ServiceServer serviceServer_; 62 | 63 | //! Algorithm computation object. 64 | Algorithm algorithm_; 65 | }; 66 | 67 | } /* namespace */ 68 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/launch/launch_Node.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | modular_pub_sub 4 | 0.0.0 5 | A minimal roscpp modular pub-sub package! 6 | (Heavily based off of https://github.com/ethz-asl/ros_best_practices) 7 | 8 | methylDragon 9 | methylDragon 10 | http://github.com/methylDragon 11 | 12 | MIT 13 | 14 | catkin 15 | 16 | roscpp 17 | std_msgs 18 | std_srvs 19 | 20 | roscpp 21 | std_msgs 22 | std_srvs 23 | 24 | roscpp 25 | std_msgs 26 | std_srvs 27 | 28 | 29 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/src/Node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PACKAGE_HEADERS/nodeClassInterface.hpp" 3 | 4 | int main(int argc, char** argv) 5 | { 6 | ros::init(argc, argv, "Node"); 7 | ros::NodeHandle nodeHandle("~"); 8 | 9 | // Construct the node 10 | // (assigning to variable Node_object, but you can call it anything you want) 11 | node_class_interface::RosNodeTemplate Node_object(nodeHandle); 12 | 13 | // Run it 14 | ros::spin(); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include "PACKAGE_HEADERS/algorithm.hpp" 2 | 3 | namespace node_class_interface { 4 | 5 | // Here's the implementation 6 | // The private variables are listed in the header file (.hpp) 7 | Algorithm::Algorithm() 8 | : average_(0.0), 9 | nMeasurements_(0) 10 | { 11 | } 12 | 13 | Algorithm::~Algorithm() 14 | { 15 | } 16 | 17 | // When data is added, recalculate the average 18 | void Algorithm::addData(const double data) 19 | { 20 | average_ = (nMeasurements_ * average_ + data) / (nMeasurements_ + 1); 21 | nMeasurements_++; 22 | } 23 | 24 | // Getter method 25 | double Algorithm::getAverage() const 26 | { 27 | return average_; 28 | } 29 | 30 | } /* namespace */ 31 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/modular_pub_sub/src/nodeClassInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "PACKAGE_HEADERS/nodeClassInterface.hpp" 2 | 3 | // STD 4 | #include 5 | 6 | namespace node_class_interface { 7 | 8 | RosNodeTemplate::RosNodeTemplate(ros::NodeHandle& nodeHandle) 9 | : nodeHandle_(nodeHandle) 10 | { 11 | if (!readParameters()) { 12 | ROS_ERROR("Could not read parameters."); 13 | ros::requestShutdown(); 14 | } 15 | subscriber_ = nodeHandle_.subscribe(subscriberTopic_, 1, 16 | &RosNodeTemplate::topicCallback, this); 17 | serviceServer_ = nodeHandle_.advertiseService("get_average", 18 | &RosNodeTemplate::serviceCallback, this); 19 | ROS_INFO("Successfully launched node."); 20 | } 21 | 22 | RosNodeTemplate::~RosNodeTemplate() 23 | { 24 | } 25 | 26 | bool RosNodeTemplate::readParameters() 27 | { 28 | if (!nodeHandle_.getParam("subscriber_topic", subscriberTopic_)) return false; 29 | return true; 30 | } 31 | 32 | void RosNodeTemplate::topicCallback(const std_msgs::Int32& message) 33 | { 34 | algorithm_.addData(message.data); 35 | } 36 | 37 | bool RosNodeTemplate::serviceCallback(std_srvs::Trigger::Request& request, 38 | std_srvs::Trigger::Response& response) 39 | { 40 | response.success = true; 41 | response.message = "The average is " + std::to_string(algorithm_.getAverage()); 42 | return true; 43 | } 44 | 45 | } /* namespace */ 46 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(msg_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | msg_example_msgs 7 | message_generation 8 | ) 9 | 10 | catkin_package( 11 | INCLUDE_DIRS src 12 | CATKIN_DEPENDS roscpp msg_example_msgs 13 | ) 14 | 15 | include_directories( 16 | ${catkin_INCLUDE_DIRS} 17 | ) 18 | 19 | add_executable(msg_example src/msg_example) 20 | target_link_libraries(msg_example ${catkin_LIBRARIES}) 21 | add_dependencies(msg_example msg_example_msgs_generate_messages_cpp) 22 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | msg_example 4 | 0.0.0 5 | An example basic roscpp publisher package that utilises custom messages! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | msg_example_msgs 17 | 18 | roscpp 19 | msg_example_msgs 20 | 21 | roscpp 22 | msg_example_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example/src/msg_example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | msg_example_msgs::My_msg msg; 5 | 6 | int main(int argc, char **argv) 7 | { 8 | ros::init(argc, argv, "msg_example_node"); 9 | ros::NodeHandle nh; 10 | 11 | ros::Publisher chatter_publisher = nh.advertise("msg_example", 1); 12 | 13 | ros::Rate loopRate(10); 14 | 15 | unsigned int count = 0; 16 | 17 | while (ros::ok()) 18 | { 19 | msg_example_msgs::My_msg msg; // Make a new message object 20 | msg.header.stamp = ros::Time::now(); 21 | 22 | msg.name = "methylDragon"; 23 | msg.dragon_rating = 10; 24 | 25 | ROS_INFO_STREAM(" . .\n" 26 | " . |\\-^-/| .\n" 27 | "FIND MY OUTPUT ON /msg_example ! /| } O.=.O { |\\ \n"); 28 | 29 | chatter_publisher.publish(msg); 30 | 31 | ros::spinOnce(); 32 | loopRate.sleep(); 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(msg_example_msgs) 3 | 4 | # Standard dependencies 5 | find_package(catkin REQUIRED COMPONENTS 6 | message_generation 7 | roscpp 8 | rospy 9 | std_msgs 10 | ) 11 | 12 | # Your message files! 13 | add_message_files( 14 | FILES 15 | My_msg.msg # <-- Like this one! 16 | ) 17 | 18 | # You need to include this in as well 19 | # Call it BEFORE catkin_package 20 | generate_messages( 21 | DEPENDENCIES 22 | std_msgs # You might have additional message files from other packages 23 | ) 24 | 25 | # Additional catkin dependencies 26 | catkin_package(CATKIN_DEPENDS 27 | message_runtime 28 | ) 29 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example_msgs/msg/My_msg.msg: -------------------------------------------------------------------------------- 1 | Header header 2 | string name 3 | uint8 dragon_rating 4 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/msg_example_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | msg_example_msgs 6 | 0.0.0 7 | An example basic msg package 8 | 9 | methylDragon 10 | methylDragon 11 | http://github.com/methylDragon 12 | 13 | MIT 14 | 15 | catkin 16 | message_generation 17 | 18 | roscpp 19 | rospy 20 | std_msgs 21 | 22 | roscpp 23 | rospy 24 | std_msgs 25 | 26 | roscpp 27 | rospy 28 | std_msgs 29 | message_runtime 30 | 31 | 32 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/param_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(param_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | ) 7 | 8 | catkin_package( 9 | INCLUDE_DIRS src 10 | CATKIN_DEPENDS roscpp 11 | DEPENDS system_lib 12 | ) 13 | 14 | include_directories( 15 | ${catkin_INCLUDE_DIRS} 16 | ) 17 | 18 | add_executable(param_example src/param_example.cpp) 19 | target_link_libraries(param_example ${catkin_LIBRARIES}) 20 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/param_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | param_example 4 | 0.0.0 5 | An example basic roscpp package that demonstrates parameters! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | roscpp 17 | roscpp 18 | 19 | 20 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/param_example/src/param_example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | ros::init(argc, argv, "param_info_node"); 6 | ros::NodeHandle nh; 7 | 8 | nh.setParam("/info_param", "methylDragon"); 9 | 10 | ros::Rate loopRate(10); 11 | 12 | while (ros::ok()) 13 | { 14 | std::string info; 15 | 16 | nh.getParam("/info_param", info); 17 | 18 | ROS_INFO_STREAM("info_param value: " + info); 19 | ROS_INFO_STREAM("To test it out some more, use: rosparam set /info_param \n"); 20 | 21 | loopRate.sleep(); 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(pub_sub_nodelet_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | std_msgs 7 | nodelet 8 | ) 9 | 10 | catkin_package( 11 | INCLUDE_DIRS src 12 | CATKIN_DEPENDS roscpp std_msgs nodelet 13 | DEPENDS system_lib 14 | ) 15 | 16 | include_directories( 17 | include 18 | ${catkin_INCLUDE_DIRS} 19 | ) 20 | 21 | add_library(${PROJECT_NAME} src/PubSubNodelet.cpp) 22 | target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES}) 23 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/include/pub_sub_nodelet_example/PubSubNodelet.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace pub_sub_nodelet_example 6 | { 7 | class PubSubNodelet : public nodelet::Nodelet 8 | { 9 | protected: 10 | ros::NodeHandle nh; 11 | 12 | ros::Publisher pub; 13 | ros::Subscriber sub; 14 | 15 | std_msgs::String message; 16 | unsigned int count = 0; 17 | 18 | public: 19 | virtual void onInit(); 20 | void msgCB(const std_msgs::StringConstPtr& msg); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/launch/nodelet.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/nodelet_plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Example nodelet that features publisher and subscriber capabilities. 4 | 5 | 6 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | pub_sub_nodelet_example 4 | 0.0.0 5 | A minimal roscpp basic pub-sub package, implemented as a nodelet! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | std_msgs 17 | 18 | roscpp 19 | std_msgs 20 | 21 | roscpp 22 | std_msgs 23 | 24 | nodelet 25 | nodelet 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/pub_sub_nodelet_example/src/PubSubNodelet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pub_sub_nodelet_example/PubSubNodelet.h" 3 | 4 | ros::Rate r = ros::Rate(25); 5 | 6 | namespace pub_sub_nodelet_example 7 | { 8 | void PubSubNodelet::onInit() 9 | { 10 | // Init nodehandle 11 | nh = getNodeHandle(); 12 | 13 | // Bind subscription topic 14 | sub = nh.subscribe("chatter", 1, &PubSubNodelet::msgCB, this); 15 | pub = nh.advertise("chatter", 1); 16 | 17 | NODELET_INFO("NODELET READY!"); 18 | 19 | while (ros::ok()) 20 | { 21 | std::ostringstream string_count; 22 | string_count << count; 23 | message.data = "Rawr " + string_count.str(); 24 | 25 | pub.publish(message); 26 | ros::spinOnce(); 27 | r.sleep(); 28 | 29 | count++; 30 | } 31 | } 32 | 33 | void PubSubNodelet::msgCB(const std_msgs::StringConstPtr& msg) 34 | { 35 | NODELET_INFO_STREAM(msg->data); 36 | } 37 | } 38 | 39 | // Export the nodelet as a plugin 40 | PLUGINLIB_EXPORT_CLASS(pub_sub_nodelet_example::PubSubNodelet, nodelet::Nodelet) 41 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/simple_action_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(simple_action_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | actionlib 7 | actionlib_msgs 8 | ) 9 | 10 | find_package(Boost REQUIRED COMPONENTS system) 11 | 12 | add_action_files( 13 | DIRECTORY action 14 | FILES Fibonacci.action 15 | ) 16 | 17 | generate_messages( 18 | DEPENDENCIES 19 | actionlib_msgs 20 | std_msgs 21 | ) 22 | 23 | catkin_package( 24 | INCLUDE_DIRS src 25 | CATKIN_DEPENDS roscpp actionlib_msgs 26 | ) 27 | 28 | include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) 29 | 30 | # Link the nodes 31 | add_executable(fibonacci_server src/fibonacci_server.cpp) 32 | 33 | target_link_libraries( 34 | fibonacci_server 35 | ${catkin_LIBRARIES} 36 | ) 37 | 38 | add_dependencies( 39 | fibonacci_server 40 | # The one below is the name of your package!! 41 | ${simple_action_example_EXPORTED_TARGETS} 42 | ) 43 | add_executable(fibonacci_client src/fibonacci_client.cpp) 44 | 45 | target_link_libraries( 46 | fibonacci_client 47 | ${catkin_LIBRARIES} 48 | ) 49 | 50 | add_dependencies( 51 | fibonacci_client 52 | # The one below is the name of your package!! 53 | ${simple_action_example_EXPORTED_TARGETS} 54 | ) 55 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/simple_action_example/action/Fibonacci.action: -------------------------------------------------------------------------------- 1 | #goal definition 2 | int32 order 3 | --- 4 | #result definition 5 | int32[] sequence 6 | --- 7 | #feedback 8 | int32[] sequence 9 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/simple_action_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | simple_action_example 4 | 0.0.0 5 | An example basic roscpp package that implements ROS actions! Main source is http://wiki.ros.org/actionlib_tutorials/Tutorials 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | roscpp 16 | message_generation 17 | actionlib_msgs 18 | 19 | roscpp 20 | 21 | roscpp 22 | message_runtime 23 | actionlib_msgs 24 | 25 | 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/simple_action_example/src/fibonacci_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main (int argc, char **argv) 7 | { 8 | // Init ROS node called test_fibonacci 9 | ros::init(argc, argv, "test_fibonacci"); 10 | 11 | // create the action client 12 | // true causes the client to spin its own thread 13 | actionlib::SimpleActionClient ac("fibonacci", true); 14 | 15 | ROS_INFO("Waiting for action server to start."); 16 | // wait for the action server to start 17 | ac.waitForServer(); //will wait for infinite time 18 | 19 | ROS_INFO("Action server started, sending goal."); 20 | // send a goal to the action 21 | simple_action_example::FibonacciGoal goal; 22 | goal.order = 20; 23 | ac.sendGoal(goal); 24 | 25 | //wait for the action to return 26 | bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0)); 27 | 28 | if (finished_before_timeout) 29 | { 30 | actionlib::SimpleClientGoalState state = ac.getState(); 31 | ROS_INFO("Action finished: %s",state.toString().c_str()); 32 | } 33 | else 34 | ROS_INFO("Action did not finish before the time out."); 35 | 36 | //exit 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/simple_action_example/src/fibonacci_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class FibonacciAction 6 | { 7 | protected: 8 | 9 | ros::NodeHandle nh_; 10 | 11 | // NodeHandle instance must be created before this line. Otherwise strange error occurs. 12 | actionlib::SimpleActionServer as_; 13 | std::string action_name_; 14 | 15 | // create messages that are used to published feedback/result 16 | simple_action_example::FibonacciFeedback feedback_; 17 | simple_action_example::FibonacciResult result_; 18 | 19 | public: 20 | 21 | // Our constructor (with a cool initialisation list!) 22 | // https://stackoverflow.com/questions/2785612/c-what-does-the-colon-after-a-constructor-mean 23 | FibonacciAction(std::string name) : 24 | // Bind the callback to the action server. False is for thread spinning 25 | as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false), 26 | action_name_(name) 27 | { 28 | // Start the action server 29 | as_.start(); 30 | 31 | ROS_INFO("Fibonacci action server started!"); 32 | } 33 | 34 | // Destructor 35 | ~FibonacciAction(void) 36 | { 37 | } 38 | 39 | // Execute action callback (passing the goal via reference) 40 | void executeCB(const simple_action_example::FibonacciGoalConstPtr &goal) 41 | { 42 | // helper variables 43 | ros::Rate r(1); 44 | bool success = true; 45 | 46 | // push_back the seeds for the fibonacci sequence 47 | feedback_.sequence.clear(); 48 | feedback_.sequence.push_back(0); 49 | feedback_.sequence.push_back(1); 50 | 51 | // publish info to the console for the user 52 | ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]); 53 | 54 | // start executing the action (i <= goal->order, as goal is a pointer) 55 | for(int i=1; i<=goal->order; i++) 56 | { 57 | // check that preempt has not been requested by the client 58 | if (as_.isPreemptRequested() || !ros::ok()) 59 | { 60 | ROS_INFO("%s: Preempted", action_name_.c_str()); 61 | // set the action state to preempted 62 | as_.setPreempted(); 63 | success = false; 64 | break; 65 | } 66 | 67 | // Add the number to the feedback to be fed back 68 | feedback_.sequence.push_back(feedback_.sequence[i] + feedback_.sequence[i-1]); 69 | // publish the feedback 70 | as_.publishFeedback(feedback_); 71 | // this sleep is not necessary, the sequence is computed at 1 Hz for demonstration purposes 72 | r.sleep(); 73 | } 74 | 75 | if(success) 76 | { 77 | result_.sequence = feedback_.sequence; 78 | ROS_INFO("%s: Succeeded", action_name_.c_str()); 79 | // set the action state to succeeded 80 | as_.setSucceeded(result_); 81 | } 82 | } 83 | }; 84 | 85 | 86 | int main(int argc, char** argv) 87 | { 88 | ros::init(argc, argv, "fibonacci"); 89 | 90 | // Create an action server object and spin ROS 91 | FibonacciAction fibonacci("fibonacci"); 92 | ros::spin(); 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/srv_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(srv_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | message_generation 7 | std_msgs 8 | ) 9 | 10 | add_service_files( 11 | FILES 12 | AddTwoInts.srv # <-- Add your srv files 13 | ) 14 | 15 | generate_messages( 16 | DEPENDENCIES 17 | std_msgs 18 | ) 19 | 20 | catkin_package( 21 | INCLUDE_DIRS src 22 | CATKIN_DEPENDS roscpp std_msgs message_runtime # <-- Add this 23 | DEPENDS system_lib 24 | ) 25 | 26 | include_directories( 27 | ${catkin_INCLUDE_DIRS} 28 | ) 29 | 30 | add_executable(srv_example_server src/srv_example_server) 31 | add_dependencies( 32 | srv_example_server 33 | ${catkin_EXPORTED_TARGETS} 34 | ${srv_example_EXPORTED_TARGETS} 35 | ) 36 | 37 | target_link_libraries(srv_example_server ${catkin_LIBRARIES}) 38 | 39 | add_executable(srv_example_client src/srv_example_client) 40 | add_dependencies( 41 | srv_example_client 42 | ${catkin_EXPORTED_TARGETS} 43 | ${srv_example_EXPORTED_TARGETS} 44 | ) 45 | 46 | 47 | target_link_libraries(srv_example_client ${catkin_LIBRARIES}) 48 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/srv_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | srv_example 6 | 0.0.0 7 | An example basic roscpp package that demonstrates services! 8 | 9 | methylDragon 10 | methylDragon 11 | http://github.com/methylDragon 12 | 13 | MIT 14 | 15 | catkin 16 | message_generation 17 | 18 | roscpp 19 | std_msgs 20 | 21 | roscpp 22 | std_msgs 23 | 24 | roscpp 25 | std_msgs 26 | message_runtime 27 | 28 | 29 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/srv_example/src/srv_example_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | ros::init(argc, argv, "add_two_ints_client"); 8 | 9 | if (argc != 3) 10 | { 11 | ROS_INFO("Usage: %s [x y]", argv[0]); 12 | return 1; 13 | } 14 | 15 | ros::NodeHandle nh; 16 | ros::ServiceClient client = nh.serviceClient("add_two_ints"); 17 | 18 | srv_example::AddTwoInts service; 19 | service.request.A = atoi(argv[1]); 20 | service.request.B = atoi(argv[2]); 21 | 22 | // Service callback function 23 | // client.call(service) calls the client! 24 | if (client.call(service)) 25 | { 26 | ROS_INFO("Sum: %ld", (long int)service.response.Sum); 27 | } 28 | else 29 | { 30 | ROS_ERROR("Failed to call service add_two_ints"); 31 | return 1; 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/srv_example/src/srv_example_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Callback function 5 | bool add(srv_example::AddTwoInts::Request &request, 6 | srv_example::AddTwoInts::Response &response) 7 | { 8 | response.Sum = request.A + request.B; 9 | 10 | ROS_INFO("request: x=%ld, y=%ld", (long int)request.A, (long int)request.B); 11 | 12 | ROS_INFO(" sending back response: [%ld]", (long int)response.Sum); 13 | 14 | return true; 15 | } 16 | 17 | int main(int argc, char **argv) 18 | { 19 | // Start the node 20 | ros::init(argc, argv, "add_two_ints_server"); 21 | ros::NodeHandle nh; 22 | 23 | // Advertise the service 24 | ros::ServiceServer service = nh.advertiseService("add_two_ints", add); 25 | 26 | ROS_INFO("Ready to add two ints."); 27 | 28 | // Spin up 29 | ros::spin(); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/roscpp_minimal_packages/srv_example/srv/AddTwoInts.srv: -------------------------------------------------------------------------------- 1 | int64 A 2 | int64 B 3 | --- 4 | int64 Sum 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # toplevel CMakeLists.txt for a catkin workspace 2 | # catkin/cmake/toplevel.cmake 3 | 4 | cmake_minimum_required(VERSION 2.8.3) 5 | 6 | set(CATKIN_TOPLEVEL TRUE) 7 | 8 | # search for catkin within the workspace 9 | set(_cmd "catkin_find_pkg" "catkin" "${CMAKE_SOURCE_DIR}") 10 | execute_process(COMMAND ${_cmd} 11 | RESULT_VARIABLE _res 12 | OUTPUT_VARIABLE _out 13 | ERROR_VARIABLE _err 14 | OUTPUT_STRIP_TRAILING_WHITESPACE 15 | ERROR_STRIP_TRAILING_WHITESPACE 16 | ) 17 | if(NOT _res EQUAL 0 AND NOT _res EQUAL 2) 18 | # searching fot catkin resulted in an error 19 | string(REPLACE ";" " " _cmd_str "${_cmd}") 20 | message(FATAL_ERROR "Search for 'catkin' in workspace failed (${_cmd_str}): ${_err}") 21 | endif() 22 | 23 | # include catkin from workspace or via find_package() 24 | if(_res EQUAL 0) 25 | set(catkin_EXTRAS_DIR "${CMAKE_SOURCE_DIR}/${_out}/cmake") 26 | # include all.cmake without add_subdirectory to let it operate in same scope 27 | include(${catkin_EXTRAS_DIR}/all.cmake NO_POLICY_SCOPE) 28 | add_subdirectory("${_out}") 29 | 30 | else() 31 | # use either CMAKE_PREFIX_PATH explicitly passed to CMake as a command line argument 32 | # or CMAKE_PREFIX_PATH from the environment 33 | if(NOT DEFINED CMAKE_PREFIX_PATH) 34 | if(NOT "$ENV{CMAKE_PREFIX_PATH}" STREQUAL "") 35 | string(REPLACE ":" ";" CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH}) 36 | endif() 37 | endif() 38 | 39 | # list of catkin workspaces 40 | set(catkin_search_path "") 41 | foreach(path ${CMAKE_PREFIX_PATH}) 42 | if(EXISTS "${path}/.catkin") 43 | list(FIND catkin_search_path ${path} _index) 44 | if(_index EQUAL -1) 45 | list(APPEND catkin_search_path ${path}) 46 | endif() 47 | endif() 48 | endforeach() 49 | 50 | # search for catkin in all workspaces 51 | set(CATKIN_TOPLEVEL_FIND_PACKAGE TRUE) 52 | find_package(catkin QUIET 53 | NO_POLICY_SCOPE 54 | PATHS ${catkin_search_path} 55 | NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) 56 | unset(CATKIN_TOPLEVEL_FIND_PACKAGE) 57 | 58 | if(NOT catkin_FOUND) 59 | message(FATAL_ERROR "find_package(catkin) failed. catkin was neither found in the workspace nor in the CMAKE_PREFIX_PATH. One reason may be that no ROS setup.sh was sourced before.") 60 | endif() 61 | endif() 62 | 63 | catkin_workspace() 64 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/Reminder.txt: -------------------------------------------------------------------------------- 1 | Don't forget to enable execution of your Python scripts! 2 | 3 | 4 | $ chmod +x 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(basic_pub_sub) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | std_msgs 7 | ) 8 | 9 | catkin_package() 10 | catkin_python_setup() 11 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/launch/basic_pub_sub_init.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | basic_pub_sub 4 | 0.0.0 5 | A minimal rospy basic pub-sub package! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | std_msgs 17 | 18 | rospy 19 | std_msgs 20 | 21 | rospy 22 | std_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['basic_pub_sub'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/src/basic_pub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | 6 | def talker(): 7 | # Create a publisher object 8 | # It publishes String messages to the topic 'chatter' 9 | pub = rospy.Publisher('chatter', String, queue_size = 10) 10 | 11 | rospy.init_node('talker', anonymous = True) 12 | rate = rospy.Rate(10) # 10hz 13 | 14 | # Create message object 15 | string_msg = String() 16 | 17 | while not rospy.is_shutdown(): 18 | hello_str = "hello world %s" % rospy.get_time() 19 | rospy.loginfo(hello_str) 20 | 21 | # Attach data to message field 22 | string_msg.data = hello_str 23 | 24 | # Publish 25 | pub.publish(string_msg) 26 | rate.sleep() 27 | 28 | if __name__ == '__main__': 29 | try: 30 | talker() 31 | except rospy.ROSInterruptException: 32 | pass 33 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/src/basic_sub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | 6 | def callback(data): 7 | rospy.loginfo(rospy.get_caller_id() + " I heard %s", data.data) 8 | 9 | def listener(): 10 | rospy.init_node('listener', anonymous = True) 11 | 12 | # Callback function gets run each time a message is received 13 | rospy.Subscriber("chatter", String, callback) 14 | 15 | # spin() keeps Python from exiting until this node is stopped 16 | rospy.spin() 17 | 18 | if __name__ == '__main__': 19 | listener() 20 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/basic_pub_sub/src/hello_world: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # The above line is MANDATORY 3 | 4 | import rospy # Here's rospy! 5 | from std_msgs.msg import String # This is how we import message types 6 | 7 | def logger(): 8 | 9 | # Initialise the node, call it logger 10 | # Anonymous means the node gets created as talker_serialnumber 11 | # (That prevents namespace clashes) 12 | # If there's a clash, the existing node will be booted off and forced to shutdown 13 | rospy.init_node('logger', anonymous = True) 14 | 15 | rate = rospy.Rate(10) # 10hz 16 | 17 | # As long as the node is not shutdown, keep running this 18 | while not rospy.is_shutdown(): 19 | log_str = "HELLO WORLD" 20 | 21 | # ROS log is usually shown on the Terminal screen 22 | rospy.loginfo(log_str) 23 | rate.sleep() 24 | 25 | if __name__ == '__main__': 26 | try: 27 | logger() 28 | except rospy.ROSInterruptException: 29 | pass 30 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/class_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(class_pub_sub) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | std_msgs 7 | ) 8 | 9 | catkin_package() 10 | catkin_python_setup() 11 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/class_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | class_pub_sub 4 | 0.0.0 5 | A minimal rospy basic pub-sub package, implemented as a class! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | std_msgs 17 | 18 | rospy 19 | std_msgs 20 | 21 | rospy 22 | std_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/class_pub_sub/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['class_pub_sub'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/class_pub_sub/src/class_pub_sub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Author: methylDragon@gmail.com 3 | 4 | import rospy 5 | from std_msgs.msg import String 6 | 7 | class ClassPub(): 8 | def __init__(self): 9 | # Init ROS 10 | self.pub = rospy.Publisher("chatter", String, queue_size=10) 11 | self.sub = rospy.Subscriber("chatter", String, self.msg_cb, queue_size=1) 12 | self.rate = rospy.Rate(10) 13 | 14 | # Sleep to give time for publisher to bind 15 | rospy.sleep(1) 16 | 17 | # Create message object 18 | self.msg = String() 19 | 20 | while not rospy.is_shutdown(): 21 | hello_str = "Rawr! %s" % rospy.get_time() 22 | self.msg.data = hello_str 23 | 24 | self.pub.publish(self.msg) 25 | self.rate.sleep() 26 | 27 | def msg_cb(self, msg): 28 | rospy.loginfo(msg.data) 29 | 30 | if __name__ == '__main__': 31 | rospy.init_node('class_pub') 32 | class_pub = ClassPub() 33 | 34 | try: 35 | rospy.spin() 36 | except KeyboardInterrupt: 37 | print("SHUTTING DOWN CLASS PUBLISHER") 38 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(dynamic_reconfigure_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | std_msgs 7 | dynamic_reconfigure 8 | ) 9 | 10 | catkin_python_setup() 11 | 12 | generate_dynamic_reconfigure_options( 13 | cfg/Example.cfg 14 | ) 15 | 16 | catkin_package() 17 | 18 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/cfg/Example.cfg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | PACKAGE = "dynamic_reconfigure_example" 3 | 4 | from dynamic_reconfigure.parameter_generator_catkin import * 5 | 6 | gen = ParameterGenerator() 7 | 8 | # Add parameters 9 | gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100) 10 | gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1) 11 | gen.add("str_param", str_t, 0, "A string parameter", "Hello World") 12 | gen.add("bool_param", bool_t, 0, "A Boolean parameter", True) 13 | 14 | # Create an enum mapping (Small is 0, Medium is 1, ...) 15 | size_enum = gen.enum([gen.const("Small", int_t, 0, "A small constant"), 16 | gen.const("Medium", int_t, 1, "A medium constant"), 17 | gen.const("Large", int_t, 2, "A large constant"), 18 | gen.const("ExtraLarge", int_t, 3, "An extra large constant")], 19 | "An enum to set size") 20 | 21 | # Add enum parameter 22 | gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum) 23 | 24 | exit(gen.generate(PACKAGE, "dynamic_reconfigure_example", "Example")) 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | dynamic_reconfigure_example 4 | 0.0.0 5 | A minimal rospy dynamically reconfigurable package! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | std_msgs 17 | dynamic_reconfigure 18 | 19 | rospy 20 | std_msgs 21 | 22 | rospy 23 | std_msgs 24 | dynamic_reconfigure 25 | 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['dynamic_reconfigure_example'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/src/dynamic_reconfigure_client: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | import dynamic_reconfigure.client 5 | 6 | # Optional callback for the config returned by the server 7 | def callback(config): 8 | rospy.loginfo("Config set to {int_param}, {double_param}, {str_param}, {bool_param}, {size}".format(**config)) 9 | 10 | if __name__ == "__main__": 11 | rospy.init_node("dynamic_reconfigure_client") 12 | 13 | # We target the server with the first argument 14 | client = dynamic_reconfigure.client.Client("dynamic_reconfigure_example", timeout=30, config_callback=callback) 15 | 16 | r = rospy.Rate(0.5) 17 | x = 0 18 | b = False 19 | while not rospy.is_shutdown(): 20 | x = x + 1 21 | if x > 10: 22 | x = 0 23 | b = not b 24 | client.update_configuration({"int_param": x, 25 | "double_param": (1 / (x + 1)), 26 | "str_param": str(rospy.get_rostime()), 27 | "bool_param": b, 28 | "size": 1}) 29 | r.sleep() 30 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/dynamic_configure_example/src/dynamic_reconfigure_example: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | 5 | from dynamic_reconfigure.server import Server 6 | from dynamic_reconfigure_example.cfg import ExampleConfig 7 | 8 | # Create reconfigure callback 9 | def callback(config, level): 10 | rospy.loginfo("""Reconfigure Request: {int_param}, {double_param},\ 11 | {str_param}, {bool_param}, {size}""".format(**config)) 12 | 13 | # Config is returned by the server 14 | return config 15 | 16 | if __name__ == "__main__": 17 | rospy.init_node("dynamic_reconfigure_example", anonymous = False) 18 | 19 | # Bind callback 20 | srv = Server(ExampleConfig, callback) 21 | rospy.spin() 22 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(modular_pub_sub) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | std_msgs 7 | ) 8 | 9 | catkin_package() 10 | catkin_python_setup() 11 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/config/default.yaml: -------------------------------------------------------------------------------- 1 | subscriber_topic: /some_topic 2 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/launch/launch_Node.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/launch/modular_pub_sub_init.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/nodes/modular_pub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from modular_pub_sub import pub_main 4 | 5 | if __name__ == '__main__': 6 | pub_main() 7 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/nodes/modular_sub: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from modular_pub_sub import sub_main 4 | 5 | if __name__ == '__main__': 6 | sub_main() 7 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | modular_pub_sub 4 | 0.0.0 5 | A minimal modular rospy basic pub-sub package! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | std_msgs 17 | 18 | rospy 19 | std_msgs 20 | 21 | rospy 22 | std_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['modular_pub_sub'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/src/modular_pub_sub/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from pub_source import pub_main 4 | from sub_source import sub_main 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/src/modular_pub_sub/pub_source.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | from rawr_package import rawr 6 | 7 | def talker(): 8 | # Create a publisher object 9 | # It publishes String messages to the topic 'chatter' 10 | pub = rospy.Publisher('chatter', String, queue_size = 10) 11 | 12 | rospy.init_node('talker', anonymous = True) 13 | rate = rospy.Rate(10) # 10hz 14 | 15 | while not rospy.is_shutdown(): 16 | rawr_str = rawr() 17 | rospy.loginfo(rawr_str) 18 | 19 | pub.publish(rawr_str) 20 | rate.sleep() 21 | 22 | def pub_main(): 23 | try: 24 | talker() 25 | except rospy.ROSInterruptException: 26 | pass 27 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/src/modular_pub_sub/rawr_package/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from rawr_source import rawr 4 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/src/modular_pub_sub/rawr_package/rawr_source.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def rawr(): 4 | return "Rawr" 5 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/modular_pub_sub/src/modular_pub_sub/sub_source.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | from std_msgs.msg import String 5 | 6 | def callback(data): 7 | rospy.loginfo(rospy.get_caller_id() + " I heard %s", data.data) 8 | 9 | def listener(): 10 | rospy.init_node('listener', anonymous = True) 11 | 12 | # Callback function gets run each time a message is received 13 | rospy.Subscriber("chatter", String, callback) 14 | 15 | # spin() keeps Python from exiting until this node is stopped 16 | rospy.spin() 17 | 18 | def sub_main(): 19 | listener() 20 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(msg_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | msg_example_msgs 7 | ) 8 | 9 | catkin_package() 10 | catkin_python_setup() 11 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | msg_example 4 | 0.0.0 5 | An example basic rospy publisher package that utilises custom messages! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | msg_example_msgs 17 | 18 | rospy 19 | msg_example_msgs 20 | 21 | rospy 22 | msg_example_msgs 23 | 24 | 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['msg_example'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example/src/msg_example: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import rospy 5 | from msg_example_msgs.msg import My_msg 6 | 7 | # Create the message object to publish 8 | msg = My_msg() 9 | 10 | # Then to use it~ 11 | def talker(): 12 | # My_msg is the topic type (aka the message file the topic takes) 13 | pub = rospy.Publisher("msg_example", My_msg, queue_size = 10) 14 | 15 | rospy.init_node("msg_example_node", anonymous = True) 16 | rate = rospy.Rate(10) 17 | 18 | while not rospy.is_shutdown(): 19 | msg.header.stamp = rospy.Time.now() # Since our message has a header 20 | # The header sequence value will increase once a subscriber is connected 21 | 22 | msg.name = "methylDragon" 23 | msg.dragon_rating = 10 24 | 25 | rospy.loginfo("FIND MY OUTPUT ON /msg_example ! ヾ(°∇°*)") 26 | 27 | pub.publish(msg) 28 | rate.sleep() 29 | 30 | if __name__ == '__main__': 31 | try: 32 | talker() 33 | except rospy.ROSInterruptException: 34 | pass 35 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example_msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(msg_example_msgs) 3 | 4 | # Standard dependencies 5 | find_package(catkin REQUIRED COMPONENTS 6 | roscpp 7 | rospy 8 | std_msgs 9 | message_generation 10 | ) 11 | 12 | # Your message files! 13 | add_message_files( 14 | FILES 15 | My_msg.msg # <-- Like this one! 16 | ) 17 | 18 | # You need to include this in as well 19 | # Call it BEFORE catkin_package 20 | generate_messages( 21 | DEPENDENCIES 22 | std_msgs # You might have additional message files from other packages 23 | ) 24 | 25 | # Additional catkin dependencies 26 | catkin_package(CATKIN_DEPENDS 27 | message_runtime 28 | ) 29 | 30 | 31 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example_msgs/msg/My_msg.msg: -------------------------------------------------------------------------------- 1 | Header header 2 | string name 3 | uint8 dragon_rating 4 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/msg_example_msgs/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | msg_example_msgs 6 | 0.0.0 7 | An example basic msg package 8 | 9 | methylDragon 10 | methylDragon 11 | http://github.com/methylDragon 12 | 13 | MIT 14 | 15 | catkin 16 | message_generation 17 | 18 | roscpp 19 | rospy 20 | std_msgs 21 | 22 | roscpp 23 | rospy 24 | std_msgs 25 | 26 | roscpp 27 | rospy 28 | std_msgs 29 | message_runtime 30 | 31 | 32 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/param_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(param_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | std_msgs 7 | ) 8 | 9 | catkin_package() 10 | catkin_python_setup() 11 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/param_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | param_example 4 | 0.0.0 5 | An example basic rospy package that demonstrates parameters! 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | rospy 17 | rospy 18 | 19 | 20 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/param_example/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['param_example'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/param_example/src/param_example: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rospy 4 | 5 | def logger(): 6 | rospy.init_node('param_info_node', anonymous = True) 7 | rate = rospy.Rate(10) 8 | 9 | # Set a parameter value! 10 | rospy.set_param('/info_param', 'methylDragon') 11 | 12 | while not rospy.is_shutdown(): 13 | 14 | # ROS log is usually shown on the Terminal screen 15 | rospy.loginfo("info_param value: " + str(rospy.get_param('/info_param'))) 16 | rospy.loginfo("To test it out some more, use: rosparam set /info_param \n") 17 | rate.sleep() 18 | 19 | if __name__ == '__main__': 20 | try: 21 | logger() 22 | except rospy.ROSInterruptException: 23 | pass 24 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(simple_action_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | rospy 6 | actionlib 7 | actionlib_msgs 8 | ) 9 | 10 | catkin_python_setup() 11 | 12 | add_action_files( 13 | DIRECTORY action 14 | FILES Fibonacci.action 15 | ) 16 | 17 | generate_messages( 18 | DEPENDENCIES 19 | actionlib_msgs 20 | std_msgs 21 | ) 22 | 23 | catkin_package( 24 | CATKIN_DEPENDS actionlib_msgs 25 | ) 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/action/Fibonacci.action: -------------------------------------------------------------------------------- 1 | #goal definition 2 | int32 order 3 | --- 4 | #result definition 5 | int32[] sequence 6 | --- 7 | #feedback 8 | int32[] sequence 9 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | simple_action_example 4 | 0.0.0 5 | An example basic rospy package that implements ROS actions! Main source is http://wiki.ros.org/actionlib_tutorials/Tutorials 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | 11 | MIT 12 | 13 | catkin 14 | 15 | rospy 16 | message_generation 17 | actionlib_msgs 18 | 19 | rospy 20 | 21 | rospy 22 | message_runtime 23 | actionlib_msgs 24 | 25 | 26 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['simple_action_example'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/src/fibonacci_client: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | from __future__ import print_function # Lets you print like Python 3 4 | import rospy 5 | import actionlib 6 | import simple_action_example.msg 7 | 8 | def fibonacci_client(): 9 | # SimpleActionClient consruction, targeting the fibonacci topic of type Fibonacci 10 | client = actionlib.SimpleActionClient('fibonacci', 11 | simple_action_example.msg.FibonacciAction) 12 | 13 | # Waits until the action server has started up and started 14 | # listening for goals. (So the goals aren't ignored.) 15 | client.wait_for_server() 16 | 17 | # Creates a goal to send to the action server. 18 | goal = simple_action_example.msg.FibonacciGoal(order=20) 19 | 20 | # Sends the goal to the action server. 21 | client.send_goal(goal) 22 | 23 | # Waits for the server to finish performing the action. 24 | client.wait_for_result() 25 | 26 | # Prints out the result of executing the action 27 | return client.get_result() # A FibonacciResult 28 | 29 | if __name__ == '__main__': 30 | try: 31 | # Initializes a rospy node so that the SimpleActionClient can 32 | # publish and subscribe over ROS. 33 | rospy.init_node('fibonacci_client_py') 34 | result = fibonacci_client() 35 | 36 | print("Result:", ', '.join([str(n) for n in result.sequence])) 37 | except rospy.ROSInterruptException: 38 | print("program interrupted before completion", file=sys.stderr) 39 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/simple_action_example/src/fibonacci_server: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import rospy 4 | import actionlib 5 | import simple_action_example.msg 6 | 7 | # Create the action server as a class 8 | # The object is just in-case Python 2 is being used to interpret this 9 | # https://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python 10 | class FibonacciAction(object): 11 | # Create the Feedback and Result messages 12 | _feedback = simple_action_example.msg.FibonacciFeedback() 13 | _result = simple_action_example.msg.FibonacciResult() 14 | 15 | # Constructor 16 | def __init__(self, name): 17 | self._action_name = name 18 | 19 | # Hook callbacks 20 | self._as = actionlib.SimpleActionServer(self._action_name, 21 | simple_action_example.msg.FibonacciAction, 22 | execute_cb=self.execute_cb, 23 | auto_start = False) 24 | 25 | # Start the action server 26 | self._as.start() 27 | 28 | rospy.loginfo("Fibonacci action server started!") 29 | 30 | # Goal execution callback 31 | def execute_cb(self, goal): 32 | # helper variables 33 | r = rospy.Rate(1) 34 | success = True 35 | 36 | # append the seeds for the fibonacci sequence 37 | self._feedback.sequence = [] 38 | self._feedback.sequence.append(0) 39 | self._feedback.sequence.append(1) 40 | 41 | # Publish info 42 | rospy.loginfo('%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i' % (self._action_name, goal.order, self._feedback.sequence[0], self._feedback.sequence[1])) 43 | 44 | # Execute the action 45 | for i in range(1, goal.order): 46 | # Check that preempt has not been requested by the client 47 | # If yes, kill the action 48 | if self._as.is_preempt_requested(): 49 | rospy.loginfo('%s: Preempted' % self._action_name) 50 | self._as.set_preempted() 51 | success = False 52 | break 53 | 54 | self._feedback.sequence.append(self._feedback.sequence[i] + self._feedback.sequence[i-1]) 55 | 56 | # publish the feedback 57 | self._as.publish_feedback(self._feedback) 58 | 59 | # this step is not necessary, the sequence is computed at 1 Hz for demonstration purposes 60 | r.sleep() 61 | 62 | if success: 63 | self._result.sequence = self._feedback.sequence 64 | rospy.loginfo('%s: Succeeded' % self._action_name) 65 | self._as.set_succeeded(self._result) 66 | 67 | if __name__ == '__main__': 68 | rospy.init_node('fibonacci') 69 | server = FibonacciAction(rospy.get_name()) 70 | rospy.spin() 71 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(srv_example) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | message_generation 6 | rospy 7 | std_msgs 8 | ) 9 | 10 | catkin_python_setup() 11 | 12 | add_service_files( 13 | FILES 14 | AddTwoInts.srv # <-- Add your srv files 15 | ) 16 | 17 | generate_messages( 18 | DEPENDENCIES 19 | std_msgs 20 | ) 21 | 22 | catkin_package(CATKIN_DEPENDS 23 | message_runtime # <-- Add this 24 | ) 25 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | srv_example 6 | 0.0.0 7 | An example basic rospy package that demonstrates services! 8 | 9 | methylDragon 10 | methylDragon 11 | http://github.com/methylDragon 12 | 13 | MIT 14 | 15 | catkin 16 | message_generation 17 | 18 | rospy 19 | std_msgs 20 | 21 | rospy 22 | std_msgs 23 | 24 | rospy 25 | std_msgs 26 | message_runtime 27 | 28 | 29 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | from catkin_pkg.python_setup import generate_distutils_setup 5 | 6 | setup_args = generate_distutils_setup( 7 | packages = ['msg_example'], 8 | package_dir = {'': 'src'}, 9 | install_requires = [''] 10 | ) 11 | 12 | setup(**setup_args) 13 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/src/srv_example_client: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import rospy 5 | from srv_example.srv import * 6 | 7 | # Service call handler 8 | def add_two_ints_client(x, y): 9 | # Wait for service to become available 10 | rospy.wait_for_service('add_two_ints') 11 | 12 | try: 13 | # The service proxy handles the service call, like a temporary node! 14 | # add_two_ints is the service name 15 | # AddTwoInts is the service type/file 16 | add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts) 17 | resp1 = add_two_ints(x, y) 18 | return resp1.Sum 19 | 20 | except rospy.ServiceException, e: 21 | print("Service call failed: %s" % e) 22 | 23 | # Invalid call reminder 24 | def usage(): 25 | return "Usage: %s [x y]" % sys.argv[0] 26 | 27 | if __name__ == "__main__": 28 | 29 | # If the service call was properly formatted, proceed 30 | if len(sys.argv) == 3: 31 | x = int(sys.argv[1]) 32 | y = int(sys.argv[2]) 33 | 34 | # Else, remind the user of the proper usage 35 | else: 36 | print(usage()) 37 | sys.exit(1) # Terminate the script 38 | 39 | print("Requesting %s+%s" % (x, y)) 40 | print("%s + %s = %s" % (x, y, add_two_ints_client(x, y))) 41 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/src/srv_example_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from srv_example.srv import * 4 | import rospy 5 | 6 | # Here's your service callback function 7 | def handle_add_two_ints(req): 8 | print("Returning [%s + %s = %s]" % (req.A, req.B, (req.A + req.B))) 9 | return AddTwoIntsResponse(req.A + req.B) 10 | 11 | def add_two_ints_server(): 12 | rospy.init_node('add_two_ints_server') 13 | 14 | # Here's your service hook (AddTwoInts is the service type/file) 15 | s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints) 16 | print("Ready to add two ints.") 17 | rospy.spin() 18 | 19 | if __name__ == "__main__": 20 | add_two_ints_server() 21 | -------------------------------------------------------------------------------- /ROS/Starter Code and Resources/ROS_Minimal_Projects/rospy_minimal_packages/srv_example/srv/AddTwoInts.srv: -------------------------------------------------------------------------------- 1 | int64 A 2 | int64 B 3 | --- 4 | int64 Sum 5 | -------------------------------------------------------------------------------- /ROS/assets/1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/1.1.png -------------------------------------------------------------------------------- /ROS/assets/1.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/1.2.png -------------------------------------------------------------------------------- /ROS/assets/14599315912601528.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/14599315912601528.png -------------------------------------------------------------------------------- /ROS/assets/2.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/2.1.png -------------------------------------------------------------------------------- /ROS/assets/2.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/2.2.png -------------------------------------------------------------------------------- /ROS/assets/3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/3.1.png -------------------------------------------------------------------------------- /ROS/assets/3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/3.2.png -------------------------------------------------------------------------------- /ROS/assets/3.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/3.3.png -------------------------------------------------------------------------------- /ROS/assets/3.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/3.4.png -------------------------------------------------------------------------------- /ROS/assets/7580OS_09_16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/7580OS_09_16.jpg -------------------------------------------------------------------------------- /ROS/assets/8ros-lt-nodelet-4-638.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/8ros-lt-nodelet-4-638.jpg -------------------------------------------------------------------------------- /ROS/assets/Screenshot-Reconfigure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/ROS/assets/Screenshot-Reconfigure.png -------------------------------------------------------------------------------- /assets/1563793456590.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/assets/1563793456590.png -------------------------------------------------------------------------------- /assets/COFFEE BUTTON ヾ(°∇°^).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/assets/COFFEE BUTTON ヾ(°∇°^).png -------------------------------------------------------------------------------- /assets/CylinderSegmentationFast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/assets/CylinderSegmentationFast.gif -------------------------------------------------------------------------------- /assets/youtube_thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/ros-tutorials/3b501c15328a1fef3e8b8c0b43182427bf724a16/assets/youtube_thumbnail.png --------------------------------------------------------------------------------