ROS2学习笔记 - 2、类的继承及使用

1、基于Python类的实现

1.1、定义父类 AnimalNode

在 ~/ros2_workspace/src/python_package/python_package 目录下、创建一个新的文件:animal_node.py 文件内容如下:

python 复制代码
class AnimalNode:
    """
    动物节点类,用于描述动物的基本属性和行为
    """
    
    def __init__(self, species_name: str, weight: int, age: int) -> None:
        """
        初始化动物节点
        
        参数:
            species_name (str): 动物物种名称,如 'zebra', 'kangaroo'
            weight (int): 动物体重,单位为公斤(kg)
            age (int): 动物年龄,单位为岁
        """
        self.species_name = species_name  # 存储物种名称
        self.weight = weight              # 存储体重
        self.age = age                    # 存储年龄
        
    def do_action(self, action_name: str) -> None:
        """
        打印动物执行某个动作的信息
        
        参数:
            action_name (str): 动物正在执行的动作描述,如 'running', 'hopping'
        """
        # 使用 f-string 格式化输出动物的属性信息和正在执行的动作
        # 输出格式示例: "The 63-kilogram,7-year-old zebra is running."
        print(f"The {self.weight}-kilogram,{self.age}-year-old {self.species_name} is {action_name}.")
        

def main():
    """
    主函数:创建动物节点实例并测试其行为
    """
    # 创建第一个动物节点:7岁、63公斤的斑马
    node = AnimalNode('zebra', 63, 7)
    # 让斑马执行奔跑动作
    node.do_action('running')
    
    # 创建第二个动物节点:6岁、29公斤的袋鼠
    node2 = AnimalNode('kangaroo', 29, 6)
    # 让袋鼠执行跳跃奔跑动作
    node2.do_action('hopping and running')

然后要测试一下父类是否可以正常工作、先在setup.py中添加节点的入口名称:animal_node

c 复制代码
    entry_points={
        'console_scripts': [
            'test_node = python_package.test:main',
            'animal_node = python_package.animal_node:main',
        ],
    },

执行编译(--symlink-install 的意思是:在 install/ 目录中创建指向 src/ 源文件的"符号链接"(类似快捷方式),而不是复制文件, 也就是说修改源文件保存后马上生效、不需要重新编译就可以直接运行)

c 复制代码
colcon build --packages-select python_package --symlink-install

加载环境变量

c 复制代码
source ~/ros2_workspace/install/setup.bash

运行 animal_node

c 复制代码
ros2 run python_package animal_node

执行结果如下:

1.2、定义子类 ZebraNode

在 ~/ros2_workspace/src/python_package/python_package 目录下、创建一个新的文件:zebra_node.py 文件内容如下:

python 复制代码
# 从 python_package 模块的 animal_node 文件中导入 AnimalNode 基类
from python_package.animal_node import AnimalNode

class ZebraNode(AnimalNode):
    """
    斑马节点类,继承自 AnimalNode 基类
    
    这个类专门用于描述斑马的行为,继承了父类的属性和方法,
    并对 do_action 方法进行了封装,固定为 'running' 动作
    """
    
    def __init__(self, weight: int, age: int) -> None:
        """
        初始化斑马节点
        
        参数:
            weight (int): 斑马的体重,单位:公斤(kg)
            age (int): 斑马的年龄,单位:岁
        
        说明:
            调用父类 AnimalNode 的构造函数,固定传入物种名称 'zebra'
        """
        # 调用父类构造函数,传入固定的物种名称 'zebra',以及体重和年龄
        super().__init__('zebra', weight, age)
    
    def do_action(self) -> str:
        """
        执行斑马的动作
        
        返回:
            str: 父类 do_action 方法的返回值(打印信息的返回值)
        
        说明:
            这个方法重写了父类的方法,但固定了动作参数为 'running'
            实际调用父类的 do_action 方法,传入 'running' 作为动作描述
        """
        # 调用父类的 do_action 方法,固定传入 'running' 动作
        # super() 表示调用父类(AnimalNode)的方法
        return super().do_action('running')


def main() -> None:
    """
    主函数:创建斑马节点实例并测试其行为
    
    创建一个 7岁、63公斤 的斑马对象,然后调用其 do_action 方法
    """
    # 创建斑马节点:7岁,63公斤
    node = ZebraNode(63, 7)
    # 调用斑马节点的 do_action 方法,输出动作信息
    node.do_action()

测试一下子类是否可以正常工作、先在setup.py中添加节点的入口名称:zebra_node

c 复制代码
    entry_points={
        'console_scripts': [
            'test_node = python_package.test:main',
            'animal_node = python_package.animal_node:main',
            'zebra_node = python_package.zebra_node:main',
        ],
    },

执行编译

c 复制代码
colcon build --packages-select python_package --symlink-install

加载环境变量

c 复制代码
source ~/ros2_workspace/install/setup.bash

运行 zebra_node

c 复制代码
ros2 run python_package zebra_node

执行结果如下:

1.3、添加ROS2的Node

修改AnimalNode类的定义、让其继续自Node、修改代码如下:

python 复制代码
import rclpy
from rclpy.node import Node

class AnimalNode(Node):
    def __init__(self, species_name:str, weight:int,age:int) -> None:
        super().__init__('ROS2_'+species_name)
        self.species_name = species_name
        self.weight = weight
        self.age = age
        
    def do_action(self,action_name:str):
        print(f"The {self.weight}-kilogram,{self.age}-year-old {self.species_name} is {action_name}.")
        
def main():
    rclpy.init()
    node = AnimalNode('zebra',63,7)
    node.do_action('running')
    node2 = AnimalNode('kangaroo',29,6)
    node2.do_action('hopping and running')
    rclpy.spin(node2)
    rclpy.shutdown()

重新编译代码

c 复制代码
colcon build --packages-select python_package --symlink-install

加载环境变量

c 复制代码
source ~/ros2_workspace/install/setup.bash

运行 animal_node

c 复制代码
ros2 run python_package animal_node

分两个窗口可以查看当前已经运行的 ros2的Node 执行结果如下:

再次修改do_action、让其使用ros2的Node特性的方法来输出日志:

python 复制代码
    def do_action(self,action_name:str):
        self.get_logger().info(f"The {self.weight}-kilogram,{self.age}-year-old {self.species_name} is {action_name}.")

再次运行结果如下:

2、基于 C++ 类的实现

在 ~/ros2_workspace/src/c_package/src 目录下、创建一个新的文件:animal_node.cpp 实现功能与python的一样,文件内容如下:

cpp 复制代码
#include "rclcpp/rclcpp.hpp"

class AnimalNode : public rclcpp::Node
{
    private:
        std::string species_name_;
        int weight_;
        short age_;

    public:
        AnimalNode(const std::string &species_name, int weight, int age) : 
            Node("ROS2_"+species_name),
            species_name_(species_name),
            weight_(weight),
            age_(age)
        {

        }

        void do_action(const std::string &action_name)
        {
            RCLCPP_INFO(this->get_logger(),"The %d-kilogram, %d-year-old %s is %s.",this->weight_,this->age_,this->species_name_.c_str(),action_name.c_str());
        }  
};

int main(int argc, char **argv)
{
    rclcpp::init(argc,argv);
    auto node = std::make_shared<AnimalNode>("zebra",63,7);
    node->do_action("running");
    rclcpp::spin(node);
    rclcpp::shutdown();
}

编辑 CMakeLists.txt

c 复制代码
nano ~/ros2_workspace/src/c_package/CMakeLists.txt

添加如下信息至文件:

c 复制代码
# ============================================
# 添加可执行文件(关键!)
# ============================================
add_executable(animal_node src/test.cpp)
ament_target_dependencies(animal_node rclcpp std_msgs)

# ============================================
# 安装可执行文件(关键!)
# ============================================
install(TARGETS
  animal_node
  DESTINATION lib/${PROJECT_NAME}
)

修改后的效果如下:

切换至 ~/ros2_workspace 目录、编译程序:

c 复制代码
colcon build --packages-select c_package --event-handlers console_direct+
运行 animal_node 节点
c 复制代码
ros2 run c_package animal_node

运行效果如下:

相关推荐
ILYT NCTR2 小时前
爬虫学习案例3
爬虫·python·学习
孙同学_2 小时前
【项目篇】高并发服务器 - HTTP服务器组件拆解,从Util到HttpServer
运维·服务器·http
Sherry Wangs2 小时前
服务器 CUDA版本升级指南
运维·服务器
不灭锦鲤2 小时前
网络安全学习第59天
学习·安全·web安全
CQU_JIAKE2 小时前
4.17[Q]
java·linux·服务器
上海云盾-小余3 小时前
DDoS 攻击应急响应全流程:从告警触发到业务恢复的黄金 15 分钟
服务器·安全·游戏·ddos
LXY_BUAA3 小时前
《ubuntu22.04》_新系统的配置_20260418
linux·运维·服务器
上海云盾-小余3 小时前
API 接口 DDoS 与 CC 攻击防护实战:守住业务最脆弱的数字入口
服务器·ddos
楼田莉子3 小时前
同步/异步日志系统:日志落地模块\日志器模块\异步日志模块
linux·服务器·c++·学习·设计模式