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

运行效果如下:

相关推荐
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
通信小呆呆2 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
H__Rick2 天前
自动对焦学习-3
人工智能·学习·计算机视觉
Daisy Lee2 天前
量化学习-第1章-什么是量化金融
学习·金融·datawhale
小宇宙Zz2 天前
Maven依赖冲突
java·服务器·maven
Alsn862 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
YM52e2 天前
买菜计算器小应用 - HarmonyOS ArkUI 开发实战-PC版本
学习·华为·harmonyos·鸿蒙·鸿蒙系统
小雨下雨的雨2 天前
HarmonyOS ArkUI训练营入门-组件掌握系列-Animation 动画效果实现-PC版本
学习·华为·harmonyos·鸿蒙
闪闪发亮的小星星2 天前
高斯光以及高斯光公式解释
笔记
古城小栈2 天前
Unix 与 Linux 异同小叙
linux·服务器·unix