Skip to main content

Wrapyfi is a wrapper for simplifying Middleware communication

Project description

webpage paper researchgate paperswithcode modularml arXiv doi

codecov Code style: black PyPI - Implementation PyPI - Python Version

PyPI version PyPI total downloads Docker Hub Pulls

License FOSSA status Documentation status

Wrapyfi is a middleware communication wrapper for transmitting data across nodes, without altering the operation pipeline of your Python scripts. Wrapyfi introduces a number of helper functions to make middleware integration possible without the need to learn an entire framework, just to parallelize your processes on multiple machines. Wrapyfi supports YARP, ROS, ROS 2, ZeroMQ, and Websocket.

To integrate Wrapyfi with your scripts, add the decorators describing the transmitting and listening method parameters.

Attribution

Please refer to the following paper when citing Wrapyfi in academic work:

@inproceedings{abawi2024wrapyfi,
  title = {Wrapyfi: A Python Wrapper for Integrating Robots, Sensors, and Applications across Multiple Middleware},
  author = {Abawi, Fares and Allgeuer, Philipp and Fu, Di and Wermter, Stefan},
  booktitle = {Proceedings of the ACM/IEEE International Conference on Human-Robot Interaction (HRI '24)},
  year = {2024},
  organization = {ACM},
  isbn = {79-8-4007-0322-5},
  doi = {10.1145/3610977.3637471},
  url = {https://github.com/fabawi/wrapyfi}
}

Getting Started

Before using Wrapyfi, YARP, ROS, or ZeroMQ must be installed.

  • Follow the YARP installation guide. Note that the iCub package is not needed for Wrapyfi to work and does not have to be installed if you do not intend to use the iCub robot.

  • For installing ROS, follow the ROS installation guide [Ubuntu][Windows]. We recommend installing ROS on Conda using the RoboStack environment. Additionally, the Wrapyfi ROS interfaces must be built to support messages needed for audio transmission ROS Package Index

  • For installing ROS 2, follow the ROS 2 installation guide [Ubuntu][Windows]. We recommend installing ROS 2 on Conda using the RoboStack environment. Additionally, the Wrapyfi ROS 2 interfaces must be built to support messages and services needed for audio transmission and the REQ/REP pattern ROS Package Index

  • ZeroMQ can be installed using pip: pip install pyzmq. The xpub-xsub pattern followed in our ZeroMQ implementation requires a proxy broker. A broker is spawned by default as a daemon process. To avoid automatic spawning, pass the argument start_proxy_broker=False to the method register decorator. A standalone broker can be found here

  • Websocket can be installed using pip: pip install python-socketio. The xpub-xsub pattern followed in our Websocket implementation requires a socket server. We recommend setting the server to run using Flask-SocketIO which can be installed with pip install flask-socketio. Note that the server must be running and also scripted to forward messages to the listening from the publishing client as demonstrated in the example found here

Compatibility

  • Operating System

    • Ubuntu >= 18.04 (Not tested with earlier versions of Ubuntu or other Linux distributions)
    • Windows >= 10 [beta support]:
      • Multiprocessing is disabled. ZeroMQ brokers spawn as threads only
      • Not tested with YARP and ROS 2
      • ROS only tested within mamba/micromamba environment installed using RoboStack
      • ROS and ROS 2 interfaces not tested
      • Installation instructions across Wrapyfi guides and tutorials are not guaranteed to be compatible with Windows 11
    • MacOS 10.14 Mojave planned
  • Python >= 3.6

  • OpenCV >= 4.2

  • NumPy >= 1.19

  • YARP >= v3.3.2

  • ROS Noetic Ninjemys

  • ROS 2 Humble Hawksbill | Galactic Geochelone | Foxy Fitzroy

  • PyZMQ 16.0, 17.1 and 19.0

  • Python-SocketIO >= 5.0.4

Installation

You can install Wrapyfi with pip or from source.

Pip

To install all the necessary components for the majority of common uses of Wrapyfi (e.g., NativeObject, Image, Audio, etc.) using pip, this process installs both Wrapyfi and its dependencies, like NumPy and OpenCV (opencv-contrib-python, opencv-headless, and opencv-python are supported), that are essential for various workloads, along with ZeroMQ being the default middleware. This option is the best for users running Wrapyfi out of the box in a newly created environment (without any middleware installed beforehand), installing numpy, opencv-contrib-python, and pyzmq:

pip install wrapyfi[all]

Note that most plugins require additional dependencies and should be installed separately.

or when installing Wrapyfi on a server (headless) including numpy, opencv-python-headless, and pyzmq:

pip install wrapyfi[headless]

Other middleware such as ROS are environment-specific and require dependencies that cannot be installed using pip. Wrapyfi could and should be used within such environments with minimal requirements to avoid conflicts with existing NumPy and OpenCV packages:

pip install wrapyfi

Source (Pip)

Clone this repository:

git clone --recursive https://github.com/fabawi/wrapyfi.git
cd wrapyfi

You can choose to install minimal dependencies including numpy, opencv-contrib-python, and pyzmq, for running a basic Wrapyfi script:

pip install .[all]

or when installing Wrapyfi on a server (headless) including numpy, opencv-python-headless, and pyzmq:

pip install .[headless]

or when installing Wrapyfi to work with websockets (headless) including numpy, opencv-python-headless, and python-socketio:

pip install .[headless_websockets]

or install Wrapyfi without NumPy, OpenCV, ZeroMQ, and Websockets:

pip install .

Docker

Wrapyfi Docker images can be pulled/installed directly from the modularml/wrapyfi repository on the Docker Hub. Dockerfiles for all supported environments can be built as well by following the Wrapyfi Docker instructions.

Usage

Wrapyfi supports two patterns of communication:

  • Publisher-Subscriber (PUB/SUB): A publisher sends data to a subscriber accepting arguments and executing methods on the publisher's end. e.g., with YARP
Without Wrapyfi With Wrapyfi
# Just your usual Python class


class HelloWorld(object):
    
    
    
    
    def send_message(self):
        msg = input("Type your message: ")
        obj = {"message": msg}
        return obj,


hello_world = HelloWorld()



    

while True:
    my_message, = hello_world.send_message()
    print(my_message)
from wrapyfi.connect.wrapper import MiddlewareCommunicator


class HelloWorld(MiddlewareCommunicator):
    @MiddlewareCommunicator.register("NativeObject", "yarp",
                                     "HelloWorld", 
                                     "/hello/my_message", 
                                     carrier="", should_wait=True)
    def send_message(self):
        msg = input("Type your message: ")
        obj = {"message": msg}
        return obj,


hello_world = HelloWorld()

LISTEN = True
mode = "listen" if LISTEN else "publish"
hello_world.activate_communication(hello_world.send_message, mode=mode)

while True:
    my_message, = hello_world.send_message()
    print(my_message)

Run yarpserver from the command line. Now execute the Python script above (with Wrapyfi) twice setting LISTEN = False and LISTEN = True. You can now type with the publisher's command line and preview the message within the listener's

  • Request-Reply (REQ/REP): A requester sends a request to a responder, which responds to the request in a synchronous manner. e.g., with ROS
Without Wrapyfi With Wrapyfi
# Just your usual Python class


class HelloWorld(object):
    
    
    
    
    def send_message(self, a, b):
        msg = input("Type your message: ")
        obj = {"message": msg, 
               "a": a, "b": b, "sum": a + b}
        return obj,


hello_world = HelloWorld()



    

while True:
    my_message, = hello_world.send_message(a=1, 
                                           b=2)
    print(my_message)
from wrapyfi.connect.wrapper import MiddlewareCommunicator


class HelloWorld(MiddlewareCommunicator):
    @MiddlewareCommunicator.register("NativeObject", "ros",
                                     "HelloWorld", 
                                     "/hello/my_message", 
                                     carrier="", should_wait=True)
    def send_message(self, a, b):
        msg = input("Type your message: ")
        obj = {"message": msg, 
               "a": a, "b": b, "sum": a + b}
        return obj,


hello_world = HelloWorld()

LISTEN = True
mode = "request" if LISTEN else "reply"
hello_world.activate_communication(hello_world.send_message, mode=mode)

while True:
    my_message, = hello_world.send_message(a=1 if LISTEN else None, 
                                           b=2 if LISTEN else None)
    print(my_message)

Run roscore from the command line. Now execute the Python script above (with Wrapyfi) twice setting LISTEN = False and LISTEN = True. You can now type within the server's command line and preview the message within the client's. Note that the server's command line will not show the message until the client's command line has been used to send a request. The arguments are passed from the client to the server and the server's response is passed back to the client.

For more examples of usage, refer to the user guide. Run scripts in the examples directory for trying out Wrapyfi.

Supported Formats

Middleware

  • YARP
  • ROS
  • ROS 2
  • ZeroMQ [beta feature]:
    • should_wait trigger introduced with event monitoring
    • Event monitoring currently cannot be disabled planned
  • Websockets Only PUB/SUB [alpha support]:

Serializers

  • JSON
  • msgpack
  • protobuf

Data Structures

Supported Objects by the NativeObject type include:

Image

Supported Objects by the Image type include:

Sound

Supported Objects by the AudioChunk type include:

  • Tuple(NumPy Array, int) [supports the sounddevice format]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wrapyfi-0.4.45.tar.gz (7.9 MB view details)

Uploaded Source

Built Distribution

wrapyfi-0.4.45-py3-none-any.whl (8.1 MB view details)

Uploaded Python 3

File details

Details for the file wrapyfi-0.4.45.tar.gz.

File metadata

  • Download URL: wrapyfi-0.4.45.tar.gz
  • Upload date:
  • Size: 7.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for wrapyfi-0.4.45.tar.gz
Algorithm Hash digest
SHA256 489916d54662cd37c4a36c45abc99ee88297294480426a4fba45eb60616c8123
MD5 a39fb14059bc7b290b07b5e97f933513
BLAKE2b-256 f213698affb7ffd6fc813658f081d579ed02235ab6e167b53f0a3af94bfb3617

See more details on using hashes here.

File details

Details for the file wrapyfi-0.4.45-py3-none-any.whl.

File metadata

  • Download URL: wrapyfi-0.4.45-py3-none-any.whl
  • Upload date:
  • Size: 8.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for wrapyfi-0.4.45-py3-none-any.whl
Algorithm Hash digest
SHA256 22775cf3fc8c698dd7993351e1faf7909a7a42ec063d01bd1ca904ba647db895
MD5 96f57d68aa53208b61a1007883da2450
BLAKE2b-256 bd83e68a294f353d7ae2c80479c1b077a71fa641f987a505747f61f499dcf2fc

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page