From 4cd323344217a5d0747f39655d34c872b8d29e42 Mon Sep 17 00:00:00 2001 From: tmacy Date: Thu, 26 Mar 2026 21:54:37 +0800 Subject: [PATCH 01/13] feat: add Docker support, sync functionality and documentation updates --- .cnb.yml | 24 +++++++++ .dockerignore | 13 +++++ Dockerfile | 71 ++++++++++++++++++++++++++ README.md | 121 ++++++++++++++++++++++++++++++++++++++++++--- docker-compose.yml | 33 +++++++++++++ 5 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 .cnb.yml create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.cnb.yml b/.cnb.yml new file mode 100644 index 00000000..3d82d6a4 --- /dev/null +++ b/.cnb.yml @@ -0,0 +1,24 @@ +# .cnb.yml +main: + push: + - imports: https://cnb.cool/tmacychen/sec/-/blob/main/envs.yml + stages: + - name: sync to github + image: tencentcom/git-sync + settings: + target_url: https://github.com/tmacychen/AKA-Sim.git + auth_type: https + username: $GIT_USERNAME + password: $GIT_ACCESS_TOKEN + +$: + push: + - imports: https://cnb.cool/tmacychen/sec/-/blob/main/envs.yml + stages: + - name: sync to github + image: tencentcom/git-sync + settings: + target_url: https://github.com/tmacychen/AKA-Sim.git + auth_type: https + username: $GIT_USERNAME + password: $GIT_ACCESS_TOKEN \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..e86eed9f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +__pycache__/ +.git/ +.idea/ +node_modules/ +static/ +output/ +checkpoints/ +*.pyc +*.pyo +.env +.DS_Store +.codebuddy/ +.github/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..353cd7ec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,71 @@ +# ============================================================ +# AKA-Sim Dockerfile +# Multi-stage: dev (development) + prod (production) +# ============================================================ + +# ---------- Base ---------- +FROM python:3.11-slim AS base + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + curl \ + wget \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +# Install Node.js 20 LTS +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Install Python dependencies first (layer cache) +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Install frontend dependencies +COPY frontend/package.json frontend/package-lock.json ./frontend/ +RUN cd frontend && npm ci + +# ---------- Development ---------- +FROM base AS dev + +# Install dev tools +RUN pip install --no-cache-dir \ + debugpy \ + watchdog \ + flake8 \ + black + +# Keep all source mounted, expose ports +# Port 80: Flask HTTP +# Port 5000: Flask fallback HTTP (Windows) +# Port 5173: Vite dev server +EXPOSE 80 5000 5173 + +CMD ["python", "run.py"] + +# ---------- Production ---------- +FROM base AS prod + +# Build frontend +COPY frontend/ ./frontend/ +RUN cd frontend && npm run build + +# Copy backend source +COPY backend/ ./backend/ +COPY run.py . +COPY https_init.sh . +COPY init.sh . +COPY main.html . +COPY templates/ ./templates/ + +# Copy built frontend to static folder +RUN cp -r frontend/dist/. static/ 2>/dev/null || mkdir -p static && cp -r frontend/dist/. static/ + +EXPOSE 80 443 + +CMD ["sh", "-c", "chmod +x /app/https_init.sh && /app/https_init.sh && python run.py"] diff --git a/README.md b/README.md index 12f5f903..452c6509 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,110 @@ AKA-Sim/ ## 快速开始 -### 1. 环境配置 +### 方式一:Docker(推荐) + +项目提供了多阶段 Docker 镜像,包含开发环境和生产环境两种构建目标。远程镜像已发布,可直接拉取使用,无需本地构建。 + +#### 环境要求 + +- Docker 20.10+ +- Docker Compose 2.0+(可选) + +#### 1. 拉取预构建镜像(推荐) + +跳过构建,直接拉取已有镜像: + +```bash +docker pull docker.cnb.cool/tmacychen/chenlongos-aka-sim:latest +docker tag docker.cnb.cool/tmacychen/chenlongos-aka-sim:latest aka-sim:dev +``` + +#### 2. 启动容器 + +```bash +# 启动开发容器(挂载本地源码) +docker run -d --name aka-sim-dev \ + -p 80:80 -p 5000:5000 \ + -v $(pwd):/app \ + -v /app/frontend/node_modules \ + -e PYTHONPATH=/app/backend \ + -w /app \ + aka-sim:dev + +# 首次启动需要构建前端静态资源 +docker exec aka-sim-dev bash -c "cd /app/frontend && npm run build" +``` + +访问 http://localhost:80 即可使用。 + +#### 3. 本地构建镜像 + +如需自定义构建,可使用以下命令: + +```bash +# 构建开发镜像 +docker build --target dev -t aka-sim:dev . + +# 构建生产镜像 +docker build --target prod -t aka-sim:prod . + +# 启动开发容器(挂载本地源码,支持热重载) +docker run -d --name aka-sim-dev \ + -p 80:80 -p 5000:5000 \ + -v $(pwd):/app \ + -v /app/frontend/node_modules \ + -e PYTHONPATH=/app/backend \ + -w /app \ + aka-sim:dev + +# 首次启动需要构建前端静态资源 +docker exec aka-sim-dev bash -c "cd /app/frontend && npm run build" + +# 启动生产容器 +docker run -d --name aka-sim-prod \ + -p 80:80 -p 443:443 \ + -e PYTHONPATH=/app/backend \ + aka-sim:prod +``` + +#### 使用 Docker Compose + +```bash +# 开发环境(源码挂载,支持热重载) +docker compose up dev + +# 生产环境(构建前端,仅运行时依赖) +docker compose up prod --build +``` + +#### 端口说明 + +| 端口 | 用途 | 说明 | +|------|------|------| +| 80 | Flask HTTP | 主服务端口 | +| 443 | Flask HTTPS | 生产环境,自动生成自签名证书 | +| 5000 | Flask HTTP 备用 | Windows 环境下的默认端口 | +| 5173 | Vite 开发服务器 | 仅开发环境 | + +#### Dockerfile 构建阶段 + +| 阶段 | 说明 | 基础镜像 | +|------|------|----------| +| `base` | 安装 Python 3.11、Node.js 20 及所有依赖 | python:3.11-slim | +| `dev` | 开发环境,额外安装 debugpy/watchdog/flake8/black | base | +| `prod` | 生产环境,自动构建 React 前端并复制到 static/ | base | + +#### GPU 支持(可选) + +如需 CUDA 加速,将 Dockerfile 基础镜像替换为: +```dockerfile +FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04 AS base +``` +并安装对应版本的 PyTorch,运行时添加 `--gpus all` 参数。 + +### 方式二:本地安装 + +#### 1. 环境配置 创建 Python 3.11 环境: @@ -52,21 +155,27 @@ conda create -n aka-sim python=3.11 -y conda activate aka-sim ``` -### 2. 安装依赖 +#### 2. 安装依赖 ```bash pip install -r requirements.txt ``` -### 3. 启动后端服务 +#### 3. 构建前端(React) + +```bash +cd frontend && npm ci && npm run build && cd .. +``` + +#### 4. 启动后端服务 ```bash -python run.py +PYTHONPATH=backend python run.py ``` -后端启动后,将main.html拖到浏览器中打开前端页面: +#### 5. 访问服务 -服务启动后访问: +- http://localhost/ - 首页 - http://localhost/sim - 模拟器 ## API 接口 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..601d7001 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +services: + # -------- Development -------- + dev: + build: + context: . + target: dev + container_name: aka-sim-dev + ports: + - "80:80" + - "5000:5000" + - "5173:5173" # Vite dev server + volumes: + - .:/app # Mount source code for hot reload + - /app/frontend/node_modules # Prevent host/node_modules conflict + environment: + - FLASK_DEBUG=1 + - APP_HTTP_PORT=5000 + - PYTHONPATH=/app/backend + command: python run.py + + # -------- Production -------- + prod: + build: + context: . + target: prod + container_name: aka-sim-prod + ports: + - "80:80" + - "443:443" + environment: + - APP_HTTP_PORT=80 + - APP_HTTPS_PORT=443 + restart: unless-stopped From dc02888b33107c9640757e23120173f997d77ac0 Mon Sep 17 00:00:00 2001 From: tmacy Date: Thu, 26 Mar 2026 22:12:32 +0800 Subject: [PATCH 02/13] fix: prefer WebSocket transport with polling fallback for socket.io Change transports from polling-only to websocket-first with automatic polling fallback, and enable upgrade to reduce latency and bandwidth overhead in real-time control scenarios. --- frontend/src/api/socket.ts | 4 +- frontend/vite.config.ts | 2 +- websocket-issue.md | 94 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 websocket-issue.md diff --git a/frontend/src/api/socket.ts b/frontend/src/api/socket.ts index 27e812ff..a1f4d4b8 100644 --- a/frontend/src/api/socket.ts +++ b/frontend/src/api/socket.ts @@ -2,8 +2,8 @@ import {io} from "socket.io-client"; export const socket = io({ path: "/socket.io", - transports: ["polling"], - upgrade: false, + transports: ["websocket", "polling"], + upgrade: true, reconnection: true, reconnectionAttempts: Infinity, reconnectionDelay: 500, diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index fbdb7647..af7e68cd 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ }, "/socket.io": { target: "http://localhost:5000", - ws: false, + ws: true, changeOrigin: true, }, }, diff --git a/websocket-issue.md b/websocket-issue.md new file mode 100644 index 00000000..fc870ffe --- /dev/null +++ b/websocket-issue.md @@ -0,0 +1,94 @@ +使用 HTTP 长轮询而非原生 WebSocket 存在以下问题: + +## 主要缺点 + +### 1. **性能开销大** +``` +HTTP 长轮询: + 每次请求/响应都需完整的 HTTP 头 (约 1KB) + 20FPS 控制频率 = 每秒 20 次请求/响应对 + → 每秒网络流量 ~40KB,带宽浪费 + +WebSocket: + 握手后仅需 2-14 字节帧头 + → 同频率下流量 < 1KB,节省 95%+ 带宽 +``` + +### 2. **延迟更高** +``` +轮询延迟 = RTT + 服务端排队时间 + 轮询间隔: 50ms (20FPS) + + 网络往返: 10-50ms + → 总延迟 60-100ms + +WebSocket: 持久连接,消息即时推送 + → 延迟 ~10-20ms +``` + +### 3. **连接不稳定** +- 长轮询连接超时需要重建(浏览器/代理超时通常 30-120s) +- 网络波动时频繁断线重连,用户体验差 + +### 4. **服务器压力大** +``` +长轮询: 每个客户端占用 1 个 HTTP 线程/连接池槽位 + 高并发时易耗尽连接池 + +WebSocket: 建立后占用极低资源 + 适合多客户端场景 +``` + +--- + +## 当前项目中的影响 + +| 场景 | 长轮询 | WebSocket | +|------|--------|-----------| +| **20FPS 控制指令** | ✅ 可用,但延迟高、带宽浪费 | ✅ 理想选择 | +| **推理 5Hz 轮询** | 已走 REST,不受影响 | — | +| **训练状态 1Hz 轮询** | 已走 REST,不受影响 | — | + +> 当前配置的 **唯一合理理由** 是兼容性:某些公司防火墙或代理可能屏蔽原生 WebSocket,长轮询能保证功能可用。 + +--- + +## 改进建议 + +### 1. 优先使用 WebSocket,降级长轮询 + +```typescript +// /workspace/frontend/src/api/socket.ts +export const socket = io({ + path: "/socket.io", + transports: ["websocket", "polling"], // 优先 WebSocket,失败时自动降级 + upgrade: true, // 允许升级 + reconnection: true, + reconnectionAttempts: Infinity, + reconnectionDelay: 500, + timeout: 20000 +}); +``` + +### 2. 添加传输检测提示 + +```typescript +socket.on("connect", () => { + console.log(`Socket connected via ${socket.io.engine.transport.name}`); + if (socket.io.engine.transport.name === "polling") { + console.warn("⚠️ Using long polling instead of WebSocket (higher latency)"); + } +}); +``` + +--- + +## 总结 + +| 评估维度 | 当前配置 | 推荐 | +|---------|---------|------| +| 性能 | ⚠️ 中等 (高延迟、高带宽) | ✅ 优秀 | +| 稳定性 | ⚠️ 中等 (频繁重连) | ✅ 优秀 | +| 兼容性 | ✅ 极好 | ✅ 良好 (降级机制) | +| 适用场景 | 低频控制、受限网络 | 高频实时控制 | + +**当前项目问题不大**:20FPS 控制频率不算极端,但改用 `["websocket", "polling"]` 优先 WebSocket 能明显提升响应速度,同时保留降级保底。 \ No newline at end of file From c1a7966beded9fc3ff09e3c48ce176a56633c276 Mon Sep 17 00:00:00 2001 From: tmacy Date: Fri, 27 Mar 2026 10:13:27 +0800 Subject: [PATCH 03/13] feat:add setup script for start up project ; add sim3d for frontend --- backend/app/routes/frontend.py | 13 +- setup.sh | 210 +++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100755 setup.sh diff --git a/backend/app/routes/frontend.py b/backend/app/routes/frontend.py index c3b0b368..cf08a50d 100644 --- a/backend/app/routes/frontend.py +++ b/backend/app/routes/frontend.py @@ -1,7 +1,18 @@ -from flask import Blueprint, render_template +import os +from flask import Blueprint, render_template, send_file frontend_bp = Blueprint("frontend", __name__) +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +@frontend_bp.route("/sim3d") +def serve_sim3d(): + """3D 模拟器页面,使用独立 main.html(Three.js + TensorFlow.js)""" + main_html = os.path.join(ROOT_DIR, "main.html") + if os.path.exists(main_html): + return send_file(main_html) + return {"error": "main.html not found"}, 404 + @frontend_bp.route("/", defaults={"path": ""}) @frontend_bp.route("/") def serve_react(path): diff --git a/setup.sh b/setup.sh new file mode 100755 index 00000000..efc457ae --- /dev/null +++ b/setup.sh @@ -0,0 +1,210 @@ +#!/bin/bash + +set -e + +IMAGE_NAME="docker.cnb.cool/tmacychen/chenlongos-aka-sim:latest" +TAG_NAME="aka-sim:dev" +CONTAINER_NAME="aka-sim-dev" +HTTP_PORT=80 +FALLBACK_PORT=5000 + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +info() { echo -e "${CYAN}[INFO]${NC} $1"; } +ok() { echo -e "${GREEN}[OK]${NC} $1"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +err() { echo -e "${RED}[ERROR]${NC} $1"; } + +check_docker() { + if ! command -v docker &>/dev/null; then + err "未检测到 Docker,请先安装 Docker 20.10+" + exit 1 + fi + if ! docker info &>/dev/null; then + err "Docker 守护进程未运行,请先启动 Docker" + exit 1 + fi +} + +# ---- 停止容器 ---- +do_stop() { + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + info "停止容器 ${CONTAINER_NAME} ..." + docker stop "${CONTAINER_NAME}" + ok "容器已停止" + else + warn "容器 ${CONTAINER_NAME} 未在运行" + fi +} + +# ---- 删除容器 ---- +do_rm() { + do_stop 2>/dev/null || true + if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + info "删除容器 ${CONTAINER_NAME} ..." + docker rm "${CONTAINER_NAME}" + ok "容器已删除" + fi +} + +# ---- 启动容器 ---- +do_start() { + check_docker + + # 拉取镜像 + info "拉取预构建镜像 ${IMAGE_NAME} ..." + if docker pull "${IMAGE_NAME}"; then + ok "镜像拉取成功" + else + warn "镜像拉取失败,尝试使用本地已存在的镜像..." + fi + + docker tag "${IMAGE_NAME}" "${TAG_NAME}" 2>/dev/null || true + ok "镜像标签: ${TAG_NAME}" + + # 清理旧容器 + if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + warn "容器 ${CONTAINER_NAME} 已存在,正在停止并删除..." + docker stop "${CONTAINER_NAME}" 2>/dev/null || true + docker rm "${CONTAINER_NAME}" 2>/dev/null || true + ok "旧容器已清理" + fi + + # 检查端口 + check_port() { + if ss -tlnp 2>/dev/null | grep -q ":${1} "; then + return 1 + fi + return 0 + } + + PORT_FLAG="-p ${HTTP_PORT}:80 -p ${FALLBACK_PORT}:5000" + if ! check_port ${HTTP_PORT}; then + warn "端口 ${HTTP_PORT} 已被占用,改用 8080" + PORT_FLAG="-p 8080:80 -p ${FALLBACK_PORT}:5000" + fi + if ! check_port ${FALLBACK_PORT}; then + warn "端口 ${FALLBACK_PORT} 已被占用,改用 5001" + PORT_FLAG="${PORT_FLAG/5000:5000/5001:5000}" + fi + + info "启动容器 ${CONTAINER_NAME} ..." + docker run -d --name "${CONTAINER_NAME}" \ + ${PORT_FLAG} \ + -v "$(pwd)":/app \ + -v /app/frontend/node_modules \ + -e PYTHONPATH=/app/backend \ + -w /app \ + "${TAG_NAME}" + + ok "容器已启动" + + # 构建前端 + info "构建前端静态资源..." + if docker exec "${CONTAINER_NAME}" bash -c "cd /app/frontend && npm run build"; then + ok "前端构建成功" + else + warn "前端构建失败,尝试跳过(可能已有缓存构建)..." + fi + + # 等待服务就绪 + info "等待服务启动..." + sleep 3 + + if check_port ${HTTP_PORT}; then + ACCESS_PORT=${HTTP_PORT} + elif [[ "${PORT_FLAG}" == *"8080"* ]]; then + ACCESS_PORT=8080 + else + ACCESS_PORT=${FALLBACK_PORT} + fi + + for i in $(seq 1 10); do + if curl -s -o /dev/null -w "%{http_code}" "http://localhost:${ACCESS_PORT}" 2>/dev/null | grep -q "200\|302\|304"; then + ok "服务已就绪" + break + fi + if [ $i -eq 10 ]; then + warn "服务启动超时,请手动检查: docker logs ${CONTAINER_NAME}" + fi + sleep 2 + done + + echo "" + echo "=========================================" + echo -e " ${GREEN}AKA-Sim 已成功启动!${NC}" + echo "=========================================" + echo "" + echo -e " ${CYAN}前端页面:${NC} http://localhost:${ACCESS_PORT}" + echo -e " ${CYAN}模拟器:${NC} http://localhost:${ACCESS_PORT}/sim" + echo -e " ${CYAN}3D模拟器:${NC} http://localhost:${ACCESS_PORT}/sim3d" + echo -e " ${CYAN}API:${NC} http://localhost:${ACCESS_PORT}/api/datasets" + echo "" + echo -e " 查看日志: ${YELLOW}docker logs -f ${CONTAINER_NAME}${NC}" + echo -e " 停止服务: ${YELLOW}./setup.sh stop${NC}" + echo -e " 重启服务: ${YELLOW}./setup.sh restart${NC}" + echo "" +} + +# ---- 重启容器 ---- +do_restart() { + check_docker + do_stop 2>/dev/null || true + do_start +} + +# ---- 显示状态 ---- +do_status() { + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + ok "容器 ${CONTAINER_NAME} 正在运行" + docker port "${CONTAINER_NAME}" 2>/dev/null | while read line; do + info "端口映射: ${line}" + done + else + warn "容器 ${CONTAINER_NAME} 未在运行" + if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + info "容器已停止,可通过 ./setup.sh start 启动" + fi + fi +} + +# ---- 查看日志 ---- +do_logs() { + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + docker logs -f "${CONTAINER_NAME}" + else + err "容器 ${CONTAINER_NAME} 未在运行" + exit 1 + fi +} + +# ---- 用法 ---- +usage() { + echo "" + echo -e "${CYAN}用法:${NC} ./setup.sh [命令]" + echo "" + echo -e " ${GREEN}start${NC} 启动服务(默认)" + echo -e " ${GREEN}stop${NC} 停止服务" + echo -e " ${GREEN}restart${NC} 重启服务" + echo -e " ${GREEN}status${NC} 查看服务状态" + echo -e " ${GREEN}logs${NC} 查看实时日志" + echo -e " ${GREEN}rm${NC} 停止并删除容器" + echo "" +} + +# ---- 入口 ---- +case "${1:-start}" in + start) do_start ;; + stop) check_docker; do_stop ;; + restart) do_restart ;; + status) check_docker; do_status ;; + logs) check_docker; do_logs ;; + rm) check_docker; do_rm ;; + -h|--help|help) usage ;; + *) err "未知命令: $1"; usage; exit 1 ;; +esac From d32861871d24f6406ff6783b1ffbb026d2d55bef Mon Sep 17 00:00:00 2001 From: tmacy Date: Fri, 27 Mar 2026 10:59:38 +0800 Subject: [PATCH 04/13] feat: merge 3D interface with robotic arm from 3d-front branch - Add Three.js 3D simulator with robotic arm (src/sim/) - Add React frontend with Vite (src/App.tsx, src/components/) - Add cloud training service integration (src/services/) - Update main.html with UI improvements and collapsible sections - Add demo.html and demo2.html standalone demos - Add arm toggle feature persisted to localStorage --- .env.example | 9 + demo.html | 1158 +++++++ demo2.html | 1239 +++++++ index.html | 15 + learn1.md | 322 ++ learn2.md | 194 ++ main.html | 86 +- metadata.json | 5 + package-lock.json | 5756 +++++++++++++++++++++++++++++++ package.json | 42 + src/App.tsx | 2316 +++++++++++++ src/api/socket.ts | 36 + src/components/Header.tsx | 22 + src/components/SidebarLeft.tsx | 371 ++ src/components/SidebarRight.tsx | 64 + src/index.css | 159 + src/main.tsx | 10 + src/services/actService.ts | 89 + src/services/cloudService.ts | 118 + src/sim/environment.ts | 97 + src/sim/robot.ts | 164 + src/sim/scene.ts | 58 + src/types.ts | 84 + tsconfig.json | 26 + vite.config.ts | 36 + 25 files changed, 12439 insertions(+), 37 deletions(-) create mode 100644 .env.example create mode 100644 demo.html create mode 100644 demo2.html create mode 100644 index.html create mode 100644 learn1.md create mode 100644 learn2.md create mode 100644 metadata.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/App.tsx create mode 100644 src/api/socket.ts create mode 100644 src/components/Header.tsx create mode 100644 src/components/SidebarLeft.tsx create mode 100644 src/components/SidebarRight.tsx create mode 100644 src/index.css create mode 100644 src/main.tsx create mode 100644 src/services/actService.ts create mode 100644 src/services/cloudService.ts create mode 100644 src/sim/environment.ts create mode 100644 src/sim/robot.ts create mode 100644 src/sim/scene.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..7a550fe7 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +# GEMINI_API_KEY: Required for Gemini AI API calls. +# AI Studio automatically injects this at runtime from user secrets. +# Users configure this via the Secrets panel in the AI Studio UI. +GEMINI_API_KEY="MY_GEMINI_API_KEY" + +# APP_URL: The URL where this applet is hosted. +# AI Studio automatically injects this at runtime with the Cloud Run service URL. +# Used for self-referential links, OAuth callbacks, and API endpoints. +APP_URL="MY_APP_URL" diff --git a/demo.html b/demo.html new file mode 100644 index 00000000..fdd19054 --- /dev/null +++ b/demo.html @@ -0,0 +1,1158 @@ + + + + + + LeRobot ACT 模型教学模拟器 + + + + + + + + +
+
+
🤖
+
+

LeRobot ACT Simulator

+

Action Chunking with Transformers - Educational Edition

+
+
+
+
+ + Simulation Active +
+
60 FPS
+
+
+ + +
+ + + + + +
+
+ + +
+
Position: 0.00, 0.00
+
Rotation:
+
Velocity: 0.0 m/s
+
+ + +
+ 手动控制模式 +
+
+ + + +
+ + + + diff --git a/demo2.html b/demo2.html new file mode 100644 index 00000000..315c022a --- /dev/null +++ b/demo2.html @@ -0,0 +1,1239 @@ + + + + + + LeRobot ACT Simulator (Vanilla JS) + + + + + + + + + +
+
+
🤖
+
+

LeRobot ACT Simulator

+

Action Chunking with Transformers - Vanilla JS Edition

+
+
+
+
+ + Simulation Active +
+
60 FPS
+
+
+ +
+ + + + +
+
+ +
+
Position: 0.00, 0.00
+
Rotation:
+
Velocity: 0.0 m/s
+
+ +
+ 手动控制模式 +
+
+ + + +
+ + + + diff --git a/index.html b/index.html new file mode 100644 index 00000000..5fe11357 --- /dev/null +++ b/index.html @@ -0,0 +1,15 @@ + + + + + + + + AKA ACT Simulator + + +
+ + + + diff --git a/learn1.md b/learn1.md new file mode 100644 index 00000000..e7e97480 --- /dev/null +++ b/learn1.md @@ -0,0 +1,322 @@ +## AKA-Sim (阿卡0号开源机器人) — 项目分析与学习指南 + +--- + +### 一、项目是什么 + +这是一个面向 **AKA-00 机器人小车** 的开源模拟训练平台,核心目标是实现 **ACT (Action Chunking Transformer)** 策略学习。用户可以在浏览器中操控虚拟小车、采集数据、训练神经网络、让模型自主驾驶。 + +--- + +### 二、技术栈总览 + +| 层级 | 技术 | +|------|------| +| 后端 | Python 3.11 + Flask + Flask-SocketIO | +| 机器学习 | PyTorch, einops, torchvision, accelerate | +| ACT 模型 | 自实现的 Action Chunking Transformer (~500行) | +| React 前端 | React 19 + TypeScript + Vite 8 + Zustand | +| HTML 前端 | Three.js 3D + TensorFlow.js (单文件) | +| 部署 | Docker 多阶段构建 + Docker Compose | + +--- + +### 三、项目架构 + +``` +/workspace/ +├── run.py # 主入口,启动 Flask HTTP/HTTPS +├── backend/ +│ ├── app/ +│ │ ├── __init__.py # Flask 工厂函数 +│ │ ├── extensions.py # SocketIO 实例 +│ │ └── routes/ +│ │ ├── api.py # REST API (数据集/模型/训练/推理/控制) ~640行 +│ │ ├── frontend.py # 前端路由 SPA fallback +│ │ └── websocket.py # WebSocket 事件处理 +│ ├── policies/act/ +│ │ ├── configuration_act.py # ACT 配置 +│ │ └── modeling_act.py # ACT Transformer 完整实现 ~500行 +│ ├── sim/model/car.py # 简单车体物理模型 +│ ├── train.py # 训练流程 ~390行 +│ ├── configs/types.py # 策略特征类型定义 +│ └── utils/ # 常量 & 随机工具 +├── frontend/ +│ └── src/ +│ ├── pages/ +│ │ ├── BaseControlPage.tsx # 远程控制台 +│ │ └── SimPage.tsx # 2D 模拟器 ~1050行 (核心) +│ ├── components/target/ # 目标物管理组件 +│ ├── api/socket.ts # Socket.IO + fetch 封装 +│ └── store/targetStore.ts # Zustand 状态管理 +├── main.html # 独立 Three.js 前端 ~1500行 +├── docker-compose.yml # dev/prod 两种部署 +└── Dockerfile # 多阶段构建 +``` + +--- + +### 四、推荐学习路径 + +#### 阶段 1:理解项目目标与整体架构 (1-2天) + +| 顺序 | 内容 | 文件 | +|------|------|------| +| 1 | 阅读项目文档 | `docs/src/index.md`, `docs/src/start.md` | +| 2 | 阅读入口与配置 | `run.py`, `backend/app/__init__.py` | +| 3 | 了解 API 接口 | `docs/src/api.md`, `backend/app/routes/api.py` | +| 4 | 理解通信机制 | `backend/app/routes/websocket.py`, `frontend/src/api/socket.ts` | + +**目标**: 理解前后端如何通过 REST API + WebSocket 协作。 + +#### 阶段 2:后端核心 — ACT 模型与训练 (3-5天) + +| 顺序 | 内容 | 文件 | +|------|------|------| +| 1 | 理解模型配置 | `backend/policies/act/configuration_act.py` | +| 2 | 深入 ACT 模型实现 | `backend/policies/act/modeling_act.py` | +| 3 | 理解数据集与训练流程 | `backend/train.py` | +| 4 | 理解物理模型 | `backend/sim/model/car.py` | +| 5 | 了解常量定义 | `backend/utils/constants.py` | + +**关键知识点**: +- **ACT 架构**: Transformer encoder-decoder + 可选 VAE encoder + 可选 ResNet18 视觉骨干 +- **训练流程**: 采集数据 → `.pt` 文件 → 后台线程训练 → 保存 checkpoint +- **推理流程**: 加载模型 → 5Hz 推理循环 → 输出动作向量 + +> **前置知识**: PyTorch 基础、Transformer 架构、VAE、LeRobot 数据格式 + +#### 阶段 3:前端核心 — 2D 模拟器 (3-5天) + +| 顺序 | 内容 | 文件 | +|------|------|------| +| 1 | 路由与入口 | `frontend/src/main.tsx`, `frontend/src/App.tsx` | +| 2 | 远程控制台 | `frontend/src/pages/BaseControlPage.tsx` | +| 3 | **2D 模拟器 (核心)** | `frontend/src/pages/SimPage.tsx` | +| 4 | 目标物渲染引擎 | `frontend/src/components/target/TargetRenderer.tsx` | +| 5 | 状态管理 | `frontend/src/store/targetStore.ts`, `frontend/src/model/target.ts` | + +**关键知识点**: +- Canvas 2D 渲染 (俯视图 + 伪3D第一人称射线投射) +- 20FPS 游戏循环 (requestAnimationFrame) +- 数据采集流程:开始 → 操控 → 复位保存 → 上传 +- ACT 自主推理的 5Hz 循环 + +#### 阶段 4:独立 3D 前端 (进阶,2-3天) + +| 内容 | 文件 | +|------|------| +| Three.js 3D 渲染 + 多场景 | `main.html` | +| 前端 TensorFlow.js 训练 | `main.html` 中的 ACT 模型 | +| 车载摄像头渲染 | WebGLRenderTarget | + +#### 阶段 5:部署与实战 (1-2天) + +| 内容 | 文件 | +|------|------| +| Docker 部署 | `Dockerfile`, `docker-compose.yml` | +| 真机部署 | `init.sh`, `https_init.sh` | + +--- + +### 五、动手实践建议 + +1. **先跑起来**: + ```bash + pip install -r requirements.txt + cd frontend && npm ci && npm run build && cd .. + python run.py + ``` + 打开浏览器访问,手动操控小车,体验数据采集 → 训练 → 推理的完整流程。 + +2. **阅读顺序建议**: + - `api.py` → 理解数据如何存储和查询 + - `train.py` → 理解如何从数据集训练模型 + - `modeling_act.py` → 深入理解 ACT Transformer 实现 + - `SimPage.tsx` → 理解前端如何将一切串联起来 + +3. **推荐前置知识**: + - Python Flask Web 开发 + - PyTorch 深度学习基础 + - Transformer / VAE 架构原理 + - React + TypeScript 基础 + - WebSocket 实时通信 + - Canvas 2D 绘图基础 + +--- + +### 六、核心数据流 + +``` +手动操控采集数据 → POST /api/dataset (保存 .pt) + ↓ +POST /api/train/start → 后台 PyTorch 训练 ACT + ↓ +POST /api/infer/start → POST /api/infer/step (5Hz) + ↓ +模型输出动作 → 小车自动行驶 +``` + +总结:这个项目是一个非常好的 **端到端机器人学习** 实战项目,涵盖了数据采集、模型训练、在线推理、Web 可视化等完整链路,适合对具身智能/机器人学习方向感兴趣的开发者深入学习。 + + + +## 前后端 REST API + WebSocket 协作分析 + +### 项目概览 + +AKA-Sim 是一个面向 AKA-00 机器人小车的模拟训练平台,实现了 ACT (Action Chunking Transformer) 策略学习。核心数据流是:**手动控制采集数据 → 训练 ACT 模型 → 模型自主推理**。 + +--- + +### 架构总览 + +``` +┌──────────────────────────────────────────────────┐ +│ 单一 Flask 容器 │ +│ │ +│ React SPA (/:80) ──┐ │ +│ Three.js (/:80) ──┤ │ +│ ▼ │ +│ ┌─── REST API (/api/*) ────┐ │ +│ │ 数据集 CRUD │ │ +│ │ 训练 启动/状态查询 │ ←─ fetch 轮询 │ +│ │ 推理 启动/步骤/停止 │ ←─ 5Hz POST │ +│ │ 远程控制代理 │ │ +│ └──────────────────────────┘ │ +│ │ +│ ┌─── Socket.IO (/socket.io) ─┐ │ +│ │ action C → S │ ←─ 20FPS 实时 │ +│ │ get_car_state C → S │ │ +│ │ reset_car_state C → S │ │ +│ │ car_state S → C │ ←─ 状态广播 │ +│ │ act_infer C → S │ ←─ WS推理(备用) │ +│ │ act_action S → C │ │ +│ └──────────────────────────┘ │ +│ │ +│ PyTorch ACT Model (线程内) │ +│ CarModel 单例 (全局状态) │ +└──────────────────────────────────────────────────┘ +``` + +--- + +### 通信职责划分 + +**REST API** — 用于**数据密集型、非实时**操作: + +| 端点 | 方法 | 用途 | 调用频率 | +|------|------|------|---------| +| `/api/dataset` | POST | 保存采集数据集 | 采集结束时 1 次 | +| `/api/datasets` | GET | 列出数据集 | 初始化 + 采集后刷新 | +| `/api/datasets/` | DELETE | 删除数据集 | 手动 | +| `/api/models` | GET | 列出模型 | 初始化 + 手动 | +| `/api/models/` | DELETE | 删除模型 | 手动 | +| `/api/train/start` | POST | 启动训练 | 按钮触发 | +| `/api/train/status` | GET | 查询训练进度 | **1 秒轮询** | +| `/api/infer/start` | POST | 加载推理模型 | 按钮触发 | +| `/api/infer/step` | POST | 执行一步推理 | **5Hz 轮询** | +| `/api/infer/stop` | POST | 停止推理 | 按钮触发 | +| `/api/control` | GET | 远程控制代理 | 实车模式 | +| `/api/ip` | GET | 获取本机 IP | 初始化 | + +**Socket.IO** — 用于**高频实时**操作: + +| 事件 | 方向 | 用途 | 频率 | +|------|------|------|------| +| `action` | C→S | 发送控制指令 (up/down/left/right/stop) | **20FPS** | +| `car_state` | S→C | 广播小车位置/角度 | 每次 action 后 | +| `get_car_state` | C→S | 查询当前状态 | 初始化时 1 次 | +| `reset_car_state` | C→S | 重置小车 | 复位按钮 | +| `act_infer` / `act_action` | C↔S | ACT 推理 (备用通道) | 按需 | + +> **注意**: Socket.IO 配置为 `transports: ["polling"]`, `upgrade: false`,实际使用 HTTP 长轮询而非原生 WebSocket。 + +--- + +### 核心业务流程 + +#### 1. 数据采集 (手动控制) + +``` +用户 WASD 键盘 + → socket.emit('action', 'up') [20FPS] + → 后端 handle_action() 更新 CarModel + → socket.emit('car_state', {x,y,angle}) + → 前端更新画布坐标 + +同时前端本地采集: + → getObservationVectors() [state[14], envState[7]] + → fpvCanvas.toDataURL() [base64 截图] + → push 到 currentEpisodeRef +``` + +#### 2. 数据集保存 + +``` +采集结束 → packDataset(episodes) + → POST /api/dataset {states, env_states, actions, action_is_pad, images} + → 后端 base64 解码图片 → torch.save() → output/datasets/*.pt +``` + +#### 3. 模型训练 + +``` +POST /api/train/start {dataset_path, num_epochs, ...} + → 后端 threading.Thread 后台运行 train_act() + → 更新全局 train_state + ← GET /api/train/status (前端 1s 轮询) + → 返回 {status, epoch, avg_loss, progress} +``` + +#### 4. ACT 自主推理 + +``` +POST /api/infer/start {model_id} → 加载模型 +POST /api/infer/step {state, env_state} → 5Hz 推理循环 + → 后端 ACT 前向推理 → _map_action() → "up" + → _apply_action() → emit('car_state') + ← 返回 {action: "up", action_vector: [...]} + → 前端 actCommandRef 控制 updatePhysics() +``` + +--- + +### 关键架构特点 + +1. **混合通信策略**: REST 处理数据 CRUD 和训练流程,Socket.IO 处理高频实时控制,职责清晰 +2. **推理双通道**: SimPage 的 ACT 推理走 REST `POST /api/infer/step`(带状态同步),WebSocket 的 `act_infer` 是备用通道(Three.js 前端使用) +3. **无认证无数据库**: 所有端点完全开放,数据以 `.pt` 文件存储,零外部依赖 +4. **坐标偏移**: 后端 CarModel 以 `(0,0)` 为中心,前端画布偏移 `(400,300)` 映射 +5. **SPA 部署**: 生产环境 Flask 同时提供 API + React 静态文件,开发环境 Vite 代理 `/api` 和 `/socket.io` 到 Flask 5000 端口 + + + + +## `main.html` vs React 前端对比分析 + +`main.html` 是一个**独立的 3D 模拟器页面**,与当前 React 前端的 `/sim` 页面功能相似但实现完全不同: + +### 核心差异 + +| 维度 | `main.html` (Three.js) | React 前端 `/sim` (Canvas 2D) | +|------|----------------------|------------------------------| +| **3D 渲染** | **Three.js + WebGL**,真3D场景(网格体、材质、光影) | **Canvas 2D 光线投射**(Wolfenstein 3D 风格伪3D) | +| **视觉效果** | 纹理地面(木纹/瓷砖/草地)、动态光照、阴影、雾效 | 扁平色块,无纹理、无光影,像素风 | +| **场景** | 4种场景(基础/客厅/教室/网球场)+ 复杂度调节 + 光源控制 | 固定网格,自由放置矩形/圆形障碍物 | +| **相机** | 第三人称跟随相机 + 车载第一人称相机(320x240) | 俯视图 + 伪3D第一人称 | +| **物理引擎** | 简单碰撞检测,无旋转碰撞 | 支持旋转矩形碰撞、圆形碰撞 | +| **前端训练** | TensorFlow.js 在浏览器端训练 ACT 模型 | 无前端训练,仅云端训练 | +| **训练模式** | 双模式:**前端TF.js训练** + **云端训练** | 仅云端训练 | +| **推理** | 前端 TF.js 推理(Temporal Ensembling)+ 云端推理 | 仅云端推理 5Hz | +| **目标管理** | 固定目标点(红色方块 + 黄色球),无编辑器 | 完整 CRUD:创建/编辑/删除/拖拽/导入导出 | +| **数据采集** | 64x64 图像 + 14维状态向量 + one-hot action | 类似,320x240 图像作为 base64 | +| **通信** | 仅 REST API(无 WebSocket) | Socket.IO + REST API | +| **状态持久化** | 无 | Zustand + localStorage | + +### 关键总结 + +1. **`main.html` 更"炫"** — Three.js 真正的 3D 渲染,多场景多纹理,视觉效果远超 React 版 +2. **`main.html` 更完整的功能闭环** — 支持浏览器端 TF.js 训练 + 推理,不依赖后端也能完成 AI 流程 +3. **React 前端更实用** — 目标编辑器更完善(拖拽/导入导出/持久化),WebSocket 实时通信,更适合实际数据采集 +4. **两者互不替代** — `main.html` 像是一个早期原型或演示页面,React 前端是正式版本 \ No newline at end of file diff --git a/learn2.md b/learn2.md new file mode 100644 index 00000000..c0e512f4 --- /dev/null +++ b/learn2.md @@ -0,0 +1,194 @@ +## 前后端数据交互分析 + +### 一、整体通信架构 + +前端与后端通过**两种通道**交互: + +| 通道 | 技术 | 用途 | +|------|------|------| +| **HTTP REST** | `fetch` → Flask Blueprint `/api/*` | 数据集保存/列表/删除、训练启动/状态、推理启动/步进/停止、模型管理 | +| **WebSocket** | Socket.IO (polling) → Flask-SocketIO | 实时小车动作下发、状态回传、ACT推理 | + +--- + +### 二、信息采集流程 + +采集分为 **前端本地采集** 和 **后端共享采集** 两条并行路径: + +#### 1. 前端本地模拟 + 采集(`SimPage.tsx`) + +这是核心采集路径,**所有模拟和采集都在前端完成,不需要后端实时参与**。 + +**渲染循环**(20 FPS,`692:763`): + +``` +requestAnimationFrame → 50ms 节流 + ├─ ACT推理(5Hz,每200ms一次 POST /api/infer/step) + ├─ updatePhysics()(物理更新:键盘→指令→移动→碰撞检测) + ├─ drawTopDown()(俯视图Canvas渲染) + ├─ drawFirstPerson()(伪3D第一人称Canvas渲染) + └─ 数据采集(如果 collecting=true) +``` + +**每帧采集的数据**(`743:762`): + +```typescript +EpisodeStep = { + state: number[]; // 14维 — 小车自身状态 + envState: number[]; // 7维 — 环境观测状态 + action: number[]; // 5维 — one-hot 动作编码 + image?: string; // base64 PNG — 第一人称画布截图 +} +``` + +**`getObservationVectors()`**(`496:515`)构建观测向量: + +- **state(14维)**:`[x, y, angle, speed, ballDistance, 0,0,0,0,0,0,0,0,0]` — 只用了前5维 +- **envState(7维)**:`[x, y, angle, speed, isCollision, forwardDistance, ballDistance]` + +其中 `forwardDistance` 通过射线-线段求交(`465:479`)计算前方障碍物距离,`ballDistance` 计算到最近圆形目标的距离。 + +**动作编码**(`450:463`): + +| 指令 | one-hot向量 | +|------|------------| +| up | `[1,0,0,0,0]` | +| down | `[0,1,0,0,0]` | +| left | `[0,0,1,0,0]` | +| right | `[0,0,0,1,0]` | +| stop | `[0,0,0,0,5]` | + +**采样策略**(`746:751`): +- 非stop指令:每帧都记录 +- stop指令:每5帧记录1次(`STOP_RECORD_STRIDE=5`),避免冗余数据 + +**回合管理**(`828:858`): +- 每回合至少15步(`MIN_STEPS_PER_EPISODE=15`) +- 用户点击"复位保存" → 当前回合存入 `episodesRef` → 小车重置到地图中心 +- 达到目标回合数(默认8轮)后自动结束采集 + +#### 2. 前端 → 后端的数据保存 + +`packDataset()`(`517:556`)将所有回合数据打包为 chunk 结构: + +``` +每10步为一个chunk(CHUNK_SIZE=10) + ├─ state: 取chunk第一步的state(1×14) + ├─ env_state: 取chunk第一步的envState(1×7) + ├─ action: chunk内所有步的动作序列(10×5) + ├─ action_is_pad: padding标记(不足10步补0,padding位置为1) + └─ images: 每步的第一人称截图 base64(10×1) +``` + +通过 `POST /api/dataset` 发送到后端,后端(`api.py:65:185`): +1. 验证 JSON payload 完整性 +2. 将 states/env_states/actions/action_is_pad 转为 `torch.Tensor` +3. 解码 base64 图片 → 保存为 PNG 文件到 `output/datasets/images_xxx/` 目录 +4. 记录图片相对路径到 dataset 的 `obs_images` 字段 +5. 整体序列化为 `act_dataset_xxx.pt`(PyTorch 文件) + +--- + +### 三、训练流程 + +#### 1. 触发训练 + +前端 `startTrain()`(`239:260`)→ `POST /api/train/start` → 后端启动**独立线程** + +后端 `_run_training()`(`287:336`): +``` +train_thread (daemon=True) + └─ train_from_dataset() + ├─ load_dataset_from_local(path) → torch.load → ACTDataset + ├─ build_config(state_dim=14, env_state_dim=7, action_dim=5, chunk_size=10) + ├─ ACT(config) → 创建 Transformer 模型 + └─ train_act() → 训练循环 +``` + +#### 2. 训练细节(`train.py:44:174`) + +**模型架构**(ACT - Action Chunking Transformer): +- 输入:state(14维)+ env_state(7维)→ 线性投影 → Transformer Encoder +- 输出:Transformer Decoder → 生成 **chunk_size 步** 的动作序列(10×5) +- 可选 VAE:encoder 将动作编码为 latent → decoder 重建(本场景默认关闭) + +**训练循环**: +``` +每 epoch: + 每 batch: + 1. model(batch) → actions_pred(B,10,5), (mu, log_sigma) + 2. loss = MSE(actions_pred, actions_gt) // 行为克隆 + 3. 可选: loss += kl_weight * KL_loss // VAE正则 + 4. loss.backward() → grad_clip(1.0) → optimizer.step() + 5. progress_callback(epoch, total, avg_loss) → 更新 train_state(线程安全) +``` + +**前端轮询训练状态**(`222:237`):每秒 `GET /api/train/status` 获取 epoch、loss、progress + +#### 3. 训练产物 + +保存到 `output/train/act_YYYYMMDD_HHMMSS/`: +- `act_checkpoint.pt` — 包含 `model_state_dict` + `state_dim` + `env_state_dim` + `action_dim` + `chunk_size` +- `training_metrics.json` — 每步的 loss、lr、epoch 等指标 + +--- + +### 四、推理流程 + +#### 1. 加载模型 + +前端选择模型 → `POST /api/infer/start` → 后端(`api.py:490:528`): +1. `torch.load(checkpoint)` → 读取维度参数 +2. `build_config()` + `ACT(config)` + `load_state_dict()` → 恢复模型 +3. 存入 `infer_state`(内存中常驻) + +#### 2. 步进推理 + +渲染循环中 5Hz 触发(`701:738`): +``` +每 200ms: + 1. getObservationVectors() → 获取当前 {state:14维, env_state:7维} + 2. POST /api/infer/step {state, env_state} + 3. 后端: tensor(state) → model({obs_state, env_state}) → actions[0,0] → _map_action() + 4. _map_action(): 取5维向量中最大值索引 → "up"/"down"/"left"/"right"/"stop" + 5. _apply_action(): 更新后端 car 物理状态 + socketio.emit('car_state') + 6. 返回 {status:"ok", action:"up"} → 前端 actCommandRef.current = "up" + 7. updatePhysics() 读取 actCommandRef → 驱动前端小车移动 +``` + +关键点:推理时**后端也同步驱动了 car 单例**(`_apply_action`),并通过 WebSocket 广播状态,但前端主要用返回的 action 字符串在本地 `applyLocalAction()` 驱动渲染。 + +--- + +### 五、数据流全景图 + +``` +┌──────────────── 前端(SimPage.tsx)────────────────┐ +│ │ +│ 键盘WASD ──→ 指令 ──→ applyLocalAction() │ +│ │ ├─ 物理更新(本地carState) │ +│ │ ├─ 碰撞检测 │ +│ │ └─ emit('action') ──────────→│──→ Socket.IO ──→ 后端 car 单例 +│ │ │ +│ 采集时: │ +│ 每帧 getObservationVectors() → {state, envState} │ +│ commandToActionVec(cmd) → [one-hot] │ +│ fpvCanvas.toDataURL() → base64 PNG │ +│ → EpisodeStep 存入 currentEpisode │ +│ │ +│ 复位保存 → packDataset() → POST /api/dataset ──────→│──→ HTTP ──→ 后端保存 .pt + PNG +│ │ +│ 开始训练 → POST /api/train/start ─────────────────→│──→ HTTP ──→ 后端训练线程 +│ 轮询状态 → GET /api/train/status ←─────────────────│←── HTTP ←── train_state +│ │ +│ ACT推理(5Hz): │ +│ state+envState → POST /api/infer/step ────────────→│──→ HTTP ──→ 后端 model() +│ ←── {action:"up"} ←───────────────────────────────│←── HTTP ←── action映射 +│ actCommandRef = "up" → applyLocalAction("up") │ +│ │ +│ 俯视图 Canvas 第一人称 Canvas │ +│ (800×600 2D) (320×240 伪3D) │ +└─────────────────────────────────────────────────────┘ +``` + +**核心设计思想**:前端完全自治模拟物理和渲染,后端只负责三件事 —— 数据持久化(`.pt`)、模型训练(ACT Transformer)、模型推理(tensor forward pass)。前端通过 HTTP API 与后端交互,两者是松耦合的。 \ No newline at end of file diff --git a/main.html b/main.html index 5292c9bd..bfc28659 100644 --- a/main.html +++ b/main.html @@ -3,7 +3,7 @@ - LeRobot ACT Simulator (Main) + AKA ACT Simulator (Main) @@ -47,7 +47,7 @@
🤖
-

LeRobot ACT Simulator

+

AKA ACT Simulator

Action Chunking with Transformers - Main Edition

@@ -100,8 +100,11 @@

-

场景设置

-
+ +