diff --git a/docs/urdf.xml b/docs/urdf.xml
new file mode 100644
index 0000000..88bf427
--- /dev/null
+++ b/docs/urdf.xml
@@ -0,0 +1,309 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/EffortJointInterface
+
+
+ 1
+
+
+
+
+
+ /
+
+
+
\ No newline at end of file
diff --git a/public/robot_kinematics_three_test.html b/public/robot_kinematics_three_test.html
index be32103..8c29ce8 100644
--- a/public/robot_kinematics_three_test.html
+++ b/public/robot_kinematics_three_test.html
@@ -382,9 +382,16 @@
+
+
+
+
+
@@ -507,6 +514,7 @@
wasmStatus: document.getElementById("wasm-status"),
solverStatus: document.getElementById("solver-status"),
robotUuid: document.getElementById("robot-uuid"),
+ urdfFile: document.getElementById("urdf-file"),
jointControls: document.getElementById("joint-controls"),
requestJson: document.getElementById("request-json"),
responseJson: document.getElementById("response-json"),
@@ -521,6 +529,7 @@
jointCountValue: document.getElementById("joint-count-value"),
toast: document.getElementById("toast"),
initBtn: document.getElementById("init-btn"),
+ registerUrdfBtn: document.getElementById("register-urdf-btn"),
resetBtn: document.getElementById("reset-btn"),
fkBtn: document.getElementById("fk-btn"),
ikBtn: document.getElementById("ik-btn"),
@@ -756,6 +765,67 @@
}
}
+ // 读取本地 URDF 文件并注册为当前 robot_uuid。
+ async function registerUrdfFromFile() {
+ await ensureInitialized();
+ const file = elements.urdfFile.files?.[0];
+ const robotUuid = elements.robotUuid.value.trim();
+
+ if (!file) {
+ showToast("请选择 URDF 文件");
+ return;
+ }
+
+ if (!robotUuid) {
+ showToast("请先填写 robot_uuid");
+ return;
+ }
+
+ setBusy(true, "正在注册 URDF");
+ try {
+ const urdfText = await file.text();
+ const request = {
+ msg: "threejs init robot from urdf",
+ req_code: `THREE_INIT_URDF_${Date.now()}`,
+ req_from: "threejs_test",
+ req_cmd: "Cmd_InitRobot",
+ req_param: {
+ robot_uuid: robotUuid,
+ force_update: true,
+ urdf_base64: encodeUtf8Base64(urdfText),
+ },
+ };
+
+ renderJson(request, null);
+ const response = await api.processBusinessRequest(request);
+ renderJson(request, response);
+
+ if (response.success && response.res_data?.success) {
+ state.latestIkJoints = null;
+ elements.applyIkBtn.disabled = true;
+ setStatus("URDF 注册完成", true);
+ await runForwardKinematics();
+ } else {
+ setStatus("URDF 注册失败", false);
+ showToast(response.res_data?.message || response.msg || "URDF 注册失败");
+ }
+ } catch (error) {
+ showError(error);
+ } finally {
+ setBusy(false);
+ }
+ }
+
+ // 将 URDF 文本编码成接口需要的 UTF-8 Base64 字符串。
+ function encodeUtf8Base64(value) {
+ const bytes = new TextEncoder().encode(value);
+ let binary = "";
+ bytes.forEach((byte) => {
+ binary += String.fromCharCode(byte);
+ });
+ return btoa(binary);
+ }
+
// 确保调用算法前已经完成初始化。
async function ensureInitialized() {
if (!state.initialized) {
@@ -1029,6 +1099,7 @@
function setBusy(isBusy, label) {
[
elements.initBtn,
+ elements.registerUrdfBtn,
elements.resetBtn,
elements.fkBtn,
elements.ikBtn,
@@ -1095,6 +1166,7 @@
}
elements.initBtn.addEventListener("click", initializeWasm);
+ elements.registerUrdfBtn.addEventListener("click", registerUrdfFromFile);
elements.resetBtn.addEventListener("click", resetJoints);
elements.fkBtn.addEventListener("click", runForwardKinematics);
elements.ikBtn.addEventListener("click", runInverseKinematics);