12/18/24

Intro

https://articulatedrobotics.xyz/tutorials/ready-for-ros/packages/

Create a Package

  • Set up workspace
mkdir -p ~/training_ws/src
cd ~/training_ws

9/7/25

Create an empty Python package

ROS2 Python packages

my_package/
β”œβ”€β”€ package.xml    # File containing meta-information about the package
β”œβ”€β”€ resource/
β”‚   └── my_package # Marker file for the package.
β”œβ”€β”€ setup.cfg      # Required when a package has executables, so `ros2 run` can locate them.
β”œβ”€β”€ setup.py       # Contains instructions for how to install the package.
└── my_package/    # A directory with the same name as your package, used by ROS 2 tools to locate your package; it 
                   # contains `__init__.py`.

Create an empty CMake package

ROS2 CMake Packages

my_package/  
β”œβ”€β”€ CMakeLists.txt      # Describes how to build the code within the package  
β”œβ”€β”€ include/  
β”‚   └── my_package/     # Directory containing the public headers for the package  
β”œβ”€β”€ package.xml         # File containing meta-information about the package  
└── src/                # Directory containing the source code for the package  
  • Create an empty package using CMake
ros2 pkg create --build-type ament_cmake my_package
  • Open the workspace in VS Code
    • Since we’re using python-only code, we can delete the include and src folders which are used for C++ code
cd ..
code .

launch

  • Create a launch folder and add a talker.launch.py file
from launch import LaunchDescription
from launch_ros.actions import Node
 
def generate_launch_description():
    return LaunchDescription({
        Node(
            package='demo_nodes_cpp',
            executable='talker'
        )
    })
  • Add a listener.launch.py file
from launch import LaunchDescription
from launch_ros.actions import Node
 
def generate_launch_description():
    return LaunchDescription([
        Node(
            package='demo_nodes_py',
            executable='listener'
        )
    ])
  • This will launch the talker and listener nodes from the demo_nodes_cpp package:
demo_nodes_cpp/
β”œβ”€β”€ CMakeLists.txt
β”œβ”€β”€ package.xml
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ talker.cpp
β”‚   └── listener.cpp
└── launch/
    └── demo_nodes_cpp_launch.py

CMakeLists.txt

  • Update CMakeLists to tell colcon how to build the files
    • Add the following lines just before ament_package()
install(DIRECTORY launch
  DESTINATION share/${PROJECT_NAME}
)

package.xml

  • Update package.xml to include additional information for ROS and colcon to recognize and manage the package, including dependencies (e.g. the demo_nodes_cpp and demo_nodes_py packages)
    • We use <exec_depend> because these dependencies are needed for execution.
    • Alternatively, we could use <build_depend> if the dependencies are required only for building or <depend> for both building and executing.
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>my_package</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="email@gmail.com">Name</maintainer>
  <license>TODO: License declaration</license>
 
  <buildtool_depend>ament_cmake</buildtool_depend>
 
  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>
 
  <exec_depend>demo_nodes_cpp</exec_depend>
  <exec_depend>demo_nodes_py</exec_depend>
 
  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>
  • Additionally, it’s good practice to update other fields in the package.xml such as:
    • name: The name of the package.
    • email: The maintainer’s contact email.
    • description: A brief description of the package.
    • license: The license under which the package is distributed.

Build the Package

  • Build the package from the workspace directory
    • This option uses symlinks instead of copies, so you don’t need to rebuild when tweaking certain files
colcon build --symlink-install

Push the package to GitHub

  • Create a repository on GitHub
  • Initialize git (from inside your local my_package directory)
echo "# my_package" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:<github_username>/<repo_name>.git
git push -u origin main

Pull the package onto the Pi

  • Create a robot_ws workspace on the other machine (e.g. Raspberry Pi 4B) and cd into it
    • Make sure SSH authentication is set up
mkdir -p ~/robot_ws/src
cd ~/robot_ws
  • Clone the repo into the src folder
git clone git@github.com:<github_username>/<repo_name>.git
  • cd back into the root of the workspace for both machines and run
colcon build --symlink-install

Test the package

  • cd into the workspace directory and source the workspace (on both machines)
source install/setup.bash

Normally you would have separate terminals for building and running the package

  • Run the publisher node on the dev machine
ros2 launch my_package talker.launch.py
  • Run the publisher node on the pi
ros2 launch my_package listener.launch.py

picture 2