当前位置: 首页 > article >正文

ros2笔记-2.5.1 面向对象编程

面向对象

编程思想主要是面向过程、面向对象、函数式几种。

涉及的概念:

类、抽象、封装、继承、多态。这里没有展开。

python 版本

新建节点代码

还是上一节基础上,再demo_python_pkg 包下面新建person_node.py

class PersonNode:
    def __init__(self,name_val: str,age_val: int) -> None:
        self.name = name_val
        self.age  = age_val
        
    def eat(self,food_name: str):
        print(f"{self.name},{self.age}岁,爱吃{food_name}")    

def main():
    node = PersonNode('张三',18)
    node.eat('鱼香肉丝')

定义了一个类PersonNode,属性eat

注册

接着修改setup.py

    entry_points={
        'console_scripts': [
            'python_node = demo_python_pkg.python_node:main',
            'person_node = demo_python_pkg.person_node:main'
        ],
    },

增加新加的节点入口函数。

编译测试

执行colcon build.

加载环境变量,

执行

bohu@bohu-TM1701:~/2/2_ws$ colcon build
Starting >>> demo_cpp_pkg
Finished <<< demo_cpp_pkg [0.18s]                     
Starting >>> demo_python_pkg
Finished <<< demo_python_pkg [1.61s]          

Summary: 2 packages finished [2.13s]
bohu@bohu-TM1701:~/2/2_ws$ source install/setup.bash 
bohu@bohu-TM1701:~/2/2_ws$ ros2 run demo_python_pkg person_node
张三,18岁,爱吃鱼香肉丝

其中__init__方法在创建该类的对象时候会被调用。当要给该类添加属性时,一般会通过__init__方法的参数来传递初始值。可以打个日志

bohu@bohu-TM1701:~/2/2_ws$ ros2 run demo_python_pkg person_node
PersonNode 的 __init__被调用了
张三,18岁,爱吃鱼香肉丝

继承

新建writer_node.py

from demo_python_pkg.person_node import PersonNode

class WriterNode(PersonNode):
    def __init__(self,name:str,age:int,book_val: str) -> None:
        print('WriterNode 的 __init__被调用了')
        #调用父类的init
        super().__init__(name,age)
        self.book = book_val
        

    
def main():
    node = WriterNode('张三',18,'ros2 机器人开发')
    node.eat('鱼香肉丝')

 注册节点

修改setup.py

    entry_points={
        'console_scripts': [
            'python_node = demo_python_pkg.python_node:main',
            'person_node = demo_python_pkg.person_node:main',
            'writer_node = demo_python_pkg.writer_node:main'
        ],
    },

重新构建运行

bohu@bohu-TM1701:~/2/2_ws$ ros2 run demo_python_pkg writer_node
WriterNode 的 __init__被调用了
PersonNode 的 __init__被调用了
张三,18岁,爱吃鱼香肉丝

可以看到WriterNode成功继承类PersonNode的属性和方法。

接下来,我们尝试把PersonNode 变成真正的ROS2节点,修改如下

import rclpy
from rclpy.node import Node

class PersonNode(Node):
    def __init__(self,node_name:str,name_val: str,age_val: int) -> None:
        print('PersonNode 的 __init__被调用了')
        super().__init__(node_name)
        self.name = name_val
        self.age  = age_val

    def eat(self,food_name: str):
        #print(f"{self.name},{self.age}岁,爱吃{food_name}")    
        self.get_logger().info(f"{self.name},{self.age}岁,爱吃{food_name}") 

def main():
    rclpy.init()
    node = PersonNode('zhangsan','张三',18)
    node.eat('鱼香肉丝')
    rclpy.spin(node)
    rclpy.shutdown()

重新运行,注意日志部分换成了ros2 的logger. 可以看到成功输出日志,新开终端也能看到节点。

C++ 版本

编写节点代码

在demo_cpp_pkg 下面新建person_node.cpp

#include <string>
#include "rclcpp/rclcpp.hpp"

class PersonNode : public rclcpp::Node
{
private:
//声明
    std::string name_;
    int age_;
public:
    PersonNode(const std::string &node_name,const std::string &name,const int &age):Node(node_name)/*调用父类的构造函数 */
    {
        this->name_ = name;
        this->age_ = age;
    };
    void eat(const std::string & food_name)
    {
        RCLCPP_INFO(get_logger(),"我是%s,今年%d岁,爱吃%s",name_.c_str(),age_,food_name.c_str());
    }

};

int main(int argc, char **argv)
{
    rclcpp::init(argc,argv);
    auto node = std::make_shared<PersonNode>("cpp_node","李四",18);
    RCLCPP_INFO(node->get_logger(),"你好 c++节点");
    node->eat("鱼香ros");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

开头是头文件。接着是使用class 定义了PersonNode类,继承了Node节点。内部private 定义类2个属性。

 public 定义构造函数PersonNode,并传入节点名称、姓名、和年龄作为参数,其中参数传递采用了静态引用方式。前面的const 表示不能通过引用对目标变量的值进行修改。

接下来是eat方法,内部调用类ros2的日志模块来输出。里面有c_str()方式适配C风格类型的字符串。

main函数与之前类似,构造的节点是PersonNode的对象,并赋值给node,然后调用node的eat方法和ros2的相关方法。

编译

修改CMakeLists.txt,添加person_node节点。

cmake_minimum_required(VERSION 3.8)
project(demo_cpp_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# 查找rclcpp头文件和库文件的路径
find_package(rclcpp REQUIRED) 

add_executable(cpp_node src/cpp_node.cpp)
add_executable(person_node src/person_node.cpp)

# 给可执行文件包含头文件
# target_include_directories(cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS})
# 给可执行文件链接库文件
# target_link_libraries(cpp_node ${rclcpp_LIBRARIES})
ament_target_dependencies(cpp_node rclcpp)
ament_target_dependencies(person_node rclcpp)

install(TARGETS cpp_node person_node
  DESTINATION lib/${PROJECT_NAME}
)

# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

构建

colcon build

加载环境变量,运行节点

bohu@bohu-TM1701:~/2/2_ws$ colcon build
Starting >>> demo_cpp_pkg
Finished <<< demo_cpp_pkg [4.65s]                     
Starting >>> demo_python_pkg
Finished <<< demo_python_pkg [1.43s]          

Summary: 2 packages finished [6.43s]
bohu@bohu-TM1701:~/2/2_ws$ source install/setup.bash 
bohu@bohu-TM1701:~/2/2_ws$ ros2 run demo_cpp_pkg person_node
[INFO] [1736046779.467568587] [cpp_node]: 你好 c++节点
[INFO] [1736046779.467701782] [cpp_node]: 我是张三,今年18岁,爱吃鱼香ros

C++ \python  的语法还是不熟悉,我跟着视频巧了一遍代码,其中一点小差错就编译不过。少个括号或者双引号写成单引号诸如此类。折腾半天。还是欠缺很多基础。


http://www.kler.cn/a/468836.html

相关文章:

  • C++单例模式跨DLL调用问题梳理
  • Spring AMQP ----注解篇
  • OpenKit 介绍
  • SQL编程语言
  • 【three.js】场景搭建
  • RabbitMQ案例
  • 双馈风电DFIG并网系统次转子侧变流器RSC抑制策略研究基于LADRC和重复控制的方法
  • 【视觉SLAM:八、后端Ⅱ】
  • C#Halcon跨窗口颜色识别
  • 使用 Spring Boot 进行数据校验
  • 如何构建云原生时空大数据平台?
  • EasyExcel监听器详解
  • 【QED】暴食海獭
  • DDcGAN_多分辨率图像融合的双鉴别条件生成对抗网络_y译文马佳义
  • 若依中Feign调用的具体使用(若依微服务版自身已集成openfeign依赖,并在此基础上定义了自己的注解)
  • 4_TypeScript 条件语句 --[深入浅出 TypeScript 测试]
  • 强化学习常用库的版本对应关系
  • 【C语言】可移植性陷阱与缺陷(六): 内存位置0的访问
  • C++并发:在线程间共享数据
  • 鸿蒙day1-ArkTS-认识和存储数据
  • C语言:调试的概念和调试器的选择
  • Laravel操作ElasticSearch
  • FFMPEG 保存实时流到本地文件
  • 【JVM】总结篇-运行时内存篇
  • 我用AI学Android Jetpack Compose之开篇
  • opengauss安装指南