# 内置机器人与 URL 自动导入 ## 给接入方的链接 ```text https://cadworld-sim.robotquan.com/?robot=lekiwi-v1 ``` - 参数名:`robot`;当前唯一值:`lekiwi-v1`,区分大小写。 - 如果链接已有查询参数,使用 `&robot=lekiwi-v1`。其他参数不影响加载。 - 打开页面后自动下载、校验、解压,选择 `URDF/LeKiwi.urdf` 和 `lekiwi-v1` profile,转换 MJCF 并加载进当前浏览器仿真;不再弹出入口/URDF 配置确认框。 - 默认暂停,可点击播放或在「控制台 → 机器人语言控制」输入指令。URL 本身不触发机器人运动、付费模型、Python/ONNX 或外控授权。 - 无 `robot` 参数:保持空白工作台,不下载 ZIP。未知、空值、重复参数:明确报错,不加载默认机器人,也不访问参数中的任意 URL/文件路径。 - 刷新页面会重新导入;删除工程或手动换模型不会被参数反复覆盖。参数只在页面启动时读取,改变浏览器地址后需导航/刷新。 - 下载或校验失败时显示错误,可刷新重试,也可直接手动导入;不自动重试。下载等待上限 120 秒,离开页面取消下载。 ## LeKiwi 双摄像头 自动导入同时创建前置与腕部两台独立相机,不再用通用的“首个 camera/head 名称 + 10 cm 偏移 + 局部 +X”规则。原先误挂到 `Camera-Mount-v8` 支架且侧向取景,是位置和方向错误的原因。 左下角画面顶部的「摄像头视角」下拉框可切换「前置摄像头」和「腕部摄像头」,默认前置。一次渲染选中的一路,避免完整 CAD 多视口的额外开销。切换只改变查看器使用的相机 ID,不重新加载模型、不推进物理、不改变控制权;隐藏/显示保留所选相机,同名相机在场景重编译后保持选择,刷新页面默认前置。 ### 前置摄像头 - 固连 Body:`Camera-Model-v3`,MJCF 名称 `__platform_camera__`。 - 局部光心(米):`[-0.012161199990, 0.024589244440, -0.012071624890]`。 - 局部旋转四元数(MuJoCo wxyz):`[0.413175911167, 0.492403876506, 0.492403876506, -0.586824088833]`。 - 参数由原始 URDF 的视觉原点和 STL 镜头坐标推导:STL 光轴为 +Z,镜头最前端 z=21.5 mm,虚拟光心放在其前方 1 mm,避免模型遮挡自身画面。MuJoCo 使用 -Z 看向前方、+Y 图像向上,不能直接套用 Body +X。 - 经 profile 的 CAD -90° 转向后,镜头朝机器人前方 +X,保留 CAD 安装的向上 10° 倾角,图像不侧转/倒置,随底盘运动。初始世界光心约 `[0.130956, 0, 0.062079]` m。 ### 腕部摄像头 - 固连 Body:`Camera-Model-v3-1`,MJCF 名称 `__platform_camera__wrist`。 - 局部光心(米):`[0.024189561811, -0.017694392834, -0.000153127430]`。 - 局部旋转四元数(wxyz):`[0.459991520356, -0.040244043349, -0.883635489162, -0.077308087991]`。 - 使用腕部相机自己的 URDF 视觉原点推导光心与光轴,同样位于 STL 镜头前方 1 mm,不能照搬前置的局部姿态。初始世界光心约 `[0.215392, 0.004250, 0.168290]` m,初始前向约 `[-0.173648, 0, -0.984808]`,朝夹爪作业区;随腕部/手臂运动实时更新。 - 两相机都由 MuJoCo 的 `cam_xpos/cam_xmat` 驱动画面;真实 WASM 运动学回归验证腕部运动不改变前置相机、转动底盘时两者同步跟随。 两路都是 CAD 对齐的仿真视点,不是实机内外参标定;保持 45° 垂直视场角/640×480 配置。不增加控制桥相机 API,也不改原 ZIP/网格、动力学或手动 profile 的“无相机”行为。 ## 资产与部署 用户指定的原文件:`build/lekiwi/lekiwi-v1.zip`。 发布源文件:`web_platform/assets/robots/lekiwi-v1.zip`,与原文件逐字节一致。该副本作为正式内置资产保存,不依赖被 Git 忽略的 `build/`,也不需要访问者拥有本地文件。 - 大小:22,040,277 字节(约 22 MB)。 - SHA-256:`a10ac577ea49cdf87f324f3f6e9a7a887a1e3c0254ae638059711fef9e385b04`。 - 51 个文件;包含 URDF、完整 STL 网格、许可、引用、来源清单及仿真用途说明。 - 原始来源:SIGRobotics-UIUC/LeKiwi,固定 revision `efa608d7ee5a495a4803b1d28cd0c955b4f1e033`,Apache-2.0。未改动用户指定的 ZIP。 注册表位于 `web_platform/src/project/builtinRobots.ts`。Vite `?url` 导入将 ZIP 输出为带内容哈希的独立 `/assets/lekiwi-v1-*.zip` 文件,不塞进 JavaScript,也不会在普通首页预下载整个 ZIP。网站与本地两种构建均支持,同样兼容静态子目录部署。构建后必须发布完整静态目录,不要只复制 JS/HTML;不要对外发送带哈希的 ZIP 路径,接入方只使用稳定的 `robot=lekiwi-v1`。 新增机器人时需明确增加内置资产和注册项,并验证入口/profile;不开放 URL 任意远程下载。替换 ZIP 时同步更新大小、SHA256 并重新跑门禁;如果机械模型/profile 语义变化,应使用新的机器人 ID。下载流有大小上限、SHA256 校验,随后仍走原 ZIP 路径/文件数量/解压预算校验和 profile 来源校验。 ## 发布与验收记录(2026-09-24) ### 双摄像头补齐 已发布 `20260924T052730Z-dual-camera`,上一版本 `20260924T050135Z-camera-fix`。前置和腕部相机分别固连用户指定的两个 Body,后端打包逐文件无变化,原 ZIP 哈希不变。 - 655 项单测、TypeScript、ESLint、变更文件格式检查、本地/网站双构建通过。 - 浏览器自动导入与双视角切换:生产构建 6/6、开发 StrictMode 6/6、公网 HTTPS 6/6。实际导出两台相机并校验各自光心、光轴和图像向上方向;确认切换/隐藏不重新下载模型,刷新恢复前置视角。 - 独立真实 WASM 运动学回归 1/1:腕部屈曲 0.35 rad 时仅腕部相机随动,底盘旋转 90° 时两相机共同旋转;测试在开发夹具独立实例中执行,不增加产品的位姿直写接口。 - 原网站假上游物理回归 3/3、公网非付费功能/安全回归 2/2;未调用真实付费模型。 - 证据:`build/website-deployment/dual-camera-*`,含两路截图、`dual-cameras.json` 和 `dual-camera-kinematics.json`。 ### 摄像头修正 已发布 `20260924T050135Z-camera-fix`,上一版本 `20260924T043358Z-builtin-robot`。修复只改变前端自动导入的相机预设及转换器对四元数的支持;后端打包逐文件无变化,ZIP 哈希不变。 - 648 项单测、TypeScript、ESLint、格式检查与本地/网站双构建通过。 - 自动导入回归:开发 StrictMode 6/6、生产构建 6/6、公网 HTTPS 6/6;另有原网站假上游物理回归 3/3、公网非付费回归 2/2。 - 公网真实 WASM 导出的相机光心约 `[0.13095586, 0.000000036, 0.06207925]` m,前向约 `[0.98480779, 0, 0.17364796]`,向上约 `[-0.17364796, 0, 0.98480779]`,与源 CAD 推导值误差小于 2e-6。确认镜头位置、朝前与图像上下方向,而非仅检查模型成功加载。 - 证据:`build/website-deployment/camera-fix-*`,含 `front-camera.json` 与实际浏览器截图。未调用真实付费模型。 ### 首次 URL 自动导入 已发布 `20260924T043358Z-builtin-robot`,上一版本 `20260924T035108Z-hosted`。通过既有成对发布/回滚流程,后端打包内容逐文件比较无变化,密钥和调用额度配置未改动。 - TypeScript、ESLint、变更文件格式检查及网站/本地双构建通过。 - Vitest:133 文件、640 项通过;后端 unittest:43 项中 40 通过、3 项可选门禁跳过。 - 自动导入浏览器回归:生产构建 6/6、开发 StrictMode 6/6、公网 HTTPS 6/6。 - 原网站假上游+真实 WASM 动作/抓放/停止回归 3/3;公网非付费功能与安全回归 2/2。 - 公网实际下载 ZIP 的 SHA256 与指定原包一致;真实浏览器确认模型显示、LeKiwi profile 生效、默认暂停、刷新可重新导入。未进行真实付费模型调用。 - 本地证据:`build/website-deployment/robot-url-*`(日志、发布校验和浏览器截图)。 ## 验证命令 ```bash npm run typecheck npm run lint npm test npm run build:website npm run test:e2e:builtin # 开发态 React StrictMode: CADWORLD_BUILTIN_DEV=1 npm run test:e2e:builtin # 独立真实 WASM 双摄像头随动回归,不接控制桥/付费模型: npx playwright test -c web_platform/playwright.lekiwi.config.ts lekiwi.cameras.spec.ts # 显式对真实网站执行,无付费模型调用;故障测试仅在本浏览器拦截资源: CADWORLD_PRODUCTION_TEST=1 npm run test:e2e:builtin ``` 覆盖真实 ZIP 校验、无效参数/任意 URL 拒绝、HTTP 错误、损坏/超大文件、取消;浏览器覆盖真实 WASM 自动加载/profile、双相机位置/朝向与视角切换、暂停、刷新、无参数不下载、重复/未知参数及失败后手动导入。开发态仅把 ZIP 字节请求计为下载,Vite 的 `.zip?import&url` 是小型 JS 地址模块,不能误计或拦截它。