npm package: @moescet/simple-teleop
Description: Simple teleoperation capability for remote robot control with keyboard
Author: moescet
Latest version: 0.1.0

# Simple Teleoperation Capability

A lightweight remote teleoperation capability for the Transitive Robotics framework that enables keyboard control of a simulated robot with real-time position and velocity feedback.

## Features

- **Keyboard Control**: Use arrow keys to control robot movement
  - ↑/↓ for forward/backward motion
  - ←/→ for left/right turning
- **Real-time Feedback**: Live display of robot position (x, y, θ) and velocities
- **Smooth Movement**: 50Hz physics simulation for smooth, non-jagged motion
- **Zero Latency**: Direct MQTT communication between web UI and robot
- **No ROS Required**: Pure Node.js implementation
- **Self-hosted**: Runs on your own Transitive instance

## Architecture

This capability consists of three components:

1. **Robot Component** (`robot/`) - Node.js simulator with 2D physics
   - Maintains robot state (position and velocity)
   - Runs physics simulation at 50Hz
   - Publishes state updates at 10Hz
   - Receives velocity commands via MQTT

2. **Web Component** (`web/`) - React-based UI with keyboard control
   - Captures arrow key events
   - Publishes velocity commands
   - Displays real-time robot state
   - Visual feedback for active keys

3. **Cloud Component** (`cloud/`) - Optional monitoring/logging
   - Logs commands and state updates
   - Can be extended for analytics

## Installation

### Prerequisites

- Node.js >= 14.0.0
- Self-hosted Transitive Robotics instance
- npm or yarn package manager

### Setup

1. **Clone or create the capability package**:
   ```bash
   cd /path/to/your/capabilities
   mkdir -p @local/simple-teleop
   cd @local/simple-teleop
   ```

2. **Copy all files** into the directory with this structure:
   ```
   @local/simple-teleop/
   ├── package.json
   ├── README.md
   ├── robot/
   │   ├── package.json
   │   └── index.js
   ├── web/
   │   ├── package.json
   │   └── index.jsx
   └── cloud/
       ├── package.json
       └── index.js
   ```

3. **Install dependencies** for each component:
   ```bash
   # Robot component
   cd robot && npm install && cd ..

   # Web component
   cd web && npm install && cd ..

   # Cloud component
   cd cloud && npm install && cd ..
   ```

4. **Register the capability** with your Transitive instance:
   ```bash
   transitive-cli capability add @local/simple-teleop
   ```

## Quick Start

### 1. Start the Robot Simulator

```bash
cd robot
node index.js
```

You should see output like:
```
[simple-teleop-robot] Initializing robot simulator
[simple-teleop-robot] Robot simulator initialized and running
[simple-teleop-robot] Physics update rate: 50 Hz
[simple-teleop-robot] State publish rate: 10 Hz
```

### 2. Start the Cloud Component (Optional)

In a new terminal:
```bash
cd cloud
node index.js
```

### 3. Access the Web UI

Open your Transitive web interface and navigate to the Simple Teleoperation capability. You should see:
- Connection status (Connected/Disconnected)
- Robot state display showing position and velocity
- Keyboard control visual indicators
- Speed settings

### 4. Control the Robot

Click anywhere in the web UI to focus it, then use arrow keys:
- **↑** - Move forward
- **↓** - Move backward
- **←** - Turn left (counter-clockwise)
- **→** - Turn right (clockwise)

The robot will move smoothly, and you'll see real-time updates of:
- Position: x, y (in meters), θ (in degrees)
- Velocity: linear (m/s), angular (rad/s)

## Testing the Simulator

### Test 1: Forward Motion

1. Press and hold **↑** for 2 seconds
2. Release the key
3. Expected result:
   - Linear velocity shows 0.5 m/s while key is pressed
   - Linear velocity returns to 0 when released
   - Position x increases (assuming θ = 0°)
   - Movement is smooth, not jerky

### Test 2: Turning

1. Press and hold **←** for ~3 seconds
2. Release the key
3. Expected result:
   - Angular velocity shows 1.0 rad/s while key is pressed
   - θ increases from 0° toward 180° (counter-clockwise)
   - Angular velocity returns to 0 when released

### Test 3: Combined Movement

1. Press and hold **↑** and **←** together
2. Hold for 5 seconds
3. Release both keys
4. Expected result:
   - Robot moves in a circular arc to the left
   - Both linear and angular velocities are non-zero
   - Path is smooth and continuous
   - Both velocities return to 0 when released

### Test 4: Response Time

1. Quickly tap **↑** (very brief press)
2. Expected result:
   - Velocity command sent immediately on keydown
   - Stop command (0,0) sent immediately on keyup
   - No noticeable lag between key press and robot response

## Understanding the Coordinate System

The robot operates in a 2D Cartesian coordinate system:

```
         +Y (North)
          ^
          |
          |
    -X <--+--> +X (East)
          |
          |
          v
        -Y (South)
```

### Position
- **x, y**: Position in meters from origin (0, 0)
- **θ (theta)**: Heading angle in radians
  - 0° = facing East (+X direction)
  - 90° = facing North (+Y direction)
  - 180° / -180° = facing West (-X direction)
  - -90° = facing South (-Y direction)

### Physics Model

The simulator uses simple 2D kinematics:

```javascript
// Update rate: 50Hz (dt = 0.02 seconds)
theta += angular_velocity * dt
x += linear_velocity * cos(theta) * dt
y += linear_velocity * sin(theta) * dt
```

### Default Speeds
- **Linear velocity**: 0.5 m/s (forward/backward)
- **Angular velocity**: 1.0 rad/s (≈ 57.3°/s rotation speed)

## Communication Architecture

```
┌─────────────┐         MQTT          ┌──────────────┐
│   Web UI    │ ←------------------→  │    Robot     │
│  (Browser)  │                        │  Simulator   │
└─────────────┘                        └──────────────┘
      ↓                                        ↓
      └────────→  MQTTSync  ←─────────────────┘
                     ↓
              ┌─────────────┐
              │    Cloud    │
              │  Component  │
              └─────────────┘
```

### MQTT Topics

- `${prefix}/cmd` - Velocity commands from web to robot
  - Message: `{ linear: number, angular: number }`
  - Published at 20Hz while keys are pressed

- `${prefix}/state` - Robot state from robot to web
  - Message: `{ position: {x, y, theta}, velocity: {linear, angular}, timestamp }`
  - Published at 10Hz

- `${prefix}/status` - Heartbeat and status updates
  - Published every 1 second

## Customization

### Adjust Speeds

Edit `web/index.jsx`:
```javascript
const DEFAULT_LINEAR_SPEED = 0.5;  // Change to desired m/s
const DEFAULT_ANGULAR_SPEED = 1.0;  // Change to desired rad/s
```

### Adjust Update Rates

Edit `robot/index.js`:
```javascript
const PHYSICS_DT = 0.02;  // Physics loop: 0.02 = 50Hz
const STATE_PUBLISH_INTERVAL = 100;  // State publishing: 100ms = 10Hz
```

Edit `web/index.jsx`:
```javascript
const COMMAND_PUBLISH_RATE = 50;  // Command rate: 50ms = 20Hz
```

### Add More Controls

You can extend the keyboard controls in `web/index.jsx`:
- Add different speed modes
- Add boost functionality
- Add emergency stop button
- Add waypoint navigation

## Troubleshooting

### Robot not responding to commands

1. Check MQTT connection status in web UI (should show "Connected")
2. Verify robot component is running (`node robot/index.js`)
3. Check browser console for errors
4. Ensure web UI has focus (click on the page)

### Jerky or laggy movement

1. Check your network latency to MQTT broker
2. Verify physics loop is running at 50Hz (check robot logs)
3. Ensure no CPU throttling on robot machine
4. Try reducing command publish rate in web component

### Keys not working

1. Click on the web UI to give it focus
2. Check browser console for event listener errors
3. Verify arrow keys aren't captured by browser shortcuts
4. Try a different browser

### State not updating

1. Verify robot component is publishing state (check logs)
2. Check MQTT connection in web UI
3. Verify network connectivity to MQTT broker
4. Check browser console for subscription errors

## Development

### Project Structure

```
@local/simple-teleop/
├── package.json              # Capability metadata
├── README.md                 # This file
├── robot/
│   ├── package.json          # Robot dependencies
│   └── index.js              # Robot simulator with physics
├── web/
│   ├── package.json          # Web dependencies
│   └── index.jsx             # React UI component
└── cloud/
    ├── package.json          # Cloud dependencies
    └── index.js              # Cloud monitoring component
```

### Adding New Features

1. **Add sensors**: Extend robot state in `robot/index.js`
2. **Add visualizations**: Modify `web/index.jsx` to display new data
3. **Add logging**: Extend `cloud/index.js` for analytics
4. **Add obstacles**: Implement collision detection in robot physics

## License

MIT

## Support

For issues with:
- **This capability**: Check the troubleshooting section above
- **Transitive framework**: Refer to Transitive Robotics documentation
- **MQTT connectivity**: Check your Transitive instance configuration