Metadata-Version: 2.4
Name: ros2-cyphal-bridge
Version: 0.2.0
Summary: ROS2 to Cyphal bridge (YAML-configured)
Author-email: Dmitry Ponomarev <ponomarevda96@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Dmitry Ponomarev
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/PonomarevDA/ros2-cyphal-bridge
Project-URL: Issues, https://github.com/PonomarevDA/ros2-cyphal-bridge/issues
Keywords: ros2,cyphal,bridge,yaml
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Operating System :: OS Independent
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: empy
Requires-Dist: catkin_pkg
Requires-Dist: lark
Requires-Dist: pycyphal
Requires-Dist: yakut
Requires-Dist: nunavut
Dynamic: license-file

# ros2-cyphal-bridge [![PyPI](https://img.shields.io/pypi/v/ros2-cyphal-bridge?logo=pypi&style=flat)](https://pypi.org/project/ros2-cyphal-bridge/) [![ci-and-deploy](https://github.com/PonomarevDA/ros2_cyphal_bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/PonomarevDA/ros2_cyphal_bridge/actions/workflows/ci.yml)

ROS 2 <-> Cyphal bridge with YAML-configured routing and transforms.

## Install

```bash
pip install ros2-cyphal-bridge
```

## Requirements

- ROS 2 installed and sourced (for `rclpy`).
- Python >= 3.9.
- Cyphal DSDL types available via `CYPHAL_PATH` (e.g., the public regulated data types).

## Usage

```bash
ros2-cyphal-bridge --config bridge.yaml
```

## Config format

Example `example_bridge.yaml`:

```yaml
version: 1
cyphal:
  node_id: 99
  node_name: "com.manufacturer.project.example_ros2_bridge"
  can_iface: "socketcan:slcan0"
  can_mtu: 8
cyphal_to_ros2:
  - rule: "uavcan.node.Heartbeat.1.0@42 -> /nodes/uptime:std_msgs/msg/UInt32"
    transform: "data=int(msg.uptime)"

  - rule: "2000:uavcan.si.unit.pressure.Scalar.1.0 -> /robot/sensors/pressure:sensor_msgs/msg/FluidPressure"
    transform: "fluid_pressure=float(msg.pascal);variance=0.0"

  - rule: "2003:uavcan.si.unit.temperature.Scalar.1.0 -> /robot/sensors/temperature:sensor_msgs/msg/Temperature"
    transform: "temperature=float(msg.kelvin - 273.15);variance=0.0"

  - rule: "2001:uavcan.primitive.scalar.Bit.1.0 -> /robot/sensors/limit_switch:std_msgs/msg/Bool"
    transform: "data=bool(msg.value)"

ros2_to_cyphal:
  - rule: "/setpoint:std_msgs/msg/Float32 -> 2002:uavcan.primitive.scalar.Real32.1.0"
    transform: "value=float(msg.data)"
```

### Cyphal config

- `node_id`: Optional Cyphal node-ID; if omitted, uses `UAVCAN__NODE__ID` or leaves it unset.
- `node_name`: Optional node name for `uavcan.node.GetInfo`; defaults to `com.manufacturer.project.ros2_bridge`.
- `can_iface`: Optional PyCyphal CAN interface (e.g., `socketcan:slcan0`).
- `can_mtu`: Optional CAN MTU (e.g., `8`).
- `udp_iface`: Optional UDP interface (e.g., `127.0.0.1`).

### Rule syntax

- Cyphal endpoint: `port_id@node_id:dsdl_type`
  - `port_id` can be omitted to use the fixed port ID (e.g., `uavcan.node.Heartbeat.1.0`).
  - `@node_id` is optional.
- ROS 2 endpoint: `/topic:pkg/msg/Type`.
- Rules use `left -> right` for direction.

### Transform syntax

Transforms are assignment expressions separated by `;`:

```
field=value
```

The left-hand side is a target field on the output message. The right-hand side is a Python expression evaluated with:
- `msg` (input message)
- `float`, `int`, `bool`, `abs`, `min`, `max`, `math`

Examples:
- `data=float(msg.pascal)`
- `value=float(msg.data)`

Security note: transforms use Python `eval` and must be treated as trusted input only.

## Quick start (Docker)

Run the bridge container with the example config:

```bash
docker run --rm --net=host \
  -v $(pwd)/tools/docker/example_bridge.yaml:/tmp/bridge.yaml:ro \
  ros2-cyphal-bridge:v0.2.0 --verbose
```

## Notes

- Requires a ROS 2 environment (`rclpy`) for execution.
- Cyphal DSDL types are resolved via `CYPHAL_PATH`.
- Cyphal `uavcan.node.GetInfo` reports `software_version` from the package version (setuptools-scm tag).
