ROS2- 构建-topic发布者和订阅者-08
RCLCPP实现topic操作
RCLCPP为Node类提供了丰富的API接口,其中就包括创建话题发布者和创建话题订阅者。
控制节点+被控节点
控制节点创建一个话题发布者,发布控制命令(command)话题,接口类型为字符串(string),控制接点通过发布者发布控制命令(前进、后退、左转、右转、停止)
被控节点创建一个订阅者,订阅控制命令,收到控制命令后根据命令内容打印对应速度出来。
创建chapt3_ws工作空间、example_topic_rclcpp功能包和topic_publisher_01.cpp
mkdir -p chapt3/chapt3_ws/src
cd chapt3/chapt3_ws/src
ros2 pkg create example_topic_rclcpp --build-type ament_cmake --dependencies rclcpp
touch example_topic_rclcpp/src/topic_publisher_01.cpp
└── src
└── example_topic_rclcpp
├── CMakeLists.txt
├── include
│ └── example_topic_rclcpp
├── package.xml
└── src
└── topic_publisher_01.cpp
#include "rclcpp/rclcpp.hpp"
class TopicPublisher01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
TopicPublisher01(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<TopicPublisher01>("topic_publisher_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
修改CMakeLists.txt
add_executable(topic_publisher_01 src/topic_publisher_01.cpp)
ament_target_dependencies(topic_publisher_01 rclcpp)
install(TARGETS
topic_publisher_01
DESTINATION lib/${PROJECT_NAME}
)
cd chapt3/chapt3_ws/
colcon build --packages-select example_topic_rclcpp
source install/setup.bash
ros2 run example_topic_rclcpp topic_publisher_01
发布者的创建
参考官网:https://docs.ros2.org/latest/api/rclcpp/
create_publisher 需要传入消息类型(msgT)、话题名称(topic_name)和 服务指令(qos)
消息的interface
消息接口是ROS2通信时必须的一部分,通过消息接口ROS2才能完成消息的序列化和反序列化。
ROS2定义好了常用的消息接口,并生成了C++和Python的依赖文件,可以直接在程序中进行导入。
ament_cmake 类型功能包导入消息接口分为三步
在CMakeLists.txt中导入,具体是先find_packages再ament_target_dependencies。
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(topic_publisher_01 src/topic_publisher_01.cpp)
ament_target_dependencies(topic_publisher_01 rclcpp std_msgs)
在./src/example_topic_rclcpp/package.xml中导入,具体是添加depend标签并将消息接口写入。
<buildtool_depend>ament_cmake</buildtool_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
在代码中导入,C++中是#include"消息功能包/xxx/xxx.hpp"。
整体代码如下:
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class TopicPublisher01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
TopicPublisher01(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "%s节点已经启动.", name.c_str());
command_publisher_ = this->create_publisher<std_msgs::msg::String>("command", 10);
// 创建定时器,500ms为周期,定时发布
timer_ = this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&TopicPublisher01::timer_callback, this));
}
private:
// 声明节点
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr command_publisher_;
void timer_callback()
{
// 创建消息
std_msgs::msg::String message;
message.data = "forward";
// 日志打印
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
// 发布消息
command_publisher_->publish(message);
}
// 声名定时器指针
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<TopicPublisher01>("topic_publisher_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
ros2 interface show std_msgs/msg/String
看到其内部包含了一个string data,ROS2会将消息文件转换成一个类,并把其中的定义转换成类的成员函数。
cd chapt3/chapt3_ws/
colcon build --packages-select example_topic_rclcpp # colcon这个命令一定要注意运行的路径是在workspace路径下
source install/setup.bash
ros2 run example_topic_rclcpp topic_publisher_01
另一个窗口:
查看列表
ros2 topic list
输出内容
ros2 topic echo /command
编写订阅者
cd chapt3_ws/src/example_topic_rclcpp
touch src/topic_subscribe_01.cpp
#include "rclcpp/rclcpp.hpp"
class TopicSubscribe01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
TopicSubscribe01(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<TopicSubscribe01>("topic_subscribe_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
CMakeLists.txt
add_executable(topic_subscribe_01 src/topic_subscribe_01.cpp)
ament_target_dependencies(topic_subscribe_01 rclcpp)
install(TARGETS
topic_subscribe_01
DESTINATION lib/${PROJECT_NAME}
)
cd chapt3/chapt3_ws/
colcon build --packages-select example_topic_rclcpp
source install/setup.bash
ros2 run example_topic_rclcpp topic_subscribe_01
root@ubuntu-16:~/stephen/chapt3/chapt3_ws# colcon build --packages-select example_topic_rclcpp
source install/setup.bash
ros2 run example_topic_rclcpp topic_subscribe_01
Starting >>> example_topic_rclcpp
Finished <<< example_topic_rclcpp [4.44s]
Summary: 1 package finished [4.73s]
[INFO] [1749469572.895619578] [topic_subscribe_01]: 大家好,我是topic_subscribe_01.
上面只有订阅者节点 并无功能
create_subscription函数需要实现
编写代码
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class TopicSubscribe01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
TopicSubscribe01(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "大家好,我是%s.", name.c_str());
// 创建一个订阅者订阅话题
command_subscribe_ = this->create_subscription<std_msgs::msg::String>("command", 10, std::bind(&TopicSubscribe01::command_callback, this, std::placeholders::_1));
}
private:
// 声明节点
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr command_subscribe_;
// 收到话题数据的回调函数
void command_callback(const std_msgs::msg::String::SharedPtr msg)
{
double speed = 0.0f;
if(msg->data == "forward")
{
speed = 0.2f;
}
RCLCPP_INFO(this->get_logger(), "收到[%s]指令,发送速度 %f", msg->data.c_str(),speed);
}
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<TopicSubscribe01>("topic_subscribe_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
CMakeLists.txt添加下std_msgs依赖
ament_target_dependencies(topic_subscribe_01 rclcpp std_msgs) # 知识修改这一行 末尾增加std_msgs (参考topic_publisher_01)
packages.xml就不需要了,同一个功能包,已经添加了
colcon build --packages-select example_topic_rclcpp
source install/setup.bash
ros2 run example_topic_rclcpp topic_subscribe_01
另一窗口启动发布者
cd chapt3/chapt3_ws/
source install/setup.bash
ros2 run example_topic_rclcpp topic_publisher_01
效果
sub:
root@ubuntu-16:~/stephen/chapt3/chapt3_ws# colcon build --packages-select example_topic_rclcpp
source install/setup.bash
ros2 run example_topic_rclcpp topic_subscribe_01
Starting >>> example_topic_rclcpp
Finished <<< example_topic_rclcpp [9.52s]
Summary: 1 package finished [9.81s]
[INFO] [1749471011.393608017] [topic_subscribe_01]: 大家好,我是topic_subscribe_01.
[INFO] [1749471022.586113314] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471023.586640002] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471024.586656471] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471025.586613935] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471026.586633255] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471027.586673598] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471028.586600778] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471029.586575787] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471030.586675936] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
[INFO] [1749471031.586729370] [topic_subscribe_01]: 收到[forward]指令,发送速度 0.200000
pub:
root@ubuntu-16:~/stephen/chapt3/chapt3_ws# ros2 run example_topic_rclcpp topic_publisher_01
[INFO] [1749471093.112536733] [topic_publisher_01]: topic_publisher_01节点已经启动.
[INFO] [1749471093.614092743] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471094.114084285] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471094.614078421] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471095.114072903] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471095.614074947] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471096.114058372] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471096.614043448] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471097.114018324] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471097.614060707] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471098.114006809] [topic_publisher_01]: Publishing: 'forward'
[INFO] [1749471098.614025468] [topic_publisher_01]: Publishing: 'forward'
4.python版
cd chapt3/chapt3_ws/src/
ros2 pkg create example_topic_rclpy --build-type ament_python --dependencies rclpy
cd example_topic_rclpy/example_topic_rclpy
touch topic_subscribe_02.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class NodeSubscribe02(Node):
def __init__(self,name):
super().__init__(name)
self.get_logger().info("大家好,我是%s!" % name)
# 创建订阅者
self.command_subscribe_ = self.create_subscription(String,"command",self.command_callback,10)
def command_callback(self,msg):
speed = 0.0
if msg.data=="backup":
speed = -0.2
self.get_logger().info(f'收到[{msg.data}]命令,发送速度{speed}')
def main(args=None):
rclpy.init(args=args) # 初始化rclpy
node = NodeSubscribe02("topic_subscribe_02") # 新建一个节点
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy
touch topic_publisher_02.py
import rclpy
from std_msgs.msg import String
from rclpy.node import Node
class NodePublisher02(Node):
def __init__(self,name):
super().__init__(name)
self.get_logger().info("大家好,我是%s!" % name)
self.command_publisher_ = self.create_publisher(String,"command", 10)
self.timer = self.create_timer(0.5, self.timer_callback)
def timer_callback(self):
"""
定时器回调函数
"""
msg = String()
msg.data = 'backup'
self.command_publisher_.publish(msg)
self.get_logger().info(f'发布了指令:{msg.data}') #打印一下发布的数据
def main(args=None):
rclpy.init(args=args) # 初始化rclpy
node = NodePublisher02("topic_publisher_02") # 新建一个节点
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy
setup.py
修改 注意末尾的,
entry_points={
'console_scripts': [
"topic_publisher_02 = example_topic_rclpy.topic_publisher_02:main",
"topic_subscribe_02 = example_topic_rclpy.topic_subscribe_02:main"
],
},
编译
cd chapt3/chapt3_ws/
colcon build
测试
cd chapt3/chapt3_ws/
source install/setup.bash
ros2 run example_topic_rclpy topic_publisher_02
cd chapt3/chapt3_ws/
source install/setup.bash
ros2 run example_topic_rclpy topic_subscribe_02
效果
root@ubuntu-16:~/stephen/chapt3/chapt3_ws# source install/setup.bash
ros2 run example_topic_rclpy topic_publisher_02
[INFO] [1749471991.589694468] [topic_publisher_02]: 大家好,我是topic_publisher_02!
[INFO] [1749471992.092904438] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471992.592818231] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471993.092611300] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471993.592778126] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471994.092757608] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471994.592724685] [topic_publisher_02]: 发布了指令:backup
[INFO] [1749471995.092957723] [topic_publisher_02]: 发布了指令:backup
source install/setup.bash
ros2 run example_topic_rclpy topic_subscribe_02
[INFO] [1749472015.876325291] [topic_subscribe_02]: 大家好,我是topic_subscribe_02!
[INFO] [1749472016.093318771] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472016.593235108] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472017.093261376] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472017.593319627] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472018.093335419] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472018.593305671] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472019.093244578] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472019.593174787] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472020.093265443] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472020.593029732] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472021.093340110] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2
[INFO] [1749472021.593298624] [topic_subscribe_02]: 收到[backup]命令,发送速度-0.2

浙公网安备 33010602011771号