6.2. Image Server Client¶

We also configure the Image Server client, which allows this module to communicate with the image server. It does this much in the same way that a Publisher publishes messages… when the module is ready for a new image it broadcasts that it is waiting for an image. The image server is a subscriber of these broadcasts, and once it hears this message it will provide an image to the model server.

The reason we have chosen this method rather than providing a service is that a service call blocks the kernel from processing more code until the call has completed and a response has been received, whereas a publisher will simply continue to broadcast a message, regardless if it is received or not. This ensures that processes are not tied up in a service call.

Once the Image Server hears that the client is in need of an image it begins the process and communicates to all nodes after it has updated the model server with the new image. It then changes these nodes “waiting” status to false via the ImageServerClient.callback. This ensures that while the module is engaging the model server the image server does not wastefully deliver images which no module will use, potentially reducing bandwidth by nearly 87% (assuming that an request is made twice a second, and the image server is reciving images at the rate of 16 FPS; since only two of those frames out of 16 can be used, only two will be delivered to the model server which would otherwise receive all 16!).

from viper_toolkit import Dissect
import inspect
from image_server import ImageServerClient
source = inspect.getsource(ImageServerClient)
print (source)
class ImageServerClient(object):
    def __init__(self, name: str):
        self._name = name
        self.waiting = Bool()
        self.remote_status = Bool()
        self.setup_publisher()
        self.setup_subscriber()
        
    def setup_publisher(self):
        self.pub = rospy.Publisher(
            f'image_request/{self._name}',
            Bool,
            queue_size=1
            )
        rospy.loginfo(
            f'[{self._name}] Image server request services online.'
            )
            
    def update(self, state: bool):
        self.waiting.data = state
        self.pub.publish(self.waiting)
   
    def status(self, entity = "server"):
        if entity == "server":
            return self.remote_status.data
        else:
            return self.waiting.data
    
    def refresh(self, state: bool):
        self.waiting.data = state
        
    def setup_subscriber(self):
        rospy.Subscriber(
            'image_server/status',
            Bool,
            self.callback,
            queue_size=1
            )
        rospy.loginfo(
            f'[{self._name}] Subscribed to Image Server.'
            )

    def callback(self, msg):
        self.remote_status = msg