ROS2实践:创建一个包和节点
准备
在ROS2中什么是包,什么是节点?
- 包(Package) 是 ROS 2 的基本构建单元,包含了代码、资源、配置和依赖,组织着机器人的各个功能模块。这个packge可以理解为openwrt的package,主要用于怎么构建、编译代码,存放程序的配置等等。
- 节点(Node) 是 ROS 2 中执行的具体单元,它是一个程序,可以完成传感器读取、控制计算、数据处理等任务,并通过话题、服务或动作与其他节点进行通信。可以理解为openwrt中package中实际的程序,一个节点是一个进程。
一个包中可以有多个节点,节点与包是包含的关系。
安装前面的文章安装好ROS2的开发环境。
安装colcon编译工具、rosdep工具。
sudo apt install python3-colcon-ros
创建一个工作空间
mkdir -p ~/dev_ws/src
python的方式
创建一个包
cd ~/dev_ws/src/
ros2 pkg create --build-type ament_cmake learning_pkg_python
创建完成后,会产生如下文件
.
├── learning_pkg_python
│   ├── learning_pkg_python
│   │   └── __init__.py
│   ├── package.xml
│   ├── resource
│   │   └── learning_pkg_python
│   ├── setup.cfg
│   ├── setup.py
│   └── test
│       ├── test_copyright.py
│       ├── test_flake8.py
│       └── test_pep257.py
创建节点程序
在~/dev_ws/src/learning_pkg_python/learning_pkg_python目录下创建一个node_helloworld_class.py文件,实现代码如下:
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import rclpy
from rclpy.node import Node
import time
class HelloworldNode(Node):
    def __init__(self, name):
        super().__init__(name)
        while rclpy.ok():
            self.get_logger().info("Hello World")
            time.sleep(0.5)
def main(args=None):
    rclpy.init(args=args)
    node = HelloworldNode("node_helloworld_class")
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
注意node_helloworld_class.py文件要和默认的init.py在一个目录下,保持同级。
设置程序入口
    entry_points={
        'console_scripts': [
            'node_helloworld_class = learning_pkg_python.node_helloworld_class:main',
        ],
    },
设置python的程序入口,让ROS2系统知道python程序的入口。
- console_scripts::这告诉Python包管理器(如pip)要创建哪些命令行可执行脚本。
- node_helloworld_class:这是终端中ros2 run后面直接运行的命令名称。
- learning_pkg_python.node_helloworld_class:main:这是Python模块的路径(包名.模块名)
编译
cd ~/dev_ws/
colcon build
编译的时候,要切换到工程的根目录下进行编译。因为编译会在当前的根目录下生成build、install、log,而工程下会有很多包,因此建议都切换到工程的根目录下进行编译。
执行
ros2 run learning_pkg_python node_helloworld_class
CPP方式
创建一个包
执行创建包的命令
ros2 pkg create --build-type ament_cmake learning_pkg_cpp
下面是生成的包的目录结构
.
├── learning_pkg_cpp
│   ├── CMakeLists.txt
│   ├── include
│   │   └── learning_pkg_cpp
│   ├── package.xml
│   └── src
创建节点程序
在learning_pkg_cpp/src目录下创建一个node_helloworld_class.cpp文件,编写代码。
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class HelloWorldClass : public rclcpp::Node
{
    public:
        HelloWorldClass():Node("hello_world_class")
        {
            while(rclcpp::ok()) {
                RCLCPP_INFO(this->get_logger(), "Hello World");
                sleep(1);
            }
        }
};
int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<HelloWorldClass>());
    rclcpp::shutdown();
    return 0;
}
设置编译选项
python是不用编译的,但是C++程序需要编译因此需要更新CmakeLists.txt。在文件中添加一下内容。
find_package(rclcpp REQUIRED)
# 查找依赖的功能包rclcpp,提供ROS2 C++的基础接口
add_executable(node_helloworld_class src/node_helloworld_class.cpp)
# 添加一个可执行文件名称为node_helloworld_class,源码路径为src/node_helloworld_class.cpp
ament_target_dependencies(node_helloworld_class rclcpp)
#编译时链接rclcpp的依赖库
install(TARGETS
  node_helloworld_class
  DESTINATION lib/${PROJECT_NAME}
)
#将可执行文件拷贝到install目录下。
编译执行
# 编译
cd ~/dev_ws/
colcon build
# 运行
source install/setup.bash
#先执行一下环境变量,可以补全新的命令。
常用命令
创建包
创建一个功能包的命令
ros2 pkg create --build-type <build-type> <packge_name>
- pkg:调用功能包相关功能的子命令。
- create:创建功能包的子命令。
- build-type:表示新创建的功能包是C++还是Python,如果使用C++或者C,这里是”ament_cmake”;如果使用python,这里就是”ament_python”。
- packege_name:新建功能包的名字。
示例
cd ~/dev_ws/src
ros2 pkg create --build-type ament_cmake learning_pkg_cpp
ros2 pkg create --build-type ament_python learning_pkg_python
注意执行上面命令时,就会在当前目录下进行创建包,因此为了工程目录的结构,要切换到指定的目录进行创建。
运行
ros2 run <package_name> <executable_name> [arguments]
