首页 > 其他分享 >ROS2开发前置基础知识

ROS2开发前置基础知识

时间:2024-09-11 17:21:33浏览次数:3  
标签:std 函数 package 前置 基础知识 main 环境变量 ROS2

前言

笔者发现现在市面上(主要是某站上)的ros2相关的教程内容大多不太基础(例如古某居(手动狗头保命),对于那些不熟悉Linux和C++甚至Python的童鞋来说不太友好,之前笔者自己在跟着学习过程中也有不少疑惑,踩了不少坑,现进行一些前置知识的总结(主要学习古某居和鱼香ros的教程,墙裂推荐),一方面对自己的学习做一些记录,另一方面也希望能对别的童鞋入门有帮助。当然,这并不是一个完整的ROS2教程,只是笔者根据自身学习过程中的所遇到的疑惑和问题情况进行的一些总结。

环境变量

我们在终端中执行ros2 run package_name node_name 来启动节点时,其实是通过$AMENT_PREFIX_PATH这个环境变量来找到路径的,开始时这个环境变量中只存了opt/ros/humble,我们创建一个新的功能包并编译后,通过

source install/setup.bash

执行脚本(另外提一句,install目录下有好几个setup脚本,不同终端对应不同的脚本,.sh是一种通用性的)来改变这个环境变量,实际上就是将这个功能包的路径添加到$AMENT_PREFIX_PATH这个环境变量中;另外如果是Python功能包会将install的lib目录下Python包路径添加到$PYTHONPATH环境变量中。需要注意的是这些更改只对当前终端生效,打开一个新的终端时直接ros2 run 启动这个节点的话就会报错找不到这个功能包。在古月居的教程中,则是直接将这样一句source的指令添加到了.bashrc中,每次打开一个新的终端时会自动调用,省去自己手动调用的麻烦。(在安装ros2时也会自动把

source opt/ros/humble/setup.bash

指令保存到.bashrc中,每次打开新终端时自动调用,更新ros2相关的环境变量)

通过printenv打印出所有的环境变量,可以通过| grep过滤出想要查看的环境变量。export可以更改环境变量,但也只对当前终端生效。

另外我们在终端中很多类似的操作都是同样通过环境变量来实现的,比如在终端中直接python3运行某个Python文件,是因为$PATH中保存了Python的bin文件的路径,可以直接调用该python3解释器。可以通过

which python3
whereis python3

查看相关信息。

VSCode中python代码提示也是通过环境变量实现的,$PYTHONPATH环境变量中存了python库的路径,在代码中import导入某个库后,调用库中的函数时,编辑器进行搜索

python基础

库导入

通过import module会导入整个模块,然后通过module.a调用该模块中的函数、类等,这样不会导致命名重复的问题;import module as ...可以改名字,简写模块名称,一般有某些固定简写名称,比如import numpy as np;from ... import ...则是导入特定的函数或者类等,一般需要调用模块中特定对象时使用,需要注意可能的命名问题;如果from ... import *则导入所有对象,一般不这样。

程序入口配置

与C++不同的时,Python程序不存在真正的"main"函数,也就是说Python程序执行时不会把自己定义的main函数当作程序入口(程序的主要逻辑还是写在main函数里,其实可以不命名为main,只是一种习惯性的做法),所以我们在ROS2中写Python节点时需要在setup文件中配置节点可执行文件的入口为某个.py文件的main函数(通常我们都在main函数中定义节点对象并spin运行)。另外我们在调试时没有创建功能包,只写了一个.py文件,main函数中定义了节点对象并spin,可以在该文件中加上一下内容:

if __name__=="main":
    main()

 则可以直接运行该节点,调试时比较方便,省去创建功能包和编译的麻烦。(这两句代码在Python中是为了在脚本被直接运行时执行main()函数,而在脚本被作为模块导入时不执行)

C++基础

共享指针

ROS2中的节点对象通常使用共享指针来进行管理。创建节点时,通常会使用std::make_shared来生成共享指针。

// 使用std::shared_ptr创建节点
auto node = std::make_shared<MyNode>();

在ROS2中,定时器(timer)通常与共享指针一起使用,以确保定时器回调函数中的资源在使用时不会被释放。

rclcpp::TimerBase::SharedPtr timer_;  // 使用共享指针管理定时器
// 创建一个定时器,使用共享指针
timer_ = this->create_wall_timer(
    std::chrono::seconds(1),
    std::bind(&TimerNode::timer_callback, this));

在消息传递中,std::shared_ptr被广泛用于发布或订阅消息时,确保消息的正确生命周期管理。

    void publish_message() {
        auto message = std::make_shared<std_msgs::msg::String>();
        message->data = "Hello, ROS2!";
        RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message->data.c_str());
        publisher_->publish(*message);  // 发布消息
    }

Lamda表达式

在ROS2中,订阅者、服务、定时器等需要回调函数来处理事件。通常可以将这些回调函数作为lambda表达式传入。

auto subscription = node->create_subscription<std_msgs::msg::String>(
        "topic",
        10,
        // 使用lambda表达式作为回调函数
        [](const std_msgs::msg::String::SharedPtr msg) {
            RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "I heard: '%s'", msg->data.c_str());
        });

auto timer = node->create_wall_timer(
        std::chrono::milliseconds(500),
        // 使用lambda表达式作为定时器回调
        []() {
            RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Timer triggered");
        });

std::bind

当需要传递一个成员函数作为回调时,直接传递this指针不够,因为成员函数依赖对象的上下文。通过std::bind可以将成员函数和对象实例绑定,从而正确传递回调函数。

// 使用std::bind将成员函数与对象实例绑定,并生成可调用对象
    subscription_ = this->create_subscription<std_msgs::msg::String>(
            "topic", 10,
            std::bind(&MyNode::topic_callback, this, std::placeholders::_1));
    }

C++功能包构建

在 ROS2 开发中,依赖管理和库的查找主要通过 CMakeLists.txtpackage.xml 实现,具体步骤如下:

  1. find_package() 查找 ROS2 包。
  2. ament_target_dependencies() 将依赖包关联到目标。
  3. install() 安装可执行文件。
  4. ament_export_dependencies() 导出包的依赖关系。
  5. package.xml 声明编译时和运行时依赖。
  6. 通过 colconament_cmake 构建和管理依赖。

 以下是一个典型的CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.5)
project(my_cpp_package)

# 查找依赖库
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

# 添加可执行文件
add_executable(my_cpp_node src/my_cpp_node.cpp)

# 链接依赖库
ament_target_dependencies(my_cpp_node rclcpp std_msgs)

# 安装可执行文件
install(TARGETS
  my_cpp_node
  DESTINATION lib/${PROJECT_NAME})

# 使package能够被ament构建
ament_package()

标签:std,函数,package,前置,基础知识,main,环境变量,ROS2
From: https://blog.csdn.net/Huizhongs/article/details/137174865

相关文章

  • 电脑键盘功能基础知识汇总
    电脑键盘是我们平时使用电脑时最常用的输入设备之一,了解键盘的基本功能,不见能提升工作效率,还能让我们在使用电脑时更加得心应手。今天要和大家探讨一下电脑键盘的基础功能,并介绍一些小技巧,帮助大家更好的利用这个工具。在深入了解键盘基本功能之前,我们先一起认识一下键盘的组成部分......
  • 电脑键盘功能基础知识汇总
    电脑键盘是我们平时使用电脑时最常用的输入设备之一,了解键盘的基本功能,不见能提升工作效率,还能让我们在使用电脑时更加得心应手。今天要和大家探讨一下电脑键盘的基础功能,并介绍一些小技巧,帮助大家更好的利用这个工具。在深入了解键盘基本功能之前,我们先一起认识一下键盘的组成部分......
  • 面试-JS基础知识-作用域和闭包、this
    函数作为返回值functioncreate(){consta=100returnfunction(){console.log(a)//a在这里是自由变量,向上寻找}}constfn=create()consta=200fn()//100函数作为参数functionprint(fn){consta=13fn()}consta=100functionfn(......
  • 第一章 网页制作的基础知识
    1.1认识网页和网站1.网页和网站以及重要常用术语网页和网站的区别:网页是由HTML编写,通过WWW网传输:功能主要展示信息网站是由多个网页的集合;功能多样化,能进行用户的交互重要常用术语:URL2.静态和动态网页静态网页和动态网页的区别静态网页HLML和CSS       ......
  • 第一章 网页制作的基础知识
    1.1认识网页网站1.1.1网页、网站网页和网站的区别:网页和网站之间的主要区别可以用表格对比的形式更清楚地说明,如下图所示:常用术语:Interner(全球性网络)WWW(万维网)URL(统一资源定位符,指定通信协议和地址)IP(网际协议)域名(网站名称,全世界唯一,书写格式:机构名.主机名.类别......
  • arm64高速缓存基础知识
    高速缓存的替换策略随机法:随机地确定替换的高速缓存行,由一个随机数产生器产生随机数来确认替换行FIFO法:选择最先调入的高速缓存行进行替换LRU法:最少使用的行优先替换。高速缓存的共享属性内部共享的高速缓存通常指的是CPU内部集成的高速缓存,它们最靠近CPU内核外部......
  • 《教育基础知识与能力》
    1.简述政治经济制度对教育的制约政治经济制度决定教育的性质;政治经济制度决定教育的宗旨和目的;政治经济制度决定教育的领导权;政治经济制度决定受教育权;政治经济制度决定教育内容和教育管理体制;2.简述个体身心发展的一般规律个体身心发展具有顺序性。它是有个由低级到高......
  • C++入门基础知识61——【关于C++继承】
    成长路上不孤单......
  • C++入门基础知识60——【关于C++ 类 & 对象】
    成长路上不孤单......
  • C++入门基础知识59——【关于C++数据结构】
    成长路上不孤单......