Skip to content

Commit 868859a

Browse files
authored
Merge pull request #337 from open-edge-platform/update-branch
865 user story add ai powered robotic arm demo integration with intel robotics ai suite (#879)
2 parents 6dc22c3 + b3ec08b commit 868859a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+16501
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Robotic Imitation Learning
2+
3+
A lightweight UI and server for robotic imitation learning—covering data capture, conversion, and inference—for a robotic arm demo integrated with Intel® Robotics AI Suite components. The project provides a Python server for data handling and a web UI for interaction.
4+
5+
Robotic imitation learning demo showing a web dashboard controlling a robotic arm during a training session in a lab with UI panels displaying camera view controls, movement controls, and status indicators in a focused technical setting
6+
7+
## Features
8+
9+
- Compatible with Intel® Robotics AI Suite components or Edge Developer Kit Reference Scripts
10+
- Data capture: Record sensor/telemetry and control events
11+
- Conversion tools: Optional data format conversion utilities
12+
- Inference: Run model inference scripts from the server
13+
- Web UI: Vite-based frontend for control and visualization
14+
- Modular layout: Separate `server` and `webui` workflows
15+
16+
## Architecture Diagram
17+
18+
![User Flow Diagram](./docs/userflow.jpg)
19+
![Archictecture Diagram](./docs/archdiagram.jpg)
20+
21+
## Directory Structure
22+
23+
- `server/`: Python server, configs, and scripts
24+
- `webui/`: Frontend app (Vite + Node.js*)
25+
26+
## Hardware Requirements
27+
28+
- CPU: Intel® Core™ Ultra processors (Series 2) and above
29+
- GPU: Intel® Arc™ B-Series Graphics (Optional)
30+
- RAM: 32GB RAM
31+
- SSD: 500GB and above
32+
33+
## Software Requirements
34+
35+
- **Operating System:** Ubuntu 24.04 LTS
36+
37+
## Setup (Server)
38+
39+
Follow the [doc](server/README.md) to setup
40+
41+
## Setup (Web UI)
42+
43+
Follow the [doc](webui/README.md) to setup
44+
45+
## Trademarks and Notes
46+
47+
- Intel®, Intel® Atom®, Intel® Core™, Intel® Xeon® are trademarks of Intel Corporation.
48+
- Third-party names such as Ubuntu*, Node.js*, NVM*, Vite*, GitHub* are used for identification purposes only.
49+
- Ubuntu* is a trademark of Canonical Limited.
50+
- Node.js* and NPM* are trademarks of OpenJS Foundation.
51+
52+
## License
53+
54+
This project is licensed under the Apache License, Version 2.0.
214 KB
Loading
150 KB
Loading
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Python-generated files
2+
__pycache__/
3+
*.py[oc]
4+
build/
5+
dist/
6+
wheels/
7+
*.egg-info
8+
9+
# Virtual environments
10+
.venv
11+
data/
12+
output/
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Server App for Robotic EmbodiedAI
2+
3+
This server application is a core component of the Robotic EmbodiedAI project. It provides backend services, data management, and robot simulation utilities for embodied AI research and development.
4+
5+
## Features
6+
7+
- Robot and teleoperator calibration
8+
- Data management for simulation and real-world experiments
9+
- Model training and checkpointing
10+
- MuJoCo-based simulation runner
11+
- Modular architecture for easy extension
12+
13+
## Setup
14+
15+
1. **Install system dependencies**
16+
```bash
17+
sudo apt install build-essential git cmake libevdev-dev python3-dev
18+
```
19+
20+
2. **Install UV**
21+
```bash
22+
curl -LsSf https://astral.sh/uv/install.sh | sh
23+
```
24+
25+
3. **Create a Python virtual environment**
26+
```bash
27+
uv venv --python 3.11 .venv
28+
```
29+
30+
31+
4. **Install Python dependencies**
32+
```bash
33+
source .venv/bin/activate
34+
uv pip install -r requirements.txt --index-strategy unsafe-best-match
35+
uv pip install torch==2.9.1 torchvision==0.24.1 torchaudio==2.9.1 --index-url https://download.pytorch.org/whl/xpu
36+
```
37+
38+
## Run Server
39+
40+
1. **Plug in the devices according to the order**
41+
42+
First plug in the leader arm, then followed by the USB/RealSense camera that point at the follower arm. Finally, plug in the follower arm with the camera on the follower arm. Ordering is very important in helping to identify the device later while setting the configurations.
43+
44+
| Device | Port |
45+
| ------ | ---- |
46+
| Leader Arm | ttyACM0 |
47+
| USB/RealSense Camera | /dev/video0 |
48+
| Follower Arm | ttyACM1 |
49+
| Camera on Follower Arm | /dev/video2 |
50+
51+
2. **Ensure permission are set for the motor drivers**
52+
53+
**This must be run whenever you plug out and plug in back the device.** In our case, The leader arm at `TTYACM0` and follower arm at `TTYACM1`.
54+
```bash
55+
sudo chmod 666 /dev/ttyACM0
56+
sudo chmod 666 /dev/ttyACM1
57+
```
58+
59+
3. **Calibrate the leader and the follower arm (One time only)**
60+
61+
Use the `calibrate-leader.sh` and `calibrate-robot.sh` script to calibrate the leader and the follower arm accordingly. Refer to the video in the [link](https://huggingface.co/docs/lerobot/en/so101#calibration-video) if you are not sure how to do it.
62+
63+
4. **Run the command below to start the server**
64+
65+
Once started, the server will be brought up at http://localhost:5989.
66+
```bash
67+
source .venv/bin/activate
68+
python main.py
69+
```
70+
71+
## Inference with the trained model using OpenVINO
72+
73+
1. Use the script `convert.py` to convert the model to OpenVINO format after training completed. Example command as below. `task-uuid` and `dataset-name` can be refer in the UI.
74+
```bash
75+
python3 convert.py --model-weight-dir ./output/<task-uuid>/<dataset-name>/checkpoints/last/pretrained_model/ --dataset-dir ./data/datasets/<dataset-name>/
76+
```
77+
78+
2. Use the provided `inference.sh` script to run the inference easily. Configure the `CAMERA_CONFIG` and `POLICY_PATH` based on your training dataset. Configure the `OPENVINO_DEVICE` to run inference on different devices on Intel platform.
79+
80+
## License
81+
82+
See the root project for license information.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import zmq
5+
import time
6+
import gymnasium as gym
7+
import numpy as np
8+
import json
9+
import gym_hil # noqa: F401
10+
11+
context = zmq.Context()
12+
socket = context.socket(zmq.PUB)
13+
socket.bind("tcp://*:5556")
14+
15+
def main():
16+
env_id = "gym_hil/PandaPickCubeKeyboard-v0"
17+
env = gym.make(
18+
env_id,
19+
render_mode="human",
20+
image_obs=True,
21+
use_gamepad=False,
22+
max_episode_steps=1000, # 100 seconds * 10Hz
23+
)
24+
25+
# Print observation space for the wrapped environment
26+
print("Wrapped observation space:", env.observation_space)
27+
28+
# Reset and check wrapped observation structure
29+
obs, _ = env.reset()
30+
print("Wrapped observation keys:", list(obs.keys()))
31+
32+
# Reset environment
33+
obs, _ = env.reset()
34+
dummy_action = np.zeros(4, dtype=np.float32)
35+
dummy_action[-1] = 1
36+
37+
topic = "live_data"
38+
39+
try:
40+
while True:
41+
# Step the environment
42+
obs, reward, terminated, truncated, info = env.step(dummy_action)
43+
44+
try:
45+
socket.send_string("NUMPY_DATA", zmq.SNDMORE)
46+
socket.send_pyobj(obs)
47+
# socket.send_multipart([topic.encode('utf-8'), message.encode('utf-8')])
48+
except:
49+
pass
50+
51+
# Print some feedback
52+
if info.get("succeed", False):
53+
print("\nSuccess! Block has been picked up.")
54+
55+
# If auto-reset is disabled, manually reset when episode ends
56+
if terminated or truncated:
57+
print("Episode ended, resetting environment")
58+
obs, _ = env.reset()
59+
60+
time.sleep(0.1)
61+
62+
except KeyboardInterrupt:
63+
print("Interrupted by user")
64+
finally:
65+
env.close()
66+
print("Session ended")
67+
68+
69+
if __name__ == "__main__":
70+
main()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import zmq
5+
import sys
6+
import numpy as np
7+
import cv2
8+
9+
# Define the connection details
10+
ZMQ_ADDRESS = "tcp://10.158.108.112:5556"
11+
# The topic we want to subscribe to (e.g., 'STATUS').
12+
# Use b'' or b' ' for all topics.
13+
SUBSCRIPTION_TOPIC = b"live_data"
14+
15+
# 1. Get the ZeroMQ context
16+
context = zmq.Context()
17+
18+
# 2. Create the SUB socket
19+
socket = context.socket(zmq.SUB)
20+
21+
# 3. Connect to the publisher server
22+
print(f"Connecting to ZMQ publisher at {ZMQ_ADDRESS}...")
23+
socket.connect(ZMQ_ADDRESS)
24+
25+
# 4. Set the subscription filter
26+
# The socket receives only messages starting with this topic byte string.
27+
# An empty string (b'') subscribes to ALL messages.
28+
socket.subscribe("NUMPY_DATA")
29+
print(f"Subscribed to topic: {SUBSCRIPTION_TOPIC.decode()}")
30+
31+
try:
32+
# 5. Start the message receiving loop
33+
while True:
34+
# zmq.SUB sockets often send messages in two parts (multipart):
35+
# [Topic, Message]
36+
topic = socket.recv_string()
37+
38+
# Use recv_multipart() to get both parts
39+
received_array = socket.recv_pyobj()
40+
41+
for k, v in received_array['pixels'].items():
42+
if isinstance(v, np.ndarray):
43+
cv2.imshow("frame", v)
44+
45+
cv2.waitKey(10)
46+
47+
# print(f"Received topic: {topic}")
48+
# print(f"Received array:\n{received_array}")
49+
50+
51+
except KeyboardInterrupt:
52+
print("\nShutting down SUB client...")
53+
finally:
54+
# 6. Clean up
55+
socket.close()
56+
context.term()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright (C) 2025 Intel Corporation
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
set -euo pipefail
7+
8+
lerobot-calibrate --teleop.type=so101_leader --teleop.port=/dev/ttyACM0 --teleop.id=my_leader_arm
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright (C) 2025 Intel Corporation
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
set -euo pipefail
7+
8+
lerobot-calibrate --robot.type=so101_follower --robot.port=/dev/ttyACM1 --robot.id=my_follower_arm

0 commit comments

Comments
 (0)