[英]ROS subscriber to socket in python
大家好,我想实现一个 python ros 节点,它订阅一个主题(在我的例子中是 odom)并在套接字上重新传输部分消息。 我已经实现了这样的事情:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
import socket
import sys
from nav_msgs.msg import Odometry
import struct
from time import sleep
import socket, threading
class ClientThread(threading.Thread):
def __init__(self,clientAddress,clientsocket):
threading.Thread.__init__(self)
self.csocket = clientsocket
print ("New connection added: ", clientAddress)
rospy.init_node('serverOdom', anonymous=True)
rospy.Subscriber('odom',Odometry, callback)
print ("New subscriber 'severOdom' added: ")
def run(self):
rospy.spin()
def callback(msg):
string=str(msg.pose.pose.position.x)+"\n"+str(msg.pose.pose.position.y)+"\n"
try:
##How i can refeer to the socket??
self.csocket.send(string.encode())
print (string)
except socket.error:
print ("Error client lost")
##How to exit from spin()??
if __name__ == '__main__':
LOCALHOST = "192.168.2.150"
PORT = 5005
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((LOCALHOST, PORT))
print("Server started")
print("Waiting for client request..")
while True:
server.listen(1)
clientsock, clientAddress = server.accept()
newthread = ClientThread(clientAddress, clientsock)
newthread.start()
现在我有两个问题:第一个在回调 function 中我无法使用
self.csocket.send(string.encode())
而且我不知道如何将字符串发送给客户端。
第二个是如果客户端断开我不能退出回调 function
一些想法? 我是 python 和 ros 的初学者,在此先感谢
编辑:我建立了一个解决方案。 也许它不优雅但它有效。
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
import socket
import sys
from nav_msgs.msg import Odometry
import struct
from time import sleep
import socket, threading
class ClientThread(threading.Thread):
def __init__(self,clientAddress,clientsocket):
threading.Thread.__init__(self)
self.csocket = clientsocket
print ("New connection added: ", clientAddress)
rospy.init_node('serverOdom', anonymous=True)
rospy.Subscriber('odom',Odometry, callback)
print ("New subscriber 'severOdom' added: ")
def run(self):
while True:
msg = rospy.wait_for_message("odom", Odometry, timeout=None)
string=str(msg.pose.pose.position.x)+"\n"+str(msg.pose.pose.position.y)+"\n"
try:
self.csocket.send(string.encode())
except socket.error:
print ("Error client lost", clientAddress)
return
def callback(msg):
pass
if __name__ == '__main__':
LOCALHOST = ""
PORT = 5005
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((LOCALHOST, PORT))
print("Server started")
print("Waiting for client request..")
while True:
sleep(2)
server.listen(5)
clientsock, clientAddress = server.accept()
newthread = ClientThread(clientAddress, clientsock)
newthread.start()
我需要更多的客户端来连接,当与客户端的连接丢失时(例如因为客户端关闭),服务器创建的线程结束。 对于服务器创建的每个线程,我的解决方案也创建了一个订阅者,可能最好为所有创建的线程使用一个订阅者,但现在我还不能这样做。
如果将回调定义为 ClientThread 的成员,则可以访问 self. 前任
class ClientThread(...):
def callback(self, msg):
self.csocket.send(string.encode())
此外,您的控制流程很不稳定。 节点的所有初始化都应该发生在 main 中; 这就是为什么你感到困惑。 例如python 节点。
此外,您的代码不太有意义,因为它似乎既是服务器又是客户端。
前任。
这是一个轻微的重写,但它并没有真正意义并且不会表现正确。
(除了ros部分应该是正确的)。
就像,您似乎正在尝试使用线程...来完成 ros 的工作,其中每个节点
都已经像一个线程了。
# server_odom.py
# Ros imports
import rospy
from std_msgs.msg import String
from nav_msgs.msg import Ododmetry
# Sys imports
import sys
import socket
import struct
import threading
from time import sleep
class ClientThread(threading.Thread):
def __init__(self,clientAddress,clientsocket):
threading.Thread.__init__(self)
self.csocket = clientsocket
print ("New connection added: ", clientAddress)
rospy.init_node('serverOdom', anonymous=True)
rospy.Subscriber('odom',Odometry, self.callback)
print ("New subscriber 'severOdom' added: ")
def run(self):
rospy.spin()
def callback(self, msg):
string=str(msg.pose.pose.position.x)+"\n"+str(msg.pose.pose.position.y)+"\n"
try:
self.csocket.send(string.encode())
print (string)
except socket.error:
print ("Error client lost")
return
if __name__ == '__main__':
LOCALHOST = ""
PORT = 5005
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((LOCALHOST, PORT))
print("Server started")
print("Waiting for client request..")
while True:
sleep(2)
server.listen(5)
clientsock, clientAddress = server.accept()
newthread = ClientThread(clientAddress, clientsock)
newthread.start()
如果您只是想将里程计消息格式化为字符串或串行缓冲区,那么代码会少得多。
# server_odom_min.py
# Ros imports
import rospy
from std_msgs.msg import String
from nav_msgs.msg import Ododmetry
str_pub = None
def callback(self, msg):
s = String()
s.data = str(msg.pose.pose.position.x)+"\n"+str(msg.pose.pose.position.y)+"\n"
if str_pub:
str_pub.publish(s)
if __name__ == '__main__':
rospy.init_node('server_odom_min')
rospy.Subscriber('odom', Odometry, callback)
str_pub = rospy.Publisher('odom/string', String, queue_size = 1)
rospy.spin()
编辑(回应编辑):我知道你现在在做什么,我的错; 第二个例子并不真正适用于这个问题。 我编辑了我的第一个例子来反映你的意思。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.