Skip to main content

EymOS - Lightweight Middleware for Robotics

Project description

EymOS banner

EymOS - Lightweight Middleware for Robotics

EymOS is a lightweight and efficient middleware for robotics, providing streamlined node communication and device control, designed for simplicity and high performance
Report bug · Request feature

Table of contents

Introduction

EymOS is a lightweight and efficient middleware designed for robotics applications, inspired by the flexibility and modularity of systems like ROS, but optimized to be faster and lighter.

Originally developed for the robot Eymo, EymOS has evolved into an independent platform that provides all the essential functionalities for node communication, device control, and process management, with a focus on simplicity and performance.

Features

  • Lightweight and fast communication between nodes
  • Device control and process management for small-scale robots
  • Minimal resource usage, ideal for embedded systems and small robots
  • Easy integration with cloud services for advanced features

What's included

Within the download you'll find the following directories and files:

root/
├── eymos/
│   ├── services/
│   │   ├── __init__.py
│   │   └── camera.py
│   ├── __init__.py
│   ├── logger.py
│   ├── service.py
│   ├── service_manager.py
│   └── utils.py
├── examples/
│   ├── timer/
│   └── camera_timer/
├── LICENSE
├── logo.png
├── README.md
├── requirements.txt
└── setup.py

Installation

Prerequisites

Ensure you have the following installed on your system:

  • Python 3.9 or higher

Setup with pip (recommended)

Use pip to install the package from PyPI.

  1. Install the package using pip:
    pip install eymos
    
  2. Import the package and start using it.

Setup from source

Alternatively, you can clone the repository and install the package from the source code.

  1. Clone the repository:
    git clone https://github.com/EymoLabs/eymos.git
    
  2. Navigate to the project directory and install the required dependencies:
    cd eymos
    pip install -r requirements.txt
    
  3. You’re ready to use EymOS! Start using it.

Usage

After installing the package, you need to create the services for your robot, which will handle the communication between nodes and devices. Next, you could initialize them and start the service.

Create a new service

Create a new Python file for your service, and define the class for the service. The service should inherit from the Service class provided by EymOS.

from eymos import Service, utils, log

class TimerService(Service):
	def init(self):
		"""Initialize the service. Required."""
		self.__time = 0
		self.__is_running = False
		self.__max_time = self._config.get("max_time", 300)
		self._loop_delay = 1  # Control the loop delay in seconds

	def destroy(self):
		"""Destroy the service. Required."""
		self.__time = None
		self.__is_running = None
		self.__max_time = None

	def before(self):
		"""Before the loop. (Before the loop method is called, in the service thread) Optional."""
		# Not required for this service
		pass

	def loop(self):
		"""Service loop. Optional."""
		if not self.__is_running:
			return
		if self.__time > 0:
			self.__time -= 1
		if self.__time == 0:
			self.__is_running = False
			log("Timer stopped")
		else:
			log(f"Time left: {self.__time}")
		
	# Add more custom methods if needed
	def start_timer(self, time):
		self.__time = min(time, self.__max_time)
		self.__is_running = True
		log("Timer started")
	  
	def stop_timer(self):
		self.__is_running = False
		self.__time = 0
		log("Timer stopped")
	  
	def get_time(self):
		return self.__time

Initialize and start the service

Create a new Python file for your main program, and initialize the service manager. Add the services to the manager, and start the services.

from eymos import ServiceManager
from eymos.services import CameraService
from services.timer import TimerService

def main():
	# Create a new service manager
	service_manager = ServiceManager()
	
	# Link a configuration to the service manager
	service_manager.set_config_file("config.json")
	
	# Add the services to the manager
	service_manager.add("timer", TimerService)
	service_manager.add("camera", CameraService)
	
	# Initialize the services
	service_manager.start()	# Start the first service added, and then the rest

if __name__ == "__main__":
	main()

Configuration file

Create a configuration file for the services, and specify the parameters for each service.

{
	"timer": {
		"max_time": 300
	},
	"camera": {
		"resolution": [640, 480],
		"fps": 30
	}
}

Optionally, you could use the set_config method to set the configuration dictionary directly, instead of using a configuration file.

service_manager.set_config({
	"timer": {
		"max_time": 300
	},
})

Services

EymOS provides a set of services that can be used to control devices and processes in your robot. Each service is defined as a class that inherits from the Service class, and implements the required methods and attributes.

First steps

When a service is initialized, some actions are performed automatically, to ensure the service is correctly set up and ready to run.

On start, when a service is started, the init method is called, which initializes the variables and configurations for the service. This method is required for all services. Additionally, a new asyncronous thread is created for the service, which will run the before and loop methods in a loop, with a delay specified by the loop_delay attribute.

On stop, when a service is stopped, the destroy method is called, which cleans up the resources used by the service. This method is required for all services.

Dependencies

A service can define dependencies on other services, which will be started before the service is started. This is useful when a service requires another service to be running before it can start.

To define dependencies, set the DEPENDENCIES constant in the service class, with the names of the services that the service depends on.

class MyService(Service):
	DEPENDENCIES = ["camera", "motor"]

Methods

A service can define custom methods to perform specific actions or operations. These methods can be created as needed, and can be called from other services or external programs.

Method Description Required
init Initialize the service, setting up the variables and configurations. Yes
destroy Destroy the service, cleaning up the resources used by the service. Yes
before Perform actions before the loop starts. This method is called in the service thread, before the loop method. No
loop Perform the main actions of the service. This method is called in the service thread, in a loop with a delay specified by the loop_delay attribute or the LOOP_DELAY constant. No

Additionally, a service has some reserved methods that should not be overridden:

Method Description
start Start the service, initializing the service and starting the service thread. When the service is started, automatically starts all the other services that have not been started yet. If the service has dependencies, starts the dependencies first.
stop Stop the service, stopping the service thread and cleaning up the resources used by the service. When the service is stopped, automatically stops all the other services that depend on this service.
is_initialized Check if the service has been initialized.
__init__ Initialize the service instance, setting up the service attributes.
__reboot Reboot all the services, stopping and starting all the services.
__thread__execution Execute the service thread, calling the before and loop methods in a loop with the specified delay.
__start_other_service Start another service that has not been started yet.

Attributes

The service class has some attributes that can be used to configure the service during the execution, or to access some information.

Attribute Description Default
_config The configuration dictionary for the service. It contains the parameters specified in the configuration file (only the configuration dictionary identified by the service name). {} (set in constructor)
_global_config The global configuration dictionary for all the services. It contains the parameters specified in the global configuration file. None (set in constructor)
_loop_delay The delay between each loop iteration, in seconds. It controls the frequency of the loop method. self.LOOP_DELAY
_manager The service manager object that is running the service. None
_name The name of the service. It allows, for example, identifying other services and accessing to them (e.g., self._services["camera"].get_frame()). None (set in constructor)
_services The dictionary of all the services in the service manager. It allows accessing other services and calling their methods. None
__errors The number of consecutive errors that have occurred during the execution of the service. 0
__initialized A flag that indicates if the service has been initialized. False
__init_try The number of times the service has tried to initialize. 0
__thread The thread object that is running in the service. None
__thread_stop_event The event object that controls the stopping of the service thread. None

Definitions

Some constants are defined in the service class, which can be used to configure the service or to define some properties.

Constant Description Default
DEPENDENCIES The list of services that the service depends on. The services in the list will be started before the service is started. []
ERROR_INTERVAL The interval between each error, in seconds. It controls the frequency of the error messages and helps to avoid flooding the logs. 5
LOOP_DELAY The default delay between each loop iteration, in seconds. It controls the frequency of the loop method. 0.25 (4 times per second)
MAX_ERRORS The maximum number of consecutive errors that can occur before the service is stopped. Can be disabled by setting it to -1. 5
MAX_ERRORS_REBOOT The maximum number of consecutive errors that can occur before all the services are rebooted. Can be disabled by setting it to -1. -1 (disabled)

ServiceManager

The ServiceManager class is used to manage the services in the robot, including all the necessary operations to start, stop, restart, reboot, and configure the services, allowing the interaction between them.

The class provides the following methods to manage the services:

Method Description
add Add a new service to the manager.
get Get a service instance from the manager.
get_services Get a dictionary with all the services in the manager.
start Start all the services in the manager.
stop Stop all the services in the manager.
restart Restart all the services in the manager.
reboot Reboot the system, forcing all the services to be stopped. This method requires elevated permissions to be executed.
exit Stop all the services and exit the program.
set_config Set the global configuration dictionary for all the services.
set_config_file Set the global configuration file for all the services.

Utilities

EymOS provides some utilities that can be used to simplify the development of services and programs, including a logger and an OS utility.

Logger

The log(<message>, <type>) function allows you to log messages to the console, with different levels of severity.

Arguments

The first argument is the message to log, and the second argument is the level of the message (by default, logging.INFO).

Levels

The following levels are available (require the import logging statement):

  • logging.DEBUG
  • logging.INFO
  • logging.WARNING
  • logging.ERROR
  • logging.CRITICAL

Example

import logging
from eymos import log

log("This is an info message")
log("This is a debug message", logging.DEBUG)
log("This is a warning message", logging.WARNING)
log("This is an error message", logging.ERROR)
log("This is a critical message", logging.CRITICAL)

My OS

The utils.my_os() function allows you to get the name of the operating system running on the device.

Returns

The function returns a string with the name of the operating system. The possible values are: "Windows", "Linux", "Mac" and "Rpi". If the operating system is not recognized, the function returns None.

Example

from eymos import utils

os_name = utils.my_os()
print(f"Operating system: {os_name}")

if os_name == "Rpi":
	print("Do something specific for Raspberry Pi")
elif os_name == "Mac":
	print("Do something specific for Mac")
else:
	print("Do something generic")

Bugs and feature requests

Have a bug or a feature request? Please search for existing and closed issues. If your problem or idea is not addressed yet, open a new issue.

Creators

This project was developed entirely by Xavi Burgos, as part of the EymoLabs team.

Xavi Burgos

Collaborators

Special thanks to the following people from the EymoLabs team for their contributions to the project:

Yeray Cordero

Javier Esmorris

Gabriel Juan

Samya Karzazi

License

This project is licensed under a custom license, that allows you to use and modify the code for any purpose, as long as you provide attribution to the original authors, but you cannot distribute the code or any derivative work without permission. For more information, see the LICENSE file.

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

eymos-1.0.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distributions

eymos-1.0.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

EymOS-1.0.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file eymos-1.0.0.tar.gz.

File metadata

  • Download URL: eymos-1.0.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for eymos-1.0.0.tar.gz
Algorithm Hash digest
SHA256 c13c6b242e122e6f34fd482944a2b26ddab0cefd43d04e70114516ccc052837c
MD5 9599718a280c55798fec47e0688df77e
BLAKE2b-256 7d34caa148878d0ccc87ec70f15a396085abb8afb450990caadebeb9d42d4df8

See more details on using hashes here.

File details

Details for the file eymos-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: eymos-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for eymos-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f4615c7f4b5a2dcd85eb5d7f7c1fe5d31a27f6d19f122593b50a8cd64605baa8
MD5 cbd6f458ff7d5d36864c59ff52ed8b35
BLAKE2b-256 b34ccd99defbfd80244307d80295704a127e68312f4021e09447a52d3beeb485

See more details on using hashes here.

File details

Details for the file EymOS-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: EymOS-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for EymOS-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bf5bbf0d83e3c4601d5956025072daefc6140571a6e924ffe09a985ea148cb77
MD5 2e28d6dad98f0873723e7df4ceac11b0
BLAKE2b-256 927566b0be985f87290dd7902d742e1a0247791cfea1a5a4a4858cf703d28894

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