# ============================================================================= # setup.py —— ament_python 包的安装清单,等同于"Python 项目的 setup.py"。 # # 与 ROS1 不同,ROS2 采用 setuptools + ament_python 协同: # - 标准 Python setup() 描述包元数据; # - data_files 把"ROS 标签"文件(package.xml、ament 索引、launch 等) # 装到 install//share//,被 colcon 和 ros2 工具识别。 # # colcon build 调用链: colcon → ament_python build_type → python setup.py build # install → install/bin + install/lib/... # + install//share// # ============================================================================= # find_packages:setuptools 工具,自动扫描当前目录下含 __init__.py 的目录, # 收录为要安装的 Python 包。 # setup:setuptools 的入口函数,描述包元数据 / 文件 / 入口点。 from setuptools import find_packages, setup # 这个 ROS 包的"名字"——必须与 package.xml 中的 一致,这是 ament # 索引文件 resource/ 用到的标识。 package_name = 'py_pubsub' setup( # 包名,暴露给 pip / colcon 用以识别。 name=package_name, version='0.1.0', # find_packages(exclude=['test']): # 自动发现 "py_pubsub/" 这个 Python 子包, # "test/" 目录被排除,以免污染运行时。 packages=find_packages(exclude=['test']), # data_files:(target_dir, [src_file, ...]) 元组列表。 # 描述"额外要装的非 .py 文件",ament 强制要求三类: # 1) ament 索引标记 ← resource/ # 2) 元数据 package.xml ← share// # 3) launch 文件 ← share//launch/ data_files=[ # 让 `ros2 pkg prefix py_pubsub` 能找到本包路径(ament_index 必备)。 ('share/ament_index/resource_index/packages', ['resource/' + package_name]), # 把 package.xml 拷到 share//,ros2 工具靠它识别包元数据。 ('share/' + package_name, ['package.xml']), # launch 文件必须装到 share//launch/ 下, # `ros2 launch py_pubsub pubsub_launch.py` 才能找到。 ('share/' + package_name + '/launch', ['launch/pubsub_launch.py']), ], # 仅依赖 setuptools(ROS 基础能力由 apt 安装的 rclpy 提供,不需列在 install_requires)。 install_requires=['setuptools'], # 安装时把所有 .py 编到 egg,zip-safe 让 colcon 能直接用源码/egg。 zip_safe=True, maintainer='xs', maintainer_email='dev@example.com', description='Python talker/listener demo for ROS2 Humble', license='Apache-2.0', # 标记这是 Python 测试依赖(本项目未配测试,可保留以备扩展)。 tests_require=['pytest'], # entry_points/console_scripts: # 列出本包提供的"命令行可执行"。`ros2 run py_pubsub talker` 会 # 在该列表里找 'talker',实际指向 py_pubsub.publisher_member_function.main # (注意 main() 的位置必须是模块级函数,被 import 调用)。 entry_points={ 'console_scripts': [ # 左:ros2 run 后跟的可执行名;右:模块路径:main() 函数 'talker = py_pubsub.publisher_member_function:main', 'listener = py_pubsub.subscriber_member_function:main', ], }, )