0

I want to communicate using subprocess in ros melodic package.

Because ros uses python2 as default, I had some python version problems with python3 libraries. That's why I decided to use a subprocess.

Here are two of my codes: first is a node of ros(as a client), second is a python3 file as a server.
- Client(image_bus.py)

#!/usr/bin/env python
import rospy
import cv2
import numpy as np
import os
import subprocess
from cv_bridge import CvBridge, CvBridgeError
from std_msgs.msg import String
from sensor_msgs.msg import Image
from json_socket import Client

HOST_IP = "127.0.0.1"
HOST_PORT = 9989

class ImageBus:

    def __init__(self):
        self.sub_video_capture = rospy.Subscriber('/video_capture', Image, self.send_to_face_detector)
        self.cvb = CvBridge()
        self.rate = rospy.Rate(2)
        self.client = Client()


    def send_to_face_detector(self, image):
        try:
            cv_image = self.cvb.imgmsg_to_cv2(image, "bgr8")
        except CvBridgeError as e:
            print(e)

        filename = os.path.dirname(os.path.abspath(__file__)) + "/face_detector.py"

        p = subprocess.Popen(["python3", filename])
        print("p : ", p)
        self.rate.sleep()

        # client = Client()
        c = self.client.connect(HOST_IP, HOST_PORT)

        send_data = {}
        send_data['video_cap'] = cv_image

        self.client.send(send_data)

        recv_data = self.client.recv()
        self.rate.sleep()

        self.client.close()


if __name__ == '__main__':
    rospy.init_node('ImageBus', anonymous=False)
    ib = ImageBus()

    try:
        rospy.spin()
    except rospy.ROSInterruptException:
        pass
  • Server(face_detector.py)
import cv2
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import math
from sklearn.decomposition import PCA
import os
import glob
from jsonsocket import Server

BIND_IP = "127.0.0.1"
BIND_PORT = 9989

class FaceDetector:

    def __init__(self):
        self.socket = Server(BIND_IP, BIND_PORT)

    # Some Codes Here

    def check_face(self, frame):
        # Some codes Here

                return boxed_frame

if __name__=="__main__":
    fd = FaceDetector()
    fd.socket.accept()

    while True:
        print("SERVER")
        recv_image = fd.socket.recv()
        if not recv_image:
            break

        video_cap = recv_data['video_cap']

        face_detected_image = fd.check_face(video_cap)

        send_image = {}
        send_image['face_detected_image'] = face_detected_image

        fd.socket.send(send_image)

    fd.socket.close()

And below code is my jsonsocket.py.

import socket
import json

def _send(socket, send_data):
    json_data = json.JSONEncoder().encode(send_data)
    socket.sendall(json_data.encode()) 


def _recv(socket):
    recv_data = socket.recv(4096)
    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()
        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('Cantnot 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 __del__(self):
        self.close()

    def connect(self, host, port):
        self.socket = socket.socket()
        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 receving data.')

        return _recv(self.socket)

    def close(self):
        if self.socket:
            self.socket.close()
            self.socket =None

When I roslaunch this package with my launch file, then It outputs:

File "/catkin_ws/src/jetson/src/image_bus.py", line 37, in send_to_face_detector
    c = self.client.connect(HOST_IP, HOST_PORT)
  File "/catkin_ws/src/jetson/src/json_socket.py", line 67, in connect
    self.socket.connect((host, port))
  File "/usr/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 111] Connection refused

How can I solve this problem?

I tried to change the port number, change the variable name, check where the problem occurs exactly. However, I couldn't find out.

Help me, please. Thank you.

Valerii Boldakov
  • 1,751
  • 9
  • 19
kiera Lee
  • 23
  • 4
  • For the record, it is possible to use python3 with ros, although debugging is up to you. [link](https://medium.com/@beta_b0t/how-to-setup-ros-with-python-3-44a69ca36674) – JWCS Mar 24 '20 at 15:26

1 Answers1

0

Stripped down, this looks purely like an issue with your socket code: you're trying to connect() and the other side isn't allowing it. I notice your socket() calls, however, are empty; try socket.socket(socket.AF_INET, socket.SOCK_DGRAM) instead of the empty call. Try isolating/testing just the server/client, there are other questions that address issues with socket connections.

JWCS
  • 1,120
  • 1
  • 7
  • 17