The variable naming follows KUKA convention (robot's perspective) where send_variables = what the robot sends us (RIst, RSol) and receive_variables = what the robot receives from us (RKorr, DiO). All APIs were using them backwards — writing corrections to send_variables and building response XML from them, meaning the robot never received actual corrections. - network_handler: parse incoming XML into send_variables, build response XML from receive_variables, use local dict snapshots to avoid per-key Manager IPC within the 4ms cycle - motion_api: check receive_variables for RKorr/AKorr - tools_api: write user corrections to receive_variables - monitoring_api: read robot state from send_variables - io_api: read digital inputs from send_variables - krl_api: read Tech.T params from send_variables - rsi_cli/rsi_graphing: add --config arg, remove hardcoded paths - main.py: test runner with all examples and multiprocessing guard
80 lines
3.5 KiB
Markdown
80 lines
3.5 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What This Project Does
|
|
|
|
RSIPI enables real-time control of KUKA industrial robots from Python via the RSI (Robot Sensor Interface) protocol. The robot sends its position ~250 times/second over UDP, and this library lets you send back position corrections to control the robot externally.
|
|
|
|
## Build & Development Commands
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pip install -e .
|
|
|
|
# Or install from requirements (if present)
|
|
pip install pandas>=2.0 numpy>=1.22 matplotlib>=3.5 lxml>=4.9 scipy>=1.8
|
|
|
|
# Run the CLI
|
|
python -m RSIPI.rsi_cli --config RSI_EthernetConfig.xml
|
|
|
|
# Run the echo server (for offline testing without a real robot)
|
|
python -m RSIPI.rsi_echo_server
|
|
```
|
|
|
|
**No test suite exists** - testing is done via the echo server simulation and example scripts in `examples/`.
|
|
|
|
## Architecture
|
|
|
|
### Core Communication Flow
|
|
|
|
```
|
|
KUKA Robot Controller <--UDP/XML--> NetworkProcess <--multiprocessing.Manager--> RSIClient <-- RSIAPI/CLI
|
|
```
|
|
|
|
1. **NetworkProcess** (`network_handler.py`) - Runs in separate process via `multiprocessing.Process`. Binds to UDP socket, receives XML from robot, parses into `receive_variables`, sends XML from `send_variables` back to robot. Uses `start_event` to wait for explicit start signal.
|
|
|
|
2. **RSIClient** (`rsi_client.py`) - Orchestrates the system. Initializes ConfigParser, SafetyManager, and NetworkProcess. Uses `multiprocessing.Manager` dicts for thread-safe variable sharing between processes.
|
|
|
|
3. **RSIAPI** (`rsi_api.py`) - High-level API wrapping RSIClient. Runs RSIClient in a daemon thread. Provides trajectory planning, logging, plotting, and safety controls.
|
|
|
|
4. **RSICommandLineInterface** (`rsi_cli.py`) - Interactive CLI that wraps RSIAPI.
|
|
|
|
### Key Shared State
|
|
|
|
Variables are shared between processes using `multiprocessing.Manager().dict()`:
|
|
- `send_variables` - Values to send to robot (RKorr corrections, digital outputs, etc.)
|
|
- `receive_variables` - Values received from robot (RIst position, ASPos joints, IPOC timestamp)
|
|
|
|
### Configuration
|
|
|
|
`RSI_EthernetConfig.xml` defines:
|
|
- Network settings (IP, port) in `<CONFIG>` section
|
|
- Send variables in `<SEND><ELEMENTS>` - what the robot receives from us
|
|
- Receive variables in `<RECEIVE><ELEMENTS>` - what we receive from robot
|
|
|
|
Variable tags like `DEF_RIst` get the `DEF_` prefix stripped and are expanded using `internal_structure` in ConfigParser to full dicts (e.g., `RIst: {X, Y, Z, A, B, C}`).
|
|
|
|
### Safety Layer
|
|
|
|
**SafetyManager** (`safety_manager.py`) validates all outgoing values against configurable limits. Can load limits from `.rsi.xml` files. Supports emergency stop and safety override modes.
|
|
|
|
### Trajectory Execution
|
|
|
|
`TrajectoryPlanner` generates interpolated waypoints. `execute_trajectory()` in RSIAPI uses asyncio to send points at specified rate (default 12ms for Cartesian, 400ms for joints).
|
|
|
|
## Important Patterns
|
|
|
|
- **IPOC synchronization**: The robot sends an IPOC (timestamp) value. The response must include `IPOC + 4` to maintain sync. This is handled automatically in `NetworkProcess.process_received_data()`.
|
|
|
|
- **Lazy client initialization**: RSIAPI uses `_ensure_client()` pattern - RSIClient is created on first use, not at RSIAPI instantiation.
|
|
|
|
- **Non-blocking start**: `start_rsi()` runs the client loop in a daemon thread. The NetworkProcess waits on `start_event` before binding the socket.
|
|
|
|
## File Locations
|
|
|
|
- Source code: `src/RSIPI/`
|
|
- Example scripts: `examples/`
|
|
- Config template: `RSI_EthernetConfig.xml`
|
|
- Logs written to: `logs/` (created at runtime)
|