ROS2 + C++ 节点(自用笔记)

本文详细介绍了使用C++在ROS2中创建并运行节点的步骤。包括创建工作空间和功能包,使用RCLCPP编写节点代码,对代码进行分析,最后进行编译运行。通过一系列操作,成功实现了一个节点的运行,为ROS2开发提供了实践指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

留空



前言

自用


一、创建工作空间和功能包

1、工作空间

(1)Ctrl+Win+T开启终端

(2)创建一个叫towm_ws的工作空间

mkdir -p towm_ws

(3)进入工作空间

cd towm_ws

(4)在工作空间中创建一个文件夹src存放功能包

mkdir -p src

(5)编译工作空间

colcon build

在执行colcon build之前,通常需要先进入工作空间并创建一个空的src文件夹。colcon build命令会自动生成install、build、log文件夹。
在这里插入图片描述

2、功能包

(1)进入src文件夹

cd src

(2)创建一个基于C++learning_node功能包

ros2 pkg create learning_node --build-type ament_cmake --dependencies rclcpp

在这里插入图片描述
(3)在Vscode中打开src
在这里插入图片描述
打开后可以看见刚刚创建的功能包
在这里插入图片描述

二、使用RCLCPP编写节点

1、创建节点

在vscode中,learning_node -> 新建文件 -> wang2_node.cpp
在这里插入图片描述
在这里插入图片描述

2、编写代码

(1)完整代码

#include "rclcpp/rclcpp.hpp"

class LearningNode : public rclcpp::Node
{

    public:
        LearningNode(std::string name) : Node(name)
        {
            RCLCPP_INFO(this->get_logger(),"节点%s已启动",name.c_str());
        }
    private:
        
};

int main(int argc,char** argv)
{
    rclcpp::init(argc,argv);
    auto node = std::make_shared<LearningNode>("wang2");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

(2)每次编写完代码记得修改CmakeLists.txt,添加以下代码

add_executable(wang2_node src/wang2.cpp)
ament_target_dependencies(wang2_node rclcpp)

install(TARGETS
    wang2_node
    DESTINATION lib/${PROJECT_NAME}
)

在这里插入图片描述

三、分析代码

1、主函数:程序的入口

 编写主函数的步骤:
 (1)初始化rclcpp
 (2)产生一个节点
 (3)运行节点
 (4)停止运行
 (5)return 0
int main(int argc,char** argv)
{
    rclcpp::init(argc,argv);
    auto node = std::make_shared<LearningNode>("wang2");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

(1)初始化ROS2客户端库。这是创建ROS2节点之前必须做的第一步

rclcpp::init(argc,argv);

可以看看这篇文章:理解argc和argv是什么

(2)创建一个叫“wang2”的节点

auto node = std::make_shared<LearningNode>("wang2");

std::make_shared<LearningNode>("wang2"):这部分代码使用std::make_shared函数创建了一个指向LearningNode对象的shared_ptr智能指针。LearningNode是一个自定义的类,继承自ROS2的rclcpp::Node类。在这里,通过make_shared函数创建了一个名为node的智能指针,并将其初始化为指向一个具有名称"wang2"的LearningNode对象。

auto node = ...:使用auto关键字可以让编译器根据右侧表达式的类型推断出node的类型,这里推断出node是一个指向LearningNode对象的shared_ptr智能指针。

综合起来,这行代码的作用是创建一个名为node的智能指针,指向一个具有名称"wang2"的LearningNode对象(这样就是创建了一个ROS 2节点),并赋予了节点一个特定的名称,以便在程序中引用和操作该节点。

(3)使节点进入事件循环,开始运行节点的回调函数并处理 ROS2中的事件。这个循环会持续运行,直到被外部因素(如程序结束或收到信号)打断。

rclcpp::spin(node);

(4)关闭ROS2系统,清理资源并终止节点运行

rclcpp::shutdown();

2、LearningNode类

class LearningNode : public rclcpp::Node
{

    public:
        LearningNode(std::string name) : Node(name)
        {
            RCLCPP_INFO(this->get_logger(),"节点%s已启动",name.c_str());
        }
        
    private:
         
};

(1)定义了一个继承自rclcpp::Node的类LearningNode

class LearningNode : public rclcpp::Node

class LearningNode :定义了一个名为LearningNode的类
: public rclcpp::Node:表示LearningNode类继承自rclcpp::Node类。这意味着LearningNode类将获得rclcpp::Node类的所有成员变量和方法,同时还可以添加自己的成员变量和方法。

(2) 表示接下来的成员变量和方法在类的访问权限部分

 public/private:

pubilc:接下来的成员变量和方法是类的公共访问权限部分,可以被外部访问。
private:接下来的成员变量和方法是类的私有访问权限部分,只能在类的内部访问。

(3)这是LearningNode类中公有的构造函数

LearningNode(std::string name) : Node(name)
{
	
}

LearningNode(std::string name): 这是LearningNode类的构造函数,它接受一个 std::string类型的参数name

: Node(name): 这部分代码调用基类rclcpp::Node的构造函数,并将前部分代码的name参数传递给它。这意味着当你创建一个LearningNode对象时,它首先会调用rclcpp::Node的构造函数来初始化基类部分。

(4)打印一条消息(类似于C语言中的"printf")

RCLCPP_INFO(this->get_logger(),"节点%s已启动",name.c_str());

RCLCPP_INFO: 这是一个ROS 2的宏,用于记录信息级别的日志。在ROS 2中,日志系统用于记录不同级别的信息,如调试、信息、警告和错误等。

this->get_logger(): this 是一个指向当前对象的指针。get_logger() 是从基类 rclcpp::Node 继承的一个方法,它返回一个与当前节点关联的日志记录器对象。通过这个日志记录器,我们可以记录与节点相关的日志信息。

"节点%s已启动": 这是一个格式字符串,用于定义日志消息的格式。%s 是一个占位符,它将被后面的参数替换。在这个例子中,%s 将被替换为节点的名称。

name.c_str(): name 是一个 std::string 类型的变量,它包含了节点的名称。c_str()std::string类的一个方法,用于返回一个指向以空字符结尾的字符数组的指针,这个字符数组就是该字符串的C风格表示。这是因为RCLCPP_INFO宏的格式化字符串参数需要C风格的字符串(即 char* 类型)。

综上所述,这行代码的作用是:使用当前节点的日志记录器,输出一条信息级别的日志,内容大致为“节点[节点名称]已启动”,其中[节点名称]是传递给构造函数的name参数的值。


四、编译

下面是简洁的叙述,想要了解深入一点,可以看看这篇ROS2编译运行节点代码

打开终端,输入命令行

(1)进入工作空间

cd towm_ws

(2)这个命令告诉计算机去构建一个叫做learning_node的ROS2软件包。就像在工厂里生产一个特定的产品一样。

colcon build --packages-select learning_node

(3)这个命令告诉计算机设置一些东西,让它知道在哪里找到刚刚构建好的软件包。这就像是在告诉工厂工人,新生产的产品应该放在哪个仓库或货架上,以便后续可以轻松地找到并使用它们。

source install/setup.bash

(4)这个命令告诉计算机去运行learning_node软件包中的wang2节点,

ros2 run learning_node wang2_node

在这里插入图片描述

(5)运行结果

[INFO] [1714027571.680855970] [wang2]: 节点wang2已启动

到此,我们就成功的运行了一个节点!

总结

自用

创建ROS C++节点的步骤如下: 1. 安装ROS:如果你还没有安装ROS,可以参考ROS官方文档进行安装。 2. 创建ROS工作空间:在终端中输入以下命令,创建一个ROS工作空间。 ``` $ mkdir -p ~/catkin_ws/src $ cd ~/catkin_ws/ $ catkin_make ``` 3. 创建ROS包:在工作空间的src目录下,使用catkin_create_pkg命令创建一个ROS包。 ``` $ cd ~/catkin_ws/src $ catkin_create_pkg my_package roscpp std_msgs ``` 这里创建了一个名为my_package的ROS包,依赖于roscpp和std_msgs。 4. 创建节点:在my_package包下,创建一个名为my_node.cpp的文件,作为节点的源文件。 ``` $ cd ~/catkin_ws/src/my_package $ touch my_node.cpp ``` 在my_node.cpp中,可以使用roscpp库提供的API编写节点代码。以下是一个简单的示例: ``` #include <ros/ros.h> #include <std_msgs/String.h> void messageCallback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char **argv) { ros::init(argc, argv, "my_node"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("my_topic", 10, messageCallback); ros::spin(); return 0; } ``` 在这个示例中,我们订阅了一个名为my_topic的话题,并在回调函数中打印出接收到的消息。 5. 编译节点:在终端中输入以下命令,编译my_package包。 ``` $ cd ~/catkin_ws/ $ catkin_make ``` 如果编译成功,应该能够在devel/lib/my_package目录下找到生成的可执行文件my_node。 6. 运行节点:在终端中输入以下命令,启动my_node节点。 ``` $ source devel/setup.bash $ rosrun my_package my_node ``` 如果一切正常,节点应该已经开始运行,并在终端中输出接收到的消息。 以上就是创建ROS C++节点的基本步骤。当然,实际的开发可能涉及到更多的细节和复杂性,需要根据具体情况进行调整和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值