Hi everyone I would like to implement a python ros node that subscribes to a topic (odom in my case) and retransmits part of the message on a socket. I have already implemented such a thing:
#!/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()
now I have two problems: The first one that inside the callback function I can't use
self.csocket.send(string.encode())
and i don't know how to send the string to the client.
The second is that if the client disconnects I cannot exit the callback function
some idea? I'm a beginner with python and ros, thanks in advance
EDIT: I founded a solution. maybe it's not elegant but it works.
#!/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()
I needed more clients to connect and that when the connection with a client was lost (for example because the client was closed) the thread created by the server ended. with my solution for each thread created by the server a subscriber is also created, probably it would be better to use a single subscriber for all the threads created, but for now I have not been able to do it.