Package: wrapyfi
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 supportsYARP,ROS,ROS 2, andZeroMQ.To integrate Wrapyfi with your scripts, add the decorators describing the transmitting and listening method parameters.AttributionPlease refer to the followingpaperwhen 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 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 StartedBefore using Wrapyfi, YARP, ROS, or ZeroMQ must be installed.Follow theYARP 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 on using the iCub robot.For installing ROS, follow the ROS installation guide[Ubuntu][Windows].
We recommend installing ROS on Conda using theRoboStackenvironment. Additionally, theWrapyfi ROS interfacesmust be
built to support messages needed for audio transmissionFor installing ROS 2, follow the ROS 2 installation guide[Ubuntu][Windows].
We recommend installing ROS 2 on Conda using theRoboStackenvironment. Additionally, theWrapyfi ROS 2 interfacesmust be built to support messages and services needed for audio transmission and the REQ/REP pattern supportZeroMQ 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 argumentstart_proxy_broker=Falseto the method register decorator.
A standalone broker can be foundhereCompatibilityOperating SystemUbuntu >= 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 onlyNot tested with YARP and ROS 2ROS only tested within mamba/micromamba environment installed usingRoboStackROS and ROS 2 interfaces not testedInstallation instructions across Wrapyfi guides and tutorials are not guaranteed to be compatible with Windows 11MacOS 10.14 MojavePython >= 3.6OpenCV >= 4.2NumPy >= 1.19YARP >= v3.3.2ROS Noetic NinjemysROS 2 Humble Hawksbill|Galactic Geochelone|Foxy FitzroyPyZMQ 16.0, 17.1 and 19.0InstallationYou can install Wrapyfi withpipor from source.PipTo install all the necessary components for the majority of common uses of Wrapyfi (e.g., NativeObject, Image, Audio, etc.) usingpip, this process installs both Wrapyfi and its dependencies, like NumPy and OpenCV (opencv-contrib-python,opencv-headless, andopencv-pythonare 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), installingnumpy,opencv-contrib-python, andpyzmq:pip install wrapyfi[all]Note that most plugins require additional dependencies and should be installed separately.or when installing Wrapyfi on aserver(headless) includingnumpy,opencv-python-headless, andpyzmq:pip install wrapyfi[headless]Other middleware such as ROS are environment-specific and require dependencies that cannot be installed using pip.
Wrapyficouldand should be used within such environments with minimal requirements to avoid conflicts with existing NumPy and OpenCV packages:pip install wrapyfiSource (Pip)Clone this repository:git clone --recursive https://github.com/fabawi/wrapyfi.git
cd wrapyfiYou can choose to install minimal dependencies includingnumpy,opencv-contrib-python, andpyzmq, for running a basic Wrapyfi script:pip install .[all]or when installing Wrapyfi on aserver(headless) includingnumpy,opencv-python-headless, andpyzmq:pip install .[headless]or install WrapyfiwithoutNumPy, OpenCV, and ZeroMQ:pip install .DockerWrapyfi Docker images can be pulled/installed directly from themodularml/wrapyfirepository on the Docker Hub. Dockerfiles for all supported environments can be built as well by following theWrapyfi Docker instructions.UsageWrapyfi 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 YARPWithout WrapyfiWith Wrapyfi# Just your usual Python classclassHelloWorld(object):defsend_message(self):msg=input("Type your message: ")obj={"message":msg}returnobj,hello_world=HelloWorld()whileTrue:my_message,=hello_world.send_message()print(my_message)fromwrapyfi.connect.wrapperimportMiddlewareCommunicatorclassHelloWorld(MiddlewareCommunicator):@MiddlewareCommunicator.register("NativeObject","yarp","HelloWorld","/hello/my_message",carrier="",should_wait=True)defsend_message(self):msg=input("Type your message: ")obj={"message":msg}returnobj,hello_world=HelloWorld()LISTEN=Truemode="listen"ifLISTENelse"publish"hello_world.activate_communication(hello_world.send_message,mode=mode)whileTrue:my_message,=hello_world.send_message()print(my_message)Runyarpserverfrom the command line. Now execute the Python script above (with Wrapyfi) twice settingLISTEN = FalseandLISTEN = True. You can now type with the publisher's command line and preview the message within the listener'sRequest-Reply(REQ/REP): A requester sends a request to a responder, which responds to the request in a synchronous manner.
e.g., with ROSWithout WrapyfiWith Wrapyfi# Just your usual Python classclassHelloWorld(object):defsend_message(self,a,b):msg=input("Type your message: ")obj={"message":msg,"a":a,"b":b,"sum":a+b}returnobj,hello_world=HelloWorld()whileTrue:my_message,=hello_world.send_message(a=1,b=2)print(my_message)fromwrapyfi.connect.wrapperimportMiddlewareCommunicatorclassHelloWorld(MiddlewareCommunicator):@MiddlewareCommunicator.register("NativeObject","ros","HelloWorld","/hello/my_message",carrier="",should_wait=True)defsend_message(self,a,b):msg=input("Type your message: ")obj={"message":msg,"a":a,"b":b,"sum":a+b}returnobj,hello_world=HelloWorld()LISTEN=Truemode="request"ifLISTENelse"reply"hello_world.activate_communication(hello_world.send_message,mode=mode)whileTrue:my_message,=hello_world.send_message(a=1ifLISTENelseNone,b=2ifLISTENelseNone)print(my_message)Runroscorefrom the command line. Now execute the Python script above (with Wrapyfi) twice settingLISTEN = FalseandLISTEN = 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 theuser guide. Run scripts in theexamples directoryfor trying out Wrapyfi.Supported FormatsMiddlewareYARPROSROS 2ZeroMQ[beta feature]:should_waittrigger introduced with event monitoringEvent monitoring currently cannot be disabledSerializersJSONmsgpackprotobufData StructuresSupported Objects by theNativeObjecttype include:NumPy Array | GenericPyTorch TensorTensorFlow 2 TensorJAX TensorTrax ArrayMXNet TensorPaddlePaddle Tensorpandas DataFrame | SeriesPillow ImagePyArrow ArrayCuPy ArrayXarray DataArray | DatasetDask Array | DataFrameZarr Array | GroupPint QuantityGmpy 2 MPZMLX TensorImageSupported Objects by theImagetype include:NumPy Array[supports many libraries includingscikit-image,imageio,Open CV,imutils,matplotlib.image, andMahotas]SoundSupported Objects by theAudioChunktype include:Tuple(NumPy Array, int) [supports thesounddeviceformat]