# s4851211/edge_operator architecture

> Architecture diagram of the GitHub repository s4851211/edge_operator, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/s4851211/edge_operator
- Repository: https://github.com/s4851211/edge_operator

## Overview

1. **What this repository is**
   - This is an edge-side operator application for a **Fairino robot**, used to **receive trajectories from VILMA**, **inspect status**, and **execute robot motion** locally.
   - The codebase is split into a small operator UI, a set of background service modules, local trajectory/data files, and a vendored robot SDK.

2. **System boundary**
   - The repository is not just an app; it spans:
     - **Local Python control software**
     - **Robot vendor SDK bindings**
     - **ROS 2 / DDS connectivity infrastructure**
     - **Docker-managed bridge/services**
   - The supported runtime is **Ubuntu 22.04**, with Python managed by **uv**.

3. **Infrastructure layer**
   - `docker-compose.yml` starts the external runtime dependencies:
     - **Zenoh DDS bridge** (`zenoh_edge`)
     - **Vulcanexus / ROS 2 Humble environment** (`vulcanexus_vm`)
   - These containers provide the communication path between the upstream trajectory producer and the edge operator, and a ROS-compatible environment for debugging or future integration.

4. **Operator UI**
   - `ui/app.py` is the **Streamlit-based control panel**.
   - It is the human-facing entry point for:
     - checking robot/trajectory status
     - viewing received trajectories
     - initiating execution actions
   - The UI is likely a thin orchestration layer that calls into the service modules rather than directly talking to hardware.

5. **Trajectory ingress path**
   - The trajectory receiver is centered around `services/trajectory_receiver.py`.
   - Per the README, it waits for **`/learned_trajectory`** and saves incoming data to:
     - `data/trajectories/received_trajectory.csv`
   - This is the main data ingestion flow from VILMA into the edge system.

6. **Trajectory storage and working data**
   - `data/trajectories/` is the local persistence boundary for received motion programs.
   - The repository also includes example/reference motion artifacts such as:
     - `skill_reuse_live_screwdriver_1_events_mm.csv`
     - `pick_place_points.json`
   - These files suggest the system supports both imported learned trajectories and task-specific point definitions.

7. **Execution pipeline**
   - `services/trajectory_executor.py` is the component that likely turns a stored trajectory into executable robot commands.
   - It sits between trajectory data and the robot control layer, which makes it the key execution boundary for:
     - loading the chosen CSV/trajectory
     - applying calibration/coordinate transforms
     - dispatching motion steps to the robot driver

8. **Robot control layer**
   - `services/robot_service.py` is the abstraction over the physical Fairino robot.
   - The actual low-level robot API is vendored in `fairino-python-sdk-main/`, which contains platform-specific bindings for Linux and Windows, though the README says **Windows is not supported** in this project.
   - This layer is the hard boundary to hardware: everything above it is application logic, everything below it is vendor SDK / robot communication.

9. **Gripper and task scripts**
   - `gripper_linux.py` and `pick_place_linux.py` look like standalone robot task scripts, likely for manual operation or specific demos.
   - They are separate from the main UI/service flow and represent task-oriented automation examples built on the same robot SDK.

10. **Status and observability**
   - `services/status_service.py` appears to consolidate system state for the UI.
   - `services/receiver_service.py` likely tracks trajectory reception state, while `services/robot_service.py` handles robot connectivity/health.
   - This creates an internal status plane so the Streamlit UI can present current readiness and execution conditions without directly coupling to every backend module.

11. **ROS/Zenoh integration services**
   - `services/zenoh_service.py`, `services/zenoh_launcher.py`, `services/ros2_service.py`, and `services/receiver_launcher.py` suggest the project manages some background processes programmatically.
   - These modules are the integration boundary between:
     - Zenoh transport
     - ROS 2 / DDS tooling
     - the Python operator workflow
   - They likely encapsulate startup, connection management, and process lifecycle for the infrastructure services.

12. **Calibration and coordinate frames**
   - Several JSON files define robot and environment calibration inputs:
     - `colleague_cam2base_calibration.json`
     - `identity_robot_calibration.json`
     - `trajectory_calibration.json`
   - These are important because execution depends on consistent frame transforms between camera, robot base, and trajectory coordinates.

13. **Configuration and build tooling**
   - `config/settings.yaml` is the main application configuration file.
   - `pyproject.toml`, `uv.lock`, and `.python-version` define the Python environment and dependency management.
   - The project is designed to be run by first bringing up Docker services, then activating the Python environment, then launching the Streamlit UI or receiver process.

14. **Overall data flow**
   - The main runtime flow is:
     - VILMA produces a trajectory
     - the Zenoh/DDS bridge transports it to the edge
     - `trajectory_receiver` stores it locally as CSV
     - the UI inspects the received result and status
     - `trajectory_executor` sends motion commands through `robot_service`
     - the robot executes the trajectory, potentially using calibration data and gripper/task helpers

Main entry points: [`services/robot_service.py`](https://github.com/s4851211/edge_operator/blob/main/services/robot_service.py) (Robot Service), [`ui/app.py`](https://github.com/s4851211/edge_operator/blob/main/ui/app.py) (Operator UI), [`services/status_service.py`](https://github.com/s4851211/edge_operator/blob/main/services/status_service.py) (Status), [`services/trajectory_executor.py`](https://github.com/s4851211/edge_operator/blob/main/services/trajectory_executor.py) (Executor)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_ui_app["Operator UI<br/>streamlit app<br/>[app.py]"]
  node_main_entry["Main<br/>app entry<br/>[main.py]"]
  node_follow_csv["CSV Runner<br/>trajectory script"]
  node_gripper_script["Gripper Task<br/>robot script<br/>[gripper_linux.py]"]
  node_pick_place_script["Pick Place<br/>robot script"]
end

subgraph group_services["Services"]
  node_status_service["Status<br/>state service<br/>[status_service.py]"]
  node_receiver_service["Receiver State<br/>ingress state"]
  node_trajectory_receiver["Trajectory Rx<br/>ingress worker"]
  node_trajectory_executor["Executor<br/>motion pipeline"]
  node_robot_service["Robot Service<br/>robot adapter<br/>[robot_service.py]"]
  node_zenoh_service["Zenoh Service<br/>transport service<br/>[zenoh_service.py]"]
  node_zenoh_launcher["Zenoh Launcher<br/>process launcher<br/>[zenoh_launcher.py]"]
  node_ros2_service["ROS 2 Service<br/>ros service<br/>[ros2_service.py]"]
  node_receiver_launcher["Receiver Launcher<br/>process launcher"]
end

subgraph group_infra["Infra"]
  node_docker_compose["Docker Compose<br/>infra config<br/>[docker-compose.yml]"]
end

subgraph group_assets["Assets"]
  node_settings["Settings<br/>config<br/>[settings.yaml]"]
  node_traj_data[("Trajectories<br/>data dir")]
  node_trajectory_calibration["Traj Calib<br/>calibration"]
  node_robot_calibration["Robot Calib<br/>calibration"]
  node_cam_calibration["Cam Calib<br/>calibration"]
  node_task_points["Task Points<br/>task data"]
  node_example_traj["Example Traj<br/>trajectory data"]
end

subgraph group_sdk["Vendor SDK"]
  node_vendor_sdk["Fairino SDK<br/>vendor bindings"]
end

node_main_entry -->|"starts"| node_ui_app
node_main_entry -->|"runs"| node_trajectory_receiver
node_ui_app -->|"reads"| node_status_service
node_ui_app -->|"reads"| node_receiver_service
node_ui_app -->|"triggers"| node_trajectory_executor
node_receiver_launcher -->|"starts"| node_trajectory_receiver
node_trajectory_receiver -->|"listens via"| node_zenoh_service
node_trajectory_receiver -->|"writes"| node_traj_data
node_receiver_service -->|"tracks"| node_traj_data
node_trajectory_executor -->|"loads"| node_traj_data
node_trajectory_executor -->|"commands"| node_robot_service
node_trajectory_executor -->|"uses"| node_trajectory_calibration
node_robot_service -->|"wraps"| node_vendor_sdk
node_robot_service -->|"uses"| node_robot_calibration
node_robot_service -->|"uses"| node_cam_calibration
node_robot_service -->|"uses"| node_task_points
node_zenoh_launcher -->|"depends on"| node_docker_compose
node_ros2_service -->|"depends on"| node_docker_compose
node_zenoh_service -->|"bridges"| node_docker_compose
node_status_service -->|"queries"| node_robot_service
node_status_service -->|"queries"| node_receiver_service
node_status_service -->|"queries"| node_zenoh_service
node_follow_csv -->|"uses"| node_robot_service
node_gripper_script -->|"uses"| node_robot_service
node_pick_place_script -->|"uses"| node_robot_service
node_settings -->|"configures"| node_main_entry

click node_ui_app "https://github.com/s4851211/edge_operator/blob/main/ui/app.py"
click node_main_entry "https://github.com/s4851211/edge_operator/blob/main/main.py"
click node_follow_csv "https://github.com/s4851211/edge_operator/blob/main/fairino_follow_csv_trajectory.py"
click node_gripper_script "https://github.com/s4851211/edge_operator/blob/main/gripper_linux.py"
click node_pick_place_script "https://github.com/s4851211/edge_operator/blob/main/pick_place_linux.py"
click node_status_service "https://github.com/s4851211/edge_operator/blob/main/services/status_service.py"
click node_receiver_service "https://github.com/s4851211/edge_operator/blob/main/services/receiver_service.py"
click node_trajectory_receiver "https://github.com/s4851211/edge_operator/blob/main/services/trajectory_receiver.py"
click node_trajectory_executor "https://github.com/s4851211/edge_operator/blob/main/services/trajectory_executor.py"
click node_robot_service "https://github.com/s4851211/edge_operator/blob/main/services/robot_service.py"
click node_zenoh_service "https://github.com/s4851211/edge_operator/blob/main/services/zenoh_service.py"
click node_zenoh_launcher "https://github.com/s4851211/edge_operator/blob/main/services/zenoh_launcher.py"
click node_ros2_service "https://github.com/s4851211/edge_operator/blob/main/services/ros2_service.py"
click node_receiver_launcher "https://github.com/s4851211/edge_operator/blob/main/services/receiver_launcher.py"
click node_docker_compose "https://github.com/s4851211/edge_operator/blob/main/docker-compose.yml"
click node_settings "https://github.com/s4851211/edge_operator/blob/main/config/settings.yaml"
click node_traj_data "https://github.com/s4851211/edge_operator/tree/main/data/trajectories"
click node_trajectory_calibration "https://github.com/s4851211/edge_operator/blob/main/trajectory_calibration.json"
click node_robot_calibration "https://github.com/s4851211/edge_operator/blob/main/identity_robot_calibration.json"
click node_cam_calibration "https://github.com/s4851211/edge_operator/blob/main/colleague_cam2base_calibration.json"
click node_task_points "https://github.com/s4851211/edge_operator/blob/main/pick_place_points.json"
click node_example_traj "https://github.com/s4851211/edge_operator/blob/main/skill_reuse_live_screwdriver_1_events_mm.csv"
click node_vendor_sdk "https://github.com/s4851211/edge_operator/tree/main/fairino-python-sdk-main"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui_app,node_main_entry,node_follow_csv,node_gripper_script,node_pick_place_script toneBlue
class node_status_service,node_receiver_service,node_trajectory_receiver,node_trajectory_executor,node_robot_service,node_zenoh_service,node_zenoh_launcher,node_ros2_service,node_receiver_launcher toneAmber
class node_docker_compose toneMint
class node_settings,node_traj_data,node_trajectory_calibration,node_robot_calibration,node_cam_calibration,node_task_points,node_example_traj toneRose
class node_vendor_sdk toneIndigo
```

## Components

### Runtime

Python operator and task entrypoints.

- [Operator UI](https://github.com/s4851211/edge_operator/blob/main/ui/app.py): streamlit app · Human-facing control panel for status, trajectories, and execution. · `ui/app.py`
- [Main](https://github.com/s4851211/edge_operator/blob/main/main.py): app entry · Top-level application launcher for the operator workflow. · `main.py`
- [CSV Runner](https://github.com/s4851211/edge_operator/blob/main/fairino_follow_csv_trajectory.py): trajectory script · Standalone script for following a CSV trajectory. · `fairino_follow_csv_trajectory.py`
- [Gripper Task](https://github.com/s4851211/edge_operator/blob/main/gripper_linux.py): robot script · Standalone Linux task script for gripper control. · `gripper_linux.py`
- [Pick Place](https://github.com/s4851211/edge_operator/blob/main/pick_place_linux.py): robot script · Standalone Linux task script for pick-and-place motion. · `pick_place_linux.py`

### Services

Background control, execution, and integration modules.

- [Status](https://github.com/s4851211/edge_operator/blob/main/services/status_service.py): state service · Aggregates robot, receiver, and execution readiness for the UI. · `services/status_service.py`
- [Receiver State](https://github.com/s4851211/edge_operator/blob/main/services/receiver_service.py): ingress state · Tracks trajectory reception and storage state. · `services/receiver_service.py`
- [Trajectory Rx](https://github.com/s4851211/edge_operator/blob/main/services/trajectory_receiver.py): ingress worker · Waits for learned trajectories and writes received CSV data. · `services/trajectory_receiver.py`
- [Executor](https://github.com/s4851211/edge_operator/blob/main/services/trajectory_executor.py): motion pipeline · Loads stored trajectories and dispatches execution steps. · `services/trajectory_executor.py`
- [Robot Service](https://github.com/s4851211/edge_operator/blob/main/services/robot_service.py): robot adapter · Abstraction over the Fairino robot connection and motion API. · `services/robot_service.py`
- [Zenoh Service](https://github.com/s4851211/edge_operator/blob/main/services/zenoh_service.py): transport service · Manages Zenoh bridge connectivity and process lifecycle. · `services/zenoh_service.py`
- [Zenoh Launcher](https://github.com/s4851211/edge_operator/blob/main/services/zenoh_launcher.py): process launcher · Starts and supervises the Zenoh bridge runtime. · `services/zenoh_launcher.py`
- [ROS 2 Service](https://github.com/s4851211/edge_operator/blob/main/services/ros2_service.py): ros service · Manages ROS 2 / DDS integration process lifecycle. · `services/ros2_service.py`
- [Receiver Launcher](https://github.com/s4851211/edge_operator/blob/main/services/receiver_launcher.py): process launcher · Starts and supervises the trajectory receiver runtime. · `services/receiver_launcher.py`

### Infra

Docker and connectivity runtime dependencies.

- [Docker Compose](https://github.com/s4851211/edge_operator/blob/main/docker-compose.yml): infra config · Brings up the Zenoh bridge and Vulcanexus / ROS 2 environment. · `docker-compose.yml`

### Assets

Local trajectory, calibration, and config data.

- [Settings](https://github.com/s4851211/edge_operator/blob/main/config/settings.yaml): config · Main application configuration. · `config/settings.yaml`
- [Trajectories](https://github.com/s4851211/edge_operator/tree/main/data/trajectories): data dir · Local persistence for received and reference trajectories. · `data/trajectories`
- [Traj Calib](https://github.com/s4851211/edge_operator/blob/main/trajectory_calibration.json): calibration · Calibration inputs for trajectory-to-robot alignment. · `trajectory_calibration.json`
- [Robot Calib](https://github.com/s4851211/edge_operator/blob/main/identity_robot_calibration.json): calibration · Base-frame calibration for the robot setup. · `identity_robot_calibration.json`
- [Cam Calib](https://github.com/s4851211/edge_operator/blob/main/colleague_cam2base_calibration.json): calibration · Camera-to-base calibration for coordinate transforms. · `colleague_cam2base_calibration.json`
- [Task Points](https://github.com/s4851211/edge_operator/blob/main/pick_place_points.json): task data · Named point definitions for pick-and-place style motions. · `pick_place_points.json`
- [Example Traj](https://github.com/s4851211/edge_operator/blob/main/skill_reuse_live_screwdriver_1_events_mm.csv): trajectory data · Reference learned trajectory artifact in CSV form. · `skill_reuse_live_screwdriver_1_events_mm.csv`

### Vendor SDK

Vendored Fairino robot bindings.

- [Fairino SDK](https://github.com/s4851211/edge_operator/tree/main/fairino-python-sdk-main): vendor bindings · Vendored Fairino robot SDK and platform-specific C/Python bindings. · `fairino-python-sdk-main`

## Connections

- Main → Operator UI: starts · Launches the operator UI.
- Main → Trajectory Rx: runs · Can start the receiver workflow.
- Operator UI → Status: reads · Displays system readiness and robot state.
- Operator UI → Receiver State: reads · Shows trajectory reception state.
- Operator UI → Executor: triggers · Initiates trajectory execution.
- Receiver Launcher → Trajectory Rx: starts · Supervises the ingress worker.
- Trajectory Rx → Zenoh Service: listens via · Receives trajectories through the transport layer.
- Trajectory Rx → Trajectories: writes · Persists received trajectories as local CSV.
- Receiver State → Trajectories: tracks · Reports stored trajectory availability.
- Executor → Trajectories: loads · Reads the selected trajectory for execution.
- Executor → Robot Service: commands · Sends motion steps to the robot adapter.
- Executor → Traj Calib: uses · Applies trajectory calibration during execution.
- Robot Service → Fairino SDK: wraps · Uses the vendored Fairino SDK for hardware control.
- Robot Service → Robot Calib: uses · Relies on robot frame calibration data.
- Robot Service → Cam Calib: uses · Supports camera-to-base transforms.
- Robot Service → Task Points: uses · Consumes named points for task scripts.
- Zenoh Launcher → Docker Compose: depends on · Runs alongside containerized transport services.
- ROS 2 Service → Docker Compose: depends on · Uses the ROS 2 / DDS environment provided by containers.
- Zenoh Service → Docker Compose: bridges · Connects the edge app to the external transport runtime.
- Status → Robot Service: queries · Collects robot health and connectivity.
- Status → Receiver State: queries · Collects ingestion readiness.
- Status → Zenoh Service: queries · Collects transport status.
- CSV Runner → Robot Service: uses · Drives robot motion from a CSV file.
- Gripper Task → Robot Service: uses · Controls the gripper through the robot adapter.
- Pick Place → Robot Service: uses · Runs a pick-and-place task through the robot adapter.
- Settings → Main: configures · Provides runtime configuration for the application.
