I tried to send/receive a large video capture image by tcp python socket on ROS-melodic. I need to use subprocess because ROS-melodic is running on python2 but I need python3 libraries.
I have a Server and a Client.
Client : It is a ROS node that sending the received video capture image(its type is 'list') from camera node after subprocess.Popen(['python3', Serverfile])
and client.connect(HOST_IP, HOST_PORT)
Server : It is a python3 code that receiving the data and doing its functions and then sending the new image to Client.
Here is my socket code.
import socket
import json
import sys
BUFSIZE = 4096
def _send(socket, send_data):
json_data = json.JSONEncoder().encode(send_data)
socket.sendall(json_data.encode())
def _recv(socket):
recv_data = socket.recv(BUFSIZE)
json_data = json.loads(recv_data.decode())
return json_data
class Server(object):
backlog = 1
client = None
def __init__(self, host, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Error for using port
self.socket.bind((host, port))
self.socket.listen(self.backlog)
def __del__(self):
self.close()
def accept(self):
if self.client:
self.client.close()
self.client, self.client_addr = self.socket.accept()
return self
def send(self, data):
if not self.client:
raise Exception('Cannot send data, no client is connected.')
_send(self.client, data)
return self
def recv(self):
if not self.client:
raise Exception('Cannot receive data, no client is connected.')
return _recv(self.client)
def close(self):
if self.client:
self.client.close()
self.client = None
if self.socket:
self.socket.close()
self.socket =None
class Client(object):
socket = None
def __init__(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __del__(self):
self.close()
def connect(self, host, port):
self.socket.connect((host, port))
return self
def send(self, data):
if not self.socket:
raise Exception('You have to connect first before sending data.')
_send(self.socket, data)
return self
def recv(self):
if not self.socket:
raise Exception('You have to connect first before receiving data.')
return _recv(self.socket)
def close(self):
if self.socket:
self.socket.close()
self.socket = None
It outputs 'Message too long' when I use socket.SOCK_DGRAM
. So I changed it socket.SOCK_STREAM
then it now outputs 'Connection refused'
Here is a full example, where I used zmq for transferring images from client to server
Client
import rospy
import rospkg
import roslib
import sys
import rospy
import cv2
from std_msgs.msg import String
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import zmq
import numpy as np
class ClientThread():
def __init__(self):
self.context = zmq.Context()
self.footage_socket = self.context.socket(zmq.PUB)
self.footage_socket.connect('tcp://0.0.0.0:5556')
def callback(self, data):
try:
depth_image = bridge.imgmsg_to_cv2(data, "32FC1")
depth_array = np.array(depth_image, dtype=np.float32)
cv2.normalize(depth_array, depth_array, 0, 255, cv2.NORM_MINMAX)
encoded, buffer = cv2.imencode('.jpg', depth_array)
self.footage_socket.send(buffer)
cv2.imshow("Depth Image", depth_array)
cv2.waitKey(3)
except CvBridgeError as e:
print(e)
if __name__ == "__main__":
rospy.init_node('drone_client', anonymous=True)
bridge = CvBridge()
clien_ = ClientThread()
image_sub = rospy.Subscriber("/r200/depth/image_raw", Image, clien_.callback)
rospy.spin()
Server:
from threading import Thread
import cv2
import numpy as np
import pickle
import struct
import zmq
class ServerTread(Thread):
def __init__(self):
Thread.__init__(self)
self.context = zmq.Context()
self.footage_socket = self.context.socket(zmq.SUB)
self.footage_socket.bind('tcp://*:5556')
self.footage_socket.setsockopt_string(zmq.SUBSCRIBE, np.unicode(''))
def run(self):
while True:
frame = self.footage_socket.recv()
npimg = np.frombuffer(frame, dtype=np.uint8)
source = cv2.imdecode(npimg, 1)
print(source.shape)
newthread = ServerTread()
newthread.start()
newthread.join()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.