3ad29356c9
集成通用机器人数值接口、本机控制桥、LeRobot 插件和统一键盘遥操作。采用离线 CoACD 全臂碰撞配方 revision 4、局部装配区切分与结构自接触,限制直接关节位姿写入并保留安全看门狗。同步版本号、变更记录、来源许可证和兼容性验证。
47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { startBridge } from './fixtures/controlBridge';
|
|
import type {} from '../physics/runner';
|
|
|
|
test('通用单关节:真实 Python SDK ↔ 本机桥接 ↔ 浏览器 WASM,断开后安全保持', async ({ page }) => {
|
|
const bridge = await startBridge();
|
|
try {
|
|
await page.goto('http://127.0.0.1:4174/physics/runner.html');
|
|
await page.waitForFunction(() => Boolean(window.lekiwiPhysics));
|
|
await page.evaluate(() => window.lekiwiPhysics.bootSingle());
|
|
await page.evaluate(
|
|
({ endpoint, token }) => window.lekiwiPhysics.connectBridge(endpoint, token),
|
|
{ endpoint: bridge.endpoint, token: bridge.token },
|
|
);
|
|
const run = await bridge.python(`
|
|
import json, os, time
|
|
from mujoco_control_bridge import SimRobotClient
|
|
with SimRobotClient(os.environ['MUJOCO_CONTROL_ENDPOINT']) as robot:
|
|
start=time.monotonic()
|
|
for i in range(60):
|
|
accepted=robot.send_action({'slider.position': .5})
|
|
obs=robot.get_observation()
|
|
time.sleep(max(0,start+(i+1)/30-time.monotonic()))
|
|
print(json.dumps({'accepted':accepted['values'], 'measured':obs['values'], 'seq':obs['appliedActionSeq']}))
|
|
`);
|
|
const result = JSON.parse(run.stdout.trim()) as {
|
|
accepted: Record<string, number>;
|
|
measured: Record<string, number>;
|
|
seq: number;
|
|
};
|
|
expect(result.accepted['slider.position']).toBe(0.5);
|
|
expect(result.measured['slider.position']).toBeGreaterThan(0.48);
|
|
expect(result.measured['slider.position']).toBeLessThan(0.51);
|
|
expect(result.seq).toBeGreaterThan(55);
|
|
await expect
|
|
.poll(
|
|
async () =>
|
|
(await page.evaluate(() => window.lekiwiPhysics.externalState())).observation?.paused,
|
|
)
|
|
.toBe(true);
|
|
expect(bridge.errors()).toBe('');
|
|
} finally {
|
|
await page.evaluate(() => window.lekiwiPhysics?.dispose()).catch(() => {});
|
|
await bridge.stop();
|
|
}
|
|
});
|