# The Genesys way

## The Genesys Way: Declarative ROS 2 with Decorators

"The Genesys Way" is a development philosophy centered on a single goal: **letting you focus on your robot's logic, not on boilerplate and configuration.**

Instead of manually writing verbose setup code for every node, publisher, and subscriber, Genesys provides a clean, declarative API using Python decorators. You simply "decorate" your classes and methods to describe their function, and the framework handles the rest.

#### How It Works: The Magic Behind the Scenes

When you run `genesys build` or a `genesys make *` command, the framework's auto-generation engine scans your Python files for Genesys decorators (`@node`, `@publisher`, etc.).

Based on what it finds, it automatically performs tasks you would otherwise do by hand:

1. **Registers Executables:** It adds the necessary entry points to your package's [`setup.py`](code-assist-path:c:\Users\HP\Documents\genesys\Genesys\setup.py) file, turning your Python classes into runnable ROS 2 nodes.
2. **Generates Launch Files:** It creates or updates a launch file in the workspace's `launch/` directory, making your node immediately available to run with `genesys run` or `genesys launch`.

This means your node is ready to use the moment you finish writing its logic, with zero manual configuration.

***

#### Example 1: A Simple Publisher Node

Let's look at the standard publisher node generated by `genesys make node`. It's a perfect example of the Genesys Way in action.

```python
from genesys.decorators import node, timer, publisher
from genesys.helpers import spin_node
from std_msgs.msg import String

@node("my_talker_node")
class MyTalker:
    def __init__(self):
        self.counter = 0
        # A `self.logger` instance is automatically injected by @node!
        self.logger.info("Talker node has been initialized.")

    @timer(period_sec=1.0)
    @publisher(topic="chatter", msg_type=String)
    def publish_message(self):
        """
        This method runs every second. The String it returns is
        automatically published to the 'chatter' topic.
        """
        msg = String()
        msg.data = f"Hello from Genesys! Message #{self.counter}"
        self.logger.info(f'Publishing: "{msg.data}"')
        self.counter += 1
        return msg

def main(args=None):
    # The spin_node helper initializes the class and keeps the node alive.
    spin_node(MyTalker, args)

if __name__ == '__main__':
    main()

```

**Decorator Breakdown:**

* `@node("my_talker_node")`
  * This is the most important decorator. It transforms the `MyTalker` class into a full-fledged ROS 2 node.
  * The string `"my_talker_node"` becomes the executable name.
  * It automatically injects a pre-configured `rclpy` logger, available as `self.logger`.
* `@timer(period_sec=1.0)`
  * This decorator creates a ROS 2 timer that calls the `publish_message` method once every second.
* `@publisher(topic="chatter", msg_type=String)`
  * This powerful decorator creates a ROS 2 publisher.
  * It automatically takes the **return value** of the `publish_message` method and publishes it to the `/chatter` topic. You don't need to create a publisher object or call `.publish()` yourself.

***

#### Example 2: A Simple Subscriber Node

Creating a subscriber is just as easy. You define a method to handle incoming messages and decorate it appropriately.

```python
from genesys.decorators import node, subscriber
from genesys.helpers import spin_node
from std_msgs.msg import String

@node("my_listener_node")
class MyListener:
    def __init__(self):
        self.logger.info("Listener node has been initialized.")

    @subscriber(topic="chatter", msg_type=String)
    def message_callback(self, msg):
        """
        This method is called whenever a message is received on the 'chatter' topic.
        The message is automatically passed as an argument.
        """
        self.logger.info(f'I heard: "{msg.data}"')

def main(args=None):
    spin_node(MyListener, args)

if __name__ == '__main__':
    main()

```

**Decorator Breakdown:**

* `@node("my_listener_node")`
  * Just like before, this registers the class as a ROS 2 node and provides a logger.
* `@subscriber(topic="chatter", msg_type=String)`
  * This decorator creates a ROS 2 subscription to the `/chatter` topic.
  * It registers the `message_callback` method as the callback function.
  * When a message arrives, Genesys automatically passes it as the `msg` argument to your method.

#### Summary: The Benefits

Adopting "The Genesys Way" offers several key advantages:

* **Readability:** Your code clearly declares its purpose. A method decorated with `@subscriber` is obviously a subscription callback.
* **Productivity:** You save significant time by not having to manually edit [`setup.py`](code-assist-path:c:\Users\HP\Documents\genesys\Genesys\setup.py) and `CMakeLists.txt` or create launch files for every new node.
* **Reduced Errors:** Automation eliminates common mistakes like forgetting to add an entry point or sourcing a workspace.
* **Consistency:** All nodes are created, registered, and launched in a standardized way, making projects easier to maintain.

<figure><img src="https://936155606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJ3Q7jbmqQcUsEfKcTcGs%2Fuploads%2FlidRYJ5KmW1sktqzayW1%2FGenesys-banner.png?alt=media&#x26;token=6ae47eeb-1ff3-46b3-a0eb-863d327f6691" alt=""><figcaption></figcaption></figure>
