从零开始学习ROS2,作为一个小白有各种奇怪的问题。主要还是对整个项目的构建过程不太了解。我学习的资源主要来自B站赵虚左老师
以及鱼香ROS
。下面是一些学习过程中遇到的关于文件结构和配置相关的疑惑:
1.ros2项目里面的文件结构以及对应的功能是什么? 1.1 首先以一个经典的项目目录举例(一个功能包,一个节点):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ros2_ws/ ├── src/ │ ├── my_package/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── src/ │ │ │ └── my_node.cpp │ │ ├── launch/ │ │ │ └── my_launch.launch.py │ │ ├── msg/ │ │ │ └── MyMessage.msg │ │ ├── srv/ │ │ │ └── MyService.srv │ │ ├── config/ │ │ │ └── params.yaml │ │ └── tests/ │ │ └── test_my_node.cpp ----my_package2 ├── build/ ├── install/ └── log/
1.2 实际开发过程中,要实现整体机器的运转,需要多个功能包,每个功能包下面可能包含一个或者多个节点:(以自动避开障碍物的小车为例子:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 ros2_ws/ ├── src/ │ ├── sensor_interface/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── src/ │ │ │ ├── lidar_node.cpp │ │ │ ├── camera_node.cpp │ │ │ └── imu_node.cpp │ │ ├── launch/ │ │ │ └── sensor_launch.py │ │ ├── config/ │ │ │ └── params.yaml │ │ └── urdf/ │ │ ├── perception/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── src/ │ │ │ ├── obstacle_detection_node.cpp │ │ │ └── obstacle_tracker_node.cpp │ │ ├── launch/ │ │ │ └── perception_launch.py │ │ └── config/ │ │ └── detection_params.yaml │ │ ├── planning/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── src/ │ │ │ ├── local_planner_node.cpp │ │ │ └── global_planner_node.cpp │ │ ├── launch/ │ │ │ └── planning_launch.py │ │ └── config/ │ │ └── planner_params.yaml │ │ ├── control/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── src/ │ │ │ ├── speed_controller_node.cpp │ │ │ ├── steering_controller_node.cpp │ │ └── launch/ │ │ └── control_launch.py │ │ ├── simulation/ │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ ├── worlds/ │ │ │ └── test_world.world │ │ ├── launch/ │ │ │ └── gazebo_launch.py │ │ ├── models/ │ │ │ ├── car_description.urdf.xacro │ │ │ └── lidar_sensor.urdf.xacro │ │ └── src/ │ │ └── sim_bridge_node.cpp │ │ └── bringup/ │ ├── package.xml │ ├── CMakeLists.txt │ ├── launch/ │ │ ├── all_system_launch.py │ │ ├── rviz_launch.py │ └── config/ │ └── rviz_config.rviz ├── build/ ├── install/ └── log/
2.如何从零构建一个ros2项目?
1.创建工作空间:手动创建工作空间以及对应的代码目录src
—mkdir -p work_space/src
进入src
,创建功能包ros2 pkg create --build-type ament_cmake base_interfaces_demo
,其中(--build-type ament_cmake
这个是默认的,也可以不写。base_interface_demo
是功能包的名字)
(c++功能包的构建信息主要在package.xml
以及CMakeLists.txt
中,而python功能包的构建信息主要包含在packages.xml
以及setup.py
中)
3.项目里面涉及到了cpp的使用,那么里面的CmakeList.txt
包含的内容是什么意思,xml
文件是如何去配置的?
CMakeList.txt
的一个例子:首先这个文件的作用是什么?
定义构建规则 :CMakeLists.txt
告诉 CMake 如何编译和链接代码,生成可执行文件或库。
管理依赖项 :它会声明当前项目所依赖的其他库或包(如 ROS 的核心库)。
配置测试 :如果项目包含测试代码,CMakeLists.txt
也会定义如何运行测试。
设置编译选项 :可以通过它设置编译器选项(如警告级别、优化选项等)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 cmake_minimum_required (VERSION 3.8 ) # 作用:指定 CMake 的最低版本要求。这里要求 CMake 的版本至少为 3.8 。project (base_interfaces_demo) # 定义项目的名称,这里是 base_interfaces_demo(和packages.xml里面的保持一致)if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) add_compile_options (-Wall -Wextra -Wpedantic) endif ()# 作用:为 GCC 或 Clang 编译器添加编译选项。 -Wall:启用所有常见的警告。 -Wextra:启用额外的警告。 -Wpedantic:启用严格的标准兼容性警告。 # find dependencies find_package (ament_cmake REQUIRED) 查找并加载 ament_cmake 包,这是 ROS 2 的核心构建工具之一。# uncomment the following section in order to fill in # further dependencies manually. # find_package (<dependency> REQUIRED) 如果项目依赖于 rclcpp,可以添加 find_package (<rclcpp> REQUIRED) if (BUILD_TESTING) # 如果启用了测试(BUILD_TESTING 为 ON),则查找并加载 ament_lint_auto 包 find_package (ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # comment the line when a copyright and license is added to all source files set (ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # comment the line when this package is in a git repo and when # a copyright and license is added to all source files set (ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies () endif ()ament_package () # 标记当前项目为一个 ROS 2 包
关于xml文件,下面展示一个基础的常用的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 ----------------这个是调用了自定义接口的功能包 <?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 > py01_topic</name > <version > 0.0.0</version > <description > TODO: Package description</description > <maintainer email ="tyfelix@todo.todo" > tyfelix</maintainer > <license > TODO: License declaration</license > <depend > rclpy</depend > <depend > std_msgs</depend > <depend > base_interfaces_demo</depend > <test_depend > ament_copyright</test_depend > <test_depend > ament_flake8</test_depend > <test_depend > ament_pep257</test_depend > <test_depend > python3-pytest</test_depend > <export > <build_type > ament_python</build_type > </export > </package > ---------------------------这个是自定义接口的功能包 <?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 > base_interfaces_demo</name > <version > 0.0.0</version > <description > TODO: Package description</description > <maintainer email ="tyfelix@todo.todo" > tyfelix</maintainer > <license > TODO: License declaration</license > <buildtool_depend > ament_cmake</buildtool_depend > 因为这个地方需要去生成功能包,所以这样写的 <build_depend > rosidl_default_generators</build_depend > <exec_depend > rosidl_default_runtime</exec_depend > <member_of_group > rosidl_interface_packages</member_of_group > <test_depend > ament_lint_auto</test_depend > <test_depend > ament_lint_common</test_depend > <export > <build_type > ament_cmake</build_type > </export > </package > 描述: 1.根标签 <package > :该标签为整个 xml 文件的根标签,format 属性用来声明文件的格式版本。 2.元信息标签 <name > :包名; <version > :包的版本号; <description > :包的描述信息; <maintainer > :维护者信息; <license > :软件协议; <url > :包的介绍网址; <author > :包的作者信息。 3.依赖项 <buildtool_depend > :声明编译工具依赖; <build_depend > :声明编译依赖; <build_export_depend > :声明根据此包构建库所需依赖; <exec_depend > :声明执行时依赖; <depend > :相当于<build_depend > 、<build_export_depend > 、<exec_depend > 三者的集成;(相当于直接调用就写一个,如果是自己创建的接口,那么需要指明使用三个) <test_depend > :声明测试依赖; <doc_depend > :声明构建文档依赖。
对于python功能包,描述如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from setuptools import setuppackage_name = 'pkg02_helloworld_py' setup( name=package_name, version='0.0.0' , packages=[package_name], data_files=[ 猛狮集训营 42 ('share/ament_index/resource_index/packages' , ['resource/' + package_name]), ('share/' + package_name, ['package.xml' ]), ], install_requires=['setuptools' ], zip_safe=True , maintainer='ros2' , maintainer_email='ros2@todo.todo' , description='TODO: Package description' , license='TODO: License declaration' , tests_require=['pytest' ], entry_points={ 'console_scripts' : ['helloworld = pkg02_helloworld_py.helloworld:main' ], }, )