docs: 更新V2版机器人手臂零件设计说明与渲染截图

This commit is contained in:
cbb
2026-09-27 00:28:49 +08:00
parent 1dfd48278b
commit b3d0890809
67 changed files with 9122 additions and 264 deletions
+52 -26
View File
@@ -584,35 +584,49 @@ def write_step(items, path):
return os.path.getsize(path)
from concurrent.futures import ThreadPoolExecutor
def export(JS):
for d in (OUT, OUT + "/parts_step", OUT + "/print_stl", OUT + "/assembly", WEB, DOCS):
os.makedirs(d, exist_ok=True)
written = []
for p in PARTS:
# 1. 多线程并行导出 STEP 与 STL(复用已有标准电机 STEP,极速提速)
def export_one_part(p):
fn = "%s/%s.step" % (OUT + "/parts_step", p["name"])
write_step([(p["name"], p["shape"])], fn)
written.append(fn)
# 如果是非打印标准已有件且已存在,跳过冗余写盘
if not p["printed"] and os.path.exists(fn) and os.path.getsize(fn) > 1000:
pass
else:
write_step([(p["name"], p["shape"])], fn)
if p["printed"]:
stl = "%s/%s.stl" % (OUT + "/print_stl", p["name"])
cq.exporters.export(cq.Workplane(obj=p["shape"]), stl, exportType="STL")
write_step([(p["name"], p["shape"]) for p in PARTS],
OUT + "/assembly/ROBOT_ARM_%s.stp" % VERSION)
# printed-only assembly (what you actually bolt together)
write_step([(p["name"], p["shape"]) for p in PARTS if p["printed"]],
OUT + "/assembly/ROBOT_ARM_printed_only.stp")
# mesh json for the web viewer
parts = []
for p in PARTS:
return p["name"]
workers = min(8, os.cpu_count() or 4)
with ThreadPoolExecutor(max_workers=workers) as ex:
list(ex.map(export_one_part, PARTS))
# 2. 多线程并行生成网页 3D Mesh
def mesh_one_part(p):
key = "motor" if p["name"].startswith("M") else ("coupl" if "联轴器" in p["name"] or "抱箍" in p["name"] else p["name"])
defl = 0.85 if p["name"].startswith("M") else (0.20 if key == "coupl" else 0.055)
v, t = mesh_of(p["shape"], defl)
return (p, v, t)
with ThreadPoolExecutor(max_workers=workers) as ex:
mesh_results = list(ex.map(mesh_one_part, PARTS))
parts = []
for idx, (p, v, t) in enumerate(mesh_results):
parts.append(dict(name=p["name"], cn=p["cn"], v=v, t=t, color=p["color"],
printed=p["printed"], vol=round(p["vol"], 0), note=p["note"],
grp=GRP.get(p["name"], "root"), jaw=JAW.get(p["name"], 0.0),
ex=[round(x, 1) for x in explode_vec(p, JS, CENTS,
[sum(CENTS[k][i] for k in CENTS) / float(len(CENTS)) for i in range(3)])
],
idx=len(parts) + 1))
idx=idx + 1))
joints = [dict(id=k, cn=JS[k].cn, rear=JS[k].rear, d=JS[k].d, xdir=JS[k].xdir, hub=JS[k].hub_face())
for k in JS]
json.dump(dict(parts=parts, joints=joints, layout=dict(SH=SH, EL=EL, WR=WR,
@@ -627,8 +641,8 @@ def export(JS):
def collide():
rows = []
ps = [p for p in PARTS if p["vol"] > 1.0]
pairs = []
for i in range(len(ps)):
for j in range(i + 1, len(ps)):
a, b = ps[i], ps[j]
@@ -637,18 +651,30 @@ def collide():
av, bv = bb(a["shape"]), bb(b["shape"])
if any(av[1][k] < bv[0][k] - 0.05 or bv[1][k] < av[0][k] + 0.05 for k in range(3)):
continue
v = common_vol(a["shape"], b["shape"])
if v > 2.0:
try:
c = BRepAlgoAPI_Common(a["shape"].wrapped, b["shape"].wrapped)
c.Build()
cb = cq.Shape(c.Shape())
lo, hi = bb(cb)
loc = "@[%.0f %.0f %.0f..%.0f %.0f %.0f]" % (
lo[0], lo[1], lo[2], hi[0], hi[1], hi[2])
except Exception:
loc = "?"
rows.append((a["name"], b["name"], round(v, 1), loc))
pairs.append((a, b))
def check_pair(pair):
a, b = pair
v = common_vol(a["shape"], b["shape"])
if v > 2.0:
try:
c = BRepAlgoAPI_Common(a["shape"].wrapped, b["shape"].wrapped)
c.SetRunParallel(True)
c.Build()
cb = cq.Shape(c.Shape())
lo, hi = bb(cb)
loc = "@[%.0f %.0f %.0f..%.0f %.0f %.0f]" % (
lo[0], lo[1], lo[2], hi[0], hi[1], hi[2])
except Exception:
loc = "?"
return (a["name"], b["name"], round(v, 1), loc)
return None
workers = min(8, os.cpu_count() or 4)
with ThreadPoolExecutor(max_workers=workers) as ex:
results = list(ex.map(check_pair, pairs))
rows = [r for r in results if r is not None]
rows.sort(key=lambda r: -r[2])
json.dump([r[:3] for r in rows], open(DOCS + "/collision.json", "w", encoding="utf-8"),
ensure_ascii=False)