ROS学习记录(三)——Publisher和Subscriber编程实现

ROS学习记录(一)——基本概念
ROS学习记录(二)——创建功能包
ROS学习记录(三)——Publisher和Subscriber编程实现
ROS学习记录(四)——话题消息的定义与使用
ROS学习记录(五)——Client和Server编程实现

平台:Ubuntu18.04,ROS-melodic
实验目的:学习发布者Publisher和订阅者Subscriber的编程实现。

Publisher可以创建新话题,并可以向其发消息。Subscriber是订阅话题的。
在定义Publisher的时候,需要明确消息数据类型,而定义Subscriber时不用
Subscriber涉及到回调函数,Publisher没有
ros::spin()、ros::spinOnce()用在接受数据的情况下,如Subscriber、Server中

实验1:发布者Publisher编程

实验1(C语言版本)

设想编写Publisher,控制海龟进行匀速圆周运动。

步骤:

  1. 依次执行mkdir ~/catkin_wscd catkin_wsmkdir srccatkin_init_workspace进行初始化工作空间,catkin_create_pkg test_pkg roscpp rospy std_msgs geometry_msgs创建功能包,cd ~/catkin_ws/src/test_pkg/src进入功能包存放代码的地方,touch turtle_test.cpp
  2. 打开turtle_test.cpp文件,复制下方代码,粘贴进去,保存并关闭文件
/**
 * 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
 */
 
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc, char **argv)
{
	// ROS节点初始化
	ros::init(argc, argv, "velocity_publisher"); // 节点名字为“velocity_publisher”

	// 创建节点句柄
	ros::NodeHandle n;  // 句柄是用来管理节点资源的,在后续调用操作中

	// 创建一个Publisher,发布名为/turtle1/cmd_vel的话题,消息类型为geometry_msgs::Twist,队列长度10
	ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
	// 上述为交代了向哪个话题发布数据,即“/turtle1/cmd_vel”。队列大小就相当于发布的数据缓冲区的大小

	// 设置循环的频率
	ros::Rate loop_rate(10);
	// 下方有一个while循环,用来设定它循环的频率

	int count = 0;
	while (ros::ok())
	{
	    // 初始化geometry_msgs::Twist类型的消息
		geometry_msgs::Twist vel_msg;
		vel_msg.linear.x = 0.5;
		vel_msg.angular.z = 0.2;

	    // 发布消息
		turtle_vel_pub.publish(vel_msg);
		ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z);

	    // 按照循环频率延时
	    loop_rate.sleep();
	}

	return 0;
}

  1. 打开~/catkin_ws/src/test_pkg/CMakelist.txt
    添加add_executable(turtle_test src/turtle_test.cpp)
    target_link_libraries(turtle_test ${catkin_LIBRARIES})两行代码在
###########
## Build ##
###########

模块后,分别表示将turtle_test.cpp编译成名为turtle_test的可执行文件;并把${catkin_LIBRARIES}指向的库(即:可执行二进制代码)链接到它身上。

  1. cd ~/catkin_wscatkin_make等待编译完成 这里注意,编译一定是要进入工作空间的根目录下,也就是~/catkin_ws,再执行source devel/setup.bash确保系统环境变量可以找到你的代码
  2. 进行实验:打开一个新终端,启动ROS masterroscore,再打开一个新终端,启动turtle_noderosrun turtlesim turtlesim_node,启动成功时,屏幕上出现一个乌龟窗口,接下来调用上述产生的功能包,再打开一个新终端rosrun test_pkg turtle_test

注意,运行的trutle_test存放在devel/lib/test_pkg下

  1. 看到乌龟在做匀速圆周运动,成功。

实验1(python语言版本)

注意点:在使用python语言版本的程序时,程序脚本需要有可执行权限,可以使用chomd +x 文件名赋予可执行权限

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist

import rospy
from geometry_msgs.msg import Twist

def velocity_publisher():
	# ROS节点初始化
    rospy.init_node('velocity_publisher', anonymous=True)

	# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)

	#设置循环的频率
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():
		# 初始化geometry_msgs::Twist类型的消息
        vel_msg = Twist()
        vel_msg.linear.x = 0.5
        vel_msg.angular.z = 0.2

		# 发布消息
        turtle_vel_pub.publish(vel_msg)
    	rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z)

		# 按照循环频率延时
        rate.sleep()

if __name__ == '__main__':
    try:
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass

有一个问题,只要你将source ~/catkin_ws/devel/setup.bash添加进了.bashrc文件里,终端就可以无视路径,随时随地就可以直接调用功能包了。

实验2:订阅者Subscriber编程

运行海龟仿真器,作为Publisher发布数据,实验编写Subscriber达到订阅海龟Pose信息。
话题名/turtle1/pose。
订阅信息:turtlesim::Pose
框架图:
在这里插入图片描述

实验2(C语言版本)

步骤:

  1. cd ~/catkin_ws/src/test_pkg/src进入功能包存放代码的地方,touch turtle_test_subscriber.cpp
  2. 打开turtle_test_subscriber.cpp文件,复制下方代码,粘贴进去,保存并关闭文件
/**
 * 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
 */
 
#include <ros/ros.h>
#include "turtlesim/Pose.h"

// 接收到订阅的消息后,会进入消息回调函数
void poseCallback(const turtlesim::Pose::ConstPtr& msg) //turtlesim::Pose是订阅的话题发布的信息类型,msg是消息变量指针
{
    // 将接收到的消息打印出来
    ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}

int main(int argc, char **argv)
{
    // 初始化ROS节点,所有节点进行之前都要做的一件事:初始化节点
    ros::init(argc, argv, "pose_subscriber");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为/turtle1/pose的话题topic,注册回调函数poseCallback
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
    // 队列长度为10,作为接收到信息的缓冲区大小,poseCallback是回调函数
    //回调函数的目的是:订阅者不知道发布者什么时候会发信息过来,所以需要有回调函数,起到一个监听的作用

    // 循环等待调用回调函数
    ros::spin();
    //持续查看队列是否有消息,有消息就调用回调函数;没有就继续等待,阻塞在此处。

    return 0;
}

需要注意:回调函数里的操作一定要是高效的,如果不高效的话,当新消息来了,也不会再调用回调函数进行处理,会卡在里面。即回调函数不会嵌套调用。

  1. 打开~/catkin_ws/src/test_pkg/CMakelist.txt
    添加add_executable(turtle_test_subscriber src/turtle_test_subscriber.cpp)
    target_link_libraries(turtle_test_subscriber ${catkin_LIBRARIES})两行代码在
###########
## Build ##
###########

模块后,分别表示将turtle_test_subscriber.cpp编译成名为turtle_test_subscriber的可执行文件;并把${catkin_LIBRARIES}指向的库(即:可执行二进制代码)链接到它身上。

  1. cd ~/catkin_wscatkin_make等待编译完成 这里注意,编译一定是要进入工作空间的根目录下,也就是~/catkin_ws,再执行source devel/setup.bash确保系统环境变量可以找到你的代码
  2. 进行实验:打开一个新终端,启动ROS masterroscore,再打开一个新终端,启动turtle_noderosrun turtlesim turtlesim_node,启动成功时,屏幕上出现一个乌龟窗口,接下来调用上述产生的功能包,再打开一个新终端rosrun turtlesim turtle_teleop_key,再打开一个新终端rosrun test_pkg turtle_test_subscriber
  3. 通过上下左右操作海龟运动,turtle_test_subscriber实时打印出海龟坐标位置,成功。

实验2(python语言版本)

注意点:在使用python语言版本的程序时,程序脚本需要有可执行权限,可以使用chomd +x 文件名赋予可执行权限

使用python脚本,只需要将.py脚本拷贝到test_pkg/src中,给予可执行权限,直接用rosrun test_pkg 脚本.py即可。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose

import rospy
from turtlesim.msg import Pose

def poseCallback(msg):
    rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)

def pose_subscriber():
	# ROS节点初始化
    rospy.init_node('pose_subscriber', anonymous=True)

	# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    rospy.Subscriber("/turtle1/pose", Pose, poseCallback)

	# 循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    pose_subscriber()

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: ROS中的publishersubscriber是用于实现节点之间通信的两个重要概念。 publisher是一个节点,它可以将数据发布到一个特定的主题(topic)上。其他节点可以订阅这个主题,以接收该节点发布的数据。publishersubscriber之间的通信是异步的,即publisher不需要等待subscriber的响应。 subscriber是一个节点,它可以订阅一个特定的主题(topic),以接收其他节点发布的数据。当有新的数据发布到该主题上时,subscriber会自动接收并处理这些数据。subscriber可以订阅多个主题,以接收来自不同节点的数据。 通过使用publishersubscriberROS节点可以实现分布式计算,从而更好地完成各种任务。 ### 回答2: ROS (Robot Operating System)是一个开源机器人操作系统,它提供了一系列工具和库,使得机器人的开发、测试和部署更加简单、高效。ROS的核心概念之一就是发布/订阅模式(Publisher-Subscriber),这是ROS实现消息传递机制的基础。 ROS Publisher(发布者)是指向ROS消息总线发布消息的节点。节点可以向一个或者多个主题(Topic)发布消息。主题是让多个节点之间进行通信的一种机制。当一个Publisher节点发布了一条消息后,所有订阅了该主题的Subscriber就会接收到这条消息。发布者将消息发布到主题上时,需要指定主题的名称和消息类型。ROS提供了各种不同类型的消息,如字符串、数组、图像等。发布者节点用于发布消息会向主题发送一个消息头(Header),包含时间戳(Stamp)、FRAME_ID等信息,并在这个消息头中注册一些回调函数,以便接收机制可以使用这些信息来更优雅、有效的处理消息。 ROS Subscriber(订阅者)是指向ROS消息总线订阅消息的节点。Subscriber将使用主题的名称和消息类型来订阅特定的主题。当主题被发布者发布消息时,所有订阅主题的Subscriber节点都将接收到这条消息。Subscriber节点使用回调函数处理消息。回调函数是将由节点执行的函数,这些函数会在消息到达时被调用。当Subscriber节点收到一条消息时,它会触发回调函数,并将接收到的消息作为参数传递给回调函数。回调函数然后处理消息,并根据需要执行其他操作。Subscriber节点的实现可以是同步的,也可以是异步的。同步的Subscriber节点会在每次接收到消息后立即处理,异步的Subscriber节点可能会在更长的时间内缓冲消息,以便将消息打包成一组或仅处理特定类别的消息。 总之,ROS PublisherSubscriberROS中非常重要的概念,它们允许节点之间通过主题交换消息,实现ROS系统的消息传递机制。通过发布/订阅模式,节点之间可以共享数据,实现对机器人各个部分的控制和监视。同时,发布/订阅模式提供了一种透明的、分布式的、去中心化的消息通信机制,允许ROS系统在各种硬件和操作系统平台上运行,并与外部系统长期保持稳定连接。 ### 回答3: ROS PublisherSubscriber是ROBOT OPERATING SYSTEM(ROS)中经常使用的两种通信方式,用于在ROS系统中的不同模块之间进行信息传递和数据共享。 PublisherROS中的一种发布者,它可以将数据发布到指定话题(topic)上。发布者可以是一个传感器,比如激光雷达,也可能是某个算法模块,比如机器人路径规划。发布者将数据发送到话题,然后该话题上的所有订阅者都可以接收到该数据。 SubscriberROS中的一种订阅者,它可以订阅某个话题上的数据。一旦订阅者订阅了某个话题,它就可以在该话题上接收该话题上所有的数据。订阅者可能是一个控制模块,用于接收激光雷达数据,并控制机器人的行动。当订阅者收到数据后,它会进行特定的处理,如执行行动或更新机器人的状态等。 ROS PublisherSubscriber的优点在于它们提供了一种分布式系统的通信方式,这使得多个系统之间的数据共享变得更加容易和方便。在ROS系统中,一个发布者可以同时向多个话题发布数据,而订阅者也可以订阅多个话题上的数据。这使得ROS在机器人控制和其他领域中都具有广泛的应用。 在ROS中,PublisherSubscriber的使用非常简单。开发人员只需要在ROS节点中定义一个发布者和一个订阅者即可。ROS提供了许多现成的库和工具,可以帮助开发人员轻松创建发布者和订阅者,使得开发过程更加简单和快速。 总之,ROS PublisherSubscriberROS系统中非常重要的两个组件,它们可以方便地完成机器人控制、感知和决策等任务。这些组件的优点在于可以实现分布式通信,从而促进信息的共享和机器人系统的自主性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值