from __future__ import annotations from app.models import LinkDef, RobotDraft from app.services.a7_gold import A7_LINK_ORDER, enforce_a7_gold_kinematics, gold_joint_defs def _norm(name: str) -> str: return name.strip() def group_links_a7(product_names: list[str], robot_name: str = "ARM7_urdf") -> RobotDraft: """ARM7 gold kinematics; part_names filled later (Solid_N clustered on client).""" names = [_norm(n) for n in product_names if _norm(n)] # Spread Solid_* across gold links by index so apply has a starting bind. links = [LinkDef(name=n, part_names=[]) for n in A7_LINK_ORDER] solids = [n for n in names if n.lower().startswith("solid")] other = [n for n in names if not n.lower().startswith("solid")] if solids: n_link = len(links) for i, sn in enumerate(solids): links[min(i * n_link // max(len(solids), 1), n_link - 1)].part_names.append(sn) if other: links[0].part_names.extend(other) draft = RobotDraft( name=robot_name or "ARM7_urdf", profile="a7", links=links, joints=gold_joint_defs(), notes=[ "A7 profile: joints from ARM7_urdf.urdf gold standard.", "Axes: A1/3/5=[0,0,-1], A2/4/6=[1,0,0], A7=[0,1,0], A8=fixed.", ], raw_parts=names, ) return enforce_a7_gold_kinematics(draft) def seed_generic(product_names: list[str], robot_name: str = "robot") -> RobotDraft: names = [_norm(n) for n in product_names if _norm(n)] return RobotDraft( name=robot_name or "robot", profile="generic", links=[LinkDef(name="base_link", part_names=[])], joints=[], notes=["Generic seed; joints come from LLM."], raw_parts=names, ) def apply_profile(profile: str, product_names: list[str], robot_name: str) -> RobotDraft: if profile == "a7": return group_links_a7(product_names, robot_name=robot_name) return seed_generic(product_names, robot_name=robot_name)