From 0c5b47ae166f168b1107d588018e697110693228 Mon Sep 17 00:00:00 2001 From: Storm Date: Thu, 16 Oct 2025 14:57:53 +0200 Subject: [PATCH] refactor: removed hardcoded IP and port and moved video functions from main to the VideoSender class ref: N25B-171 --- src/robot_interface/endpoints/socket_base.py | 10 +++- src/robot_interface/endpoints/video_sender.py | 55 +++++++++++++++++- src/robot_interface/main.py | 57 +------------------ 3 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/robot_interface/endpoints/socket_base.py b/src/robot_interface/endpoints/socket_base.py index a5124f6..7ca3289 100644 --- a/src/robot_interface/endpoints/socket_base.py +++ b/src/robot_interface/endpoints/socket_base.py @@ -15,7 +15,7 @@ class SocketBase(object): self.name = name self.socket = None - def create_socket(self, zmq_context, socket_type, port): + def create_socket(self, zmq_context, socket_type, port, options=[]): """ Create a ZeroMQ socket. @@ -27,8 +27,16 @@ class SocketBase(object): :param port: The port to use. :type port: int + + :param options: A list of options to be set on the socket. The list contains tuples where the first element contains the option + and the second the value, for example (zmq.CONFLATE, 1). + :type options: [(zmq socket option, option value)] """ self.socket = zmq_context.socket(socket_type) + + for option, arg in options: + self.socket.setsockopt(option,arg) + self.socket.connect("tcp://localhost:{}".format(port)) def close(self): diff --git a/src/robot_interface/endpoints/video_sender.py b/src/robot_interface/endpoints/video_sender.py index d0b7ca4..2413281 100644 --- a/src/robot_interface/endpoints/video_sender.py +++ b/src/robot_interface/endpoints/video_sender.py @@ -1,8 +1,61 @@ import zmq +import threading +import qi +import logging from robot_interface.endpoints.socket_base import SocketBase +from robot_interface.state import state + class VideoSender(SocketBase): def __init__(self, zmq_context, port=5556): super(VideoSender, self).__init__("video") - self.create_socket(zmq_context, zmq.PUB, port) \ No newline at end of file + self.create_socket(zmq_context, zmq.PUB, port, [(zmq.CONFLATE,1)]) + + def start_video_rcv(self): + """ + Prepares arguments for retrieving video images from Pepper and starts video loop on a separate thread. + + :param robot_ip: The ip address of the robot to connect with. + :type robot_ip: String + + :param port: The port of the robot. + :type port: int + + :param socket: The ZMQ socket to send the video images over. + :type: VideoSender + """ + app = qi.Application() + app.start() + session = app.session + + video = session.service("ALVideoDevice") + + camera_index = 0 + kQVGA = 2 + kRGB = 11 + FPS = 15 + vid_stream_name = video.subscribeCamera("Pepper Video", camera_index, kQVGA, kRGB, FPS) + thread = threading.Thread(target=self.video_rcv_loop, args=(video, vid_stream_name)) + thread.start() + + def video_rcv_loop(self, vid_service, vid_stream_name): + """ + The main loop of retrieving video images from the robot. + + :param vid_stream: The name of a camera subscription on the video service object vid_service + :type vid_stream: String + + :param vid_service: The video service object that the active Qi session is connected to. + :type vid_service: Object (Qi service object) + + :param socket: The ZMQ socket to send the video images over. + :type: VideoSender + """ + while not state.exit_event.is_set(): + try: + img = vid_service.getImageRemote(vid_stream_name) + #Possibly limit images sent if queuing issues arise + self.socket.send(img[6]) + except: + logging.warn("Failed to retrieve video image from robot.") diff --git a/src/robot_interface/main.py b/src/robot_interface/main.py index 5ab5266..fb48040 100644 --- a/src/robot_interface/main.py +++ b/src/robot_interface/main.py @@ -1,7 +1,5 @@ import logging import time -import qi -import threading import zmq @@ -24,11 +22,7 @@ def main_loop(context): video_sender = VideoSender(context) state.sockets.append(video_sender) - # ip address of robot - robot_ip = "10.211.55.3" - # port of robot - port = 54321 - start_video_rcv(robot_ip, port, video_sender) + video_sender.start_video_rcv() # Sockets that can run on the main thread. These sockets' endpoints should not block for long (say 50 ms at most). receivers = [main_receiver] @@ -54,55 +48,6 @@ def main_loop(context): if time_spent_ms > 50: logging.warn("Endpoint \"%s\" took too long (%.2f ms) on the main thread.", receiver.name, time_spent_ms) -def start_video_rcv(robot_ip, port, socket): - """ - Prepares arguments for retrieving video images from Pepper and starts video loop on a separate thread. - - :param robot_ip: The ip address of the robot to connect with. - :type robot_ip: String - - :param port: The port of the robot. - :type port: int - - :param socket: The ZMQ socket to send the video images over. - :type: VideoSender - """ - socket.socket.setsockopt(zmq.CONFLATE,1) - - app = qi.Application(["cam", "--qi-url", "tcp://{}:{}".format(robot_ip, port)]) - app.start() - session = app.session - - video = session.service("ALVideoDevice") - - camera_index = 0 - kQVGA = 2 - kRGB = 11 - FPS = 15 - vid_stream_name = video.subscribeCamera("Pepper Video", camera_index, kQVGA, kRGB, FPS) - thread = threading.Thread(target=video_rcv_loop, args=(video, vid_stream_name, socket)) - thread.start() - -def video_rcv_loop(vid_service, vid_stream_name, socket): - """ - The main loop of retrieving video images from the robot. - - :param vid_stream: The name of a camera subscription on the video service object vid_service - :type vid_stream: String - - :param vid_service: The video service object that the active Qi session is connected to. - :type vid_service: Object (Qi service object) - - :param socket: The ZMQ socket to send the video images over. - :type: VideoSender - """ - while not state.exit_event.is_set(): - try: - img = vid_service.getImageRemote(vid_stream_name) - #Possibly limit images sent if queuing issues arise - socket.socket.send(img[6]) - except: - logging.warn("Failed to retrieve video image from robot.") def main(): context = zmq.Context()