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
运行效果如下:
