import { expect, test } from '@playwright/test'; import { resolve } from 'node:path'; import { writeFile } from 'node:fs/promises'; import type {} from '../physics/runner'; test('真实 WASM:夹爪两侧指尖覆盖、开度方向和物体阻挡,不能只检查关节数值', async ({ page, }, info) => { const errors: string[] = []; page.on('pageerror', (error) => errors.push(error.message)); await page.goto('/physics/runner.html'); await page.waitForFunction(() => Boolean(window.lekiwiPhysics)); await page.evaluate((path) => window.lekiwiPhysics.boot(path), `/@fs${resolve('build/lekiwi')}`); try { const result = await page.evaluate(() => window.lekiwiPhysics.gripperCollisionChecks()); console.log('gripper contacts', JSON.stringify(result)); await writeFile(info.outputPath('gripper-contacts.json'), JSON.stringify(result, null, 2)); await writeFile( info.outputPath('gripper-scene.xml'), await page.evaluate(() => window.lekiwiPhysics.xml()), ); expect(result.finite).toBe(true); for (const tip of result.coverage) { expect( tip.contacts.some((c) => c.other.startsWith( tip.name === 'fixed_tip' ? '__lekiwi_cad_Wrist_Roll_08c-v1__' : '__lekiwi_cad_Moving_Jaw_08d-v1__', ), ), tip.name, ).toBe(true); } for (const state of result.openings) { expect(Math.abs(state.actual - state.target)).toBeLessThan(0.01); expect(state.contacts).toEqual([]); } expect(result.openings[0].separation).toBeGreaterThan(0); expect(result.openings[0].separation).toBeLessThan(0.002); expect(result.openings[1].separation).toBeGreaterThan(result.openings[0].separation + 0.02); expect(result.openings[2].separation).toBeGreaterThan(result.openings[1].separation + 0.01); expect(result.gapContacts).toEqual([]); // a hull must not seal the open space expect(result.obstruction.maxContacts).toBeGreaterThan(0); expect(result.obstruction.maxPenetration).toBeLessThan(0.0015); expect(result.obstruction.actual).toBeGreaterThan(result.obstruction.target + 0.03); expect(result.obstruction.contacts.length).toBeGreaterThan(0); for (const contact of result.obstruction.contacts) expect(contact.distance).toBeGreaterThan(-0.0002); expect(result.fingerSelfContacts).toBeGreaterThan(0); expect(errors).toEqual([]); } finally { await page.evaluate(() => window.lekiwiPhysics.dispose()); } });