- M1 数据生成器:采样/老师/距离下界认证/时间律/统计/一致性门禁;确定性老师(碰撞次数计时 + resetSession)、pos 任务冻结 J6、--consensus 邻域共识过滤、Dr 类。 - 全流程代码与运行手册:数据打包/可微运动学与对拍/MeanFlow+WTA 模型/闭环仿真/APG/挖错循环/ONNX 导出;webapp 策略运行时 ik-policy.js、?policy=1 接入、tests/policy_bench.cjs;ik-solver 增 pairList/clusterExport/criticalPairs/pairGap/leverTable。
367 lines
29 KiB
HTML
367 lines
29 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>六电机人形机器人手臂 · 装配与打印模型</title>
|
||
<link rel="stylesheet" href="styles/base.css">
|
||
<link rel="stylesheet" href="styles/sheet-chrome.css">
|
||
<link rel="stylesheet" href="styles/sheet-theme.css">
|
||
<link rel="stylesheet" href="styles/sheet-hud.css">
|
||
<link rel="stylesheet" href="styles/guide.css">
|
||
<link rel="stylesheet" href="styles/dock.css">
|
||
<link rel="stylesheet" href="styles/ikbar.css">
|
||
<link rel="stylesheet" href="styles/viewmode.css">
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<header>
|
||
<b id="ttl">人形机器人手臂</b>
|
||
<span class="q" id="ver"></span>
|
||
<button class="tab on" data-view="model">三维模型</button>
|
||
<button class="tab" data-view="sheet">装配图</button><button class="tab" data-view="motion">运动模拟</button>
|
||
<span class="sp"></span>
|
||
<button id="bAsm" class="on">装配视图</button>
|
||
<button id="bExp">爆炸视图</button>
|
||
<input id="exp" type="range" min="0" max="100" value="0" style="width:96px">
|
||
<select id="cam">
|
||
<option value="iso">等测</option><option value="front">前视</option>
|
||
<option value="side">侧视</option><option value="top">顶视</option>
|
||
<option value="wrist">腕部特写</option><option value="joint">关节特写</option><option value="elbow">肘部特写</option><option value="hand">手部特写</option>
|
||
</select>
|
||
<button id="bWire">线框</button>
|
||
<button id="bXRay">电机半透</button>
|
||
<button id="bScr" class="on" title="显示/隐藏全部螺钉(S01~S10);点右侧 BOM 螺丝行可在模型中高亮定位">螺钉</button>
|
||
<button id="bHarn" class="on" title="显示/隐藏线束走线指示(主干4芯总线、电机出线分支、过关节U型/螺旋缓冲环、T接小板)">线束</button>
|
||
<button id="bEnv" title="显示/隐藏可达外包络(运动学边界)">可达包络</button>
|
||
<button id="bFit">复位</button>
|
||
<button id="bL" title="显示/隐藏左栏">左栏</button>
|
||
</header>
|
||
|
||
<div id="ikbar">
|
||
<div class="ikrow">
|
||
<span class="ik-t">IK</span>
|
||
<span class="lb">目标点 X</span><input type="number" id="ikX" step="1" title="CAD 世界坐标 X / mm">
|
||
<span class="lb">Y</span><input type="number" id="ikY" step="1" title="CAD 世界坐标 Y / mm">
|
||
<span class="lb">Z</span><input type="number" id="ikZ" step="1" title="CAD 世界坐标 Z / mm(桌面 z=0,向上为正)">
|
||
<span class="vsep"></span>
|
||
<span class="lb">工具长</span><input type="number" id="ikTool" value="0" step="5" title="在工具法兰面之外、沿 J6 轴线再伸出的工具长度 / mm">
|
||
<span class="lb">mm</span>
|
||
<span class="vsep"></span>
|
||
<span class="lb">扫描精度</span>
|
||
<select id="ikStep" title="冗余维 (J4,J5) 的粗扫步长:只在可行段内采样;位置任务取全局最优,姿态任务的精确解由孤立根枚举给出、与步长无关">
|
||
<option value="1">快速 1°</option>
|
||
<option value="0.5">较快 0.5°</option>
|
||
<option value="0.25" selected>标准 0.25°</option>
|
||
<option value="0.1">精细 0.1°</option>
|
||
<option value="0.05">参考级 0.05°</option>
|
||
</select>
|
||
<button id="ikSolve" title="求解并把手臂动画移动到该位姿(取相对当前姿态行程最小的构型)">求解并移动</button>
|
||
<button id="ikPose" title="开启姿态控制:除 TCP 位置外,同时指定末端工具姿态(工具轴指向 + 绕轴滚转)">姿态控制</button>
|
||
<span id="ikPoseBox">
|
||
<span class="lb">方位</span><input type="number" id="ikAz" step="5" value="0" title="工具轴(法兰朝外方向)绕 CAD Z 轴的方位角 / 度">
|
||
<span class="lb">仰角</span><input type="number" id="ikEl" step="5" value="90" title="工具轴(法兰朝外方向)自 CAD +Z 抬起的仰角 / 度:0 = 竖直向上,90 = 水平,180 = 竖直向下">
|
||
<span class="lb">滚转</span><input type="number" id="ikRoll" step="5" value="0" title="绕工具轴自身的滚转角 / 度(右手系)">
|
||
<button id="ikPoseCur" title="把当前真实工具姿态读回三个输入框">取当前</button>
|
||
<button id="ikPoseDown" title="快捷设为工具轴竖直向下(爪取常用姿态)">垂直向下</button>
|
||
<span class="lb">优先级</span>
|
||
<select id="ikPrio" title="位置与姿态不能同时满足时的取舍:位置优先 = 保 TCP 点位精确、姿态取最接近可达值;姿态优先 = 保指定姿态精确、TCP 取最接近可达点(位置差在结果栏如实给出);混合优先 = 用右侧滑杆自由分配两端比重,0% = 姿态优先、100% = 位置优先,中间值在两端锚点之间按归一化折中代价加权搜索">
|
||
<option value="pos" selected>位置优先</option>
|
||
<option value="ori">姿态优先</option>
|
||
<option value="mix">混合优先</option>
|
||
</select>
|
||
<span id="ikMixBox" title="混合优先的比重(自由分配位置与姿态):向左 = 姿态优先、向右 = 位置优先;0% / 100% 与两条纯算法逐位一致。折中代价 J = w·(e/e_ref)² + (1−w)·(o/o_ref)²,两端尺度取各自锚点(位置端 = 位置优先解的姿态残差、姿态端 = 姿态优先解的位置差),故读数即「沿折中历程的进度」。滑动即算即动,松手全量折中">
|
||
<span class="lb">姿态</span>
|
||
<input type="range" id="ikMixW" min="0" max="100" step="1" value="50">
|
||
<span class="lb">位置</span>
|
||
<span class="st" id="ikMixV">50% 位置</span>
|
||
</span>
|
||
</span>
|
||
</div>
|
||
<div class="ikrow">
|
||
<button id="ikPick" title="开启后在视图中单击,把目标点投到当前高度的水平面上">视图拾取</button>
|
||
<button id="ikRt" title="开启后拖动黄球即算即动:手臂实时追踪目标点移动(松手做一次精修求解)">实时追踪</button>
|
||
<button id="ikHome" title="所有关节角归零">归零位</button>
|
||
<button id="ikZero" title="载入一个示例目标并求解">示例目标</button>
|
||
<span class="vsep"></span>
|
||
<span class="hint" id="ikHint">拖黄球 = 移动目标(Shift 仅上下);拖箭头 = 调工具轴指向;拖箭杆或粉球 = 滚转;松手自动求解</span>
|
||
<span class="vsep"></span>
|
||
<span class="st" id="ikBar">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<aside id="left">
|
||
<div id="ikpanel">
|
||
<div class="ikh">
|
||
<h3>逆运动学 · 位置与姿态 · 最小总关节角</h3>
|
||
<span id="ikBadge" class="badge wait">待求解</span>
|
||
</div>
|
||
<table id="ikTab">
|
||
<thead><tr><th>轴</th><th>关节</th><th>角度</th><th>|θ|</th><th>限位</th></tr></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
<div class="kv" id="ikSum"></div>
|
||
<div class="src" id="ikSrc"></div>
|
||
<div id="ikAltN"></div>
|
||
<div id="ikAlts"></div>
|
||
<details id="ikChkBox"><summary>结构与精度自检 / 工作空间</summary><div class="kv" id="ikChk"></div>
|
||
<div class="kv" id="ikDep"></div></details>
|
||
<details id="ikDoc">
|
||
<summary>算法说明与公式推导</summary>
|
||
<div class="doc">
|
||
<b>模式</b>:本页「<b>运动模拟</b>」承载全部运动学能力;「三维模型」为纯静态模型视图(关节锁定在设计零位、无目标点与求解控件),「装配图」为二维图纸。运动模拟下左栏只保留 IK 结果与关节角度,零件树/打印清单自动收走。<hr>
|
||
<b>目标</b>:使 TCP(末端工具法兰 P09 安装面中心,可加“工具长”)到达给定点,并在一切满足限位的可行构型中取
|
||
<b>各电机需转过的角度之和最小</b>者(相对当前姿态的行程;连续轴 θ 与 θ±360 是同一物理位形,角差一律取 ±180° 内的短弧,见第 6 条;离线批算不给参考姿态时退化为 Σ|θᵢ| 最小)。开启上方“<b>姿态控制</b>”后,
|
||
约束升级为 <b>位置 3 + 姿态 3</b>(工具轴指向 + 绕轴滚转),见第 5 条。
|
||
<br><b>姿态操控</b>:姿态开启后目标球处出现方向箭头与粉色侧球——<b>箭头指向即工具朝外方向</b>(法兰面法向朝外,也就是工具伸出的方向)。
|
||
<b>拖箭头头部</b>用弧球法(指针射线与以目标为球心、半径=箭长的球求交,方向=交点−球心)连续调整方位/俯仰;
|
||
<b>拖箭杆或粉色侧球</b>按指针绕轴的转角增量改滚转;右侧数字框随时同步,可精确微调,
|
||
「取当前」把真实工具姿态读回、「垂直向下」一键设为爪取常用姿态。
|
||
<br><b>约定</b>:求解器内部工具坐标系 z 轴取法兰面法向(朝臂内,与 TCP 外伸反向);界面上的方位/仰角/滚转、
|
||
箭头与绿色当前轴线均以朝外法向描述,入栈时绕工具 x 轴翻 180° 换算,两者看到的物理姿态完全一致。
|
||
<ol>
|
||
<li><b>先消去一维</b>(仅位置任务):TCP 恰好落在 J6 轴线上,绕 J6 转动不改变 TCP 位置 ⇒ 对“到点”任务取
|
||
<code>θ6 = 0</code> 即已最优。</li>
|
||
<li><b>识别结构</b>:J2 / J4 / J5 三轴严格平行(轴向 Y,过 x = 19.5),J1 轴为 X,J3 轴沿臂长方向 Z。
|
||
记 <code>A = X−X0</code>、<code>R = |(Y−Y0, Z−Z1)|</code>、<code>φ = atan2(Z−Z1, Y−Y0)</code>,
|
||
则 <code>X = X0 + a</code>,而 <code>(Y, Z)</code> 由 <code>(b, c)</code> 绕 J1 轴旋转 φ 得到:<br>
|
||
<code>a = Vx·cosθ3·cosθ2 + Vz·sinθ2</code>,<code>b = −Vx·sinθ3</code>,
|
||
<code>c = C0 + (−Vx·cosθ3·sinθ2 + Vz·cosθ2)</code>,
|
||
其中 <code>Vx, Vz</code> 只是 (θ4, θ5) 的函数。</li>
|
||
<li><b>两式联立消元(关键一步)</b>:由 <code>a = A</code> 得恒等式
|
||
<code>A² + n² = Vx² + Vz²</code>(<code>n = −Vx·cosθ3·sinθ2 + Vz·cosθ2</code>);
|
||
代入 <code>b² + c² = R²</code> 后 θ3 的项<u>全部抵消</u>,于是<br>
|
||
<code>n = (R² + A² − Vx² − Vz² − C0²) / (2·C0)</code> —— <b>唯一确定</b>;<br>
|
||
再由 <code>n² + A² = Vx²·cos²θ3 + Vz²</code> 得
|
||
<code>cos²θ3 = (n² + A² − Vz²) / Vx²</code> ⇒ θ3 共四支 <code>±σ, ±(π−σ)</code>;<br>
|
||
最后 θ2 与 θ1 各由一个 2×2 线性方程组唯一确定:
|
||
<code>cosθ2 = (κA + Vz·n)/(κ² + Vz²)</code>,<code>sinθ2 = (Vz·A − κ·n)/(κ² + Vz²)</code>,
|
||
<code>κ = Vx·cosθ3</code>;<code>θ1 = φ − atan2(c, b)</code>。</li>
|
||
<li><b>遍历冗余(按行裁剪到可行段)</b>:(θ4, θ5) 就是二维冗余。闭式支只在平面支有解时才存在,
|
||
限位盒内只有 <b>7~27%</b> 的网格点能过判据,且实测(5 个目标 × 全部 θ4 行)<b>每行的可行集都是单一连续段</b>
|
||
—— 于是先用探测步找出每行的可行段、向两端各放宽一个探测步兜住段界,段内再按步长精扫。
|
||
段内密度与全域扫一致,因此<b>解的质量不动</b>,粗扫采样量降约 4.6×(但全量总耗时只降约 1.10×——局部加密窗口是 ±2h 步长 h/8,格数恒为 32×32/种子、与 h 无关,精修才是耗时地板)。
|
||
之所以不把粗扫一起放松:根枚举目前不保证完备,漏根时要靠粗扫的窄带候选兜底,
|
||
实测把粗扫同步放松会换来上百度级的代价劣化。</li>
|
||
<li><b>姿态任务(6 自由度)</b>:工具坐标系姿态 <code>R = R₁·R₂·…·R₆</code>(与场景图 6 级矩阵链一致)。
|
||
结构上 <b>J5 轴与 J6 轴在腕心 (19.5, 128, 222) 垂直相交</b>,因此 θ6 只提供绕工具自身轴的滚转:
|
||
<u>工具轴指向 = (R₁…R₅)·ẑ,与 θ6 无关,TCP 位置也与 θ6 无关</u>。每条位置闭式支都附带确定的 R₅
|
||
(= R₁…R₅),滚转角随之闭式解出:<code>N = R₅ᵀ·R_des</code>(需为 Rz(−θ6))⇒
|
||
<code>θ6 = −atan2(N₁₀, N₀₀)</code>;姿态偏差 <code>e = ∠(R₅·Rz(−θ6), R_des)</code> ≤ 2° 的支才收入。</li>
|
||
<li><b>姿态 = 孤立根求解</b>:闭式支把 θ1..θ3 吸收掉之后,姿态任务只剩「工具轴指向 = 目标轴」
|
||
这 2 个方程、2 个未知数 (θ4,θ5),解是<b>孤立点</b>(独立密集种子 + 牛顿普查实测只有 1~2 个根),
|
||
滚转再由 θ6 闭式补上。所以不再用网格密度去撞那条斜窄谷:逐行对残差两个分量找<b>变号括号</b>、
|
||
从括号中点起跑<b>阻尼高斯-牛顿</b>(奇异时加大阻尼而非退出),并对每支的 ‖e‖ 最小节点补种以收
|
||
切向相切的根;代价最优的若干条入选候选再各收口一次。于是
|
||
<b>姿态残差量级从 ~10⁻²° 变为 10⁻⁶°(工程意义上的精确)</b>,且 Σ|θ| 不劣于原路径。</li>
|
||
<li><b>两处判据陷阱</b>(都验过,写在这里防止被自证):其一,切向残差在工具轴<b>反平</b>时同样为零,
|
||
同向判据只能在收口时验,当作迭代中止条件会让每支一进来就作废;其二,求根按<b>支下标</b>对齐
|
||
prev/cur,不可行的支必须留 null 占位,否则下标错开、括号判据失配,实测会整支漏掉一个真根、
|
||
多付 130° 关节角。确有少数奇异「刀尖」构型<b>无精确根</b>,此时牛顿收敛到 ‖e‖ 的真实最小,
|
||
报出的残差不再是采样伪影。</li>
|
||
<li><b>混合优先(比重可调折中)</b>:优先级下拉的第三种模式——一根滑杆自由分配两端:
|
||
<b>0% 即姿态优先、100% 即位置优先</b>(两端直接交给上面两条专用算法,结果逐位一致),
|
||
中间值在两端锚点之间最小化<b>归一化折中代价</b>
|
||
<code>J = w·(e/e_ref)² + (1−w)·(o/o_ref)²</code>。两端尺度取锚点自身:
|
||
<code>e_ref</code> = 姿态优先解的 TCP 位置差、<code>o_ref</code> = 位置优先解的姿态残差,
|
||
于是<b>滑杆读数就是「沿折中历程的进度」</b>、与目标的绝对误差量级无关(50% ≈ 两端各自归一后对半)。
|
||
之所以不用「1 mm ↔ 1°」的绝对量纲:实测两端误差常在 100 mm / 40° 量级,绝对量纲会把读数整体挤向
|
||
位置端(折线中点落到 ~13% 处),滑杆就不好用了。两端锚点复用上面两条算法——位置端 = 位置精确族 +
|
||
闭式滚转 + 孤立根收口(位置不可达时退化为最近可达位置),姿态端 = 工具轴闭式对齐 + θ6 补滚转
|
||
(姿态精确、位置最近);中间值以两锚点及<b>关节空间插值</b>为种子,对 6 维残差
|
||
<code>[√w·(p−t)/e_ref , √(1−w)·RV°/o_ref]</code> 做<b>阻尼高斯-牛顿 + 单轴抛光</b>,取 J 最小者
|
||
(J 同量级 2% 带内取行程 — 相对当前姿态的 Σ|wrap(θᵢ−refᵢ)| — 更小者,防等价支横跳)。两端中任一端在另一维也达标
|
||
(≤0.05)时折中无意义、直接返回该端——注意位置端不达标而姿态端在位置上达标时返回<b>姿态端</b>
|
||
(它两维同时占优:位置优先族收不到的到达解,姿态端收得到)。全程无随机数,同一输入逐位可复现;
|
||
拖动走快路(同「实时续解」条哲学,归一化尺度沿用最近一次全量的缓存),松手必走全量。</li>
|
||
<li><b>连续优先(最小移动角 / 防倒摆)</b>:等价多分支(θ3 的 ±σ/±(π−σ)、肘上/肘下、J1/J3 镜像族)之间只按 Σ|θ| 选优时,
|
||
目标微动就会在分支间跳来跳去、绕远路(实测目标挪 20 mm 就翻族:垂直向下时左右移动单步最大 74.8°、
|
||
累计绕出 348°,而目标实际只扫过 160°)。交互求解以<b>当前手臂姿态</b>为参考位姿,选解判据取
|
||
<b>所有电机需要转过的角度之和最小</b>——<code>Σ|wrap180(θᵢ−refᵢ)|</code>:连续轴(J1/J3/J6)无机械限位,
|
||
θ 与 θ±360 是同一物理位形,故角差一律取短弧;末尾 <code>1e-6·Σ|θ|</code> 只作并列时的次序稳定项。
|
||
同一条扫描路径实测:单步最大 5.0°、累计 160.0°,与目标实际扫过的角度一致。
|
||
拖动动画同样对连续轴取「离起始角最近的等价角」再插值,避免 +151.9°→−167.0° 反向扫 318.9° 绕一整圈。</li>
|
||
<li><b>实时续解(拖动快路)</b>:目标每帧只挪几毫米时,真解在 (θ4,θ5) 平面上连续移动,
|
||
没必要为重扫整个冗余维付全价。<code>solveWarm</code> 只在上一帧解附近取<b>同一闭式支</b>、走一小步同支搜索,
|
||
姿态任务再收口一次;<b>任一校验不过(换支、越限、位置残差超差、姿态没收口、关节跳太大)就返回 null
|
||
自动回落全量粗扫</b>,松手后的求解一定不带 warm、走全量。快路只负责「能快的时候快」,不改变正确性判据。</li>
|
||
<li><b>代表角</b>:位姿以 360° 为周期,解角一律取 ±180° 内的等价角(|θ| 最小);J2 / J4 / J5 另受相邻件实测机械区间约束,越限即丢弃。</li>
|
||
<li><b>自检</b>:每次求解都用闭式 FK 与场景图真实 6 级矩阵链各算一次 TCP 和工具姿态并与目标比对(见上表残差)。</li>
|
||
</ol>
|
||
<hr>
|
||
<b>验证数据(本机实测,可复现)</b>
|
||
<table>
|
||
<thead><tr><th>检查项</th><th>结果</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>闭式 FK vs 6 级矩阵链(1500 组随机位形)</td><td class="good">4.6 × 10⁻¹³ mm</td></tr>
|
||
<tr><td>逆解分支重构(200 组随机可行位形)</td><td class="good">200 / 200 命中</td></tr>
|
||
<tr><td>θ6 不变性(0° → 137°,TCP 位移)</td><td class="good">0.00 mm</td></tr>
|
||
<tr><td>姿态参数 ↔ 旋转矩阵往返(2000 组随机)</td><td class="good">2.4 × 10⁻⁶°</td></tr>
|
||
<tr><td>姿态重构达标率(200 组随机可行位形,step 0.5,A/B 同机)</td><td class="good">中位残差 0.0234° → <b>0.000000°</b>;>0.05° 的例数 2 → <b>0</b>(改造前文档口径 185–191/200)</td></tr>
|
||
<tr><td>姿态解 Σ|θ| vs 改造前(60 组,step 0.25 + 连续项)</td><td>中位 +0.03°,最大 +8.4°(该例是新解更贴参考位姿、Σ|θ| 反而更大,属连续项的正常取舍而非漏解)</td></tr>
|
||
<tr><td>位置解 vs 0.05° 参考网格(100 目标,step 0.25)</td><td class="good">中位 +0.000°,最大 +0.49°,>1° 例数 0</td></tr>
|
||
<tr><td>全量求解耗时(60 组,step 0.25 + 连续项)</td><td>仅位置 70.6 → 63.3 ms;位置+姿态 88.8 → 81.0 ms(约 1.10×;粗扫采样量降 4.6×,但精修才是地板)</td></tr>
|
||
<tr><td>实时续解快路(每帧 3 mm + 1.5°,240 帧)</td><td class="good">位置命中 96%、均 0.058 ms;姿态命中 65%、均 0.59 ms —— 对全量 81 ms 约 140~1400×,是交互延迟的主要收益来源</td></tr>
|
||
<tr><td>快路结果的独立复核(fkChain / 全 6 轴 orient,非求解器自报)</td><td class="good">位置 5.5×10⁻¹³ mm · 姿态 1.7×10⁻⁶°</td></tr>
|
||
<tr><td>姿态模式候选表长度(供互异构型/碰撞改选取样)</td><td>26 → 13(精确根集合本就只有 1~2 个,达标门收紧后可选样变少;动态碰撞改选若依赖宽候选需留意)</td></tr>
|
||
<tr><td>滚转角交互 roll 0→90(参考位姿连续)</td><td class="good">Δθ6 = 89.99°,θ1..θ5 变化 < 0.01°</td></tr>
|
||
<tr><td>60 个可达目标:失败次数 / 最大残差</td><td class="good">0 次 / 3.5 × 10⁻¹³ mm</td></tr>
|
||
<tr><td>相对 0.05° 极细网格参考的最大劣化</td><td class="good">0.02°</td></tr>
|
||
<tr><td>vs 4000 次随机多起点数值解</td><td class="good">0 / 20 次劣于数值解</td></tr>
|
||
<tr><td>等价分支跳变 · 4 条扫描路径(修复前 → 后)</td><td class="good">>10° 跳变 14 → 5 次;最大单步 163.5° → 16.8°</td></tr>
|
||
<tr><td>单次求解耗时</td><td>拖动跟随走快路 ~0.1 ms;全量求解默认步长下位置 ~20 ms、姿态 ~100 ms(node 侧本机实测,浏览器同量级)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<hr>
|
||
<b>限位</b>:电机行程各轴 ±360°(=滑块范围);解角取 ±180° 内的等价角——位姿以 360° 为周期,超出 ±180° 不产生新位姿。
|
||
相邻打印件的实测机械区间封顶:J2 ∈ [−107, 128],J4 ∈ [−112, 112],J5 ∈ [−96, 96],J1 / J3 / J6 可整周。
|
||
<br><b>参考</b>:零位静态扫描 J2 [−106, 9]、J4 [−111, 16]、J5 [−95, 34] 只在其它轴全零时对固定立柱成立,已不再当可行域;
|
||
跨组零件对(腕/法兰撞立柱那类)由胶囊碰撞模型按当前姿态实时判定(实测 J1=90° 时 J2 正端从 +8° 放到 +107°)。
|
||
<br><b>局限</b>:胶囊模型故意不检相邻组零件对(|Δg|=1),那部分由上面的实测机械区间兜底;换模型须重跑
|
||
scratch/probe_adj.py 更新 collide.json 的 adj。若需要更舒展的姿态,可从上方“互异构型”列表改选次优解。
|
||
<br><b>不可达</b>:若目标超出工作空间,自动求最近可达位姿——阻尼最小二乘<b>从当前姿态锚定起步</b>(抑制退化方向的无用漂移)、固定种子的确定性重启(同一点重复解算逐位一致)、再经零空间抛光取最小总关节角的代表值;报告的距离为抛光后真实值。
|
||
<br><b>姿态不可达</b>:姿态任务超可达空间时,阻尼最小二乘误差向量升级为 6 维(位置 mm + 姿态 deg,按 20 mm/rad 折算),返回位置与姿态联合最近的位姿,两个残差分别显示。
|
||
<br><b>混合优先不可达</b>:位置超可达空间时,位置端锚点退化为「最近可达位置」、姿态端仍取「姿态精确、位置最近」,
|
||
再按同一权重折中,两端各自的残差在结果栏如实列出(与位置优先的历史兜底——6 维联合 DLS——是两个不同的代表值,切换模式可得)。
|
||
<br><b>API</b>:控制台可用 <code>IK.solver.solve([x,y,z],{step:0.25,tool:0,pose:{R:ArmIK.poseMat(az,el,roll)}})</code>;
|
||
<code>IK.setPose(az,el,roll)</code> 可直接设定目标姿态;<code>IK.setPrio('mix',0.3)</code> 切到混合优先并设比重;
|
||
<code>IK.solver.solveTo([x,y,z],{pose:{R:…},priority:'mix',mixW:0.3})</code> 直接取折中解(0 与 1 分别等于姿态优先 / 位置优先)。
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<div class="row" id="jointsHead" style="justify-content:space-between;margin:8px 0 4px">
|
||
<h3 style="margin:0">关节角度(实时联动)</h3>
|
||
<button id="resetJoints" class="tab" style="padding:1px 7px;font-size:11px" title="将所有关节角度复位为 0°">全部归零</button>
|
||
</div>
|
||
<div id="joints"></div>
|
||
<div id="treeBlock">
|
||
<h3>零件树</h3>
|
||
<div class="row"><button id="allOn" class="tab">全选</button><button id="allOff" class="tab">全不选</button>
|
||
<button id="onlyPrint" class="tab">只看打印件</button></div>
|
||
<div id="tree"></div>
|
||
<h3>打印清单(PLA)</h3>
|
||
<div class="kv" id="sum"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<div id="stage">
|
||
<canvas id="cv"></canvas>
|
||
<div id="hud"></div>
|
||
<div id="note"></div>
|
||
<div id="sheet" class="theme-paper">
|
||
<div id="sheetToolbar">
|
||
<div class="sheet-tabs" id="sheetTabs">
|
||
<button class="sheet-tab on" data-sheet="0"><span>📐</span> 01 正视图</button>
|
||
<button class="sheet-tab" data-sheet="1"><span>🔍</span> 02 A-A剖视</button>
|
||
<button class="sheet-tab" data-sheet="2"><span>💥</span> 03 爆炸图</button>
|
||
<button class="sheet-tab" data-sheet="3"><span>📐</span> 04 侧视图</button>
|
||
<button class="sheet-tab guide-tab" data-sheet="guide"><span>🛠️</span> 分步装配向导</button>
|
||
</div>
|
||
|
||
<div class="sheet-vsep"></div>
|
||
|
||
<div class="sheet-btn-group" title="图纸风格主题">
|
||
<button class="sheet-btn on" data-theme="paper" title="工程白纸图纸">白图</button>
|
||
<button class="sheet-btn" data-theme="blueprint" title="经典工程蓝图">蓝图</button>
|
||
<button class="sheet-btn" data-theme="dark" title="工业深色风格">深色</button>
|
||
</div>
|
||
|
||
<div class="sheet-vsep"></div>
|
||
|
||
<div class="sheet-layers" title="图层显示控制">
|
||
<label title="显示/隐藏气球标号与引线"><input type="checkbox" id="chkLyrBalloons" checked> 标号</label>
|
||
<label title="显示/隐藏尺寸与基准标注"><input type="checkbox" id="chkLyrDims" checked> 尺寸</label>
|
||
<label title="显示/隐藏关节轴线"><input type="checkbox" id="chkLyrAxes" checked> 轴线</label>
|
||
<label title="显示/隐藏图内零件明细表"><input type="checkbox" id="chkLyrLegend" checked> 零件表</label>
|
||
</div>
|
||
|
||
<div class="sheet-space"></div>
|
||
|
||
<button class="sheet-btn sheet-btn-accent" id="btnSheetTo3D" title="在三维模型中定位查看当前选中的部件">
|
||
<span>🧊 3D模型联动</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div id="sheetViewport">
|
||
<div id="sheetCanvas">
|
||
<div id="sheetSvgWrapper"></div>
|
||
</div>
|
||
|
||
<div id="sheetFloatBar">
|
||
<button class="sfb-btn" id="sfbIn" title="放大 (滚轮向上)">➕</button>
|
||
<button class="sfb-btn" id="sfbOut" title="缩小 (滚轮向下)">➖</button>
|
||
<button class="sfb-btn" id="sfbFit" title="自适应窗口居中 (双击空白处)">⛶ 适屏</button>
|
||
<button class="sfb-btn" id="sfb100" title="100% 原始比例">1:1</button>
|
||
<button class="sfb-btn" id="sfbReset" title="重置视角">↺ 复位</button>
|
||
<button class="sfb-btn" id="sfbFull" title="全屏视口">⛶ 全屏</button>
|
||
</div>
|
||
|
||
<div id="sheetZoomBadge" title="点击重置为 100%">100%</div>
|
||
|
||
<div id="sheetTooltip" class="sheet-tooltip"></div>
|
||
</div>
|
||
|
||
<!-- 分步装配向导面板 -->
|
||
<div id="sheetGuideView" style="display:none">
|
||
<div class="guide-header">
|
||
<div class="guide-steps-bar" id="guideStepsBar">
|
||
<!-- 步骤 chips 动态渲染 -->
|
||
</div>
|
||
<button class="sheet-btn" id="btnExitGuide" style="margin-left:auto">✕ 返回图纸</button>
|
||
</div>
|
||
<div class="guide-body">
|
||
<div class="guide-panel-left" id="guidePanelLeft">
|
||
<!-- 当前步骤详情动态渲染 -->
|
||
</div>
|
||
<div class="guide-panel-right">
|
||
<div id="guideCanvasWrapper" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative;">
|
||
<!-- 步骤关联图纸与高亮 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer>
|
||
<span id="footModel">左键旋转 · 滚轮缩放 · 右键平移(拖动) · 单击选中高亮 · <b>BOM 点螺丝行 = 高亮定位该规格螺钉(穿透显示)</b> · <b>右键单击隐藏部件(或按H键)</b> · 左侧全选/勾选恢复<span id="footIk"> · <b>运动模拟</b>:拖动黄色目标球到点(Shift 仅上下)· 开「姿态控制」后可拖箭头调末端朝向、拖箭杆或粉色侧球调滚转</span></span>
|
||
<span id="footSheet" style="display:none"><b>装配工程图纸</b>:滚轮缩放 · 按住左键/中键拖拽平移 · 双击自适应视口 · 悬停气球标号/零件轮廓双向高亮 · <b>点击部件卡片「在 3D 中定位」</b></span>
|
||
<span class="sp"></span>
|
||
<span id="stat"></span>
|
||
</footer>
|
||
</div>
|
||
|
||
<button id="bomTab" title="展开 / 收起 物料清单 BOM">物料清单 <b>BOM</b></button>
|
||
<aside id="bomDock">
|
||
<div class="dk-hd">
|
||
<b>物料清单 BOM</b><span class="q" id="bomStat"></span>
|
||
<button id="bomHide" class="dk-x" title="收起">收起 ▶</button>
|
||
</div>
|
||
<div class="dk-bd">
|
||
<div class="dk-sec">紧固件 / 螺丝清单(全部紧固点)</div>
|
||
<div class="dk-note" id="scrSum"></div>
|
||
<table id="screws"><thead><tr><th>规格</th><th>长 mm</th><th>数量</th><th>位置 / 用途</th></tr></thead><tbody></tbody></table>
|
||
<div class="dk-sec">打印件 BOM(原明细,PLA)</div>
|
||
<table id="bom"><thead><tr><th>#</th><th>件号</th><th>cm3</th><th>g</th></tr></thead><tbody></tbody></table>
|
||
</div>
|
||
</aside>
|
||
|
||
<script src="vendor/three.min.js"></script>
|
||
<!-- 数据与螺钉清单是生成物(webapp/generated/00_data.js),由 python -m arm.viewer.build_viewer 写 -->
|
||
<script src="generated/00_data.js"></script>
|
||
<script src="js/state.js"></script>
|
||
<script src="js/harness.js"></script>
|
||
<script src="js/camera.js"></script>
|
||
<script src="js/pick.js"></script>
|
||
<script src="js/ui.js"></script>
|
||
<script src="js/sheets.js"></script>
|
||
<script src="js/render.js"></script>
|
||
<script src="js/urlparams.js"></script>
|
||
<script src="js/ik-solver.js"></script>
|
||
<script src="js/ik-glue.js"></script>
|
||
<script src="js/ik-policy.js"></script>
|
||
<script src="js/ik-policy-glue.js"></script>
|
||
</body>
|
||
</html>
|