# Decorator Reference

The core of "The Genesys Way" is its declarative API, which uses Python decorators to define ROS 2 components. This page serves as a complete reference for all available decorators, their parameters, and how to use them effectively.

All decorators are imported from `framework_core.decorators`.

***

### @node

This is the most fundamental decorator. It transforms a standard Python class into a runnable ROS 2 node.

**Signature**

```python
@node(name: str)
```

**Usage** Apply this decorator to a class definition.

**Parameters**

| Parameter | Type  | Required | Description                                                                               |
| --------- | ----- | -------- | ----------------------------------------------------------------------------------------- |
| `name`    | `str` | Yes      | The executable name for the ROS 2 node. This is the name you will use with `genesys run`. |

**Behavior**

* **Node Registration:** Marks the class as a ROS 2 node, enabling the framework to automatically register it as an executable in your package's [`setup.py`](code-assist-path:c:\Users\HP\Documents\genesys\Genesys\setup.py).
* **Logger Injection:** Automatically creates and injects a pre-configured `rclpy` logger instance into your class, accessible via `self.logger`.
* **Launch File Generation:** Triggers the auto-generation of a launch file in the workspace's `launch/` directory to make the node runnable.

**Full Example**

```python
from genesys.decorators import node
from genesys.helpers import spin_node

@node(name="my_simple_node")
class MyNode:
    def __init__(self):
        # self.logger is automatically available here
        self.logger.info("My simple node has started!")

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

if __name__ == '__main__':
    main()
```

***

### @publisher <a href="#publisher" id="publisher"></a>

Creates a ROS 2 publisher and links it to a method. The method's return value is automatically published.

**Signature**

```python
@publisher(topic: str, msg_type: MsgType, qos_profile: int = 10)
```

**Usage** Apply this decorator to a method inside a `@node`-decorated class. This decorator is often combined with `@timer`.

**Parameters**

| Parameter     | Type                  | Required | Description                                                                  |
| ------------- | --------------------- | -------- | ---------------------------------------------------------------------------- |
| `topic`       | `str`                 | Yes      | The name of the topic to publish messages to (e.g., `"chatter"`).            |
| `msg_type`    | ROS Message Type      | Yes      | The message type class (e.g., `std_msgs.msg.String`).                        |
| `qos_profile` | `int` or `QoSProfile` | No       | The Quality of Service profile for the publisher. Defaults to a depth of 10. |

**Behavior**

* **Publisher Creation:** Creates an `rclpy` publisher instance when the node is initialized.
* **Automatic Publishing:** When the decorated method is called, its **return value** is automatically published to the specified topic. You do not need to call `.publish()` yourself.
* The decorated method must return an instance of the specified `msg_type`.

**Full Example**

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

@node(name="my_talker_node")
class MyTalker:
    def __init__(self):
        self.counter = 0

    @timer(period_sec=1.0)
    @publisher(topic="chatter", msg_type=String)
    def publish_message(self):
        self.counter += 1
        msg = String()
        msg.data = f"Message #{self.counter}"
        # The returned 'msg' object will be published automatically
        return msg

# ... main function ...

```

***

### @subscriber <a href="#subscriber" id="subscriber"></a>

Creates a ROS 2 subscriber and registers the decorated method as its callback.

**Signature**

```python
@subscriber(topic: str, msg_type: MsgType, qos_profile: int = 10)
```

**Usage** Apply this decorator to a method inside a `@node`-decorated class.

**Parameters**

| Parameter     | Type                  | Required | Description                                                                     |
| ------------- | --------------------- | -------- | ------------------------------------------------------------------------------- |
| `topic`       | `str`                 | Yes      | The name of the topic to subscribe to.                                          |
| `msg_type`    | ROS Message Type      | Yes      | The message type class to listen for.                                           |
| `qos_profile` | `int` or `QoSProfile` | No       | The Quality of Service profile for the subscription. Defaults to a depth of 10. |

**Behavior**

* **Subscription Creation:** Creates an `rclpy` subscription when the node is initialized.
* **Callback Registration:** The decorated method is automatically set as the callback function for the subscription.
* **Argument Passing:** When a message is received, it is automatically passed as the first argument to the decorated method.

**Full Example**

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

@node(name="my_listener_node")
class MyListener:
    @subscriber(topic="chatter", msg_type=String)
    def message_callback(self, msg: String):
        # The received 'msg' object is passed in as an argument
        self.logger.info(f'I heard: "{msg.data}"')

# ... main function ...
```

***

### @timer <a href="#timer" id="timer"></a>

Creates a ROS 2 timer that periodically calls the decorated method.

**Signature**

```python
@timer(period_sec: float)
```

**Usage** Apply this decorator to a method inside a `@node`-decorated class.

**Parameters**

| Parameter    | Type    | Required | Description                                          |
| ------------ | ------- | -------- | ---------------------------------------------------- |
| `period_sec` | `float` | Yes      | The interval in seconds at which to call the method. |

**Behavior**

* **Timer Creation:** Creates an `rclpy` timer that calls the decorated method at the specified frequency. The timer starts when the node is initialized.

**Full Example**

```python
from genesys.decorators import node, timer
from genesys.helpers import spin_node

@node(name="my_periodic_node")
class MyPeriodicTask:
    @timer(period_sec=5.0)
    def do_work(self):
        self.logger.info("This message prints every 5 seconds.")

# ... main function ...
```

### @service

Creates a ROS 2 service server that automatically handles incoming requests and returns a response.

#### Signature

```
@service(topic: str, srv_type)
```

#### Usage

Apply this decorator to a method within a

`@node`-decorated class. The method signature should accept the request message as its single argument.

#### Parameters

* topic: `str`. The name of the service topic.
* srv\_type: `str`. The ROS 2 service type (e.g.,

  `example_interfaces.srv.AddTwoInts`).

#### Behavior

Service Server Creation: Creates an `rclpy` service server that listens for requests on the specified topic.

Automatic Handling: The decorated method is called automatically when a request is received, with the request object passed as an argument. The value returned by the method is used as the service response.

***

### @action\_server

Creates a ROS 2 action server that handles goals, feedback, and results.

#### Signature

```
@action_server(topic: str, action_type)
```

#### Usage

Apply this decorator to a method that will handle the incoming action goals. This method should act as a generator, yielding feedback and returning a final result.

#### Parameters

* topic: `str`. The name of the action topic.
* action\_type: `str`. The ROS 2 action type (e.g.,

  `example_interfaces.action.Fibonacci`).

#### Behavior

Action Server Creation: Registers a new `ActionServer` for the specified topic and type.

Generator-based Logic: The decorated method should `yield` feedback messages during execution and `return` the final result message.

Automatic Handling: The `send_goal` callback is automatically handled, and the user's decorated method is executed when a goal is received.

***

### @action\_client

Creates a ROS 2 action client to send goals to an action server.

#### Signature

```
@action_client(topic: str, action_type)
```

#### Usage

Apply this decorator to a method to register an action client. The

`_initialize_action_clients` method in the `GenesysNodeWrapper` is responsible for handling this.

#### Parameters

* topic: `str`. The name of the action topic.
* action\_type: `str`. The ROS 2 action type (e.g.,

  `example_interfaces.action.Fibonacci`).

#### Behavior

Action Client Creation: A new `ActionClient` is created and configured to connect to the specified topic.

Asynchronous Goal Sending: The client is ready to send goals to a server on the specified topic.

***

### @lifecycle\_node

Designates a class as a ROS 2 Lifecycle Node, automatically wrapping it and handling state transitions.

#### Signature

```
@lifecycle_node(name: str)
```

#### Usage

Apply this decorator to a class to enable lifecycle functionality. The class should contain methods for the various state callbacks (e.g.,

`on_configure`, `on_activate`, `on_deactivate`, `on_cleanup`, `on_shutdown`, and `on_error`).

#### Parameters

* name: `str`. The name of the lifecycle node.

#### Behavior

Automatic Wrapping: The decorator wraps the user-provided class with the core `LifecycleNode` logic from `rclpy`.

Callback Handling: The `spin_node` helper function automatically detects that the node is a lifecycle node and uses a `MultiThreadedExecutor` to handle state transitions.

Simplified Management: This provides a clean, declarative way to implement lifecycle nodes without needing to manually extend `LifecycleNode` or manage the executor.
