9) Packages
A package is the high-level container in ROS 2. All code that is to be run with ros2 run ... must be in a package.
2 Types of Packages
-
Python Packages: These use
setup.pyandpackage.xml. It uses standard python installation tools under the hood. -
C++ Packages: Uses
CMakeLists.txtandpackage.xml. It will compile all code into binary executables.
Build System & Environment
Build System (colcon)
When we run colcon build, it looks for a package.xml file in every folder (package). This file defines the package name, version, and dependencies.
-
colcon: Like the main universal way of building packages regardless of the type of source files (python or C++).
-
ament:
ament_pythonorament_cmakeare build types (specific ways we can build).colconsees this and understands which ways we want to build our package.-
ament_python: Always contains python source files and a
setup.pyfile, sometimes containing asetup.cfg. -
ament_cmake: Usually contains C++ source files, but also used for "resource-only" packages that hold models, maps, custom messages, or configuration files.
-
Build Type Tags (Found in package.xml)
- For C++:
<export>
<build_type>ament_cmake</build_type>
</export>- For Python:
<export>
<build_type>ament_python</build_type>
</export>package.xml
Helping way of thinking: Just an ID card and dependency checklist.
<buildtool_depend>: Tells ROS 2 what software is needed to actually compile the package.
Note: Python (an interpreted language) packages don't need this because it doesn't get compiled unlike C++. It simply gets copied over to
/install, therefore we don't need this. C++ packages explicitly require this to be stated inpackage.xmlcos it needs to be compiled into machine's binary code.
-
<exec_depend>: Called Execution Dependencies, which is what our launch files depend on when we are running it. -
<test_depend>: Dependencies we require to test our code, such aspytest,flake8, andpep257which are all standard Python code linters (tools that check your code for formatting errors). -
<build_type>ament_python</build_type>: The tag thatcolconrequires to know whether to look forCMakeLists.txtorsetup.pyon how to handle the installation (into/install).
CMakeLists.txt (For C++ & Resource Packages)
-
project(...): This gives your package a name. It also creates a handy background variable called${PROJECT_NAME}. -
install(DIRECTORY ...): This is essentially a "copy-paste" command for the build process. When you runcolcon build, ROS 2 doesn't use the files directly from your source code folder. It needs to put them in a central "install space" so the rest of the robot system can find them. -
DESTINATION share/${PROJECT_NAME}/: This is where those folders get pasted. In ROS 2, description files, launch files, and models are standardly placed in theshare/directory of the installed package.
setup.py (For Python Packages)
-
packages=find_packages(exclude=['test']):find_packagesis a python tool that automatically searches the package directory and grabs all the python code so they can be installed. -
exclude=['test']: Intentionally ignorestest/folders so that testing scripts don't get installed onto the robot. -
install_requires=['setuptools'], tests_require=['pytest']: Tells the system it needs thesetuptoolslibrary to build the package, and thepytestpackage to run tests. -
data_files=[...]:-
Tuple 1:
('share/ament_index/resource_index/packages', ['resource/' + package_name])-> Puts a blank marker file deep inside the ROS 2 system. When we typeros2 pkg list, ROS 2 searches this exact folder to know the existing packages. -
Tuple 2:
('share/' + package_name, ['package.xml'])-> Copies thepackage.xmlfile into theshare/rc_car_teleopinstallation folder so ROS 2 can read the dependencies at runtime.
-
Entry Points Layout
Python
entry_points={
'console_scripts': [
'teleop = rc_car_teleop.teleop:main',
'odometry = rc_car_teleop.odom:main',
'lidar_processor = rc_car_teleop.lidar_processor:main',
'yolo = rc_car_teleop.yolo:main',
'camera = rc_car_teleop.camera:main',
'brain = rc_car_teleop.brain:main',
],
},-
teleop: This is the name of the executable to create. We use it when we run the command:ros2 run rc_car_teleop teleop. -
rc_car_teleop.teleop:main: This is the path to the code. It tells ROS 2, "Look inside the rc_car_teleop folder, find the teleop.py script, and execute the function called main()."
launch.py
-
Structure: Split into 3 parts: Imports, Generator Function, and Execution/Return.
-
Purpose: Allows us to run multiple configured nodes simultaneously via:
ros2 launch my_package my_launch.py