python消息发布器与订阅器代码解析

源代码

#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

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

逐行解析

#!/usr/bin/env python  

每个Python ROS 节点都会在顶部显示此声明。第一行确保您的脚本作为Python脚本执行。

import rospy from std_msgs.msg import String

 

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
这部分代码定义了讲话者与其余ROS的接口。pub = rospy.Publisher(“chatter”,String,queue_size = 10)声明您的节点使用消息类型String发布到chatter主题。这里的字符串实际上是类std_msgs.msg.String。queue_size是若消息订阅的较慢,限制消息发布的数量,,下一行rospy.init_node(NAME,...)非常重要,因为它告诉rospy节点的名称 - 直到rospy有这个信息,它才能开始与ROS Master通信。在这种情况下,您的节点将采用名称说话者。注意:名称必须是基本名称,即它不能包含任何斜杠“/”。anonymous = True通过在NAME末尾添加随机数来确保您的节点具有唯一名称。有关节点初始化选项的更多信息,请参阅rospy文档中的初始化和关闭 - 初始化ROS节点

    rate = rospy.Rate(10) # 10hz
此行创建Rate对象速率。借助其方法sleep(),它提供了一种以所需速率循环的便捷方式。它的参数为10,我们应该期望每秒循环10次(只要我们的处理时间不超过1/10秒!)
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()
这个循环是一个相当标准的rospy构造:检查rospy.is_shutdown()标志然后做工作。你必须检查is_shutdown()以检查你的程序是否应该退出(例如,如果有Ctrl-C或其他)。在这种情况下,“work”是对pub.publish(hello_str)的调用,它将字符串发布到我们的聊天主题。循环调用rate.sleep(),它睡眠的时间足够长,可以通过循环保持所需的速率。这个循环还调用rospy.loginfo(str),它执行三重任务:消息被打印到屏幕,它被写入Node的日志文件,并被写入rosoutrosout对于调试非常方便:您可以使用rqt_console来提取消息,而不必使用Node的输出找到控制台窗口。

std_msgs.msg.String是一种非常简单的消息类型,因此您可能想知道发布更复杂类型的样子。一般的经验法则是构造函数args的顺序与.msg文件中的顺序相同。您也可以不传递参数并直接初始化字段,例如

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass
除了标准的Python __main__检查之外,这还会捕获一个rospy.ROSInterruptException异常,当按下Ctrl-C或者你的节点关闭时,rospy.sleep()和rospy.Rate.sleep()方法可以抛出该异常。引发此异常的原因是,您不会在sleep()之后意外地继续执行代码。

下面创建订阅者的节点源代码

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
    
def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # node are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber("chatter", String, callback)

    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    listener()

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
发布(C++)代码如下: ```c++ #include <iostream> #include <string> #include <vector> #include <cstring> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> using namespace std; struct msgbuf { long mtype; char mtext[1024]; }; int main() { key_t key = ftok("message_queue", 1); int msgid = msgget(key, IPC_CREAT | 0666); if (msgid == -1) { cerr << "Error creating message queue" << endl; return -1; } while (true) { double num; string str; cout << "Enter a number or a string: "; if (cin >> num) { msgbuf buf; buf.mtype = 1; memcpy(buf.mtext, &num, sizeof(num)); msgsnd(msgid, &buf, sizeof(num), 0); } else { cin.clear(); cin.ignore(); getline(cin, str); msgbuf buf; buf.mtype = 2; strcpy(buf.mtext, str.c_str()); msgsnd(msgid, &buf, str.size() + 1, 0); } } return 0; } ``` 订阅(python)代码如下: ```python import struct import sys import os import time from ctypes import * from numpy import * class msgbuf(Structure): _fields_ = [ ("mtype", c_long), ("mtext", c_char * 1024) ] def main(): key = os.ftok("message_queue", 1) msgid = os.msgget(key, 0666) if msgid == -1: print("Error creating message queue") return -1 while True: buf = msgbuf() if os.msgrcv(msgid, byref(buf), sizeof(double), 1, os.MSG_NOERROR | os.IPC_NOWAIT) != -1: num = struct.unpack('d', buf.mtext)[0] print(f"Received number: {num}") if os.msgrcv(msgid, byref(buf), sizeof(buf.mtext), 2, os.MSG_NOERROR | os.IPC_NOWAIT) != -1: str_ = buf.mtext.decode('utf-8') print(f"Received string: {str_}") time.sleep(0.5) if __name__ == '__main__': main() ``` 这两个程序需要在同一个操作系统下运行。发布程序会等待用户输入消息,如果是浮点数则发送消息类型为1的消息,如果是字符串则发送消息类型为2的消息订阅程序会不断接收消息队列中的消息,如果消息类型为1,则按照浮点数解析消息并输出;如果消息类型为2,则按照字符串解析消息并输出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值