1.5.1 ROS2文件系统
立足系统架构,如下图所示,ROS2可以划分为三层:
-
操作系统层(OS Layer)
如前所述,ROS虽然称之为机器人操作系统,但实质只是构建机器人应用程序的软件开发工具包,ROS必须依赖于传统意义的操作系统,目前ROS2可以运行在Linux、Windows、Mac或RTOS上。
-
中间层(Middleware Layer)
主要由数据分发服务DDS与ROS2封装的关于机器人开发的中间件组成。DDS是一种去中心化的数据通讯方式,ROS2还引入了服务质量管理 (Quality of Service)机制,借助该机制可以保证在某些较差网络环境下也可以具备良好的通讯效果。ROS2中间件则主要由客户端库、DDS抽象层与进程内通讯API构成。
-
应用层(Application Layer)
是指开发者构建的应用程序,在应用程序中是以功能包为核心的,在功能包中可以包含源码、数据定义、接口等内容。
对于一般开发者而言,工作内容主要集中在应用层,开发者一般通过实现具有某一特定功能的功能包来构建机器人应用程序。对应的我们所介绍的ROS2文件系统主要是指在硬盘上以功能包为核心的目录与文件的组织形式。
1.概览
功能包是ROS2应用程序的核心,但是功能包不能直接构建,必须依赖于工作空间,一个ROS2工作空间的目录结构如下:
WorkSpace --- 自定义的工作空间。
|--- build:存储中间文件的目录,该目录下会为每一个功能包创建一个单独子目录。
|--- install:安装目录,该目录下会为每一个功能包创建一个单独子目录。
|--- log:日志目录,用于存储日志文件。
|--- src:用于存储功能包源码的目录。
|-- C++功能包
|-- package.xml:包信息,比如:包名、版本、作者、依赖项。
|-- CMakeLists.txt:配置编译规则,比如源文件、依赖项、目标文件。
|-- src:C++源文件目录。
|-- include:头文件目录。
|-- msg:消息接口文件目录。
|-- srv:服务接口文件目录。
|-- action:动作接口文件目录。
|-- Python功能包
|-- package.xml:包信息,比如:包名、版本、作者、依赖项。
|-- setup.py:与C++功能包的CMakeLists.txt类似。
|-- setup.cfg:功能包基本配置文件。
|-- resource:资源目录。
|-- test:存储测试相关文件。
|-- 功能包同名目录:Python源文件目录。
另外,无论是Python功能包还是C++功能包,都可以自定义一些配置文件相关的目录。
|-- C++或Python功能包
|-- launch:存储launch文件。
|-- rviz:存储rviz2配置相关文件。
|-- urdf:存储机器人建模文件。
|-- params:存储参数文件。
|-- world:存储仿真环境相关文件。
|-- map:存储导航所需地图文件。
|-- ......
上述这些目录也可以定义为其他名称,或者根据需要创建其他一些目录。
2.源文件说明
在1.3 ROS2快速体验中,实现第一个ROS2程序时,都需要创建节点,无论是C++实现还是Python实现,都是直接实例化的Node对象。
C++实例化Node示例如下:
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv)
{
rclcpp::init(argc,argv);
auto node = rclcpp::Node::make_shared("helloworld_node");
RCLCPP_INFO(node->get_logger(),"hello world!");
rclcpp::shutdown();
return 0;
}
Python实例化Node示例如下:
import rclpy
def main():
rclpy.init()
node = rclpy.create_node("helloworld_py_node")
node.get_logger().info("hello world!")
rclpy.shutdown()
if __name__ == '__main__':
main()
但是在ROS2中,上述编码风格是不被推荐的,更推荐以继承Node的方式来创建节点对象。
C++继承Node实现示例如下:
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node{
public:
MyNode():Node("node_name"){
RCLCPP_INFO(this->get_logger(),"hello world!");
}
};
int main(int argc, char *argv[])
{
rclcpp::init(argc,argv);
auto node = std::make_shared<MyNode>();
rclcpp::shutdown();
return 0;
}
Python继承Node实现示例如下: