Update workstation UI, ROS task control and device integration

This commit is contained in:
cheng
2026-10-20 15:46:13 +08:00
parent 2b74c50ba8
commit e5b06df6da
141 changed files with 91520 additions and 748 deletions
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Offline STEP -> triangle cache for Qt OpenGL. No robot/ROS/device operations.
Requires gmsh (OpenCascade). Runtime GUI needs only numpy and the generated NPZ.
"""
import argparse
import hashlib
import json
from pathlib import Path
import gmsh
import numpy as np
def convert(source, output):
source=Path(source).resolve();output=Path(output).resolve()
gmsh.initialize(['step-converter','-nopopup'])
try:
gmsh.option.setNumber('General.Terminal',0)
gmsh.option.setString('Geometry.OCCTargetUnit','MM')
gmsh.model.add('gripper')
gmsh.model.occ.importShapes(str(source));gmsh.model.occ.synchronize()
gmsh.option.setNumber('Mesh.MeshSizeMin',.8)
gmsh.option.setNumber('Mesh.MeshSizeMax',2.)
gmsh.option.setNumber('Mesh.MeshSizeFromCurvature',18)
gmsh.option.setNumber('Mesh.ElementOrder',1)
gmsh.model.mesh.generate(2)
tags,coords,_=gmsh.model.mesh.getNodes()
order=np.argsort(tags);sorted_tags=tags[order]
nodes=np.asarray(coords).reshape(-1,3)[order]
parts=[];colors=[];labels=[]
surfaces=gmsh.model.getEntities(2)
for part,(_,tag) in enumerate(surfaces):
kinds,_,element_nodes=gmsh.model.mesh.getElements(2,tag)
r,g,b,a=gmsh.model.getColor(2,tag)
base=np.array([r,g,b],float)/255.
if np.max(base)-np.min(base)<.03: base=np.array([.76,.79,.83])
for kind,indices in zip(kinds,element_nodes):
if kind!=2: raise ValueError('Only first order triangles are supported')
indices=np.asarray(indices).reshape(-1,3)
triangles=nodes[np.searchsorted(sorted_tags,indices)]
parts.append(triangles/1000.)
colors.append(np.tile(base,(len(triangles),1)))
labels.append(np.full(len(triangles),part,np.int32))
triangles=np.concatenate(parts).astype(np.float32)
rgb=np.concatenate(colors).astype(np.float32)
if not np.isfinite(triangles).all() or not len(triangles):raise ValueError('Invalid mesh')
lo=triangles.min(axis=(0,1));hi=triangles.max(axis=(0,1))
output.parent.mkdir(parents=True,exist_ok=True)
np.savez_compressed(output,triangles=triangles,colors=rgb,surface=np.concatenate(labels))
info=dict(source=source.name,source_sha256=hashlib.sha256(source.read_bytes()).hexdigest(),
units='m',source_units='mm',triangles=len(triangles),surfaces=len(surfaces),
solids=len(gmsh.model.getEntities(3)),bounds_m=[lo.tolist(),hi.tolist()],
dimensions_mm=((hi-lo)*1000).tolist(),articulated=False,
note='Original assembled STEP pose; no inferred joints or live finger animation.')
output.with_suffix('.json').write_text(json.dumps(info,ensure_ascii=False,indent=2)+'\n')
print(json.dumps(info,ensure_ascii=False))
finally:gmsh.finalize()
if __name__=='__main__':
parser=argparse.ArgumentParser();parser.add_argument('source');parser.add_argument('output')
args=parser.parse_args();convert(args.source,args.output)