🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

UR 机械臂仿真控制 NoneadChina/dsh-nonead-ursim

DeepSeek Harness
NoneadChina3 天前有提交已提供中文文档扫描:含敏感能力

本插件与该公司的 Nonead-Universal-Robots-MCP见「参考实现」一节同源,把「用 AI 控制…

32.2/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add NoneadChina/dsh-nonead-ursim
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · ui
装得上吗
静态安装检查有提示项,装前建议看一眼 README
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-nonead-ursim(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.15 · 基线 Node 22.19 满足
✓dsh CLI 依赖要求 ^0.1.2-rc.1 || ^0.1.7-rc.2 || ^0.2.0-rc.2 || ^0.2.1-alpha.5 · 最新 0.2.1-rc.2 兼容
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/20 02:48:26

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 11 处,展示前 11 条)
  • 发起网络请求
    lib/index.js:241
    const outcome = await approval.request({
  • 发起网络请求
    lib/client.js:42
    `},s=new Ni(5,5,5),r=new Un({name:"CubemapFromEquirect",uniforms:ds(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:zt,bl
  • 读取本地文件
    lib/sim-state.js:61
    raw = readFileSync(file, 'utf8');
  • 写入本地文件
    lib/sim-state.js:115
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    lib/sim-state.js:116
    writeFileSync(tmp, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
  • 写入本地文件
    lib/sim-state.js:117
    renameSync(tmp, file);
  • 删除本地文件
    lib/sim-state.js:122
    rmSync(tmp, { force: true });
  • 执行外部命令来自配置/变量
    lib/worker.js:319
    proc = spawn(this.pythonBin, ['-u', script], {
  • 读取本地文件
    lib/twin-routes.js:1253
    const info = await stat(file);
  • 读取本地文件
    lib/twin-routes.js:1256
    const body = await readFile(file);
  • 读取本地文件
    lib/twin-routes.js:1330
    const entries = await readdir(root);
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(161 字)↓

dsh-nonead-ursim 给 DSH 智能体一条能用大白话驱动的 Universal Robots 机械臂——UR 控制器全套工具面(86 个 ursim_* 工具:关节与笛卡尔运动、OptiMove、绘图图元、位姿与状态回读、RTDE 遥测、标准/工具 I/O 与寄存器、URScript、TCP/负载/工具设置

README

由 DeepSeek 最新模型翻译生成
dsh-nonead-ursim 一个让 DSH 用自然语言直接控制 Universal Robots(UR)机械臂的插件,由拓德科技(Nonead)基于自研的 nUR MCP Server 同源逻辑开发。(Suzhou Nonead Robot Technology Co., Ltd.)· 已发布到 npm:dsh-nonead-ursim(当前 0.3.12) 本插件与该公司的 Nonead-Universal-Robots-MCP(见「参考实现」一节)同源,把「用 AI 控制 UR 机器人」的能力以原生 DSH 工具的形式接入:插件启动一个常驻的 Python worker(内部复用 vendored 的 URBasic 库),工具通过该 worker 与机器人通信,connect 一次后即可在同一 IP 上持续发指令。 🧪 默认纯仿真(0.1.0 起):本插件驱动保留回环地址 127.0.0.1 上的运动学级虚拟 UR 机器人,除非你显式要求更多。默认的 motionMode: 'sim' 下它不存在任何真机通道:真机 IP 会在派发之前被判为非法输入(SIM_BADARG),vendored URBasic 的 RTDE / Dashboard / SSH 那几条路从工具面上不可达。
展开完整文档(README 剩余 1 节)
dsh-nonead-ursim

一个让 DSH 用自然语言直接控制 Universal Robots(UR)机械臂的插件,由拓德科技(Nonead)基于自研的 nUR MCP Server 同源逻辑开发。(Suzhou Nonead Robot Technology Co., Ltd.)· 已发布到 npm:dsh-nonead-ursim(当前 0.3.12)

本插件与该公司的 Nonead-Universal-Robots-MCP(见「参考实现」一节)同源,把「用 AI 控制 UR 机器人」的能力以原生 DSH 工具的形式接入:插件启动一个常驻的 Python worker(内部复用 vendored 的 URBasic 库),工具通过该 worker 与机器人通信,connect 一次后即可在同一 IP 上持续发指令。

🧪 默认纯仿真(0.1.0 起):本插件驱动保留回环地址 127.0.0.1 上的运动学级虚拟 UR 机器人,除非你显式要求更多。默认的 motionMode: 'sim' 下它不存在任何真机通道:真机 IP 会在派发之前被判为非法输入(SIM_BADARG),vendored URBasic 的 RTDE / Dashboard / SSH 那几条路从工具面上不可达。真机通道自 0.1.4 起可以显式开启(motionMode: 'real' + 白名单,见下文「真机通道(默认关闭)」一节),默认行为不因此改变。也没有"先连机器人"这一步:仿真按需自动就绪(UR12e、竖直收拢、倍率 100%),所以整个使用过程不需要任何真机存在。需要真实控制器的指令(力控、安全状态位、程序、原始脚本、传送带、上下电/刹车/自由驱动)保留工具名,但一律如实回报 SIM_UNSUPPORTED,绝不会落到真机上 —— 例外有两处:标准/工具端 I/O 与寄存器(0.1.5 起有仿真语义:内存态,输出可写可读回,输入没有信号源恒为 0,寄存器没有写入口恒为初值),以及遥测(0.1.6 起为运动学估算:关节电流/电压/速度、TCP 速度/受力、工具加速度计与关节温度由有限差分加量级模型推出,每条返回值都带 estimated: true 与 note;同一组值也加进了 ursim_get_status —— 仿真面板的遥测行读的正是它,所以那一行在仿真里不再是空的)。下面各工具小节沿用真机代码库的原文,描述的是它们当年的语义;以本条为准。

⚠️ 安全提示:本插件的目标是仿真,因此不会产生任何物理运动。各工具描述里沿用的安全警告,针对的是本插件所由派生的那份真机代码库。

🛡️ 运动审批门禁(可选开启;默认免确认):ursim_movej / ursim_movel / ursim_movep / ursim_movec / ursim_run_sequence / ursim_servoj / ursim_move_optimized / ursim_move_x / ursim_move_y / ursim_move_z / ursim_move_tool_x / ursim_move_tool_y / ursim_move_tool_z / ursim_draw_circle / ursim_draw_square / ursim_draw_rectangle / ursim_draw_star / ursim_load_program / ursim_run_program / ursim_send_script / ursim_reset_error / ursim_jog_rotate;ursim_set_freedrive / ursim_set_teach_mode / ursim_power_on / ursim_power_off / ursim_brake_release / ursim_unlock_protective_stop / ursim_shutdown / ursim_zero_ftsensor / ursim_set_conveyor_tracking;ursim_force_mode / ursim_end_force_mode / ursim_force_mode_settings / ursim_speedj / ursim_speedl / ursim_stopj / ursim_stopl / ursim_set_payload_inertia / ursim_motion_version / ursim_set_speed_scaling / ursim_set_payload / ursim_set_gravity;ursim_set_tcp / ursim_set_tool_output_mode / ursim_set_tool_voltage / ursim_set_tool_communication / ursim_set_digital_out / ursim_set_analog_out / ursim_set_conveyor_tick —— 这些会驱动机器人运动、执行程序、或让机械臂脱离程序控制 / 失去刚性支撑的指令,默认免确认(0.2.3 起产品默认 requireApprovalForMotion: false,运动不需要人工确认)。本清单与 lib/index.js 的 APPROVAL_OPS 由 scripts/check-doc-tools.mjs 双向对账:漏列、多列或前缀写错都会 FAIL。门禁是可选开启的能力:设 true 后,这些指令在真正下发到机器人前会暂停等待人工确认,且未组合审批服务 / 无代理 / 应答不是 allowed-once 的调用一律 fail-closed(拒绝且不下发);另外仿真目标(motionMode: 'sim' + 保留回环地址)在任何情况下都豁免。默认值写在代码里(config.requireApprovalForMotion ?? false),且与 schema 的默认值一致 —— 因此"调用方跳过 schema 解析"得到的行为与产品默认完全相同;要开启请设 requireApprovalForMotion: true。test/approval-gate.test.mjs 驱动真实工具注册表逐条验证上述行为,包括"多传一个 op 参数无法把调用改派到别的指令"。

简介

dsh-nonead-ursim 让 DSH 里的 AI 用自然语言驱动一台 Universal Robots 机械臂 —— 它带上了 UR 控制器的完整工具面(89 个 ursim_ 工具:关节与笛卡尔运动、多段连续轨迹、OptiMove、画圆画方等图元、位姿与状态回读、RTDE 遥测、标准/工具端 I/O 与寄存器、URScript、TCP/负载/工具设置、力控、传送带跟踪),并配一块实时 3D 仿真面板,渲染的正是这些工具读到的同一份关节数据。

开箱即用的是离线、运动学级的虚拟 UR 机器人(保留回环地址 127.0.0.1):没有硬件、没有真控制器,除 Python 之外不需要装任何东西 —— 开一台仿真就能直接发指令。真控制器只有在你显式要求之后才会被寻址(motionMode: 'real' + realRobotIps 白名单),而运动审批门禁默认关闭(0.2.3 起;要开启请设 requireApprovalForMotion: true)。

仿真"模拟了什么、没模拟什么"是一条写明的边界:运动是真实运动学;遥测是估算值并明确标注; I/O 与寄存器是内存态;真正需要控制器的那些(力控、安全状态位、程序加载与执行、原始脚本、传送带)一律回报 SIM_UNSUPPORTED,绝不假装。它不是安全评估工具 —— 没有动力学、也没有安全功能,节拍、碰撞与安全距离的问题不在它的范围内。

功能一览

共 89 个工具(ursim_)。

| 类别 | 工具(ursim_) | 说明 |
| 连接 | ursim_connect / ursim_disconnect | 按 IP 连接 / 断开一台 UR 机器人 |
| 状态 | ursim_get_status | 一次性读取 TCP、关节、型号、序列号、版本、安全模式、运行/程序状态、电压、电流、温度、开机时长、关节电流/电压/角速度、TCP 速度与受力、速度倍率 |
| 位姿 | ursim_get_tcp_pose / ursim_get_joint_pose | 读取当前 TCP 位置 / 关节角度 |
| 目标值 | ursim_get_target_values | 读取「控制器打算去哪」:目标关节角/角速度/角加速度、目标 TCP 位姿与速度(外加实际值便于对比)。来自 RTDE 的 target_ 字段,读取零代价——这是判断「指令已下发但还没执行 / 正在交融 / 被安全限速拉住」的直接依据 |
| 设备信息 | ursim_get_robot_model / ursim_get_serial_number / ursim_get_uptime / ursim_get_software_version / ursim_get_safety_mode / ursim_get_safety_status / ursim_get_robot_mode | 型号(含 remote_control 字段)/ 序列号 / 开机时长 / 软件版本 / 安全模式 / 安全与机器人状态位(哪一类安全功能被触发,含 violation / fault;限值数值需去 PolyScope 安全页读)/ 运行状态 |
| 程序 | ursim_get_program_state / ursim_load_program / ursim_run_program / ursim_stop_program / ursim_pause_program / ursim_list_programs | 程序状态、加载、运行、停止、暂停、SSH 列表(list_programs 兼容真机 /programs 与 URSim ~/URSim_Linux-/programs.;load/run 支持完整路径/URSim 路径与 programs_dir)。运行/停止/暂停都会检查控制器应答并回带运行状态,不再把 "could not understand" 一类拒绝当作成功 |
| 寄存器 | ursim_get_int_register / ursim_get_double_register / ursim_get_bit_register | 读取 Int / Double / Bool 寄存器 |
| 健康检查 | ursim_ping | 无需连接机器人,检测 worker/Python/URBasic 就绪 |
| I/O | ursim_get_digital_in / ursim_set_digital_out / ursim_get_digital_in_bits / ursim_get_digital_out_bits / ursim_get_analog_in / ursim_set_analog_out / ursim_get_tool_analog_in | 数字输入/输出(含批量读位、which="tool" 的工具端数字 I/O)、标准模拟输入/输出(按工程单位收值:URScript 的 set_analog_out 收的是相对电平 [0,1],旧实现把 5 当成满量程;full_scale 可指定电流域 20)、工具端模拟输入(函数名已对照仓库内官方手册确认,参数语义未经真机验证) |
| 工具配置 | ursim_set_tool_voltage / ursim_set_tcp / ursim_set_payload / ursim_set_payload_inertia / ursim_set_gravity / ursim_zero_ftsensor / ursim_set_tool_output_mode / ursim_set_tool_communication | 工具电压(0/12/24,旧实现调用的是 NotImplementedError 桩,从未成功过)、TCP、负载质量/重心、质量+重心+惯性矩阵一次设全(set_target_payload,5.10+;避免 set_payload 重置惯性矩阵导致三者不一致)、重力方向(非水平安装用)、力/力矩传感器归零、工具输出模式(普通 / power 双针供电)、工具串口(TCI/RS-485,⚠️ 启用会禁用工具模拟输入) |
| 控制模式 / 电源 / 安全 | ursim_set_freedrive / ursim_set_teach_mode / ursim_power_on / ursim_power_off / ursim_brake_release / ursim_unlock_protective_stop / ursim_shutdown | 自由驱动 / 示教模式(可手动拖动机械臂)、上电 / 下电 / 释放刹车(⚠️ 可能因重力掉落)、只解保护性停止(不上电、不释放刹车,与 ursim_reset_error 的区别)、关闭控制器 |
| 力控 | ursim_force_mode / ursim_end_force_mode / ursim_force_mode_settings | 力控(Force Mode):沿/绕选定轴柔性贴合环境并持续施加指定力/力矩。参数与手册逐条对齐:task_frame / selection_vector(1=柔性)/ wrench / type(1-3)/ limits(柔性轴=最大速度,刚性轴=最大偏差)/ damping / gain_scaling。脚本里按手册建议先 sleep(0.02) 再进力控;退出用 ursim_end_force_mode。⚠️ damping/gain_scaling 控制器侧无法回读,工具只回报本次设置值,不假装读到当前值 |
| 速度控制 | ursim_speedj / ursim_speedl / ursim_stopj / ursim_stopl / ursim_wait_steady | 关节/TCP 速度指令(speedj / speedl)与对应的减速停止(stopj / stopl)。⚠️ 速度指令是开放式的:t=0(默认)时"达速即返回"但机械臂仍在运动,必须用 stop* 或 ursim_wait_steady 收尾。ursim_wait_steady 轮询 RTDE 已有速度量判断是否真的停住(没有用 URScript 的 is_steady()——那个在力控/示教模式下恒为 false) |
| 实时遥测 | ursim_get_runtime_telemetry / ursim_get_robot_voltage / ursim_get_robot_current / ursim_get_joint_temperatures / ursim_get_speed_scaling / ursim_get_tcp_force / ursim_get_tool_telemetry | 关节电流/电压/角速度、TCP 线速度与受力/力矩、工具加速度计、速度倍率、整机电压电流、关节温度、工具电流/电压、I/O 电流。这些字段本来就在 500 Hz 的 RTDE 数据流里,读取零代价、无需改配置。单点读取(整机电压/电流、关节温度)与一次性汇总(ursim_get_runtime_telemetry)并存:轮询某一项时用单点,诊断时用汇总 |
| 速度倍率 | ursim_set_speed_scaling | 设置速度倍率(1%–100%,即 0.01–1.0;越界会被钳到该区间,客户端原始值仍会随回包返回)。仿真侧原地修改运行中的实例、不重建(位姿与关节角保持不变,新倍率从下一段运动开始生效);真机侧发 URScript set_speed_slider 并读回控制器实测值 —— 机器人静止时实测读 0 属正常,不是「未生效」的证据。⚠️ 影响此后所有运动的速度 |
| 传送带 | ursim_get_conveyor / ursim_set_conveyor_tick / ursim_set_conveyor_tracking | 传送带 tick 读取 / 设置、线性或圆盘跟踪的开启与停止 |
| 运动 | ursim_movej / ursim_movel / ursim_movep / ursim_movec / ursim_servoj / ursim_move_optimized / ursim_move_x / ursim_move_y / ursim_move_z / ursim_move_tool_x / ursim_move_tool_y / ursim_move_tool_z | 关节空间 / 直线 / 路径 / 真正的圆弧(旧实现内部把 movetype 写死成 'p',实际发的是 movep 且丢弃途经点;现在会把手册的 mode 参数传给控制器:0 插补姿态 / 1 固定姿态)/ 连续流 / OptiMove 平滑运动(optimovej/optimovel,jerk 受限、振动更小;⚠️ 它的 a/v 是能力比例 (0,1] 而不是 rad/s 或 m/s)/ 沿轴直线运动 —— _move_ 沿基座轴,_move_tool_ 沿当前工具轴(worker 侧用旋转矩阵换算,不依赖 URScript 的 pose_trans)。默认 a/v 已改回官方手册值(movej 1.4 / 1.05,movel 1.2 / 0.25;旧代码默认 movel v=1 m/s,是手册默认的 4 倍) |
| 方向点动 | ursim_jog_rotate | 绕指定轴增量旋转 TCP:axis 只认 rx / ry / rz(不是 x/y/z —— 那三个在别的工具里表示平移);frame="tool"(默认)绕工具自身轴、frame="base" 绕基座轴(rx/ry/rz ↔ 基座 x/y/z)。真机与仿真共用同一份几何(同一套旋转合成 ⇒ 同一个目标位姿),TCP 位置保持不变。⚠️ 会驱动机械臂运动 |
| 连续多段 | ursim_run_sequence | 一条命令走完整条多段轨迹,段与段之间不停顿。 segments 是一串 {"type":"joint","q":[…]} / {"type":"cartesian","pose":[…]};可选的 v/a(默认 0.25 / 1.2)作用于整条序列,t(≥0,默认 0 = 用 a/v)设定整条轨迹的时长,与 r(交融半径)一样只在仿真里建模 —— 真机路径逐段发 movej/movel(r 就是途经点的交融半径),并在回包里明说 t 已被忽略。★ 仿真里每一段都转成关节航点后拼成一条折线、只规划一次,整条序列共用一条时间剖面:20 段就是一次加速、一次减速,而不是二十次起停。任一段的任一细分点不可达就整条序列失败(绝不跳过那一段继续走) |
| 运动规划 | ursim_motion_version / ursim_get_freedrive_status | 设置 Motion Version(手册第 14 章)与 jerk 增益(0.01-1.0,只作用于 jerk 受限的剖面:版本 2 的 movej/movel 与 optimovej/optimovel):版本 2 规划时把速度/加速度钳到硬件上限、交融半径重叠时动态收缩,而不是像版本 1 那样跳过整段运动并给 "Overlapping Blends" 警告。⚠️ 新机型与 PolyScope X 只支持版本 2;CB3 没有这个设置。⚠️ 这两个设置没有回读通道,只报告本次设置值。ursim_get_freedrive_status 读取当前姿态在 freedrive 下离奇异点的距离(0 正常 / 1 接近 / 2 太接近——不是 freedrive 的开关状态),据此提示操作员换路径 |
| 绘图 | ursim_draw_circle / ursim_draw_square / ursim_draw_rectangle / ursim_draw_star | 画圆 / 正方形 / 长方形 / 五角星。可选的 v / a(默认 0.25 / 1.0 —— 正是从前写死的那两个值)决定速度,t(≥0,默认 0 = 用 a/v)在仿真里设定整条轮廓的时长;真机路径照旧用 a/v,并在回包里说明 t 被忽略。必须先观察到脚本真的在运行才回报「执行完成」——旧实现发完立刻探测,必然看到"没在跑",于是无论脚本是否执行都报成功 |
| 脚本 / 紧急 | ursim_send_script / ursim_reset_error | 发送 URScript(校验执行:哨兵注入到函数体内部/顶层语句之间并回读,「已发送」不再冒充「已执行」;含多个函数且看不出调用哪个时拒绝校验并给 verified: null)/ 复位错误 |
| 离线仿真 | ursim_sim_start / ursim_sim_stop / ursim_sim_status | 运动学级离线仿真:在保留地址 127.0.0.1 上创建/销毁一台虚拟 UR,让数字仿真在没有真机的情况下被驱动。sim_start(model=..., preset=..., speed_scaling=...) 开启后,运动类工具与位姿读回都作用于它;默认起始姿态是 upright(竖直收拢) —— 不传 preset 就是它,面板里换型号也会重置到它,按需自动创建的那台同样从这里开始;sim_stop 关闭(幂等);sim_status 无副作用地读状态与能力清单。其余指令在仿真目标上明确回报「无仿真语义」(SIM_UNSUPPORTED),绝不假装执行 |

除 ursim_ping 外,所有工具都接受 ip 参数。仿真目标不需要「先连接」:它按需就绪(ursim_sim_start,或在保留回环地址上的第一条运动指令时自动创建)。真控制器在配置里开启「真机通道」之前是够不到的 —— 见下文「真机通道(默认关闭)」一节。

只读 3D 数字仿真

插件还内置机器人的只读 3D 数字仿真(three.js 渲染):入口是右侧栏「开始」面板里的一张卡片,位置在「工作区文件 / 新建终端 / 浏览器」三张卡片下面;点击后 3D 视图占满右侧栏的内容区。视图订阅宿主的 SSE 实时流(/twin/stream,100 ms 一帧),始终与真机同步显示关节姿态、TCP 坐标系与近期运动轨迹。数字仿真严格只读,绝不下发任何机器人指令——它只订阅 host 的只读路由并渲染收到的数据。工具栏提供「重置视角」与等轴测/前视/侧视/俯视四个预设,且相机与基座网格按模型包围盒取景 —— UR3 与 UR20 都能正确入画;但打开「可达范围」图层时会切换成绝对取景(以全部内置型号里最大的那个可达上界为参考),让每个型号都在同一把尺子下显示:UR3 的包络(≈0.80 m)只占画面约 37%,UR20 的(≈2.17 m)正好撑满,该开关上还直接写着当前型号的上界。数值面板里还有一排工程辅助图层开关:可达范围包络、基座坐标系、TCP 受力,以及「目标姿态」——后者是真臂的半透明克隆(橙色=待审批目标、青色=控制器当前目标),用来对照"打算去哪";它只在目标与当前姿态明显不同时才出现(重合时显示只会被误读成"画面里多了一台机器人"),随时可以关掉。数值面板还会显示 dashboard 侧状态(安全模式、机器人模式、程序状态、速度倍率、关节温度、母线电压电流),同样走这条路由、按较慢的节拍取。

遥测是推送的,不是轮询的:worker 以 20 Hz 主动推送读数,面板每一帧优先读这份推送缓存,因此机器人运动期间画面照常更新 —— 运动确认占住的那条单线程命令队列完全不参与。只有缓存过期(>300 ms)或缺失时才回退到显式读,且面板的读只带 2.5 s 的专用预算且超时不杀 worker:一条只读可视化读绝不能把整条机器人会话(RTDE/Dashboard)带走。万一真的停滞,流里仍会推 stale 事件、面板写出「数据已停止更新 N s · 正在重试」,绝不静静冻住;断线后按指数退避无限重连(封顶 30 s)。诊断时可用 DSH_URSIM_TWIN_PUSH=0 关掉推送做对照。

换机器人自动换模型:型号按 IP + 连接代次缓存,所以同一个 IP 上换成另一台机器人会被发现:客户端重新加载 GLB,并丢掉上一台机器人的插值对与轨迹(否则新臂会从旧姿态滑过去、轨迹线还会把两台机器人的 TCP 连成一条从未发生过的直线),同时按新型号重新取景、更新可达范围包络与关节限位。加载失败按 3 s 节流重试,不会永远停在旧臂上。⚠️ 检测上限是 vendored 库的 30 s 数据停滞超时,这期间面板显示的仍是最后一笔读数(旧型号 + 旧姿态);想立刻纠正就重新调一次 ursim_connect。

面板里的离线仿真:面板顶部是「离线仿真」控件 —— 一个开关加型号、起始姿态、速度倍率三个选择项。现在打开面板会自己开一台仿真,默认 UR12e / 竖直收拢 / 倍率 100%,真机连着也一样 —— 卡片一展开就是可用的。之后由 AI 直接驱动这里的模型:运动类工具作用于 127.0.0.1 上的运动学虚拟机器人,画面真的会动,而真机一个字节都收不到。如果仿真已经开着(AI 用 ursim_sim_start 开的、或另一个窗口开的),面板沿用那一台、绝不重建 —— 重建会把那台虚拟机器人推回起始姿态。收起面板即停仿真,并把数据源切回"按宿主解析"。仿真态的标识做了三处冗余,因为它动起来与真机完全一样:画布左上角的紫色「仿真」角标、状态行的「离线仿真 · UR12e」、以及截图水印里的"离线仿真(非真机)"。每次切换只发一条写请求(POST /twin/sim),失败会回滚并写出原因 —— 而那一行未连接时也照样可见,自动进入失败(没装 Python、worker 起不来……)时就靠它报错与重试。开着时改型号/姿态/倍率 = 按新配置重建仿真。工具侧也能开:ursim_sim_start(model="ur10e")。不想自动开仿真的宿主可用 autoSim: false 挂载面板。

仿真由宿主自愈 —— 而且这份记忆能跨重启:SIMS 活在 Python 子进程内存里,所以子进程一旦被替换(崩溃重启、插件重载、进程被回收),那台虚拟机器人就没了。宿主因此记住仿真配置,在把仿真指令交给 worker 之前确认它还在(子进程代次变了立刻查,否则每 10 s 兜底查一次),丢了就按记忆重建并写一条日志 —— 不会留下"开关开着、指令却全报未连接"的自相矛盾。用户明确关掉仿真后不会被自愈复活;重建只发生一次,之后连续运动不再重复探测。重建后虚拟机器人回到起始姿态(这是重建的代价,日志里会说明)。

这份记忆过去只活在进程里,于是宿主自己重启(重开 DSH、重载插件)就把它弄丢了,自愈也就无从谈起。现在它会落盘(persistSimState,默认开;文件在 <DSH_HOME>/plugin-data/dsh-nonead-ursim/sim-state.json,可用 simStateFile 改):落盘的是意图(enabled)而不是"最后一帧画面" —— 关掉仿真写的是 enabled: false,所以关掉的状态同样跨重启成立;而上次还开着的,加载时会用同样的型号、起始姿态与速度倍率再建一台(日志会说明;万一恢复失败,面板会显示原因)。落盘是加分项:数据目录只读或文件损坏都只降级成"没有记忆"并留一条告警,绝不让插件启动失败。

仿真的能力边界(写死在代码里,不是文档承诺):只实现运动学 —— 正解/逆解、关节与笛卡尔轨迹插值、位姿读回。运动类工具(movej/movel/movep/movec/run_sequence/servoj/move_optimized/move_x|y|z/move_tool_/draw_/wait_steady/stopj/stopl)与读回(get_joint_pose/get_tcp_pose/get_robot_model/status/get_target_values 等)都可用;其余指令一律明确回报 SIM_UNSUPPORTED(力控、RTDE 遥测、安全状态位、程序加载与执行、原始脚本、I/O、寄存器、传送带、电源/刹车/自由驱动),并附上"要去 URSim 才能真跑这些"的提示 —— 宁可说"这里没有",也不给一个看起来能跑的结果。正解与客户端 fk.js 逐元素一致(test/sim-backend.test.mjs 钉住),所以读回的 TCP 与画面画出来的位置永远对得上。

面板跟随桌面端的配色主题:浅色 / 深色 / 跟随系统来自 DSH 自己的外观设置 —— 主题插件把解析后的快照投影到 document 上:布尔属性 body[data-ds-dark-theme] 加一整套 --dsw-alias- 设计 token。面板因此直接吃这些 token(只有在宿主 token 缺失时——例如独立预览页——才退回与主题成对的本地值),于是既跟随设置、也跟随任何通过 ctx.theme 覆盖别名的第三方主题,不需要任何 JS 参与。CSS 唯一够不到的是 WebGL 侧的基座网格:它的颜色烘在几何体顶点色里,src/client/theme.js 盯同一个信号、scene.js 的 applyTheme() 就地重刷网格(不重建几何体、不新建 GridHelper),所以切主题不会打扰相机、模型与已录轨迹。

面板界面支持 8 种语言,语言跟桌面程序一致:简体中文、英文、日语、西班牙语、法语、德语、俄语、巴西葡萄牙语(pt-BR 与桌面端的 pt 共用一套词条)。语言来源不是猜的 —— 桌面端的语言服务切语言时会把活动语言写进 (zh 写作 zh-CN,其余写原 id),面板优先读它,读不到才退回 __DSH_LOCALE__ 与 navigator.language,认不出的语言回退中文(对中文用户绝不退化成英文)。切换语言不用刷新页面:文案表走 liveStrings(),每次取值按当前 解析,下一次渲染即新语言。每种语言 143 个键、8 套逐一对称,由 test/strings.test.mjs 钉住。

面板多显示的六件事 —— 光有工具做不到这些:自 0.1.8 起,左上角那枚角标是三态模式指示,而不只是仿真水印:驱动虚拟机器人时是紫色 仿真;只要配置了 motionMode: 'real' 就常显红色 真机模式 · <允许的 IP>(断连时也显示 —— "没有角标"绝不能被读成"安全";白名单为空时明说全部拒绝);什么都不在驱动时是中性的 未连接。遥测行补上了已经送到客户端却从未画出来的两项读数(关节电流、TCP 速度),并且只要宿主标了 telemetry_estimated,这几行就带 (估算) 后缀 ——界面不能把估算值画成和测量值一样。仿真能力边界也能在面板里读到:仿真控件下面一行可展开的说明,列出每个桶有多少项,完整清单在悬停提示里。自 0.1.9 起还多了一块 「I/O 与寄存器」:展开即可读到 16 路数字输出、16 路数字输入、两路模拟输入(位串按 00000000 00000001 渲染,正好是标准端与可配置端两段),以及 int / double / bit 寄存器各 8 个值。它是按需读的:展开时数字位一次请求、每片寄存器各一次,折叠着时一个请求都不发;仿真下还会直接写明"输入没有信号源(恒 0)",不让那些 0 冒充信号。
自 0.1.11 起,它还回答画面答不了的那个问题:这个位姿离奇异点有多近? HUD 里多一行,给出腕角(第 5 关节角 —— 腕部三轴共线时趋 0,UR 手册上的经典判据)、归一化可操作度 |det J| / 臂展³、以及离最近关节限位的余量,越过标定阈值就转琥珀再转红;而任何超限关节,它在 3D 里对应的那节连杆会被染红 —— 于是"HUD 在说哪一节"一眼可见。两者都在客户端用画面同一份正解算出来:不额外走 worker 往返,也不可能出现"提示与画面不一致"。

host 侧路由(均限定 loopback 调用方):

| 路由 | 说明 |
| GET /nonead-ursim/twin/stream[?ip=<ip>] | SSE 实时流(客户端默认走这条):每 100 ms 一帧完整状态快照,另有 stale(这一帧读还没回来)与 frame-error(这一帧失败)事件 |
| GET /nonead-ursim/twin/state[?ip=<ip>][&detail=1][&io=1][&reg=int|double|bit&from=0&count=8] | 实时位姿(关节角 / TCP / 型号)。detail=1 附带 dashboard 侧状态(安全模式、运行状态、速度倍率、关节温度/电流等);io=1 附带 16 路数字输出、16 路数字输入与两路模拟输入;reg=<集合>&from=&count= 附带一片寄存器(count 上限 16 —— 它们是逐下标 getter)。位姿通道始终独立轮询:detail/io/reg 任何一路失败都不会把它带走,只在自己的字段里写 {error} |
| GET /nonead-ursim/twin/asset?model=<urXX> | GLB 网格,带内容哈希 ETag + immutable,支持 If-None-Match → 304 |
| GET /nonead-ursim/twin/models | 本地实际存在的模型清单 |
| GET /nonead-ursim/twin/sim | 离线仿真的当前状态(是否开启、型号、起始姿态、倍率、可用型号)、能力清单,以及配置里的模式(motion_mode 加 real_robots 白名单)—— 面板的模式角标读的就是它。只读,无副作用 |
| POST /nonead-ursim/twin/sim | 本插件两条写路由之一:{"enabled":true,"model":"ur10e","preset":"upright","speed_scaling":1} 开仿真、{"enabled":false} 关。写守卫比只读路由更严(除回环信任围栏外必须带 Origin、content-type: application/json、请求体 ≤4 KB)。它的副作用被限制在回环地址上的运动学虚拟机器人,任何真机都不会因此收到指令。同一条路由还承担面板的 I/O 写({"io":{"kind":"digital_out","n":3,"value":true}} —— digital_out 收布尔值,analog_out 收工程单位下的有限数并可选 full_scale 10/20),且只在离线仿真运行时才受理:否则回 409 SIM_NOT_RUNNING。面板写通道不面向真机 —— 真机 I/O 仍走工具,那里有声明面白名单与审批门(开启时) |
| POST /nonead-ursim/twin/jog | 另一条写路由 —— 面板实时控制,仅离线仿真:一个 JSON 指令对象,mode 取值共八种 —— step(axis 取 x/y/z,frame 取 base/tool,distance)、rotate(axis、delta_rad)、pose(pose)、joint(q)、home、speed(fraction)、velocity(六元 twist,可选 frame 与 ttl_ms 看门狗)、stop。任何非回环虚拟机器人的目标都回 403 SIM_ONLY,且这道判定排在 body 解析之前 —— 真机部署无论 body 写什么都不会被面板驱动;拒绝顺序为 405 → 403 信任围栏 → 403 SIM_ONLY → 400 解析 → 派发 |

失败响应带机器可读的 code(例如 no_robot / robot_not_connected / ambiguous_robot / worker_unavailable / robot_error)并回显本次解析到的 ip,界面据此给出不同的提示与处置建议(以前四种完全不同的故障都渲染成同一句「未连接机器人」)。读暂时拿不到(worker 正忙着执行运动指令是最常见的原因)时不会报 robot_error:宿主回放最后一笔已知读数并标记 stale:true(最多 30 s),仿真保留画面并显示停滞提示。

安装到 DSH profile

方式一:从 npm 安装(推荐)

本插件已发布到 npm,包名 dsh-nonead-ursim(npmjs.com/package/dsh-nonead-ursim,当前 latest 为 0.3.12)。一条命令即可装进目标 profile:

dsh plugin --profile web add dsh-nonead-ursim
不走 CLI 时等价于:cd "$DSH_HOME/profiles/web" && pnpm add dsh-nonead-ursim

装完重启 DSH。cordis.patch.yml 会自动把插件行插入配置树,工具以 ursim_ 形式出现。需要固定版本时写 dsh-nonead-ursim@0.3.12。

方式二:作为 bundle 手动安装

1. 在目标 profile 的 package.json 中把本插件加入依赖:

// C:\Users\<you>\.dsh\profiles\web\package.json
{
"dependencies": {
"dsh-nonead-ursim": "^0.3.12"
},
"dsh": {
"profile": {
"bundles": [ // 把本插件加到数组里(顺序靠后即可)
"...",
"dsh-nonead-ursim"
]
}
}
}

2. 通过 dsh plugin(等价于在 profile 目录内跑 pnpm)安装依赖:

dsh plugin --profile web install
或 cd "$DSH_HOME/profiles/web" && pnpm install

3. 重启 DSH。插件的 cordis.patch.yml 会自动把插件行插入配置树,工具以 ursim_ 形式出现在模型工具列表中。

方式三:本地路径(开发时)

把仓库路径加入 profile 依赖(pnpm 支持 file:),便于在本仓库迭代:

"dependencies": {
"dsh-nonead-ursim": "file:<你的仓库路径>/dsh-nonead-ursim" }

Python 运行时

插件需要一个可用的 Python 与若干依赖(numpy、paramiko)来启动 worker。可用 pythonBin 配置指向解释器:

pip install -r requirements.txt

cordis.patch.yml 中的 pythonBin(默认 python)、commandTimeoutMs(运动/脚本超时,默认 60000)、connectTimeoutMs(首次连接超时,默认 30000)都可按部署覆盖。若 python 不在 PATH,改成绝对路径,例如 "C:\\Python312\\python.exe" 或 "/usr/bin/python3"。

⚠️ 依赖必须装在 worker 用的那个解释器里(一个真实的坑) lib/worker.js 会把 PYTHONPATH 指向插件的 python/ 目录,而 CPython 启动时会 import 该目录下的 sitecustomize.py(如果存在)。本仓库里曾有一个本机私货 python/sitecustomize.py,它把本机用户级 site-packages 硬编码进 sys.path —— 于是"本机能跑",而换一台机器、或安装发布版(该文件不在 files 清单里)之后,import numpy 直接失败,所有工具调用都会死。
正确做法:给 pythonBin 指向的解释器装好依赖(或指向一个 venv)。ursim_ping /
npm run test:python 就是这条链路的自检入口;npm run verify:host 则用宿主真实的
schema DSL 校验工具注册(应报告 89/89)。

健康检查 / 测试

无需连接真实机器人即可验证插件与 Python 运行时是否就绪:

npm run test:python # python ur_worker.py --selfcheck:校验 Python/numpy/paramiko/URBasic/RTDE 配置
npm test # 跑全部 48 个测试文件 以及全部门禁脚本,最后汇总
npm run test:node # 只跑 Node 侧:跳过需要 Python 的测试文件与门禁
npm run check # 只跑静态 + 跨语言门禁,不跑测试文件
npm run verify:host # 用宿主真实的 schema DSL 校验全部工具注册与 peer 版本
npm run verify:models # 校验 14 个 GLB 的结构契约

npm test 跑两类东西,两类都必须过:

- 48 个测试文件(端到端协议自检、审批门禁、仿真路由、客户端状态机、FK、vendored 库回归)。
名单来自 test/test-manifest.json(依赖 Python 17 / 仅 Node 31),并由 check:manifest 保证"会调用 Python 的用例"不会被漏登记。
- 11 个门禁脚本:check-test-manifest / check-package-metadata / check-client-bundle / check-doc-tools / tool-matrix / check-doc-links(Node),以及 check-worker-ops / check-tool-params / check-rtde-recipe / check-approval-gate / check-new-ops(Python)。
解释器没有 numpy 时,依赖 Python 的项会以 SKIP + 原因出现,绝不会显示成通过。

最近一次完整回归(2026-10-28,v0.3.12)的实测结论:npm run check 全通过;npm test 59/59(48 个测试文件 + 11 道门禁,0 失败 0 跳过);npm run verify:host 报告 89/89 工具经宿主真实 DSL 注册、6 条面板路由齐全;npm run verify:models 14/14 模型通过(合计 20.86 MB);npm pack --dry-run 为 51 个文件、tarball 15.5 MB。本版没有做端到端冒烟:测试主机的宿主进程里 python 指向 Windows Store 存根,仿真 worker 直接以 code=9009 退出(verify:host 对此有 note),把 pythonBin 指向真实解释器即可复测。证据、复现命令与真机未覆盖边界见 docs/test-report-2026-10-28.md。

scripts/pdf-extract2.py:只用标准库从 ScriptManual/.pdf 抽文本到 ScriptManual/txt/.txt(两个 PolyScope 手册的字符码是 glyph id,必须走字体自带的 ToUnicode CMap 才能解出文字)。它是本版所有签名/默认值/范围的可复核来源:有疑问时重新抽取一次,直接查手册原文。

check-client-bundle.mjs 会把 src/client/ 重新构建到临时文件并与提交的 lib/client.js 逐字节比对:产物落后于源码(改了界面但没重建)会直接让检查失败,而不是静默发布。
它绝不覆盖提交产物 —— scripts/build-client.mjs 为此支持 BUILD_CLIENT_OUT。

独立版本线之前 npm test 只跑一次 worker ping,仓库里另外 20 多个 .test.mjs 一个都不跑 ——所以"npm test 绿了"完全不能说明插件是好的。现在统一由 scripts/run-tests.mjs 枚举执行并汇总。

npm test 会返回 selftest passed. 或非零退出。若 python 不在 PATH,用环境变量指定:

UR_PYTHON=C:\\Python312\\python.exe npm test

发布前、以及每次升级 DSH 内核后,都应跑一遍宿主兼容自检——它拿已安装的宿主校验本插件,而不是校验一份抄下来的关键字清单:

node scripts/check-host-compat.mjs # 缺省宿主 = ../dsh-plugin-desktop/node_modules
node scripts/check-host-compat.mjs <node_modules> # 也可显式指定宿主

它会用宿主实装版本核对 peer 范围、用宿主真实的 value-schema DSL 编译每一个工具参数 schema(被拒的 schema 会让该工具静默消失)、驱动宿主路由注册,并校验 dsh.client 声明与客户端 bundle 的 __ModuleLoader__ 注册 id。退出码 0 表示与该宿主兼容。

首次连接到某机器人时,ursim_connect 有约 20s 的 RTDE 就绪等待,超时会返回清晰错误而非卡死。

工作原理

DSH 模型 @deepseek-ai/dsh-tools python/ur_worker.py UR 机器人 │ ursim_movej(...) │ │ │ ├────────────────► ctx.tools.register(defineTool) │ │ │ lib/worker.js │ │ │ ├── spawn(ur_worker.py) ──────►│ import URBasic │ │ │ {id,op,params} ───────────►│ RTDE+Dashboard+RTC │ │ │ ◄── {message,data} ─────────┤ 各 op 执行 │ │ ◄── text ───────┤ │ │

- python/ur_worker.py:常驻 stdio JSON worker。维护 ROBOTS / ROBOT_MODELS 字典,按 IP 连接,每次调用一条指令。运动指令用「到位确认」轮询(有界),并在出错时返回结构化错误。
- lib/worker.js:按需拉起 worker 一次并保持存活,行分隔 JSON 协议配对请求/响应,带超时与取消(转发 exec.signal)。
- lib/index.js:Cordis 插件,导入 defineTool 把上述控制逻辑注册成工具;inject: ['tools']。

工具命名与示例

工具名稳定为 ursim_,示例提示词:

连接 192.168.1.199,读取当前 TCP 位姿。

ursim_connect(ip="192.168.1.199")
ursim_get_tcp_pose(ip="192.168.1.199")

让 192.168.1.199 的 TCP 沿 Z 轴下降 20mm。

ursim_get_tcp_pose(ip="192.168.1.199")
ursim_move_z(ip="192.168.1.199", distance=-0.02)

绘制一个半径 50mm 的圆(竖直平面)。

ursim_draw_circle(ip="192.168.1.199", center=[0.3,-0.2,0.4,0,3.14,0], r=0.05)

参考实现

- 本插件仓库:<https://github.com/NoneadChina/dsh-nonead-ursim>

本插件与拓德科技的 Nonead-Universal-Robots-MCP(GitHub: <https://github.com/nonead/Nonead-Universal-Robots-MCP>)同源,复用其中的 URBasic 库与机器人控制逻辑,由同一团队面向 DeepSeek Harness 重新封装为本插件的 ursim_ 工具与 stdio worker 协议。URBasic 为 MIT(© Tony Ke & Anthony Zhuang / Universal Robots,2009-2025)。

注意事项 / 限制

- 连接持久性:worker 进程在插件生命周期内常驻,机器人连接按 IP 保留;worker 崩溃或 DSH 重启后需重新 connect。
- 远程控制模式:部分 UR 机器人需处于「远程控制」才能执行运动/程序指令,ursim_connect 会报告该状态。URSoftware 3.1–3.20 之间的 CB3 机器人默认就允许远程控制(设置层面无需额外开启);但 remote_control: false 仍说明控制器当前不在远程模式——本地/示教模式下 URScript 与运动指令会被静默丢弃,需在示教器上切到远程控制。其他固件(e-Series,或不在该区间的 CB3)则需先在 PolyScope 中开启 Remote Control。ursim_get_status 另给出 remote_control_raw,状态读不到时按"未知"处理而不是假装是 false。
- 工具端数字 I/O:ursim_get_digital_in / ursim_set_digital_out 的 which="tool" 用于工具端(法兰侧)数字 I/O。工具端数字信号不经 RTDE:读取工具输入会经 SendProgram 发送一段短的 URScript 程序,可能打断正在运行的程序;写入工具输出则发送 URScript write_tool_digital_out 命令。工具端数字输出的读回不支持(无可靠的 read_tool_digital_out 表达式)。
- 关节电流:当前 RTDE 配方未直接暴露单关节电流,故未提供 ursim_get_joint_current(参考实现中的该工具存在取值错误,本实现未沿用)。
- 线程/取消:运动指令为阻塞到位的轮询,commandTimeoutMs 内完成;对长时间轨迹,请在描述中提醒模型设置合理超时或分步执行。
- 非安全边界:此插件与 bash 工具同级,可驱动物理设备,务必在真实机器人上充分测试后再用于生产。
- 包体积:发布包约 21 MB,几乎全部来自 14 个 assets/models/.glb 网格;插件自身代码只有数百 KB。网格从转换脚本的原始 35.11 MB 经两步可复现瘦身(node scripts/compress-models.mjs;npm run analyze:models 可看体积构成):先无损降到 28.27 MB(索引 uint32 → uint16 —— 这 14 个型号最大索引值仅 24228 —— 并删掉没有任何材质读取的非标准属性 _color;顶点位置、UV、贴图与索引序列逐字节/逐值不变,脚本在写盘前自证),再经一次明确决策的有损处理降到 20.86 MB:5 个新型号里共 8 张 2048×2048 底色 PNG(ur15 ×1、ur18 ×2、ur20 ×1、ur30 ×2、ur8long ×2)用块平均降到 1024×1024(--texture-size 1024)。仿真面板实际只有几百像素宽,同区域 1:1 对比看不出差别。几何精度未动(Ruling 24);test/model-contract.test.mjs 守住体积区间。若只想砍掉整个型号,可用 python scripts/convert-meshes.py --only <型号…> 重新生成子集。
- 未知型号回退:若某机器人没有内置网格(未知或定制型号字符串),会回退到近似几何体渲染而不报错,数字仿真不会因未知型号失败。
- 不接机器人时能不能驱动仿真?——能,但有明确边界:
- 插件内建的运动学仿真:ursim_sim_start(model="ur10e") 或面板上的「离线仿真」开关打开后,运动类工具与位姿读回都作用于 127.0.0.1 上的虚拟机器人,仿真跟着动 —— 不需要任何真机或 URSim。
- 它能做什么:关节/直线/路径/圆弧/沿轴/绘图/多段连续轨迹等到位型运动(含速度倍率、起始姿态选择)、关节角与 TCP 位姿读回、ursim_wait_steady/stopj/stopl;逆解用多起点数值解,不可达会明确拒绝而不是给一个近似姿态。
- 它不能做什么(也不会假装):力控、安全状态位、程序加载与执行、原始脚本、传送带、电源/刹车/自由驱动 —— 这些是控制器的行为,没有控制器就没有语义,调用会返回 SIM_UNSUPPORTED。速度指令(speedj/speedl)同样不支持:开放式速度需要持续积分与减速模型,半套模型比没有更危险。有两处例外有仿真语义:标准/工具端 I/O 与寄存器(0.1.5:输出写进内存态并可读回,输入没有信号源恒为 0,寄存器没有写入口恒为初值),以及遥测(0.1.6:由运动学估算,带 estimated: true 标记,绝不作为测量值呈现)。每一条返回值都在自己的字段里写明这一点。
- 它也不是安全评估工具:没有动力学、没有安全功能、时间只是近似(a/v 决定每段时长,不做 jerk 限幅),所以不能用它验证碰撞、节拍或安全距离。
- 想要全套语义(含 URSim)时:URSim 是 UR 官方的免费模拟控制器(跑在 VM 里,对外就是一台真控制器)。自 0.1.4 起可以把它当成"一台机器人"驱动 —— 显式开启真机通道(motionMode: 'real' 并把它的 IP 写进 realRobotIps),这时 89 个工具与仿真全部照常工作(已兼容 ~/URSim_Linux-/programs. 布局)。默认的 sim 模式下该 IP 会在派发前被判为非法输入(SIM_BADARG)。
- 为什么仿真地址是 127.0.0.1:真机的 RTDE(30003)/Dashboard(29999) 跑在控制器上,本机回环上不可能出现一台真 UR —— 于是"仿真碰不到真机"是结构性保证;配合 worker 侧的保留地址守卫,即使宿主侧的登记状态漂了,指向该地址的指令也只会得到一句拒绝。
- 资产管线:网格由 python scripts/convert-meshes.py 生成,其结构契约(每个 GLB 含 7 个固定命名节点、贴图内嵌)由 python scripts/verify-models.py 校验(也暴露为 npm run verify:models)。

第三方资产与许可

除插件自身代码外,本包还随附 14 个机器人网格 assets/models/.glb(约 21 MB)与 assets/kinematics.json,全部派生自 Universal Robots 的 Universal_Robots_ROS2_Description(humble 分支,获取日期 2026-09-21)。

许可按型号分为两类,同一型号内不会混用:

- BSD-3-Clause(9 款):ur3、ur5、ur10、ur3e、ur5e、ur7e、ur10e、ur12e、ur16e——同时涵盖 assets/kinematics.json 所派生的运动学与关节限位配置。
- UR「Graphical Documentation」条款(5 款):ur8long、ur15、ur18、ur20、ur30。这 5 款的网格不是 BSD-3-Clause,而属于 UR 的「Graphical Documentation」,其使用受 UR 的 Terms and Conditions for use of Graphical Documentation 约束——该条款不符合 OSI 开源定义,但允许在若干限制下使用、修改与分享。相关疑问请联系 <legal@universal-robots.com>。

客户端 3D 渲染基于 three.js(MIT);esbuild(MIT)仅用于构建期。

逐型号派生清单、转换参数与许可全文见 THIRD_PARTY_NOTICES.md。

真机通道(默认关闭)

本版可以驱动真控制器,但必须由使用者显式开启:

motionMode: 'real' # 默认 'sim' —— 不配它就碰不到任何真机 realRobotIps: '192.168.1.10' # 逗号分隔的白名单;留空则任何目标都被拒

- sim(默认)是结构性保证,不是策略。 worker 在派发之前就拒绝保留回环地址以外的任何地址,因此 RTDE / Dashboard / SSH / 远程控制那一整套代码不可达 —— 不是"有但不用"。
- real 还必须配白名单。 白名单外的目标在宿主侧就被拒绝,根本到不了 worker;白名单留空等于拒绝一切(fail-closed),而开启 real 却没写白名单时插件会明确 warning。
- 两种模式下仿真都仍然可用,且保留回环地址永远表示那台虚拟机器人 —— 绝不交给真机实现(否则"把真控制器端口转发到环回"就会变成一条绕回来的路)。
- real 模式下若开启了门禁,则不存在任何审批豁免:每一条受门禁的指令都要人确认,包括指向仿真的那些(默认关闭时全部放行)。这一条同时关掉了审计的 H-2 —— 从前"豁免"是宿主侧、模型自己能用 ursim_sim_start 置位的状态;现在它来自人写下的配置值。
- 指向真机之前,请先读 THIRD_PARTY_NOTICES.md 与本文档顶部的安全提示。

开发者

Suzhou Nonead Robot Technology Co., Ltd.(拓德科技) —— 研发部 Tony Ke。

- 公司:Suzhou Nonead Robot Technology Co., Ltd.(<https://www.nonead.com>)
- 开发者:研发部 Tony Ke
- 问题与反馈:请在本仓库开 issue;商业授权请联系 <service@nonead.com>。

License

本项目采用区分用户的双重许可 (User-Segmented Dual Licensing) 模式:

- AGPLv3:适用于个人用户及3人及以下企业/组织(开源;详见 <https://www.gnu.org/licenses/agpl-3.0.html>)。
- 商业许可证(必须):适用于超过3人的组织,或任何需要规避 AGPLv3 源代码公开义务(如 SaaS / 闭源分发)的用户。

完整条款见 LICENSE。商业授权请联系 service@nonead.com。

python/URBasic(vendored)仍沿用其自身 MIT 许可(© Anthony Zhuang / Universal Robots,2009-2025)。
预览分享卡片长什么样 ↓NoneadChina/dsh-nonead-ursim
分享 · DeepSeek Harness Hub
NoneadChina/dsh-nonead-ursim

本插件与该公司的 Nonead-Universal-Robots-MCP见「参考实现」一节同源,把「用 AI 控制…

回到顶部