Spaces:
Running
Running
Commit ·
44359eb
1
Parent(s): 2043c60
Deploy XoQ examples (OpenArm, Camera, URDF viewer)
Browse files- .gitattributes +1 -0
- README.md +4 -8
- assets/URDFLoader-CL7UVBjw.js +0 -0
- assets/camera-M5W9d3UM.js +1 -0
- assets/connect-DkGLCYAo.js +2 -0
- assets/download_meshes.sh +15 -0
- assets/meshes/.gitignore +3 -0
- assets/openarm-DqhZ0Caw.js +6 -0
- assets/openarm_v10.urdf +836 -0
- assets/publish-IjwDLK4H.js +1 -0
- assets/subscribe-Cz9tf8k2.js +1 -0
- assets/urdf_viewer-trQNEAhR.js +5 -0
- assets/video_player-BJSMA0Bo.js +1 -0
- camera.html +143 -0
- index.html +21 -18
- openarm.html +301 -0
- publish.html +33 -0
- style.css +0 -28
- subscribe.html +31 -0
- urdf/so101/assets/base_motor_holder_so101_v1.stl +3 -0
- urdf/so101/assets/base_so101_v2.stl +3 -0
- urdf/so101/assets/motor_holder_so101_base_v1.stl +3 -0
- urdf/so101/assets/motor_holder_so101_wrist_v1.stl +3 -0
- urdf/so101/assets/moving_jaw_so101_v1.stl +3 -0
- urdf/so101/assets/rotation_pitch_so101_v1.stl +3 -0
- urdf/so101/assets/sts3215_03a_no_horn_v1.stl +3 -0
- urdf/so101/assets/sts3215_03a_v1.stl +3 -0
- urdf/so101/assets/under_arm_so101_v1.stl +3 -0
- urdf/so101/assets/upper_arm_so101_v1.stl +3 -0
- urdf/so101/assets/waveshare_mounting_plate_so101_v2.stl +3 -0
- urdf/so101/assets/wrist_roll_follower_so101_v1.stl +3 -0
- urdf/so101/assets/wrist_roll_pitch_so101_v2.stl +3 -0
- urdf/so101/so101.urdf +411 -0
- urdf_viewer.html +305 -0
- video_player.html +176 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
*.stl filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,12 +1,8 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
-
license: apache-2.0
|
| 9 |
-
short_description: Realtime Open Arm
|
| 10 |
---
|
| 11 |
-
|
| 12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
+
title: OpenArm
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
|
|
|
|
|
assets/URDFLoader-CL7UVBjw.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/camera-M5W9d3UM.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{c as U,f as k}from"./connect-DkGLCYAo.js";const x=new URLSearchParams(location.search),R="https://cdn.1ms.ai",D="anon/camera-0",C=document.getElementById("relayUrl"),L=document.getElementById("path");C.value=x.get("relay")||R;L.value=x.get("path")||D;const a=document.getElementById("video"),S=document.getElementById("log"),h=document.getElementById("startBtn"),b=document.getElementById("stopBtn"),M=document.getElementById("status"),A=document.getElementById("groupCount"),F=document.getElementById("bytesReceived"),T=document.getElementById("bufferLength");let g=null,$=!1,l=null,d=null,p=0,B=0,E=[];function n(t,e="info"){const o=document.createElement("div");o.className=`log-entry log-${e}`,o.textContent=`[${new Date().toLocaleTimeString()}] ${t}`,S.appendChild(o),S.scrollTop=S.scrollHeight,console.log(t)}function V(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(2)} MB`}function w(){if(A.textContent=p,F.textContent=V(B),a.buffered.length>0){const t=a.buffered.end(0)-a.currentTime;T.textContent=`${Math.max(0,t).toFixed(1)}s`}}function f(t){M.textContent=t}function H(){if(E.length>0&&d&&!d.updating){const t=E.shift();try{d.appendBuffer(t)}catch(e){n(`Append error: ${e.message}`,"error")}}}async function P(t){if(!d||d.updating){E.push(t);return}try{d.appendBuffer(t)}catch(e){n(`Append error: ${e.message}`,"error")}}function j(t){const e=new Uint8Array(t),o=r=>r.toString(16).padStart(2,"0").toUpperCase();for(let r=0;r<e.length-11;r++){if(e[r+4]===97&&e[r+5]===118&&e[r+6]===99&&e[r+7]===67){const c=r+8;if(c+4<=e.length)return`avc1.${o(e[c+1])}${o(e[c+2])}${o(e[c+3])}`}if(e[r+4]===97&&e[r+5]===118&&e[r+6]===49&&e[r+7]===67){const c=r+8;if(c+4<=e.length){const u=e[c+1]>>5&7,y=e[c+1]&31,i=e[c+2]>>7&1,s=e[c+2]>>6&1,v=e[c+2]>>5&1,m=s?v?12:10:8,I=String(y).padStart(2,"0");return`av01.${u}.${I}${i?"H":"M"}.${String(m).padStart(2,"0")}`}}}return null}async function N(t){const e=j(t);if(!e)throw n("Could not detect codec from init segment","error"),new Error("No codec detected");const o=`video/mp4; codecs="${e}"`;if(!MediaSource.isTypeSupported(o))throw n(`Codec not supported: ${o}`,"error"),new Error(`Codec not supported: ${o}`);return n(`Detected codec: ${e}`,"success"),new Promise((r,c)=>{l=new MediaSource,a.src=URL.createObjectURL(l),l.addEventListener("sourceopen",()=>{n("MediaSource opened","success"),n(`Using codec: ${o}`,"success"),d=l.addSourceBuffer(o),d.mode="segments",d.addEventListener("updateend",()=>{H(),w(),a.paused&&a.buffered.length>0&&a.play().catch(()=>{})}),d.addEventListener("error",u=>{n(`SourceBuffer error: ${u.type}`,"error"),console.error("SourceBuffer error:",u)}),r()}),l.addEventListener("error",c)})}h.addEventListener("click",async()=>{try{const t=C.value,e=L.value,o=`${t}/${e}`;h.disabled=!0,b.disabled=!1,$=!0,p=0,B=0,E=[],f("Connecting..."),n(`Connecting to ${o}...`),g=await U(new URL(o)),n("Connected!","success"),f("Subscribing...");const c=g.consume(k("")).subscribe("video",0);n("Subscribed to video track","success"),f("Streaming");let u=!1;for(;$;){const y=await c.nextGroup();if(!y){n("Track ended");break}for(;$;){const i=await y.readFrame();if(!i)break;p++,B+=i.byteLength;const s=new Uint8Array(i),v=Array.from(s.slice(0,8)).map(m=>m.toString(16).padStart(2,"0")).join(" ");if(p===1)n(`First segment: ${i.byteLength} bytes [${v}...]`,"data"),s[4]===102&&s[5]===116&&s[6]===121&&s[7]===112?n("Valid ftyp box detected (init segment)","success"):s[4]===109&&s[5]===111&&s[6]===111&&s[7]===102&&n("moof box (media segment without init?)","error");else if(p<=5){const m=String.fromCharCode(s[4],s[5],s[6],s[7]);n(`Segment ${p}: ${i.byteLength} bytes, box=${m}`,"data")}u||(await N(i),u=!0),await P(i),w()}}f("Ended")}catch(t){n(`Error: ${t.message}`,"error"),console.error(t),f("Error")}finally{h.disabled=!1,b.disabled=!0}});b.addEventListener("click",async()=>{$=!1,f("Stopping...");try{await(g==null?void 0:g.close())}catch{}if(g=null,(l==null?void 0:l.readyState)==="open")try{l.endOfStream()}catch{}h.disabled=!1,b.disabled=!0,f("Disconnected"),n("Disconnected","success")});a.addEventListener("error",t=>{const e=a.error;n(`Video error: ${(e==null?void 0:e.message)||"unknown"} (code: ${e==null?void 0:e.code})`,"error")});a.addEventListener("loadedmetadata",()=>{n(`Video metadata loaded: ${a.videoWidth}x${a.videoHeight}`,"success")});a.addEventListener("canplay",()=>{n("Video can play!","success")});setInterval(w,1e3);n("Ready. Enter relay URL and path, then click Connect.","info");(x.has("relay")||x.has("path"))&&(n("Auto-connecting from query params...","info"),h.click());
|
assets/connect-DkGLCYAo.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
var Ha=Object.defineProperty;var vn=i=>{throw TypeError(i)};var za=(i,e,t)=>e in i?Ha(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var o=(i,e,t)=>za(i,typeof e!="symbol"?e+"":e,t),en=(i,e,t)=>e.has(i)||vn("Cannot "+t);var n=(i,e,t)=>(en(i,e,"read from private field"),t?t.call(i):e.get(i)),c=(i,e,t)=>e.has(i)?vn("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(i):e.set(i,t),l=(i,e,t,s)=>(en(i,e,"write to private field"),s?s.call(i,t):e.set(i,t),t),d=(i,e,t)=>(en(i,e,"access private method"),t);var bs=(i,e,t,s)=>({set _(r){l(i,e,r,t)},get _(){return n(i,e,s)}});(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const a of r)if(a.type==="childList")for(const u of a.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&s(u)}).observe(document,{childList:!0,subtree:!0});function t(r){const a={};return r.integrity&&(a.integrity=r.integrity),r.referrerPolicy&&(a.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?a.credentials="include":r.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function s(r){if(r.ep)return;r.ep=!0;const a=t(r);fetch(r.href,a)}})();var kn=Object.prototype.hasOwnProperty;function En(i,e,t){for(t of i.keys())if(qt(t,e))return t}function qt(i,e){var t,s,r;if(i===e)return!0;if(i&&e&&(t=i.constructor)===e.constructor){if(t===Date)return i.getTime()===e.getTime();if(t===RegExp)return i.toString()===e.toString();if(t===Array){if((s=i.length)===e.length)for(;s--&&qt(i[s],e[s]););return s===-1}if(t===Set){if(i.size!==e.size)return!1;for(s of i)if(r=s,r&&typeof r=="object"&&(r=En(e,r),!r)||!e.has(r))return!1;return!0}if(t===Map){if(i.size!==e.size)return!1;for(s of i)if(r=s[0],r&&typeof r=="object"&&(r=En(e,r),!r)||!qt(s[1],e.get(r)))return!1;return!0}if(t===ArrayBuffer)i=new Uint8Array(i),e=new Uint8Array(e);else if(t===DataView){if((s=i.byteLength)===e.byteLength)for(;s--&&i.getInt8(s)===e.getInt8(s););return s===-1}if(ArrayBuffer.isView(i)){if((s=i.byteLength)===e.byteLength)for(;s--&&i[s]===e[s];);return s===-1}if(!t||typeof i=="object"){s=0;for(t in i)if(kn.call(i,t)&&++s&&!kn.call(e,t)||!(t in e)||!qt(i[t],e[t]))return!1;return Object.keys(e).length===s}}return i!==i&&e!==e}const _a={},Xa=typeof _a<"u"&&!1,In=Symbol.for("@moq/signals");var Tn,A,ge,j;Tn=In;const fn=class fn{constructor(e){c(this,A);c(this,ge,new Set);c(this,j,new Set);o(this,Tn,!0);l(this,A,e)}static from(e){return typeof e=="object"&&e!==null&&In in e?e:new fn(e)}get(){return n(this,A)}peek(){return n(this,A)}set(e,t){const s=n(this,A);if(l(this,A,e),t===!1||t===void 0&&s===n(this,A)||n(this,ge).size===0&&n(this,j).size===0)return;const r=n(this,ge),a=n(this,j);l(this,j,new Set),queueMicrotask(()=>{if(t===void 0&&qt(s,n(this,A))){for(const u of a)n(this,j).add(u);return}for(const u of r)try{u(e)}catch(h){console.error("signal subscriber error",h)}for(const u of a)try{u(e)}catch(h){console.error("signal changed error",h)}})}update(e,t=!0){const s=e(n(this,A));this.set(s,t)}mutate(e,t=!0){const s=e(n(this,A));return this.set(n(this,A),t),s}subscribe(e){return n(this,ge).add(e),()=>n(this,ge).delete(e)}changed(e){return n(this,j).add(e),()=>n(this,j).delete(e)}watch(e){const t=this.subscribe(e);return queueMicrotask(()=>e(n(this,A))),t}static async race(...e){const t=[],s=await new Promise(r=>{for(const a of e)t.push(a.changed(r))});for(const r of t)r();return s}};A=new WeakMap,ge=new WeakMap,j=new WeakMap;let E=fn;var un,nt,m,Z,Y,it,at,me,ot,Zt,Yt,ue,ps,Mn;const $t=class $t{constructor(e){c(this,ue);c(this,nt);c(this,m,[]);c(this,Z,[]);c(this,Y,[]);c(this,it);c(this,at,!1);c(this,me);c(this,ot);c(this,Zt);c(this,Yt);l(this,nt,e),l(this,ot,new Promise(t=>{l(this,me,t)})),l(this,Yt,new Promise(t=>{l(this,Zt,t)})),e&&d(this,ue,ps).call(this)}get(e){if(n(this,m)===void 0)return e.peek();const t=e.peek(),s=e.changed(()=>d(this,ue,ps).call(this));return n(this,Z).push(s),t}set(e,t,...s){if(n(this,m)===void 0)return;e.set(t);const r=s[0],a=r===void 0?void 0:r;this.cleanup(()=>e.set(a))}spawn(e){const t=e().catch(s=>{console.error("spawn error",s)});n(this,m)!==void 0&&n(this,Y).push(t)}timer(e,t){if(n(this,m)===void 0)return;let s;s=setTimeout(()=>{s=void 0,e()},t),this.cleanup(()=>s&&clearTimeout(s))}timeout(e,t){if(n(this,m)===void 0)return;const s=new $t(e);let r=setTimeout(()=>{s.close(),r=void 0},t);n(this,m).push(()=>{r&&(clearTimeout(r),s.close())})}animate(e){if(n(this,m)===void 0)return;let t=requestAnimationFrame(s=>{e(s),t=void 0});this.cleanup(()=>{t&&cancelAnimationFrame(t)})}interval(e,t){if(n(this,m)===void 0)return;const s=setInterval(()=>{e()},t);this.cleanup(()=>clearInterval(s))}effect(e){if(n(this,m)===void 0)return;const t=new $t(e);n(this,m).push(()=>t.close())}subscribe(e,t){if(n(this,m)===void 0){t(e.peek());return}this.effect(s=>{const r=s.get(e);t(r)})}event(e,t,s,r){n(this,m)!==void 0&&(e.addEventListener(t,s,r),this.cleanup(()=>e.removeEventListener(t,s,r)))}reload(){d(this,ue,ps).call(this)}cleanup(e){if(n(this,m)===void 0){e();return}n(this,m).push(e)}close(){if(n(this,m)!==void 0){n(this,Zt).call(this),n(this,me).call(this);for(const e of n(this,m))e();l(this,m,void 0);for(const e of n(this,Z))e();n(this,Z).length=0,n(this,Y).length=0}}get closed(){return n(this,Yt)}get cancel(){return n(this,ot)}};un=new WeakMap,nt=new WeakMap,m=new WeakMap,Z=new WeakMap,Y=new WeakMap,it=new WeakMap,at=new WeakMap,me=new WeakMap,ot=new WeakMap,Zt=new WeakMap,Yt=new WeakMap,ue=new WeakSet,ps=function(){n(this,at)||(l(this,at,!0),queueMicrotask(()=>d(this,ue,Mn).call(this).catch(e=>{console.error("effect error",e,n(this,it))})))},Mn=async function(){if(n(this,m)!==void 0){n(this,me).call(this),l(this,ot,new Promise(e=>{l(this,me,e)}));for(const e of n(this,Z))e();n(this,Z).length=0;for(const e of n(this,m))e();if(n(this,m).length=0,n(this,Y).length>0)try{let e;const t=new Promise(s=>{e=setTimeout(()=>{s()},5e3)});await Promise.race([Promise.all(n(this,Y)),t]),e&&clearTimeout(e),n(this,Y).length=0}catch(e){console.error("async effect error",e),n(this,it)&&console.error("stack",n(this,it))}n(this,m)!==void 0&&(l(this,at,!1),n(this,nt)&&n(this,nt).call(this,this))}},c($t,un,new FinalizationRegistry(e=>{console.warn(`Signals was garbage collected without being closed:
|
| 2 |
+
${e}`)}));let xn=$t;function fs(...i){return i.join("/").replace(/\/+/g,"/").replace(/^\/+/,"").replace(/\/+$/,"")}function Ka(i,e){return i===""?!0:e.startsWith(i)?e.length===i.length?!0:e[i.length]==="/":!1}function Sn(i,e){return Ka(i,e)?i===""?e:e.length===i.length?"":e.slice(i.length+1):null}function qn(i,e){return i===""?e:e===""?i:`${i}/${e}`}function ys(){return""}class Ja{constructor(){o(this,"queue",new E([]));o(this,"closed",new E(!1))}}class Dn{constructor(e=ys()){o(this,"state",new Ja);o(this,"prefix");o(this,"closed");this.prefix=e,this.closed=new Promise(t=>{const s=this.state.closed.subscribe(r=>{r&&(t(r instanceof Error?r:void 0),s())})})}append(e){if(this.state.closed.peek())throw new Error("announced is closed");this.state.queue.mutate(t=>{t.push(e)})}close(e){this.state.closed.set(e??!0),this.state.queue.mutate(t=>{t.length=0})}async next(){for(;;){const e=this.state.queue.peek().shift();if(e)return e;const t=this.state.closed.peek();if(t instanceof Error)throw t;if(t)return;await E.race(this.state.queue,this.state.closed)}}}class Qa{constructor(){o(this,"frames",new E([]));o(this,"closed",new E(!1));o(this,"total",new E(0))}}let hn=class{constructor(e){o(this,"sequence");o(this,"state",new Qa);o(this,"closed");this.sequence=e,this.closed=new Promise(t=>{const s=this.state.closed.subscribe(r=>{r&&(t(r instanceof Error?r:void 0),s())})})}writeFrame(e){if(this.state.closed.peek())throw new Error("group is closed");this.state.frames.mutate(t=>{t.push(e)}),this.state.total.update(t=>t+1)}writeString(e){this.writeFrame(new TextEncoder().encode(e))}writeJson(e){this.writeString(JSON.stringify(e))}writeBool(e){this.writeFrame(new Uint8Array([e?1:0]))}async readFrame(){for(;;){const t=this.state.frames.peek().shift();if(t)return t;const s=this.state.closed.peek();if(s instanceof Error)throw s;if(s)return;await E.race(this.state.frames,this.state.closed)}}async readFrameSequence(){for(;;){const e=this.state.frames.peek(),t=e.shift();if(t)return{sequence:this.state.total.peek()-e.length-1,data:t};const s=this.state.closed.peek();if(s instanceof Error)throw s;if(s)return;await E.race(this.state.frames,this.state.closed)}}async readString(){const e=await this.readFrame();return e?new TextDecoder().decode(e):void 0}async readJson(){const e=await this.readString();return e?JSON.parse(e):void 0}async readBool(){const e=await this.readFrame();return e?e[0]===1:void 0}close(e){this.state.closed.set(e??!0)}};class Za{constructor(){o(this,"groups",new E([]));o(this,"closed",new E(!1))}}var ve;class Ya{constructor(e){o(this,"name");o(this,"state",new Za);c(this,ve);o(this,"closed");this.name=e,this.closed=new Promise(t=>{const s=this.state.closed.subscribe(r=>{r&&(t(r instanceof Error?r:void 0),s())})})}appendGroup(){if(this.state.closed.peek())throw new Error("track is closed");const e=new hn(n(this,ve)??0);return l(this,ve,e.sequence+1),this.state.groups.mutate(t=>{t.push(e),t.sort((s,r)=>s.sequence-r.sequence)}),e}writeGroup(e){if(this.state.closed.peek())throw new Error("track is closed");if(e.sequence<(n(this,ve)??0)){e.close();return}l(this,ve,e.sequence+1),this.state.groups.mutate(t=>{t.push(e),t.sort((s,r)=>s.sequence-r.sequence)})}writeFrame(e){const t=this.appendGroup();t.writeFrame(e),t.close()}writeString(e){const t=this.appendGroup();t.writeString(e),t.close()}writeJson(e){const t=this.appendGroup();t.writeJson(e),t.close()}writeBool(e){const t=this.appendGroup();t.writeBool(e),t.close()}async nextGroup(){for(;;){const e=this.state.groups.peek();if(e.length>0)return e.shift();const t=this.state.closed.peek();if(t instanceof Error)throw t;if(t)return;await E.race(this.state.groups,this.state.closed)}}async readFrame(){var e;return(e=await this.readFrameSequence())==null?void 0:e.data}async readFrameSequence(){var e;for(;;){const t=this.state.groups.peek();for(;t.length>1;){const h=t[0].state.frames.peek(),w=h.shift();if(w){const g=t[0].state.total.peek()-h.length-1;return{group:t[0].sequence,frame:g,data:w}}(e=t.shift())==null||e.close()}if(t.length===0){const h=this.state.closed.peek();if(h instanceof Error)throw h;if(h)return;await E.race(this.state.groups,this.state.closed);continue}const s=t[0],r=s.state.frames.peek(),a=r.shift();if(a){const h=s.state.total.peek()-r.length-1;return{group:s.sequence,frame:h,data:a}}const u=this.state.closed.peek();if(u instanceof Error)throw u;if(u)return;await E.race(this.state.groups,this.state.closed,s.state.frames)}}async readString(){const e=await this.readFrame();if(e)return new TextDecoder().decode(e)}async readJson(){const e=await this.readString();if(e)return JSON.parse(e)}async readBool(){const e=await this.readFrame();if(e){if(e.byteLength!==1||!(e[0]===0||e[0]===1))throw new Error("invalid bool frame");return e[0]===1}}close(e){this.state.closed.set(e??!0);for(const t of this.state.groups.peek())t.close(e)}}ve=new WeakMap;class eo{constructor(){o(this,"requested",new E([]));o(this,"closed",new E(!1))}}class Fn{constructor(){o(this,"state",new eo);o(this,"closed");this.closed=new Promise(e=>{const t=this.state.closed.subscribe(s=>{s&&(e(s instanceof Error?s:void 0),t())})})}async requested(){for(;;){const e=this.state.requested.peek().pop();if(e)return e;const t=this.state.closed.peek();if(t instanceof Error)throw t;if(t)return;await E.race(this.state.requested,this.state.closed)}}subscribe(e,t){const s=new Ya(e);if(this.state.closed.peek())throw new Error(`broadcast is closed: ${this.state.closed.peek()}`);return this.state.requested.mutate(r=>{r.push({track:s,priority:t}),r.sort((a,u)=>a.priority-u.priority)}),s}close(e){this.state.closed.set(e??!0);for(const{track:t}of this.state.requested.peek())t.close(e);this.state.requested.mutate(t=>{t.length=0})}}const be=class be{constructor(e){o(this,"value");if(e<0n||e>be.MAX)throw new Error(`VarInt value out of range: ${e}`);this.value=e}static from(e){return new be(BigInt(e))}size(){const e=this.value;if(e<2n**6n)return 1;if(e<2n**14n)return 2;if(e<2n**30n)return 4;if(e<2n**62n)return 8;throw new Error("VarInt value too large")}encode(e){const t=this.value,s=this.size();if(e.byteOffset+e.byteLength+s>e.buffer.byteLength)throw new Error("destination buffer too small");const r=new DataView(e.buffer,e.byteOffset+e.byteLength,s);if(s===1)r.setUint8(0,Number(t));else if(s===2)r.setUint16(0,16384|Number(t),!1);else if(s===4)r.setUint32(0,2<<30|Number(t),!1);else if(s===8)r.setBigUint64(0,3n<<62n|t,!1);else throw new Error("VarInt value too large");return new Uint8Array(e.buffer,e.byteOffset,e.byteLength+s)}static decode(e){if(e.byteLength<1)throw new Error("Unexpected end of buffer");const t=new DataView(e.buffer,e.byteOffset),s=t.getUint8(0),r=s>>6;let a,u;switch(r){case 0:a=BigInt(s&63),u=1;break;case 1:if(2>e.length)throw new Error("Unexpected end of buffer");a=BigInt(t.getUint16(0,!1)&16383),u=2;break;case 2:if(4>e.length)throw new Error("Unexpected end of buffer");a=BigInt(t.getUint32(0,!1)&1073741823),u=4;break;case 3:if(8>e.length)throw new Error("Unexpected end of buffer");a=t.getBigUint64(0,!1)&0x3fffffffffffffffn,u=8;break;default:throw new Error("Invalid VarInt tag")}const h=new Uint8Array(e.buffer,e.byteOffset+u,e.byteLength-u);return[new be(a),h]}};o(be,"MAX",(1n<<62n)-1n),o(be,"MAX_SIZE",8);let $=be;const Q={Bi:0,Uni:1};class qe{constructor(e){o(this,"value");this.value=e}static create(e,t,s){let r=e<<2n;return t===Q.Uni&&(r|=0x02n),s&&(r|=0x01n),new qe($.from(r))}get dir(){return(this.value.value&0x02n)!==0n?Q.Uni:Q.Bi}get serverInitiated(){return(this.value.value&0x01n)!==0n}canRecv(e){return this.dir===Q.Uni?this.serverInitiated!==e:!0}canSend(e){return this.dir===Q.Uni?this.serverInitiated===e:!0}}const Gn=4,jn=5,Wn=8,sn=9,Vn=29;function $n(i){switch(i.type){case"stream":{let e=new Uint8Array(new ArrayBuffer(9+i.data.length),0,1);return e[0]=i.fin?sn:Wn,e=i.id.value.encode(e),e=new Uint8Array(e.buffer,e.byteOffset,e.byteLength+i.data.length),e.set(i.data,e.byteLength-i.data.length),e}case"reset_stream":{let e=new Uint8Array(new ArrayBuffer(17),0,1);return e[0]=Gn,e=i.id.value.encode(e),e=i.code.encode(e),e}case"stop_sending":{let e=new Uint8Array(new ArrayBuffer(17),0,1);return e[0]=jn,e=i.id.value.encode(e),e=i.code.encode(e),e}case"connection_close":{const e=new TextEncoder().encode(i.reason);let t=new Uint8Array(new ArrayBuffer(9+e.length),0,1);return t[0]=Vn,t=i.code.encode(t),t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength+e.length),t.set(e,t.byteLength-e.length),t}}}function to(i){if(i.length===0)throw new Error("Invalid frame: empty buffer");const e=i[0];i=i.slice(1);let t;if(e===Gn){[t,i]=$.decode(i);const s=new qe(t);return[t,i]=$.decode(i),{type:"reset_stream",id:s,code:t}}if(e===jn){[t,i]=$.decode(i);const s=new qe(t);return[t,i]=$.decode(i),{type:"stop_sending",id:s,code:t}}if(e===Vn){[t,i]=$.decode(i);const s=t,r=new TextDecoder().decode(i);return{type:"connection_close",code:s,reason:r}}if(e===Wn||e===sn)return[t,i]=$.decode(i),{type:"stream",id:new qe(t),data:i,fin:e===sn};throw new Error(`Invalid frame type: ${e}`)}class so{constructor(){o(this,"incomingHighWaterMark");o(this,"incomingMaxAge");o(this,"maxDatagramSize");o(this,"outgoingHighWaterMark");o(this,"outgoingMaxAge");o(this,"readable");o(this,"writable");this.incomingHighWaterMark=1024,this.incomingMaxAge=null,this.maxDatagramSize=1200,this.outgoingHighWaterMark=1024,this.outgoingMaxAge=null,this.readable=new ReadableStream({}),this.writable=new WritableStream({})}}var U,ee,N,es,I,L,Ns,Ls,ts,ss,ke,Ee,Rs,Hn,f,zn,_n,Xn,Kn,Jn,Qn,Zn,ye,K,gs;const Ts=class Ts{constructor(e,t){c(this,f);c(this,U);c(this,ee,!1);c(this,N);c(this,es);c(this,I,new Map);c(this,L,new Map);c(this,Ns,0n);c(this,Ls,0n);o(this,"ready");c(this,ts);o(this,"closed");c(this,ss);o(this,"incomingBidirectionalStreams");c(this,ke);o(this,"incomingUnidirectionalStreams");c(this,Ee);o(this,"datagrams",new so);var s;if(t!=null&&t.requireUnreliable)throw new Error("not allowed to use WebSocket; requireUnreliable is true");if(t!=null&&t.serverCertificateHashes&&console.warn("serverCertificateHashes is not supported; trying anyway"),e=d(s=Ts,Rs,Hn).call(s,e),l(this,U,new WebSocket(e,["webtransport"])),this.ready=new Promise(r=>{l(this,ts,r)}),this.closed=new Promise(r=>{l(this,ss,r)}),n(this,U).binaryType="arraybuffer",n(this,U).onopen=()=>n(this,ts).call(this),n(this,U).onmessage=r=>d(this,f,zn).call(this,r),n(this,U).onerror=r=>d(this,f,_n).call(this,r),n(this,U).onclose=r=>d(this,f,Xn).call(this,r),this.incomingBidirectionalStreams=new ReadableStream({start:r=>{l(this,ke,r)}}),this.incomingUnidirectionalStreams=new ReadableStream({start:r=>{l(this,Ee,r)}}),!n(this,ke)||!n(this,Ee))throw new Error("ReadableStream didn't call start")}async createBidirectionalStream(){if(await this.ready,n(this,N))throw n(this,es)||new Error("Connection closed");const e=qe.create(bs(this,Ls)._++,Q.Bi,n(this,ee)),t=new WritableStream({start:r=>{n(this,I).set(e.value.value,r)},write:async r=>{await Promise.race([d(this,f,ye).call(this,{type:"stream",id:e,data:r,fin:!1}),this.closed])},abort:r=>{console.warn("abort",r),d(this,f,K).call(this,{type:"reset_stream",id:e,code:$.from(0)}),n(this,I).delete(e.value.value)},close:async()=>{await Promise.race([d(this,f,ye).call(this,{type:"stream",id:e,data:new Uint8Array,fin:!0}),this.closed]),n(this,I).delete(e.value.value)}});return{readable:new ReadableStream({start:r=>{n(this,L).set(e.value.value,r)},cancel:async()=>{d(this,f,K).call(this,{type:"stop_sending",id:e,code:$.from(0)}),n(this,L).delete(e.value.value)}}),writable:t}}async createUnidirectionalStream(){if(await this.ready,n(this,N))throw n(this,N);const e=qe.create(bs(this,Ns)._++,Q.Uni,n(this,ee)),t=this;return new WritableStream({start:r=>{n(t,I).set(e.value.value,r)},async write(r){var a;await Promise.race([d(a=t,f,ye).call(a,{type:"stream",id:e,data:r,fin:!1}),t.closed])},abort(r){var a;console.warn("abort",r),d(a=t,f,K).call(a,{type:"reset_stream",id:e,code:$.from(0)}),n(t,I).delete(e.value.value)},async close(){var r;await Promise.race([d(r=t,f,ye).call(r,{type:"stream",id:e,data:new Uint8Array,fin:!0}),t.closed]),n(t,I).delete(e.value.value)}})}close(e){if(n(this,N))return;const t=(e==null?void 0:e.closeCode)??0,s=(e==null?void 0:e.reason)??"";d(this,f,K).call(this,{type:"connection_close",code:$.from(t),reason:s}),setTimeout(()=>{n(this,U).close()},100),d(this,f,gs).call(this,t,s)}get congestionControl(){return"default"}};U=new WeakMap,ee=new WeakMap,N=new WeakMap,es=new WeakMap,I=new WeakMap,L=new WeakMap,Ns=new WeakMap,Ls=new WeakMap,ts=new WeakMap,ss=new WeakMap,ke=new WeakMap,Ee=new WeakMap,Rs=new WeakSet,Hn=function(e){const t=typeof e=="string"?new URL(e):e;let s=t.protocol;if(s==="https:")s="wss:";else if(s==="http:")s="ws:";else if(s!=="ws:"&&s!=="wss:")throw new Error(`Unsupported protocol: ${s}`);return`${s}//${t.host}${t.pathname}${t.search}`},f=new WeakSet,zn=function(e){if(!(e.data instanceof ArrayBuffer))return;const t=new Uint8Array(e.data);try{const s=to(t);d(this,f,Kn).call(this,s)}catch(s){console.error("Failed to decode frame:",s),this.close({closeCode:1002,reason:"Protocol violation"})}},_n=function(e){n(this,N)||(l(this,N,new Error(`WebSocket error: ${e.type}`)),d(this,f,gs).call(this,1006,"WebSocket error"))},Xn=function(e){n(this,N)||(l(this,N,new Error(`Connection closed: ${e.code} ${e.reason}`)),d(this,f,gs).call(this,e.code,e.reason))},Kn=function(e){if(e.type==="stream")d(this,f,Jn).call(this,e);else if(e.type==="reset_stream")d(this,f,Qn).call(this,e);else if(e.type==="stop_sending")d(this,f,Zn).call(this,e);else if(e.type==="connection_close")l(this,es,new Error(`Connection closed: ${e.code.value}: ${e.reason}`)),n(this,U).close();else{const t=e;throw new Error(`Unknown frame type: ${t}`)}},Jn=async function(e){const t=e.id.value.value;if(!e.id.canRecv(n(this,ee)))throw new Error("Invalid stream ID direction");let s=n(this,L).get(t);if(!s){if(e.id.serverInitiated===n(this,ee))return;if(!e.id.canRecv(n(this,ee)))throw new Error("received write-only stream");const r=new ReadableStream({start:a=>{s=a,n(this,L).set(t,a)},cancel:()=>{d(this,f,K).call(this,{type:"stop_sending",id:e.id,code:$.from(0)}),n(this,L).delete(t)}});if(!s)throw new Error("ReadableStream didn't call start");if(e.id.dir===Q.Bi){const a=new WritableStream({start:u=>{n(this,I).set(t,u)},write:async u=>{await Promise.race([d(this,f,ye).call(this,{type:"stream",id:e.id,data:u,fin:!1}),this.closed])},abort:u=>{console.warn("abort",u),d(this,f,K).call(this,{type:"reset_stream",id:e.id,code:$.from(0)}),n(this,I).delete(t)},close:async()=>{await Promise.race([d(this,f,ye).call(this,{type:"stream",id:e.id,data:new Uint8Array,fin:!0}),this.closed]),n(this,I).delete(t)}});n(this,ke).enqueue({readable:r,writable:a})}else n(this,Ee).enqueue(r)}e.data.byteLength>0&&s.enqueue(e.data),e.fin&&(s.close(),n(this,L).delete(t))},Qn=function(e){const t=e.id.value.value,s=n(this,L).get(t);s&&(s.error(new Error(`RESET_STREAM: ${e.code.value}`)),n(this,L).delete(t))},Zn=function(e){const t=e.id.value.value,s=n(this,I).get(t);s&&(s.error(new Error(`STOP_SENDING: ${e.code.value}`)),n(this,I).delete(t),d(this,f,K).call(this,{type:"reset_stream",id:e.id,code:e.code}))},ye=async function(e){for(;n(this,U).bufferedAmount>64*1024;)await new Promise(s=>setTimeout(s,10));const t=$n(e);n(this,U).send(t)},K=function(e){const t=$n(e);n(this,U).send(t)},gs=function(e,t){n(this,ss).call(this,{closeCode:e,reason:t});try{n(this,ke).close()}catch{}try{n(this,Ee).close()}catch{}for(const s of n(this,I).values())try{s.error(n(this,N))}catch{}for(const s of n(this,L).values())try{s.error(n(this,N))}catch{}n(this,I).clear(),n(this,L).clear()},c(Ts,Rs);let vs=Ts;const Yn=2**6-1,ei=2**14-1,ti=2**30-1,ro=2**31-1,ln=Number.MAX_SAFE_INTEGER,An=1024*1024*64;let ks=class rn{constructor(e){o(this,"reader");o(this,"writer");this.writer=new Ae(e.writable),this.reader=new Qr(e.readable)}static async accept(e){for(;;){const t=e.incomingBidirectionalStreams.getReader(),s=await t.read();return t.releaseLock(),s.done?void 0:new rn(s.value)}}static async open(e,t){return new rn(await e.createBidirectionalStream({sendOrder:t}))}close(){this.writer.close(),this.reader.stop(new Error("cancel"))}abort(e){this.writer.reset(e),this.reader.stop(e)}};var k,rs,te,v,ms,J,G;class Qr{constructor(e,t){c(this,v);c(this,k);c(this,rs);c(this,te);var s;l(this,k,t??new Uint8Array),l(this,rs,e),l(this,te,(s=n(this,rs))==null?void 0:s.getReader())}async read(e){return e===0?new Uint8Array:(await d(this,v,J).call(this,e),d(this,v,G).call(this,e))}async readAll(){for(;await d(this,v,ms).call(this););return d(this,v,G).call(this,n(this,k).byteLength)}async string(){const e=await this.u53(),t=await this.read(e);return new TextDecoder().decode(t)}async bool(){const e=await this.u8();if(e===0)return!1;if(e===1)return!0;throw new Error("invalid bool value")}async u8(){return await d(this,v,J).call(this,1),d(this,v,G).call(this,1)[0]}async u16(){await d(this,v,J).call(this,2);const t=new DataView(n(this,k).buffer,n(this,k).byteOffset,2).getUint16(0);return d(this,v,G).call(this,2),t}async u53(){const e=await this.u62();if(e>ln)throw new Error("value larger than 53-bits; use v62 instead");return Number(e)}async u62(){await d(this,v,J).call(this,1);const e=(n(this,k)[0]&192)>>6;if(e===0){const r=d(this,v,G).call(this,1)[0];return BigInt(r)&0x3fn}if(e===1){await d(this,v,J).call(this,2);const r=d(this,v,G).call(this,2),a=new DataView(r.buffer,r.byteOffset,r.byteLength);return BigInt(a.getUint16(0))&0x3fffn}if(e===2){await d(this,v,J).call(this,4);const r=d(this,v,G).call(this,4),a=new DataView(r.buffer,r.byteOffset,r.byteLength);return BigInt(a.getUint32(0))&0x3fffffffn}await d(this,v,J).call(this,8);const t=d(this,v,G).call(this,8);return new DataView(t.buffer,t.byteOffset,t.byteLength).getBigUint64(0)&0x3fffffffffffffffn}async done(){return n(this,k).byteLength>0?!1:!await d(this,v,ms).call(this)}stop(e){var t;(t=n(this,te))==null||t.cancel(e).catch(()=>{})}get closed(){var e;return((e=n(this,te))==null?void 0:e.closed)??Promise.resolve()}}k=new WeakMap,rs=new WeakMap,te=new WeakMap,v=new WeakSet,ms=async function(){if(!n(this,te))return!1;const e=await n(this,te).read();if(e.done)return!1;if(e.value.byteLength===0)throw new Error("unexpected empty chunk");const t=new Uint8Array(e.value);if(n(this,k).byteLength===0)l(this,k,t);else{const s=new Uint8Array(n(this,k).byteLength+t.byteLength);s.set(n(this,k)),s.set(t,n(this,k).byteLength),l(this,k,s)}return!0},J=async function(e){if(e>An)throw new Error(`read size ${e} exceeds max size ${An}`);for(;n(this,k).byteLength<e;)if(!await d(this,v,ms).call(this))throw new Error("unexpected end of stream")},G=function(e){const t=new Uint8Array(n(this,k).buffer,n(this,k).byteOffset,e);return l(this,k,new Uint8Array(n(this,k).buffer,n(this,k).byteOffset+e,n(this,k).byteLength-e)),t};var se,ns,D;const yn=class yn{constructor(e){c(this,se);c(this,ns);c(this,D);l(this,ns,e),l(this,D,new ArrayBuffer(8)),l(this,se,n(this,ns).getWriter())}async bool(e){await this.write(Es(n(this,D),e?1:0))}async u8(e){await this.write(Es(n(this,D),e))}async u16(e){await this.write(wn(n(this,D),e))}async i32(e){if(Math.abs(e)>ro)throw new Error(`overflow, value larger than 32-bits: ${e.toString()}`);await this.write(no(n(this,D),e))}async u53(e){if(e<0)throw new Error(`underflow, value is negative: ${e.toString()}`);if(e>ln)throw new Error(`overflow, value larger than 53-bits: ${e.toString()}`);await this.write(io(n(this,D),e))}async u62(e){if(e<0)throw new Error(`underflow, value is negative: ${e.toString()}`);await this.write(ao(n(this,D),e))}async write(e){await n(this,se).write(e)}async string(e){const t=new TextEncoder().encode(e);await this.u53(t.byteLength),await this.write(t)}close(){n(this,se).close().catch(()=>{})}get closed(){return n(this,se).closed}reset(e){n(this,se).abort(e).catch(()=>{})}static async open(e){const t=await e.createUnidirectionalStream();return new yn(t)}};se=new WeakMap,ns=new WeakMap,D=new WeakMap;let Ae=yn;function Es(i,e){const t=new Uint8Array(i,0,1);return t[0]=e,t}function wn(i,e){const t=new DataView(i,0,2);return t.setUint16(0,e),new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}function no(i,e){const t=new DataView(i,0,4);return t.setInt32(0,e),new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}function si(i,e){const t=new DataView(i,0,4);return t.setUint32(0,e),new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}function io(i,e){if(e<=Yn)return Es(i,e);if(e<=ei)return wn(i,e|16384);if(e<=ti)return si(i,e|2147483648);if(e<=ln)return ri(i,BigInt(e)|0xc000000000000000n);throw new Error(`overflow, value larger than 53-bits: ${e.toString()}`)}function ao(i,e){return e<Yn?Es(i,Number(e)):e<ei?wn(i,Number(e)|16384):e<=ti?si(i,Number(e)|2147483648):ri(i,BigInt(e)|0xc000000000000000n)}function ri(i,e){const t=new DataView(i,0,8);return t.setBigUint64(0,e),new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}var ct;class ni{constructor(e){c(this,ct);l(this,ct,e.incomingUnidirectionalStreams.getReader())}async next(){const e=await n(this,ct).read();if(!e.done)return new Qr(e.value)}close(){n(this,ct).cancel()}}ct=new WeakMap;function C(i){return i instanceof Error?i:new Error(String(i))}function oo(i){throw new Error(`unreachable: ${i}`)}const co=new Error("request for lock canceled");var uo=function(i,e,t,s){function r(a){return a instanceof t?a:new t(function(u){u(a)})}return new(t||(t=Promise))(function(a,u){function h(y){try{g(s.next(y))}catch(q){u(q)}}function w(y){try{g(s.throw(y))}catch(q){u(q)}}function g(y){y.done?a(y.value):r(y.value).then(h,w)}g((s=s.apply(i,e||[])).next())})};class ho{constructor(e,t=co){this._value=e,this._cancelError=t,this._queue=[],this._weightedWaiters=[]}acquire(e=1,t=0){if(e<=0)throw new Error(`invalid weight ${e}: must be positive`);return new Promise((s,r)=>{const a={resolve:s,reject:r,weight:e,priority:t},u=ii(this._queue,h=>t<=h.priority);u===-1&&e<=this._value?this._dispatchItem(a):this._queue.splice(u+1,0,a)})}runExclusive(e){return uo(this,arguments,void 0,function*(t,s=1,r=0){const[a,u]=yield this.acquire(s,r);try{return yield t(a)}finally{u()}})}waitForUnlock(e=1,t=0){if(e<=0)throw new Error(`invalid weight ${e}: must be positive`);return this._couldLockImmediately(e,t)?Promise.resolve():new Promise(s=>{this._weightedWaiters[e-1]||(this._weightedWaiters[e-1]=[]),lo(this._weightedWaiters[e-1],{resolve:s,priority:t})})}isLocked(){return this._value<=0}getValue(){return this._value}setValue(e){this._value=e,this._dispatchQueue()}release(e=1){if(e<=0)throw new Error(`invalid weight ${e}: must be positive`);this._value+=e,this._dispatchQueue()}cancel(){this._queue.forEach(e=>e.reject(this._cancelError)),this._queue=[]}_dispatchQueue(){for(this._drainUnlockWaiters();this._queue.length>0&&this._queue[0].weight<=this._value;)this._dispatchItem(this._queue.shift()),this._drainUnlockWaiters()}_dispatchItem(e){const t=this._value;this._value-=e.weight,e.resolve([t,this._newReleaser(e.weight)])}_newReleaser(e){let t=!1;return()=>{t||(t=!0,this.release(e))}}_drainUnlockWaiters(){if(this._queue.length===0)for(let e=this._value;e>0;e--){const t=this._weightedWaiters[e-1];t&&(t.forEach(s=>s.resolve()),this._weightedWaiters[e-1]=[])}else{const e=this._queue[0].priority;for(let t=this._value;t>0;t--){const s=this._weightedWaiters[t-1];if(!s)continue;const r=s.findIndex(a=>a.priority<=e);(r===-1?s:s.splice(0,r)).forEach(a=>a.resolve())}}}_couldLockImmediately(e,t){return(this._queue.length===0||this._queue[0].priority<t)&&e<=this._value}}function lo(i,e){const t=ii(i,s=>e.priority<=s.priority);i.splice(t+1,0,e)}function ii(i,e){for(let t=i.length-1;t>=0;t--)if(e(i[t]))return t;return-1}var wo=function(i,e,t,s){function r(a){return a instanceof t?a:new t(function(u){u(a)})}return new(t||(t=Promise))(function(a,u){function h(y){try{g(s.next(y))}catch(q){u(q)}}function w(y){try{g(s.throw(y))}catch(q){u(q)}}function g(y){y.done?a(y.value):r(y.value).then(h,w)}g((s=s.apply(i,e||[])).next())})};class Un{constructor(e){this._semaphore=new ho(1,e)}acquire(){return wo(this,arguments,void 0,function*(e=0){const[,t]=yield this._semaphore.acquire(1,e);return t})}runExclusive(e,t=0){return this._semaphore.runExclusive(()=>e(),1,t)}isLocked(){return this._semaphore.isLocked()}waitForUnlock(e=0){return this._semaphore.waitForUnlock(1,e)}release(){this._semaphore.isLocked()&&this._semaphore.release()}cancel(){return this._semaphore.cancel()}}async function b(i,e){let t=new Uint8Array;const s=new Ae(new WritableStream({write(r){const a=t.byteLength+r.byteLength;if(a>t.buffer.byteLength){const u=Math.max(a,t.buffer.byteLength*2),h=new ArrayBuffer(u),w=new Uint8Array(h,0,a);w.set(t),w.set(r,t.byteLength),t=w}else t=new Uint8Array(t.buffer,0,a),t.set(r,a-r.byteLength)}}));try{await e(s)}finally{s.close()}if(await s.closed,t.byteLength>65535)throw new Error(`Message too large: ${t.byteLength} bytes (max 65535)`);await i.u16(t.byteLength),await i.write(t)}async function p(i,e){const t=await i.u16(),s=await i.read(t),r=new Qr(void 0,s),a=await e(r);if(!await r.done())throw new Error("Message decoding consumed too few bytes");return a}var Cs,ai,Os,oi;const At=class At{constructor(e,t,s,r,a,u,h,w,g){c(this,Cs);o(this,"requestId");o(this,"trackNamespace");o(this,"trackName");o(this,"subscriberPriority");o(this,"groupOrder");o(this,"startGroup");o(this,"startObject");o(this,"endGroup");o(this,"endObject");this.requestId=e,this.trackNamespace=t,this.trackName=s,this.subscriberPriority=r,this.groupOrder=a,this.startGroup=u,this.startObject=h,this.endGroup=w,this.endObject=g}async encode(e){return b(e,d(this,Cs,ai).bind(this))}static async decode(e){return p(e,d(At,Os,oi))}};Cs=new WeakSet,ai=async function(e){throw new Error("FETCH messages are not supported")},Os=new WeakSet,oi=async function(e){throw new Error("FETCH messages are not supported")},c(At,Os),o(At,"id",22);let Ot=At;var Bs,ci,Ms,di;const Ut=class Ut{constructor(e){c(this,Bs);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,Bs,ci).bind(this))}static async decode(e){return p(e,d(Ut,Ms,di))}};Bs=new WeakSet,ci=async function(e){throw new Error("FETCH_OK messages are not supported")},Ms=new WeakSet,di=async function(e){throw new Error("FETCH_OK messages are not supported")},c(Ut,Ms),o(Ut,"id",24);let Bt=Ut;var Ds,ui,Fs,hi;const Pt=class Pt{constructor(e,t,s){c(this,Ds);o(this,"requestId");o(this,"errorCode");o(this,"reasonPhrase");this.requestId=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,Ds,ui).bind(this))}static async decode(e){return p(e,d(Pt,Fs,hi))}};Ds=new WeakSet,ui=async function(e){throw new Error("FETCH_ERROR messages are not supported")},Fs=new WeakSet,hi=async function(e){throw new Error("FETCH_ERROR messages are not supported")},c(Pt,Fs),o(Pt,"id",25);let Mt=Pt;var Gs,li,js,wi;const Nt=class Nt{constructor(e){c(this,Gs);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,Gs,li).bind(this))}static async decode(e){return p(e,d(Nt,js,wi))}};Gs=new WeakSet,li=async function(e){throw new Error("FETCH_CANCEL messages are not supported")},js=new WeakSet,wi=async function(e){throw new Error("FETCH_CANCEL messages are not supported")},c(Nt,js),o(Nt,"id",23);let Dt=Nt;var Ws,fi,Vs,yi;const Le=class Le{constructor(e){c(this,Ws);o(this,"newSessionUri");this.newSessionUri=e}async encode(e){return b(e,d(this,Ws,fi).bind(this))}static async decode(e){return p(e,d(Le,Vs,yi))}};Ws=new WeakSet,fi=async function(e){await e.string(this.newSessionUri)},Vs=new WeakSet,yi=async function(e){const t=await e.string();return new Le(t)},c(Le,Vs),o(Le,"id",16);let Ft=Le;async function le(i,e){const t=e.split("/");await i.u53(t.length);for(const s of t)await i.string(s)}async function we(i){const e=[],t=await i.u53();for(let s=0;s<t;s++)e.push(await i.string());return fs(...e)}const tn={MaxRequestId:2n,Implementation:7n};class O{constructor(){o(this,"vars");o(this,"bytes");this.vars=new Map,this.bytes=new Map}get size(){return this.vars.size+this.bytes.size}setBytes(e,t){if(e%2n!==1n)throw new Error(`invalid parameter id: ${e.toString()}, must be odd`);this.bytes.set(e,t)}setVarint(e,t){if(e%2n!==0n)throw new Error(`invalid parameter id: ${e.toString()}, must be even`);this.vars.set(e,t)}getBytes(e){if(e%2n!==1n)throw new Error(`invalid parameter id: ${e.toString()}, must be odd`);return this.bytes.get(e)}getVarint(e){if(e%2n!==0n)throw new Error(`invalid parameter id: ${e.toString()}, must be even`);return this.vars.get(e)}removeBytes(e){if(e%2n!==1n)throw new Error(`invalid parameter id: ${e.toString()}, must be odd`);return this.bytes.delete(e)}removeVarint(e){if(e%2n!==0n)throw new Error(`invalid parameter id: ${e.toString()}, must be even`);return this.vars.delete(e)}async encode(e){await e.u53(this.vars.size+this.bytes.size);for(const[t,s]of this.vars)await e.u62(t),await e.u62(s);for(const[t,s]of this.bytes)await e.u62(t),await e.u53(s.length),await e.write(s)}static async decode(e){const t=await e.u53(),s=new O;for(let r=0;r<t;r++){const a=await e.u62();if(a%2n===0n){if(s.vars.has(a))throw new Error(`duplicate parameter id: ${a.toString()}`);const u=await e.u62();s.setVarint(a,u)}else{if(s.bytes.has(a))throw new Error(`duplicate parameter id: ${a.toString()}`);const u=await e.u53(),h=await e.read(u);s.setBytes(a,h)}}return s}}var Hs,bi,zs,pi;const Re=class Re{constructor(e,t,s,r,a,u,h,w){c(this,Hs);o(this,"requestId");o(this,"trackNamespace");o(this,"trackName");o(this,"trackAlias");o(this,"groupOrder");o(this,"contentExists");o(this,"largest");o(this,"forward");this.requestId=e,this.trackNamespace=t,this.trackName=s,this.trackAlias=r,this.groupOrder=a,this.contentExists=u,this.largest=h,this.forward=w}async encode(e){return b(e,d(this,Hs,bi).bind(this))}static async decode(e){return p(e,d(Re,zs,pi))}};Hs=new WeakSet,bi=async function(e){if(await e.u62(this.requestId),await le(e,this.trackNamespace),await e.string(this.trackName),await e.u62(this.trackAlias),await e.u8(this.groupOrder),await e.bool(this.contentExists),this.contentExists!==!!this.largest)throw new Error("contentExists and largest must both be true or false");this.largest&&(await e.u62(this.largest.groupId),await e.u62(this.largest.objectId)),await e.bool(this.forward),await e.u53(0)},zs=new WeakSet,pi=async function(e){const t=await e.u62(),s=await we(e),r=await e.string(),a=await e.u62(),u=await e.u8(),h=await e.bool(),w=h?{groupId:await e.u62(),objectId:await e.u62()}:void 0,g=await e.bool();return await O.decode(e),new Re(t,s,r,a,u,h,w,g)},c(Re,zs),o(Re,"id",29);let Gt=Re;var _s,gi,Xs,mi;const Lt=class Lt{constructor(){c(this,_s)}async encode(e){return b(e,d(this,_s,gi).bind(this))}static async decode(e){return p(e,d(Lt,Xs,mi))}};_s=new WeakSet,gi=async function(e){throw new Error("PUBLISH_OK messages are not supported")},Xs=new WeakSet,mi=async function(e){throw new Error("PUBLISH_OK messages are not supported")},c(Lt,Xs),o(Lt,"id",30);let jt=Lt;var Ks,vi,Js,ki;const Te=class Te{constructor(e,t,s){c(this,Ks);o(this,"requestId");o(this,"errorCode");o(this,"reasonPhrase");this.requestId=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,Ks,vi).bind(this))}static async decode(e){return p(e,d(Te,Js,ki))}};Ks=new WeakSet,vi=async function(e){await e.u62(this.requestId),await e.u62(BigInt(this.errorCode)),await e.string(this.reasonPhrase)},Js=new WeakSet,ki=async function(e){const t=await e.u62(),s=Number(await e.u62()),r=await e.string();return new Te(t,s,r)},c(Te,Js),o(Te,"id",31);let ft=Te;var Qs,Ei,Zs,Ii;const Ce=class Ce{constructor(e,t,s){c(this,Qs);o(this,"requestId");o(this,"statusCode");o(this,"reasonPhrase");this.requestId=e,this.statusCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,Qs,Ei).bind(this))}static async decode(e){return p(e,d(Ce,Zs,Ii))}};Qs=new WeakSet,Ei=async function(e){await e.u62(this.requestId),await e.u62(BigInt(this.statusCode)),await e.u62(BigInt(0)),await e.string(this.reasonPhrase)},Zs=new WeakSet,Ii=async function(e){const t=await e.u62(),s=Number(await e.u62());await e.u62();const r=await e.string();return new Ce(t,s,r)},c(Ce,Zs),o(Ce,"id",11);let Ue=Ce;var Ys,xi,er,Si;const Oe=class Oe{constructor(e,t){c(this,Ys);o(this,"requestId");o(this,"trackNamespace");this.requestId=e,this.trackNamespace=t}async encode(e){return b(e,d(this,Ys,xi).bind(this))}static async decode(e){return p(e,d(Oe,er,Si))}};Ys=new WeakSet,xi=async function(e){await e.u62(this.requestId),await le(e,this.trackNamespace),await e.u53(0)},er=new WeakSet,Si=async function(e){const t=await e.u62(),s=await we(e);return await O.decode(e),new Oe(t,s)},c(Oe,er),o(Oe,"id",6);let yt=Oe;var tr,qi,sr,$i;const Be=class Be{constructor(e){c(this,tr);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,tr,qi).bind(this))}static async decode(e){return p(e,d(Be,sr,$i))}};tr=new WeakSet,qi=async function(e){await e.u62(this.requestId)},sr=new WeakSet,$i=async function(e){const t=await e.u62();return new Be(t)},c(Be,sr),o(Be,"id",7);let Wt=Be;var rr,Ai,nr,Ui;const Me=class Me{constructor(e,t,s){c(this,rr);o(this,"requestId");o(this,"errorCode");o(this,"reasonPhrase");this.requestId=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,rr,Ai).bind(this))}static async decode(e){return p(e,d(Me,nr,Ui))}};rr=new WeakSet,Ai=async function(e){await e.u62(this.requestId),await e.u62(BigInt(this.errorCode)),await e.string(this.reasonPhrase)},nr=new WeakSet,Ui=async function(e){const t=await e.u62(),s=Number(await e.u62()),r=await e.string();return new Me(t,s,r)},c(Me,nr),o(Me,"id",8);let Vt=Me;var ir,Pi,ar,Ni;const De=class De{constructor(e,t=0,s=""){c(this,ir);o(this,"trackNamespace");o(this,"errorCode");o(this,"reasonPhrase");this.trackNamespace=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,ir,Pi).bind(this))}static async decode(e){return p(e,d(De,ar,Ni))}};ir=new WeakSet,Pi=async function(e){await le(e,this.trackNamespace),await e.u62(BigInt(this.errorCode)),await e.string(this.reasonPhrase)},ar=new WeakSet,Ni=async function(e){const t=await we(e),s=Number(await e.u62()),r=await e.string();return new De(t,s,r)},c(De,ar),o(De,"id",12);let Ht=De;var or,Li,cr,Ri;const Fe=class Fe{constructor(e){c(this,or);o(this,"trackNamespace");this.trackNamespace=e}async encode(e){return b(e,d(this,or,Li).bind(this))}static async decode(e){return p(e,d(Fe,cr,Ri))}};or=new WeakSet,Li=async function(e){await le(e,this.trackNamespace)},cr=new WeakSet,Ri=async function(e){const t=await we(e);return new Fe(t)},c(Fe,cr),o(Fe,"id",9);let bt=Fe;var dr,Ti,ur,Ci;const Ge=class Ge{constructor(e){c(this,dr);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,dr,Ti).bind(this))}static async decode(e){return p(e,d(Ge,ur,Ci))}};dr=new WeakSet,Ti=async function(e){await e.u62(this.requestId)},ur=new WeakSet,Ci=async function(e){return new Ge(await e.u62())},c(Ge,ur),o(Ge,"id",21);let zt=Ge;var hr,Oi,lr,Bi;const je=class je{constructor(e){c(this,hr);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,hr,Oi).bind(this))}static async decode(e){return p(e,d(je,lr,Bi))}};hr=new WeakSet,Oi=async function(e){await e.u62(this.requestId)},lr=new WeakSet,Bi=async function(e){return new je(await e.u62())},c(je,lr),o(je,"id",26);let _t=je;const fo=128;var wr,Mi,fr,Di;const We=class We{constructor(e,t=new O){c(this,wr);o(this,"versions");o(this,"parameters");this.versions=e,this.parameters=t}async encode(e){return b(e,d(this,wr,Mi).bind(this))}static async decode(e){return p(e,d(We,fr,Di))}};wr=new WeakSet,Mi=async function(e){await e.u53(this.versions.length);for(const t of this.versions)await e.u53(t);await this.parameters.encode(e)},fr=new WeakSet,Di=async function(e){const t=await e.u53();if(t>fo)throw new Error(`too many versions: ${t}`);const s=[];for(let a=0;a<t;a++){const u=await e.u53();s.push(u)}const r=await O.decode(e);return new We(s,r)},c(We,fr),o(We,"id",32);let pt=We;var yr,Fi,br,Gi;const Ve=class Ve{constructor(e,t=new O){c(this,yr);o(this,"version");o(this,"parameters");this.version=e,this.parameters=t}async encode(e){return b(e,d(this,yr,Fi).bind(this))}static async decode(e){return p(e,d(Ve,br,Gi))}};yr=new WeakSet,Fi=async function(e){await e.u53(this.version),await this.parameters.encode(e)},br=new WeakSet,Gi=async function(e){const t=await e.u53(),s=await O.decode(e);return new Ve(t,s)},c(Ve,br),o(Ve,"id",33);let gt=Ve;const ji=2;var z,pr,Wi,gr,Vi;let Is=(z=class{constructor(e,t,s,r){c(this,pr);o(this,"requestId");o(this,"trackNamespace");o(this,"trackName");o(this,"subscriberPriority");this.requestId=e,this.trackNamespace=t,this.trackName=s,this.subscriberPriority=r}async encode(e){return b(e,d(this,pr,Wi).bind(this))}static async decode(e){return p(e,d(z,gr,Vi))}},pr=new WeakSet,Wi=async function(e){await e.u62(this.requestId),await le(e,this.trackNamespace),await e.string(this.trackName),await e.u8(this.subscriberPriority),await e.u8(ji),await e.bool(!0),await e.u53(2),await e.u53(0)},gr=new WeakSet,Vi=async function(e){const t=await e.u62(),s=await we(e),r=await e.string(),a=await e.u8(),u=await e.u8();if(u>2)throw new Error(`unknown group order: ${u}`);const h=await e.bool();if(!h)throw new Error(`unsupported forward value: ${h}`);const w=await e.u53();if(w!==1&&w!==2)throw new Error(`unsupported filter type: ${w}`);return await O.decode(e),new z(t,s,r,a)},c(z,gr),o(z,"id",3),z);var _,mr,Hi,vr,zi;let xs=(_=class{constructor(e,t){c(this,mr);o(this,"requestId");o(this,"trackAlias");this.requestId=e,this.trackAlias=t}async encode(e){return b(e,d(this,mr,Hi).bind(this))}static async decode(e){return p(e,d(_,vr,zi))}},mr=new WeakSet,Hi=async function(e){await e.u62(this.requestId),await e.u62(this.trackAlias),await e.u62(0n),await e.u8(ji),await e.bool(!1),await e.u53(0)},vr=new WeakSet,zi=async function(e){const t=await e.u62(),s=await e.u62(),r=await e.u62();if(r!==BigInt(0))throw new Error(`unsupported expires: ${r}`);return await e.u8(),await e.bool()&&(await e.u62(),await e.u62()),await O.decode(e),new _(t,s)},c(_,vr),o(_,"id",4),_);var kr,_i,Er,Xi;const He=class He{constructor(e,t,s){c(this,kr);o(this,"requestId");o(this,"errorCode");o(this,"reasonPhrase");this.requestId=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,kr,_i).bind(this))}static async decode(e){return p(e,d(He,Er,Xi))}};kr=new WeakSet,_i=async function(e){await e.u62(this.requestId),await e.u62(BigInt(this.errorCode)),await e.string(this.reasonPhrase)},Er=new WeakSet,Xi=async function(e){const t=await e.u62(),s=Number(await e.u62()),r=await e.string();return new He(t,s,r)},c(He,Er),o(He,"id",5);let mt=He;var Ir,Ki,xr,Ji;const ze=class ze{constructor(e){c(this,Ir);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,Ir,Ki).bind(this))}static async decode(e){return p(e,d(ze,xr,Ji))}};Ir=new WeakSet,Ki=async function(e){await e.u62(this.requestId)},xr=new WeakSet,Ji=async function(e){const t=await e.u62();return new ze(t)},c(ze,xr),o(ze,"id",10);let vt=ze;var Sr,Qi,qr,Zi;const _e=class _e{constructor(e,t){c(this,Sr);o(this,"namespace");o(this,"requestId");this.namespace=e,this.requestId=t}async encode(e){return b(e,d(this,Sr,Qi).bind(this))}static async decode(e){return p(e,d(_e,qr,Zi))}};Sr=new WeakSet,Qi=async function(e){await e.u62(this.requestId),await le(e,this.namespace),await e.u53(0)},qr=new WeakSet,Zi=async function(e){const t=await e.u62(),s=await we(e);return await O.decode(e),new _e(s,t)},c(_e,qr),o(_e,"id",17);let kt=_e;var $r,Yi,Ar,ea;const Xe=class Xe{constructor(e){c(this,$r);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,$r,Yi).bind(this))}static async decode(e){return p(e,d(Xe,Ar,ea))}};$r=new WeakSet,Yi=async function(e){await e.u62(this.requestId)},Ar=new WeakSet,ea=async function(e){const t=await e.u62();return new Xe(t)},c(Xe,Ar),o(Xe,"id",18);let Xt=Xe;var Ur,ta,Pr,sa;const Ke=class Ke{constructor(e,t,s){c(this,Ur);o(this,"requestId");o(this,"errorCode");o(this,"reasonPhrase");this.requestId=e,this.errorCode=t,this.reasonPhrase=s}async encode(e){return b(e,d(this,Ur,ta).bind(this))}static async decode(e){return p(e,d(Ke,Pr,sa))}};Ur=new WeakSet,ta=async function(e){await e.u62(this.requestId),await e.u62(BigInt(this.errorCode)),await e.string(this.reasonPhrase)},Pr=new WeakSet,sa=async function(e){const t=await e.u62(),s=Number(await e.u62()),r=await e.string();return new Ke(t,s,r)},c(Ke,Pr),o(Ke,"id",19);let Kt=Ke;var Nr,ra,Lr,na;const Je=class Je{constructor(e){c(this,Nr);o(this,"requestId");this.requestId=e}async encode(e){return b(e,d(this,Nr,ra).bind(this))}static async decode(e){return p(e,d(Je,Lr,na))}};Nr=new WeakSet,ra=async function(e){await e.u62(this.requestId)},Lr=new WeakSet,na=async function(e){const t=await e.u62();return new Je(t)},c(Je,Lr),o(Je,"id",20);let Et=Je;var Rr,ia,Tr,aa;const Qe=class Qe{constructor(e,t){c(this,Rr);o(this,"trackNamespace");o(this,"trackName");this.trackNamespace=e,this.trackName=t}async encode(e){return b(e,d(this,Rr,ia).bind(this))}static async decode(e){return p(e,d(Qe,Tr,aa))}};Rr=new WeakSet,ia=async function(e){await le(e,this.trackNamespace),await e.string(this.trackName)},Tr=new WeakSet,aa=async function(e){const t=await we(e),s=await e.string();return new Qe(t,s)},c(Qe,Tr),o(Qe,"id",13);let Jt=Qe;var Cr,oa,Or,ca;const M=class M{constructor(e,t,s,r,a){c(this,Cr);o(this,"trackNamespace");o(this,"trackName");o(this,"statusCode");o(this,"lastGroupId");o(this,"lastObjectId");this.trackNamespace=e,this.trackName=t,this.statusCode=s,this.lastGroupId=r,this.lastObjectId=a}async encode(e){return b(e,d(this,Cr,oa).bind(this))}static async decode(e){return p(e,d(M,Or,ca))}};Cr=new WeakSet,oa=async function(e){await le(e,this.trackNamespace),await e.string(this.trackName),await e.u62(BigInt(this.statusCode)),await e.u62(this.lastGroupId),await e.u62(this.lastObjectId)},Or=new WeakSet,ca=async function(e){const t=await we(e),s=await e.string(),r=Number(await e.u62()),a=await e.u62(),u=await e.u62();return new M(t,s,r,a,u)},c(M,Or),o(M,"id",14),o(M,"STATUS_IN_PROGRESS",0),o(M,"STATUS_NOT_FOUND",1),o(M,"STATUS_NOT_AUTHORIZED",2),o(M,"STATUS_ENDED",3);let Pe=M;const Pn={[pt.id]:pt,[gt.id]:gt,[Is.id]:Is,[xs.id]:xs,[mt.id]:mt,[yt.id]:yt,[Wt.id]:Wt,[Vt.id]:Vt,[bt.id]:bt,[vt.id]:vt,[Ue.id]:Ue,[Ht.id]:Ht,[Jt.id]:Jt,[Pe.id]:Pe,[Ft.id]:Ft,[Ot.id]:Ot,[Dt.id]:Dt,[Bt.id]:Bt,[Mt.id]:Mt,[kt.id]:kt,[Xt.id]:Xt,[Kt.id]:Kt,[Et.id]:Et,[Gt.id]:Gt,[jt.id]:jt,[ft.id]:ft,[zt.id]:zt,[_t.id]:_t};var is,re,ne,Ie,Br,Mr;class yo{constructor(e,t){o(this,"stream");c(this,is,0n);c(this,re);c(this,ne);c(this,Ie);c(this,Br,new Un);c(this,Mr,new Un);this.stream=e,l(this,re,t),l(this,ne,new Promise(s=>{l(this,Ie,s)}))}async write(e){console.debug("message write",e),await n(this,Br).runExclusive(async()=>{await this.stream.writer.u53(e.constructor.id),await e.encode(this.stream.writer)})}async read(){return await n(this,Mr).runExclusive(async()=>{const e=await this.stream.reader.u53();if(!(e in Pn))throw new Error(`Unknown control message type: ${e}`);try{const t=await Pn[e].decode(this.stream.reader);return console.debug("message read",t),t}catch(t){throw console.error("failed to decode message",e,t),t}})}maxRequestId(e){if(e<=n(this,re))throw new Error(`max request id must be greater than current max request id: max=${e} current=${n(this,re)}`);l(this,re,e),n(this,Ie).call(this),l(this,ne,new Promise(t=>{l(this,Ie,t)}))}async nextRequestId(){for(;;){const e=n(this,is);if(e<n(this,re))return l(this,is,n(this,is)+2n),e;if(!n(this,ne))return;console.warn("blocked on max request id"),await n(this,ne)}}close(){n(this,Ie).call(this),l(this,ne,void 0)}}is=new WeakMap,re=new WeakMap,ne=new WeakMap,Ie=new WeakMap,Br=new WeakMap,Mr=new WeakMap;const Nn=3;let da=class ua{constructor(e,t,s,r,a){o(this,"flags");o(this,"trackAlias");o(this,"groupId");o(this,"subGroupId");o(this,"publisherPriority");this.flags=a,this.trackAlias=e,this.groupId=t,this.subGroupId=s,this.publisherPriority=r}async encode(e){if(!this.flags.hasSubgroup&&this.subGroupId!==0)throw new Error(`Subgroup ID must be 0 if hasSubgroup is false: ${this.subGroupId}`);let t=16;this.flags.hasExtensions&&(t|=1),this.flags.hasSubgroupObject&&(t|=2),this.flags.hasSubgroup&&(t|=4),this.flags.hasEnd&&(t|=8),await e.u53(t),await e.u62(this.trackAlias),await e.u53(this.groupId),this.flags.hasSubgroup&&await e.u53(this.subGroupId),await e.u8(0)}static async decode(e){const t=await e.u53();if(t<16||t>31)throw new Error(`Unsupported group type: ${t}`);const s={hasExtensions:(t&1)!==0,hasSubgroupObject:(t&2)!==0,hasSubgroup:(t&4)!==0,hasEnd:(t&8)!==0},r=await e.u62(),a=await e.u53(),u=s.hasSubgroup?await e.u53():0,h=await e.u8();return new ua(r,a,u,h,s)}};class rt{constructor(e){o(this,"payload");this.payload=e}async encode(e,t){await e.u53(0),t.hasExtensions&&await e.u53(0),this.payload!==void 0?(await e.u53(this.payload.byteLength),this.payload.byteLength===0?await e.u53(0):await e.write(this.payload)):(await e.u53(0),await e.u53(Nn))}static async decode(e,t){const s=await e.u53();if(s!==0&&console.warn(`object ID delta is not supported, ignoring: ${s}`),t.hasExtensions){const u=await e.u53();await e.read(u)}const r=await e.u53();if(r>0){const u=await e.read(r);return new rt(u)}const a=await e.u53();if(t.hasEnd){if(a===0)return new rt(new Uint8Array(0))}else if(a===0||a===Nn)return new rt;throw new Error(`Unsupported object status: ${a}`)}}var as,T,dt,he,ha,la,wa,Cn;let bo=(Cn=class{constructor(e,t){c(this,he);c(this,as);c(this,T);c(this,dt,new Map);l(this,as,e),l(this,T,t)}publish(e,t){n(this,dt).set(e,t),d(this,he,ha).call(this,e,t)}async handleSubscribe(e){const t=e.trackNamespace,s=n(this,dt).get(t);if(!s){const u=new mt(e.requestId,404,"Broadcast not found");await n(this,T).write(u);return}const r=s.subscribe(e.trackName,e.subscriberPriority),a=new xs(e.requestId,e.requestId);await n(this,T).write(a),console.debug(`publish ok: broadcast=${t} track=${r.name}`),d(this,he,la).call(this,e.requestId,t,r)}async handleTrackStatusRequest(e){const t=new Pe(e.trackNamespace,e.trackName,Pe.STATUS_NOT_FOUND,0n,0n);await n(this,T).write(t)}async handleUnsubscribe(e){}async handlePublishNamespaceOk(e){}async handlePublishNamespaceError(e){}async handlePublishNamespaceCancel(e){}async handleSubscribeNamespace(e){}async handleUnsubscribeNamespace(e){}},as=new WeakMap,T=new WeakMap,dt=new WeakMap,he=new WeakSet,ha=async function(e,t){try{const s=await n(this,T).nextRequestId();if(s===void 0)return;const r=new yt(s,e);await n(this,T).write(r),await t.closed;const a=new bt(e);await n(this,T).write(a)}catch(s){const r=C(s);console.warn(`announce failed: broadcast=${e} error=${r.message}`)}finally{t.close(),n(this,dt).delete(e)}},la=async function(e,t,s){try{for(;;){const a=await s.nextGroup();if(!a)break;d(this,he,wa).call(this,e,a)}console.debug(`publish done: broadcast=${t} track=${s.name}`);const r=new Ue(e,200,"OK");await n(this,T).write(r)}catch(r){const a=C(r);console.warn(`publish error: broadcast=${t} track=${s.name} error=${a.message}`);const u=new Ue(e,500,a.message);await n(this,T).write(u)}finally{s.close()}},wa=async function(e,t){try{const s=await Ae.open(n(this,as)),r=new da(e,t.sequence,0,0,{hasExtensions:!1,hasSubgroup:!1,hasSubgroupObject:!1,hasEnd:!0});console.debug("sending group header",r),await r.encode(s);try{for(;;){const a=await Promise.race([t.readFrame(),s.closed]);if(!a)break;await new rt(a).encode(s,r.flags)}s.close()}catch(a){s.reset(C(a))}}finally{t.close()}},Cn);var B,ie,xe,ut,Se,ae,It,fa,ya,On;let po=(On=class{constructor(e){c(this,It);c(this,B);c(this,ie,new Set);c(this,xe,new Set);c(this,ut,new Map);c(this,Se,new Map);c(this,ae,new Map);l(this,B,e)}announced(e=ys()){const t=new Dn(e);for(const s of n(this,ie))s.startsWith(e)&&t.append({path:s,active:!0});return n(this,xe).add(t),d(this,It,fa).call(this,t,e).finally(()=>{n(this,xe).delete(t)}),t}consume(e){const t=new Fn;return(async()=>{for(;;){const s=await t.requested();if(!s)break;d(this,It,ya).call(this,e,s)}})(),t}async handleSubscribeOk(e){const t=n(this,ae).get(e.requestId);t?t.resolve(e):console.warn("handleSubscribeOk unknown requestId",e.requestId)}async handleSubscribeError(e){const t=n(this,ae).get(e.requestId);t?t.reject(new Error(`SUBSCRIBE_ERROR: code=${e.errorCode} reason=${e.reasonPhrase}`)):console.warn("handleSubscribeError unknown requestId",e.requestId)}async handleGroup(e,t){const s=new hn(e.groupId);e.subGroupId!==0&&console.warn("subgroup ID is not supported, ignoring");try{let r=n(this,Se).get(e.trackAlias);r===void 0&&(r=e.trackAlias,console.warn("unknown track alias, using request ID"));const a=n(this,ut).get(r);if(!a)throw new Error(`unknown track: trackAlias=${e.trackAlias} requestId=${n(this,Se).get(e.trackAlias)}`);for(a.writeGroup(s);await Promise.race([t.done(),s.closed,a.closed])===!1;){const h=await rt.decode(t,e.flags);if(h.payload===void 0)break;s.writeFrame(h.payload)}s.close()}catch(r){const a=C(r);s.close(a),t.stop(a)}}async handlePublish(e){const t=new ft(e.requestId,500,"publish not supported");await n(this,B).write(t)}async handlePublishDone(e){const t=n(this,ae).get(e.requestId);t&&t.reject(new Error(`PUBLISH_DONE: code=${e.statusCode} reason=${e.reasonPhrase}`))}async handlePublishNamespace(e){if(n(this,ie).has(e.trackNamespace)){console.warn("duplicate PUBLISH_NAMESPACE message");return}n(this,ie).add(e.trackNamespace),console.debug(`announced: broadcast=${e.trackNamespace} active=true`);for(const t of n(this,xe))t.append({path:e.trackNamespace,active:!0})}async handlePublishNamespaceDone(e){if(!n(this,ie).has(e.trackNamespace)){console.warn("unknown PUBLISH_NAMESPACE_DONE message");return}n(this,ie).delete(e.trackNamespace),console.debug(`announced: broadcast=${e.trackNamespace} active=false`);for(const t of n(this,xe))t.append({path:e.trackNamespace,active:!1})}async handleSubscribeNamespaceOk(e){}async handleSubscribeNamespaceError(e){throw new Error("SUBSCRIBE_NAMESPACE_ERROR messages are not supported")}async handleTrackStatus(e){throw new Error("TRACK_STATUS messages are not supported")}},B=new WeakMap,ie=new WeakMap,xe=new WeakMap,ut=new WeakMap,Se=new WeakMap,ae=new WeakMap,It=new WeakSet,fa=async function(e,t){const s=await n(this,B).nextRequestId();if(s!==void 0)try{n(this,B).write(new kt(t,s)),await e.closed}finally{n(this,B).write(new Et(s))}},ya=async function(e,t){const s=await n(this,B).nextRequestId();if(s===void 0)return;n(this,ut).set(s,t.track),console.debug(`subscribe start: id=${s} broadcast=${e} track=${t.track.name}`);const r=new Is(s,e,t.track.name,t.priority),a=new Promise((u,h)=>{n(this,ae).set(s,{resolve:u,reject:h})});await n(this,B).write(r);try{const u=await a;n(this,Se).set(u.trackAlias,s),console.debug(`subscribe ok: id=${s} broadcast=${e} track=${t.track.name}`);try{await t.track.closed;const h=new vt(s);await n(this,B).write(h),console.debug(`unsubscribe: id=${s} broadcast=${e} track=${t.track.name}`)}finally{n(this,Se).delete(u.trackAlias)}}catch(u){const h=C(u);t.track.close(h),console.warn(`subscribe error: id=${s} broadcast=${e} track=${t.track.name} error=${h.message}`)}finally{n(this,ut).delete(s),n(this,ae).delete(s)}},On);var W,V,R,x,ht,S,ba,pa,ga,ma,va,ka,Ea,Bn;let go=(Bn=class{constructor(e,t,s,r){c(this,S);o(this,"url");c(this,W);c(this,V);c(this,R);c(this,x);c(this,ht,!1);this.url=e,l(this,W,t),l(this,V,new yo(s,r)),n(this,W).closed.finally(()=>{n(this,V).close()}),l(this,R,new bo(n(this,W),n(this,V))),l(this,x,new po(n(this,V))),d(this,S,ba).call(this)}close(){if(!n(this,ht)){l(this,ht,!0);try{n(this,W).close()}catch{}}}publish(e,t){n(this,R).publish(e,t)}announced(e=ys()){return n(this,x).announced(e)}consume(e){return n(this,x).consume(e)}get closed(){return n(this,W).closed.then(()=>{})}},W=new WeakMap,V=new WeakMap,R=new WeakMap,x=new WeakMap,ht=new WeakMap,S=new WeakSet,ba=async function(){const e=d(this,S,pa).call(this),t=d(this,S,ka).call(this);try{await Promise.all([e,t])}catch(s){n(this,ht)||console.error("fatal error running connection",s)}finally{this.close()}},pa=async function(){for(;;)try{const e=await n(this,V).read();if(e instanceof Is)await n(this,R).handleSubscribe(e);else if(e instanceof vt)await n(this,R).handleUnsubscribe(e);else if(e instanceof Jt)await n(this,R).handleTrackStatusRequest(e);else if(e instanceof Wt)await n(this,R).handlePublishNamespaceOk(e);else if(e instanceof Vt)await n(this,R).handlePublishNamespaceError(e);else if(e instanceof Ht)await n(this,R).handlePublishNamespaceCancel(e);else if(e instanceof yt)await n(this,x).handlePublishNamespace(e);else if(e instanceof bt)await n(this,x).handlePublishNamespaceDone(e);else if(e instanceof xs)await n(this,x).handleSubscribeOk(e);else if(e instanceof mt)await n(this,x).handleSubscribeError(e);else if(e instanceof Ue)await n(this,x).handlePublishDone(e);else if(e instanceof Pe)await n(this,x).handleTrackStatus(e);else if(e instanceof Ft)await d(this,S,ga).call(this,e);else if(e instanceof pt)await d(this,S,ma).call(this,e);else if(e instanceof gt)await d(this,S,va).call(this,e);else if(e instanceof kt)await n(this,R).handleSubscribeNamespace(e);else if(e instanceof Xt)await n(this,x).handleSubscribeNamespaceOk(e);else if(e instanceof Kt)await n(this,x).handleSubscribeNamespaceError(e);else if(e instanceof Et)await n(this,R).handleUnsubscribeNamespace(e);else if(e instanceof Gt)await n(this,x).handlePublish(e);else{if(e instanceof jt)throw new Error("PUBLISH_OK messages are not supported");if(e instanceof ft)throw new Error("PUBLISH_ERROR messages are not supported");if(e instanceof Ot)throw new Error("FETCH messages are not supported");if(e instanceof Bt)throw new Error("FETCH_OK messages are not supported");if(e instanceof Mt)throw new Error("FETCH_ERROR messages are not supported");if(e instanceof Dt)throw new Error("FETCH_CANCEL messages are not supported");e instanceof zt?n(this,V).maxRequestId(e.requestId):e instanceof _t?console.warn("ignoring REQUESTS_BLOCKED message"):oo(e)}}catch(e){console.error("error processing control message",e);break}console.warn("control stream closed")},ga=async function(e){console.warn(`MOQLITE_INCOMPATIBLE: Received GOAWAY with redirect URI: ${e.newSessionUri}`),this.close()},ma=async function(e){console.error("Unexpected CLIENT_SETUP message received after connection established"),this.close()},va=async function(e){console.error("Unexpected SERVER_SETUP message received after connection established"),this.close()},ka=async function(){const e=new ni(n(this,W));for(;;){const t=await e.next();if(!t)break;d(this,S,Ea).call(this,t).then(()=>{t.stop(new Error("cancel"))}).catch(s=>{t.stop(s)})}},Ea=async function(e){try{const t=await da.decode(e);console.debug("received group header",t),await n(this,x).handleGroup(t,e)}catch(t){console.error("error processing object stream",t)}},Bn);const Ln={DRAFT_07:4278190087,DRAFT_14:4278190094};async function fe(i,e){let t=new Uint8Array;const s=new Ae(new WritableStream({write(r){const a=t.byteLength+r.byteLength;if(a>t.buffer.byteLength){const u=Math.max(a,t.buffer.byteLength*2),h=new ArrayBuffer(u),w=new Uint8Array(h,0,a);w.set(t),w.set(r,t.byteLength),t=w}else t=new Uint8Array(t.buffer,0,a),t.set(r,a-r.byteLength)}}));await e(s),s.close(),await s.closed,await i.u53(t.byteLength),await i.write(t)}async function X(i,e){const t=await i.u53(),s=await i.read(t),r=new Qr(void 0,s),a=await e(r);if(!await r.done())throw new Error("Message decoding consumed too few bytes");return a}async function Zr(i,e){if(!await i.done())return await X(i,e)}var Dr,Ia,os,nn;const Ze=class Ze{constructor(e,t){c(this,Dr);o(this,"suffix");o(this,"active");this.suffix=e,this.active=t}async encode(e){return fe(e,d(this,Dr,Ia).bind(this))}static async decode(e){return X(e,d(Ze,os,nn))}static async decodeMaybe(e){return Zr(e,d(Ze,os,nn))}};Dr=new WeakSet,Ia=async function(e){await e.bool(this.active),await e.string(this.suffix)},os=new WeakSet,nn=async function(e){const t=await e.bool(),s=fs(await e.string());return new Ze(s,t)},c(Ze,os);let Qt=Ze;var Fr,xa,Gr,Sa;const Rt=class Rt{constructor(e){c(this,Fr);o(this,"prefix");this.prefix=e}async encode(e){return fe(e,d(this,Fr,xa).bind(this))}static async decode(e){return X(e,d(Rt,Gr,Sa))}};Fr=new WeakSet,xa=async function(e){await e.string(this.prefix)},Gr=new WeakSet,Sa=async function(e){const t=fs(await e.string());return new Rt(t)},c(Rt,Gr);let Ss=Rt;var jr,qa,Wr,$a;const Tt=class Tt{constructor(e){c(this,jr);o(this,"suffixes");this.suffixes=e}async encode(e){return fe(e,d(this,jr,qa).bind(this))}static async decode(e){return X(e,d(Tt,Wr,$a))}};jr=new WeakSet,qa=async function(e){await e.u53(this.suffixes.length);for(const t of this.suffixes)await e.string(t)},Wr=new WeakSet,$a=async function(e){const t=await e.u53(),s=[];for(let r=0;r<t;r++)s.push(fs(await e.string()));return new Tt(s)},c(Tt,Wr);let qs=Tt;var Vr,Aa,cs,an;const Ye=class Ye{constructor(e,t){c(this,Vr);o(this,"subscribe");o(this,"sequence");this.subscribe=e,this.sequence=t}async encode(e){return fe(e,d(this,Vr,Aa).bind(this))}static async decode(e){return X(e,d(Ye,cs,an))}static async decodeMaybe(e){return Zr(e,d(Ye,cs,an))}};Vr=new WeakSet,Aa=async function(e){await e.u62(this.subscribe),await e.u53(this.sequence)},cs=new WeakSet,an=async function(e){return new Ye(await e.u62(),await e.u53())},c(Ye,cs);let $s=Ye;const pe={DRAFT_01:4279086337,DRAFT_02:4279086338};var Hr,Ua,ds,on;const et=class et{constructor(e){c(this,Hr);o(this,"priority");this.priority=e}async encode(e){return fe(e,d(this,Hr,Ua).bind(this))}static async decode(e){return X(e,d(et,ds,on))}static async decodeMaybe(e){return Zr(e,d(et,ds,on))}};Hr=new WeakSet,Ua=async function(e){await e.u8(this.priority)},ds=new WeakSet,on=async function(e){const t=await e.u8();return new et(t)},c(et,ds);let As=et;var zr,Pa,_r,Na;const Ct=class Ct{constructor(e,t,s,r){c(this,zr);o(this,"id");o(this,"broadcast");o(this,"track");o(this,"priority");this.id=e,this.broadcast=t,this.track=s,this.priority=r}async encode(e){return fe(e,d(this,zr,Pa).bind(this))}static async decode(e){return X(e,d(Ct,_r,Na))}};zr=new WeakSet,Pa=async function(e){await e.u62(this.id),await e.string(this.broadcast),await e.string(this.track),await e.u8(this.priority)},_r=new WeakSet,Na=async function(e){const t=await e.u62(),s=fs(await e.string()),r=await e.string(),a=await e.u8();return new Ct(t,s,r,a)},c(Ct,_r);let Us=Ct;var Xr,La,Kr,Ra;const tt=class tt{constructor({version:e,priority:t=void 0}){c(this,Xr);o(this,"version");o(this,"priority");this.version=e,this.priority=t}async encode(e){return fe(e,d(this,Xr,La).bind(this))}static async decode(e,t){return X(e,d(tt,Kr,Ra).bind(tt,t))}};Xr=new WeakSet,La=async function(e){if(this.version!==pe.DRAFT_02)if(this.version===pe.DRAFT_01)await e.u8(this.priority??0);else{const t=this.version;throw new Error(`unsupported version: ${t}`)}},Kr=new WeakSet,Ra=async function(e,t){let s;if(e!==pe.DRAFT_02)if(e===pe.DRAFT_01)s=await t.u8();else{const r=e;throw new Error(`unsupported version: ${r}`)}return new tt({version:e,priority:s})},c(tt,Kr);let Ps=tt;var us,H,xt,Ta,Ca;class mo{constructor(e,t){c(this,xt);o(this,"version");c(this,us);c(this,H,new E(new Map));l(this,us,e),this.version=t}publish(e,t){n(this,H).mutate(s=>{if(!s)throw new Error("closed");s.set(e,t)}),t.closed.finally(()=>{n(this,H).mutate(s=>{s==null||s.delete(e)})})}async runAnnounce(e,t){console.debug(`announce: prefix=${e.prefix}`);let s=new Set;const r=n(this,H).peek();if(!r)return;for(const u of r.keys()){const h=Sn(e.prefix,u);h!==null&&(console.debug(`announce: broadcast=${u} active=true`),s.add(h))}for(await new qs([...s]).encode(t.writer);;){let u;const h=new Promise(y=>{u=n(this,H).changed(y)}),w=await Promise.race([h,t.reader.closed]);if(u(),!w)break;const g=new Set;for(const y of w.keys()){const q=Sn(e.prefix,y);q!==null&&g.add(q)}for(const y of g.difference(s))console.debug(`announce: broadcast=${y} active=true`),await new Qt(y,!0).encode(t.writer);for(const y of s.difference(g))console.debug(`announce: broadcast=${y} active=false`),await new Qt(y,!1).encode(t.writer);s=g}}async runSubscribe(e,t){var a;const s=(a=n(this,H).peek())==null?void 0:a.get(e.broadcast);if(!s){console.debug(`publish unknown: broadcast=${e.broadcast}`),t.writer.reset(new Error("not found"));return}const r=s.subscribe(e.track,e.priority);try{await new Ps({version:this.version,priority:e.priority}).encode(t.writer),console.debug(`publish ok: broadcast=${e.broadcast} track=${r.name}`);const h=d(this,xt,Ta).call(this,e.id,e.broadcast,r,t.writer);for(;;){const w=As.decodeMaybe(t.reader),g=await Promise.any([h,w]);if(!g)break;g instanceof As&&console.warn("subscribe update not supported",g)}console.debug(`publish done: broadcast=${e.broadcast} track=${r.name}`),t.close(),r.close()}catch(u){const h=C(u);console.warn(`publish error: broadcast=${e.broadcast} track=${r.name} error=${h.message}`),r.close(h),t.abort(h)}}close(){n(this,H).update(e=>{for(const t of(e==null?void 0:e.values())??[])t.close()})}}us=new WeakMap,H=new WeakMap,xt=new WeakSet,Ta=async function(e,t,s,r){try{for(;;){const a=s.nextGroup(),u=await Promise.race([a,r.closed]);if(!u){a.then(h=>h==null?void 0:h.close()).catch(()=>{});break}d(this,xt,Ca).call(this,e,u)}console.debug(`publish close: broadcast=${t} track=${s.name}`),s.close(),r.close()}catch(a){const u=C(a);console.warn(`publish error: broadcast=${t} track=${s.name} error=${u.message}`),s.close(u),r.reset(u)}},Ca=async function(e,t){const s=new $s(e,t.sequence);try{const r=await Ae.open(n(this,us));await r.u8(0),await s.encode(r);try{for(;;){const a=await Promise.race([t.readFrame(),r.closed]);if(!a)break;await r.u53(a.byteLength),await r.write(a)}r.close(),t.close()}catch(a){const u=C(a);r.reset(u),t.close(u)}}catch(r){const a=C(r);t.close(a)}};var Jr,Oa,hs,dn;const st=class st{constructor(e){c(this,Jr);o(this,"bitrate");this.bitrate=e}async encode(e){return fe(e,d(this,Jr,Oa).bind(this))}static async decode(e){return X(e,d(st,hs,dn))}static async decodeMaybe(e){return Zr(e,d(st,hs,dn))}};Jr=new WeakSet,Oa=async function(e){await e.u53(this.bitrate)},hs=new WeakSet,dn=async function(e){const t=await e.u53();return new st(t)},c(st,hs);let cn=st;const $e={Session:0,Announce:1,Subscribe:2,ClientCompat:32,ServerCompat:33};var lt,oe,ls,St,Ba,Ma;class vo{constructor(e,t){c(this,St);c(this,lt);o(this,"version");c(this,oe,new Map);c(this,ls,0n);l(this,lt,e),this.version=t}announced(e=ys()){const t=new Dn;return d(this,St,Ba).call(this,t,e),t}consume(e){const t=new Fn;return(async()=>{for(;;){const s=await t.requested();if(!s)break;d(this,St,Ma).call(this,e,s)}})(),t}async runGroup(e,t){const s=n(this,oe).get(e.subscribe);if(!s){if(e.subscribe>=n(this,ls))throw new Error(`unknown subscription: id=${e.subscribe}`);return}const r=new hn(e.sequence);s.writeGroup(r);try{for(;await Promise.race([t.done(),s.closed,r.closed])===!1;){const u=await t.u53(),h=await t.read(u);if(!h)break;r.writeFrame(h)}r.close(),t.stop(new Error("cancel"))}catch(a){const u=C(a);r.close(u),t.stop(u)}}close(){for(const e of n(this,oe).values())e.close();n(this,oe).clear()}}lt=new WeakMap,oe=new WeakMap,ls=new WeakMap,St=new WeakSet,Ba=async function(e,t){console.debug(`announced: prefix=${t}`);const s=new Ss(t);try{const r=await ks.open(n(this,lt));await r.writer.u53($e.Announce),await s.encode(r.writer);const a=await qs.decode(r.reader);for(const u of a.suffixes){const h=qn(t,u);console.debug(`announced: broadcast=${h} active=true`),e.append({path:h,active:!0})}for(;;){const u=await Promise.race([Qt.decodeMaybe(r.reader),e.closed]);if(!u)break;if(u instanceof Error)throw u;const h=qn(t,u.suffix);console.debug(`announced: broadcast=${h} active=${u.active}`),e.append({path:h,active:u.active})}e.close()}catch(r){e.close(C(r))}},Ma=async function(e,t){const s=bs(this,ls)._++;n(this,oe).set(s,t.track),console.debug(`subscribe start: id=${s} broadcast=${e} track=${t.track.name}`);const r=new Us(s,e,t.track.name,t.priority),a=await ks.open(n(this,lt));await a.writer.u53($e.Subscribe),await r.encode(a.writer);try{await Ps.decode(a.reader,this.version),console.debug(`subscribe ok: id=${s} broadcast=${e} track=${t.track.name}`),await Promise.race([a.reader.closed,t.track.closed]),t.track.close(),a.close(),console.debug(`subscribe close: id=${s} broadcast=${e} track=${t.track.name}`)}catch(u){const h=C(u);t.track.close(h),console.warn(`subscribe error: id=${s} broadcast=${e} track=${t.track.name} error=${h.message}`),a.abort(h)}finally{n(this,oe).delete(s)}};var F,ws,ce,de,wt,P,Da,Fa,Ga,ja,Wa,Va;class ko{constructor(e,t,s,r){c(this,P);o(this,"url");o(this,"version");c(this,F);c(this,ws);c(this,ce);c(this,de);c(this,wt,!1);this.url=e,l(this,F,t),l(this,ws,s),this.version=r,l(this,ce,new mo(n(this,F),this.version)),l(this,de,new vo(n(this,F),this.version)),d(this,P,Da).call(this)}close(){if(!n(this,wt)){l(this,wt,!0),n(this,ce).close(),n(this,de).close();try{n(this,F).close()}catch{}}}publish(e,t){n(this,ce).publish(e,t)}announced(e=ys()){return n(this,de).announced(e)}consume(e){return n(this,de).consume(e)}get closed(){return n(this,F).closed.then(()=>{})}}F=new WeakMap,ws=new WeakMap,ce=new WeakMap,de=new WeakMap,wt=new WeakMap,P=new WeakSet,Da=async function(){const e=d(this,P,Fa).call(this),t=d(this,P,Ga).call(this),s=d(this,P,Wa).call(this);try{await Promise.all([e,t,s])}catch(r){n(this,wt)||console.error("fatal error running connection",r)}finally{this.close()}},Fa=async function(){try{for(;await cn.decodeMaybe(n(this,ws).reader););}finally{console.warn("session stream closed")}},Ga=async function(){for(;;){const e=await ks.accept(n(this,F));if(!e)break;d(this,P,ja).call(this,e).catch(t=>{e.writer.reset(t)}).finally(()=>{e.writer.close()})}},ja=async function(e){const t=await e.reader.u53();if(t===$e.Session)throw new Error("duplicate session stream");if(t===$e.Announce){const s=await Ss.decode(e.reader);await n(this,ce).runAnnounce(s,e);return}else if(t===$e.Subscribe){const s=await Us.decode(e.reader);await n(this,ce).runSubscribe(s,e);return}else throw new Error(`unknown stream type: ${t.toString()}`)},Wa=async function(){const e=new ni(n(this,F));for(;;){const t=await e.next();if(!t)break;d(this,P,Va).call(this,t).then(()=>{t.stop(new Error("cancel"))}).catch(s=>{t.stop(s)})}},Va=async function(e){const t=await e.u8();if(t===0){const s=await $s.decode(e);await n(this,de).runGroup(s,e)}else throw new Error(`unknown stream type: ${t.toString()}`)};function Eo(i){if(i=i.startsWith("0x")?i.slice(2):i,i.length%2)throw new Error("invalid hex string length");const e=i.match(/.{2}/g);if(!e)throw new Error("invalid hex string format");return new Uint8Array(e.map(t=>parseInt(t,16)))}const Rn=new Set;async function Po(i,e){var pn,gn,mn;let t;const s=new Promise(Yr=>{t=Yr}),r=globalThis.WebTransport?Io(i,s,e==null?void 0:e.webtransport):void 0,a=!r||Rn.has(i.toString())?0:((pn=e==null?void 0:e.websocket)==null?void 0:pn.delay)??200,u=((gn=e==null?void 0:e.websocket)==null?void 0:gn.enabled)!==!1?xo(((mn=e==null?void 0:e.websocket)==null?void 0:mn.url)??i,a,s):void 0;if(!u&&!r)throw new Error("no transport available; WebTransport not supported and WebSocket is disabled");const h=await Promise.any(r?u?[u,r]:[r]:[u]);if(t&&t(),!h)throw new Error("no transport available");h instanceof vs&&(console.warn(i.toString(),"using WebSocket fallback; the user experience may be degraded"),Rn.add(i.toString()));const w=await ks.open(h);await w.writer.u53($e.ClientCompat);const g=new TextEncoder,y=new O;y.setVarint(tn.MaxRequestId,42069n),y.setBytes(tn.Implementation,g.encode("moq-lite-js"));const q=new pt([pe.DRAFT_02,pe.DRAFT_01,Ln.DRAFT_14],y);console.debug(i.toString(),"sending client setup",q),await q.encode(w.writer);const bn=await w.reader.u53();if(bn!==$e.ServerCompat)throw new Error(`unsupported server message type: ${bn.toString()}`);const Ne=await gt.decode(w.reader);if(console.debug(i.toString(),"received server setup",Ne),Object.values(pe).includes(Ne.version))return console.debug(i.toString(),"moq-lite session established"),new ko(i,h,w,Ne.version);if(Object.values(Ln).includes(Ne.version)){const Yr=Ne.parameters.getVarint(tn.MaxRequestId)??0n;return console.debug(i.toString(),"moq-ietf session established"),new go(i,h,w,Yr)}else throw new Error(`unsupported server version: ${Ne.version.toString()}`)}async function Io(i,e,t){let s=i;const r={allowPooling:!1,congestionControl:"low-latency",...t};if(i.protocol==="http:"){const h=new URL(i);h.pathname="/certificate.sha256",h.search="",console.warn(h.toString(),"performing an insecure fingerprint fetch; use https:// in production");const w=await Promise.race([fetch(h),e]);if(!w)return;const g=await Promise.race([w.text(),e]);if(g===void 0)return;r.serverCertificateHashes=(r.serverCertificateHashes||[]).concat([{algorithm:"sha-256",value:Eo(g)}]),s=new URL(i),s.protocol="https:"}const a=new WebTransport(s,r);if(!await Promise.race([a.ready.then(()=>!0),e])){a.close();return}return a}async function xo(i,e,t){const s=new Promise(h=>setTimeout(h,e));if(!await Promise.race([t,s.then(()=>!0)]))return;e&&console.debug(i.toString(),`no WebTransport after ${e}ms, attempting WebSocket fallback`);const a=new vs(i);if(!await Promise.race([a.ready.then(()=>!0),t])){a.close();return}return a}export{Fn as B,Po as c,fs as f};
|
assets/download_meshes.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Download OpenArm STL meshes from openarm.dev
|
| 3 |
+
BASE="https://openarm.dev/urdf/openarm_v1_0/meshes"
|
| 4 |
+
DIR="$(dirname "$0")/meshes"
|
| 5 |
+
|
| 6 |
+
mkdir -p "$DIR/arm/v10/visual" "$DIR/body/v10/visual" "$DIR/ee/openarm_hand/visual"
|
| 7 |
+
|
| 8 |
+
for i in 0 1 2 3 4 5 6 7; do
|
| 9 |
+
curl -sL "$BASE/arm/v10/visual/link${i}.stl" -o "$DIR/arm/v10/visual/link${i}.stl" &
|
| 10 |
+
done
|
| 11 |
+
curl -sL "$BASE/body/v10/visual/body_link0.stl" -o "$DIR/body/v10/visual/body_link0.stl" &
|
| 12 |
+
curl -sL "$BASE/ee/openarm_hand/visual/hand.stl" -o "$DIR/ee/openarm_hand/visual/hand.stl" &
|
| 13 |
+
curl -sL "$BASE/ee/openarm_hand/visual/finger.stl" -o "$DIR/ee/openarm_hand/visual/finger.stl" &
|
| 14 |
+
wait
|
| 15 |
+
echo "Downloaded $(find "$DIR" -name '*.stl' | wc -l) mesh files"
|
assets/meshes/.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# STL meshes downloaded from openarm.dev (~14MB)
|
| 2 |
+
# Run: curl script or see js/examples/assets/download_meshes.sh
|
| 3 |
+
*.stl
|
assets/openarm-DqhZ0Caw.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import{c as It,f as bt,B as de}from"./connect-DkGLCYAo.js";import{W as ue,S as he,A as fe,D as jt,P as me,O as pe,G as ge,a as ye,B as Vt,b as Ct,c as we,d as ve,e as xe,M as Qt,f as Ie,g as be,U as Ce,h as Ee,i as $e,C as Be,L as Fe,j as Re,k as lt}from"./URDFLoader-CL7UVBjw.js";const $=new URLSearchParams(location.search),ot="openarm.",dt=(t,e)=>$.get(t)||localStorage.getItem(ot+t)||e,Y=document.getElementById("relayUrl"),ut=document.getElementById("leftPath"),ht=document.getElementById("rightPath"),ft=document.getElementById("depthPath"),mt=document.getElementById("certHash");Y.value=dt("relay","https://cdn.1ms.ai");ut.value=$.get("left")||$.get("path")||localStorage.getItem(ot+"left")||"anon/xoq-can-can0/state";ht.value=dt("right","anon/xoq-can-can1/state");ft.value=dt("depth","");mt.value=dt("certHash","");const Pe={relay:Y,left:ut,right:ht,depth:ft,certHash:mt,camX:document.getElementById("camX"),camY:document.getElementById("camY"),camZ:document.getElementById("camZ"),camRoll:document.getElementById("camRoll"),camPitch:document.getElementById("camPitch"),camYaw:document.getElementById("camYaw"),queryRate:document.getElementById("queryRate"),ptSize:document.getElementById("ptSize")};for(const[t,e]of Object.entries(Pe)){const n=localStorage.getItem(ot+t);n&&!$.has(t)&&(e.value=n),e.addEventListener("input",()=>localStorage.setItem(ot+t,e.value))}const T=document.getElementById("log"),O=document.getElementById("startBtn"),st=document.getElementById("stopBtn"),g=document.getElementById("queryBtn"),Se=document.getElementById("statusText"),rt=[{name:"J1",desc:"Shoulder pan",canId:17,color:16739125},{name:"J2",desc:"Shoulder lift",canId:18,color:16747586},{name:"J3",desc:"Shoulder rot",canId:19,color:16755021},{name:"J4",desc:"Elbow flex",canId:20,color:16765286},{name:"J5",desc:"Wrist roll",canId:21,color:448160},{name:"J6",desc:"Wrist pitch",canId:22,color:1149618},{name:"J7",desc:"Wrist rot",canId:23,color:473932},{name:"Grip",desc:"Gripper",canId:24,color:8599788}],kt=["L_J1","L_J2","L_J3","L_J4","L_J5","L_J6","L_J7"],Mt=["R_J1","R_J2","R_J3","R_J4","R_J5","R_J6","R_J7"];function Xt(){return new Array(8).fill(null).map(()=>({angle:0,velocity:0,torque:0,tempMos:0,tempRotor:0,updated:!1}))}const N=Xt(),j=Xt();let at=[],ct=!1,Et=0,$t=0,it=0,At=performance.now();const q={left:{conn:null,broadcast:null,track:null,group:null},right:{conn:null,broadcast:null,track:null,group:null}};let Z=null,k=!1,H=0,wt=0;function c(t,e="info"){const n=document.createElement("div");n.className=`log-entry log-${e}`,n.textContent=`[${new Date().toLocaleTimeString()}] ${t}`,T.appendChild(n),T.children.length>200&&T.removeChild(T.firstChild),T.scrollTop=T.scrollHeight}function Le(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} K`:`${(t/(1024*1024)).toFixed(1)} M`}function b(t){Se.textContent=t}function Zt(t,e){const n=document.getElementById(t),s=[];for(let o=0;o<rt.length;o++){const r=rt[o],a=document.createElement("div");a.className="joint-row",a.innerHTML=`
|
| 2 |
+
<span class="joint-label" style="color:#${r.color.toString(16).padStart(6,"0")}">${r.name}</span>
|
| 3 |
+
<span class="joint-angle" id="${e}-angle-${o}">0.0°</span>
|
| 4 |
+
<span class="joint-vel" id="${e}-vel-${o}">0.0</span>
|
| 5 |
+
<span class="joint-tau" id="${e}-tau-${o}">0.0</span>
|
| 6 |
+
`,n.appendChild(a),s.push({angle:a.querySelector(`#${e}-angle-${o}`),vel:a.querySelector(`#${e}-vel-${o}`),tau:a.querySelector(`#${e}-tau-${o}`)})}return s}const ke=Zt("leftJointRows","l"),Me=Zt("rightJointRows","r");function Ae(t){const e=new DataView(t.buffer,t.byteOffset,t.byteLength);if(t.length<6)return null;const n=t[0],s=e.getUint32(1,!0),o=t[5];if(t.length<6+o)return null;const r=t.slice(6,6+o);return{flags:n,canId:s,dataLen:o,data:r}}function _e(t){if(t.length<8)return null;const e=t[1]<<8|t[2],n=t[3]<<4|t[4]>>4,s=(t[4]&15)<<8|t[5],o=12.5,r=e/65535*(2*o)-o,a=45,l=n/4095*(2*a)-a,i=18,d=s/4095*(2*i)-i,h=t[6],u=t[7];return{qRad:r,vel:l,tau:d,tempMos:h,tempRotor:u}}function Bt(){const t=mt.value.trim(),e={};if(t){const n=t.replace(/[^0-9a-fA-F]/g,""),s=new Uint8Array(n.length/2);for(let o=0;o<s.length;o++)s[o]=parseInt(n.substr(o*2,2),16);e.webtransport={serverCertificateHashes:[{algorithm:"sha-256",value:s.buffer}]},c(`Using cert hash: ${n.slice(0,16)}...`,"data")}return e}function Kt(t){const e=new Uint8Array(t),n=s=>s.toString(16).padStart(2,"0").toUpperCase();for(let s=0;s<e.length-11;s++){if(e[s+4]===97&&e[s+5]===118&&e[s+6]===99&&e[s+7]===67){const o=s+8;if(o+4<=e.length)return`avc1.${n(e[o+1])}${n(e[o+2])}${n(e[o+3])}`}if(e[s+4]===97&&e[s+5]===118&&e[s+6]===49&&e[s+7]===67){const o=s+8;if(o+4<=e.length){const r=e[o+1]>>5&7,a=e[o+1]&31,l=e[o+2]>>7&1,i=e[o+2]>>6&1,d=e[o+2]>>5&1,h=i?d?12:10:8,u=String(a).padStart(2,"0");return`av01.${r}.${u}${l?"H":"M"}.${String(h).padStart(2,"0")}`}}}return null}function te(t){return t.length>=8&&t[4]===102&&t[5]===116&&t[6]===121&&t[7]===112}function ee(t,e){const n=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)];let s=0;for(;s<t.length-8;){const o=t[s]<<24|t[s+1]<<16|t[s+2]<<8|t[s+3];if(t[s+4]===n[0]&&t[s+5]===n[1]&&t[s+6]===n[2]&&t[s+7]===n[3])return s;if(o<8)break;s+=o}return-1}function De(t){const e=ee(t,"mdat");if(e<0)return null;const n=t[e]<<24|t[e+1]<<16|t[e+2]<<8|t[e+3];return t.subarray(e+8,e+n)}function Te(t){for(let e=0;e<t.length-11;e++)if(t[e+4]===97&&t[e+5]===118&&t[e+6]===49&&t[e+7]===67){const n=t[e]<<24|t[e+1]<<16|t[e+2]<<8|t[e+3];return t.slice(e+8,e+n)}return null}class Je{constructor(){this.decoder=null,this.configured=!1,this.configuredCodec=null,this.latestY=null,this.is10bit=!1,this.width=0,this.height=0,this.frameCount=0,this.copyBuf=null}onData(e){const n=new Uint8Array(e);if(te(n)){if(!this.configured){const r=Te(n),a=Kt(n);r&&a&&this.configure(a,r)}const o=ee(n,"moof");o>=0&&this.decodeSample(n.subarray(o),!0)}else this.configured&&this.decodeSample(n,!1)}configure(e,n){if(this.configuredCodec===e)return;if(this.decoder)try{this.decoder.close()}catch{}this.decoder=new VideoDecoder({output:o=>this.processFrame(o).catch(r=>console.error("Depth frame error:",r)),error:o=>console.error("Depth decoder error:",o)});const s=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);this.decoder.configure({codec:e,description:s,hardwareAcceleration:"prefer-software"}),this.configured=!0,this.configuredCodec=e,c(`Depth WebCodecs: ${e}`,"data")}decodeSample(e,n){const s=De(e);if(!s)return;const o=this.frameCount*(1e6/30);this.decoder.decode(new EncodedVideoChunk({type:n?"key":"delta",timestamp:o,data:s})),this.frameCount++}async processFrame(e){try{const n=e.displayWidth,s=e.displayHeight,o=n*s,r=e.format;this.fmtLogged||(c(`Depth frame format: ${r}, ${n}x${s}`,"data"),this.fmtLogged=!0);let a=!1;if(r){a=r.includes("10");const l=e.allocationSize();(!this.copyBuf||this.copyBuf.byteLength<l)&&(this.copyBuf=new ArrayBuffer(l));const i=await e.copyTo(this.copyBuf),d=i[0].offset,h=i[0].stride;if(a){(!this.latestY||this.latestY.length!==o)&&(this.latestY=new Uint16Array(o));const u=h/2,f=new Uint16Array(this.copyBuf);if(u===n)this.latestY.set(new Uint16Array(this.copyBuf,d,o));else for(let m=0;m<s;m++)this.latestY.set(f.subarray(d/2+m*u,d/2+m*u+n),m*n)}else{(!this.latestY||this.latestY.length!==o)&&(this.latestY=new Uint8Array(o));const u=new Uint8Array(this.copyBuf);if(h===n)this.latestY.set(new Uint8Array(this.copyBuf,d,o));else for(let f=0;f<s;f++)this.latestY.set(u.subarray(d+f*h,d+f*h+n),f*n)}}else{(!this.offCanvas||this.offCanvas.width!==n||this.offCanvas.height!==s)&&(this.offCanvas=new OffscreenCanvas(n,s),this.offCtx=this.offCanvas.getContext("2d",{willReadFrequently:!0})),this.offCtx.drawImage(e,0,0);const l=this.offCtx.getImageData(0,0,n,s).data;(!this.latestY||this.latestY.length!==o)&&(this.latestY=new Uint8Array(o));for(let i=0;i<o;i++)this.latestY[i]=l[i*4];a=!1,this.canvasFallbackLogged||(c("Depth: GPU frame, using canvas fallback (8-bit)","info"),this.canvasFallbackLogged=!0)}this.is10bit=a,this.width=n,this.height=s}finally{e.close()}}destroy(){if(this.decoder)try{this.decoder.close()}catch{}this.decoder=null,this.configured=!1,this.latestY=null}}class qe{constructor(e,n){this.video=e,this.label=n,this.ms=null,this.sb=null,this.queue=[],this.ready=!1,this.frames=0,this.seekIv=null}onData(e){if(this.frames++,!this.ready){if(!te(e))return;const n=Kt(e);if(!n){c(`${this.label}: cannot detect codec`,"error");return}this.initMse(n,e);return}this.enqueue(e)}initMse(e,n){const s=`video/mp4; codecs="${e}"`;if(c(`${this.label}: ${s}`,"data"),!MediaSource.isTypeSupported(s)){c(`${this.label}: unsupported`,"error");return}this.ms=new MediaSource,this.video.src=URL.createObjectURL(this.ms),this.ms.addEventListener("sourceopen",()=>{try{this.sb=this.ms.addSourceBuffer(s),this.sb.mode="segments",this.sb.addEventListener("updateend",()=>this.flush()),this.ready=!0,this.enqueue(n),this.video.play().catch(()=>{}),this.seekIv=setInterval(()=>{if(this.video.buffered.length>0){const o=this.video.buffered.end(this.video.buffered.length-1);o-this.video.currentTime>.5&&(this.video.currentTime=o-.05);const r=this.video.buffered.start(0);if(o-r>10&&!this.sb.updating)try{this.sb.remove(r,o-5)}catch{}}},500)}catch(o){c(`${this.label}: init failed: ${o.message}`,"error")}})}enqueue(e){this.queue.push(e),this.flush()}flush(){if(!(!this.sb||this.sb.updating||!this.queue.length))try{this.sb.appendBuffer(this.queue.shift())}catch(e){c(`${this.label}: ${e.message}`,"error")}}destroy(){if(this.seekIv&&clearInterval(this.seekIv),this.queue=[],this.ready=!1,this.ms&&this.ms.readyState==="open")try{this.ms.endOfStream()}catch{}this.video.src=""}}let W=null,p=null,G=null,J=!1;async function Ue(){const t=ft.value.trim();if(!t)return;const n=`${Y.value.trim()}/${t}`;W=new qe(document.getElementById("colorVideo"),"Color"),p=new Je;const s=Bt();c(`[depth] Connecting to ${n}...`),G=await It(new URL(n),s),c("[depth] Connected","success");const o=G.consume(bt("")),r=o.subscribe("video",0),a=o.subscribe("depth",0);c("[depth] Subscribed to video + depth tracks","success"),J=!0;async function l(i,d,h){for(;J;){const u=await i.nextGroup();if(!u){c(`[depth] ${h} track ended`);break}for(;J;){const f=await u.readFrame();if(!f)break;d(new Uint8Array(f))}}}l(r,i=>W.onData(i),"video").catch(i=>{J&&c(`[depth] video error: ${i.message}`,"error")}),l(a,i=>p.onData(i),"depth").catch(i=>{J&&c(`[depth] depth error: ${i.message}`,"error")}),c("[depth] Receiving frames...","success")}function ne(){if(J=!1,G){try{G.close()}catch{}G=null}W&&(W.destroy(),W=null),p&&(p.destroy(),p=null),C.setDrawRange(0,0)}function Ye(){return new Uint8Array([128,0,128,0,0,0,8,0])}function He(t,e){const n=new Uint8Array(6+e.length);return n[0]=0,n[1]=t&255,n[2]=t>>8&255,n[3]=t>>16&255,n[4]=t>>24&255,n[5]=e.length,n.set(e,6),n}async function _t(t,e){const n=Y.value,s=e.replace(/\/state$/,""),o=`${n}/${s}/commands`,r=q[t];c(`[${t}] Connecting commands to ${o}...`);const a=Bt();r.conn=await Promise.race([It(new URL(o),a),new Promise((i,d)=>setTimeout(()=>d(new Error(`[${t}] Command connection timeout`)),8e3))]),r.broadcast=new de,r.conn.publish(bt(""),r.broadcast),c(`[${t}] Waiting for CAN server to subscribe (10s)...`);const l=await Promise.race([r.broadcast.requested(),new Promise((i,d)=>setTimeout(()=>d(new Error(`[${t}] No subscriber after 10s — is moq-can-server running?`)),1e4))]);if(!l){c(`[${t}] Command broadcast closed`,"error");return}r.track=l.track,c(`[${t}] Command track active`,"success")}async function Oe(){const t=ut.value.trim(),e=ht.value.trim(),n=[];t&&n.push(_t("left",t)),e&&n.push(_t("right",e)),await Promise.all(n);const s=Ye();H=0,wt=0;const o=[];if(q.left.track&&o.push(q.left),q.right.track&&o.push(q.right),o.length===0){c("No command tracks connected","error");return}const r=parseInt(document.getElementById("queryRate").value)||200,a=Math.max(1,Math.round(1e3/r));Z=setInterval(()=>{const l=o[wt%o.length];if(!l.track)return;const i=H+1,d=He(i,s);l.group=l.track.appendGroup(),l.group.writeFrame(d),l.group.close(),H=(H+1)%8,H===0&&wt++},a),c(`Query loop started at ${r}Hz (${o.length} arm${o.length>1?"s":""})`,"success")}function Ft(){Z&&(clearInterval(Z),Z=null);for(const t of["left","right"]){const e=q[t];if(e.group=null,e.track){try{e.track.close()}catch{}e.track=null}if(e.broadcast){try{e.broadcast.close()}catch{}e.broadcast=null}if(e.conn){try{e.conn.close()}catch{}e.conn=null}}c("Query loop stopped")}const Rt=document.getElementById("threeCanvas");let B;try{B=new ue({canvas:Rt,antialias:!0}),B.setPixelRatio(window.devicePixelRatio),B.setClearColor(1710638)}catch(t){c(`WebGL not available: ${t.message} (3D disabled, MoQ still works)`,"error"),B=null}const F=new he,We=new fe(16777215,.4);F.add(We);const oe=new jt(16777215,.8);oe.position.set(5,10,7);F.add(oe);const se=new jt(4491519,.3);se.position.set(-5,3,-5);F.add(se);const U=new me(50,1,.01,100);U.position.set(1,.8,1.2);U.lookAt(0,.4,0);const V=new pe(U,Rt);V.target.set(0,.4,0);V.enableDamping=!0;V.dampingFactor=.1;V.update();const Ge=new ge(2,20,3355477,2236996);F.add(Ge);const ze=new ye(.1);F.add(ze);const I=640,M=480,re=I*M,K=new Float32Array(re*3),tt=new Float32Array(re*3),C=new Vt;C.setAttribute("position",new Ct(K,3));C.setAttribute("color",new Ct(tt,3));C.setDrawRange(0,0);const Pt=new we({size:.002,vertexColors:!0,sizeAttenuation:!0}),ae=new ve(C,Pt);ae.scale.set(.001,.001,.001);const A=new xe;F.add(A);A.add(ae);const Ne=new Qt(new Ie(.012,12,8),new be({color:16720418}));A.add(Ne);let X=null;function je(){X&&A.remove(X);const t=604.2,e=603.5,n=0,s=.3,o=(1023<<n)*.001,r=s*(I/2)/t,a=s*(M/2)/e,l=o*(I/2)/t,i=o*(M/2)/e,d=new Float32Array([-r,a,s,r,a,s,r,-a,s,-r,-a,s,-l,i,o,l,i,o,l,-i,o,-l,-i,o]),h=[0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7],u=new Vt;u.setAttribute("position",new Ct(d,3)),u.setIndex(h),X=new Fe(u,new Re({color:16729156,opacity:.5,transparent:!0})),A.add(X)}je();const St=document.createElement("canvas");St.width=I;St.height=M;const Dt=St.getContext("2d",{willReadFrequently:!0}),Ve=document.getElementById("colorPreview").getContext("2d"),Tt=document.getElementById("depthPreview").getContext("2d"),Qe=document.getElementById("pcStats");let Jt=0,vt=0;function Xe(){const t=document.getElementById("colorVideo");if(!t.videoWidth||!p||!p.latestY)return;const e=1,n=604.2,s=603.5,o=322.7,r=252.7,a=0;Dt.drawImage(t,0,0,I,M),Ve.drawImage(t,0,0,128,96);const l=p.latestY,i=p.width,d=p.height,h=128,u=96,f=Tt.createImageData(h,u),m=f.data,x=i/h,R=d/u;for(let w=0;w<u;w++)for(let v=0;v<h;v++){const Q=l[Math.floor(w*R)*i+Math.floor(v*x)],S=p.is10bit?Q>>2:Q,E=(w*h+v)*4;m[E]=S,m[E+1]=S,m[E+2]=S,m[E+3]=255}Tt.putImageData(f,0,0);const P=Dt.getImageData(0,0,I,M).data;let _=0;for(let w=0;w<M;w+=e)for(let v=0;v<I;v+=e){const Q=w*I+v,S=l[Q];if(S<2)continue;const E=p.is10bit?S<<a:S<<4,D=_*3;K[D]=-(v-o)*E/n,K[D+1]=-(w-r)*E/s,K[D+2]=E;const yt=(w*I+v)*4;tt[D]=P[yt]/255,tt[D+1]=P[yt+1]/255,tt[D+2]=P[yt+2]/255,_++}C.attributes.position.needsUpdate=!0,C.attributes.color.needsUpdate=!0,C.setDrawRange(0,_),C.computeBoundingSphere(),Jt++,vt||(vt=performance.now());const pt=(performance.now()-vt)/1e3,gt=pt>0?(Jt/pt).toFixed(1):"0";Qe.textContent=`${_.toLocaleString()} pts | ${gt} fps | step=${e}`}document.getElementById("ptSize").addEventListener("input",t=>{Pt.size=parseFloat(t.target.value)*.001});Pt.size=parseFloat(document.getElementById("ptSize").value)*.001;const qt=new lt,Ut=new lt,Yt=new lt,xt=new lt;function ce(){const t=parseFloat(document.getElementById("camX").value)||0,e=parseFloat(document.getElementById("camY").value)||0,n=parseFloat(document.getElementById("camZ").value)||0,s=(parseFloat(document.getElementById("camRoll").value)||0)*Math.PI/180,o=(parseFloat(document.getElementById("camPitch").value)||0)*Math.PI/180,r=(parseFloat(document.getElementById("camYaw").value)||0)*Math.PI/180;A.position.set(t,e,n),qt.makeRotationX(s),Ut.makeRotationY(o),Yt.makeRotationZ(r),xt.multiplyMatrices(Yt,Ut),xt.multiply(qt),A.setRotationFromMatrix(xt)}for(const t of["camX","camY","camZ","camRoll","camPitch","camYaw"])document.getElementById(t).addEventListener("input",ce);ce();let y=null;const ie=new Ce;ie.loadMeshCb=(t,e,n)=>{t.endsWith(".stl")?new Ee(e).load(t,s=>{n(new Qt(s,new $e))},null,s=>n(null,s)):t.endsWith(".dae")?new Be(e).load(t,s=>n(s.scene),null,s=>n(null,s)):n(null,new Error(`Unknown mesh format: ${t}`))};b("Loading 3D model...");c("Loading URDF model...");ie.load("./assets/openarm_v10.urdf",t=>{y=t,y.rotation.x=-Math.PI/2,F.add(y),b("Idle"),c("3D model loaded","success")},void 0,t=>{c(`URDF load error: ${t}`,"error"),b("Model load failed")});const Ze=-1.0472,Ht=.044;function Ot(t){return Math.max(0,Math.min(Ht,Ht*(t/Ze)))}function Ke(){if(!y)return;for(let n=0;n<7;n++)y.joints[kt[n]]&&y.joints[kt[n]].setJointValue(N[n].angle),y.joints[Mt[n]]&&y.joints[Mt[n]].setJointValue(j[n].angle);const t=Ot(N[7].angle),e=Ot(j[7].angle);y.joints.L_EE&&y.joints.L_EE.setJointValue(t),y.joints.R_EE&&y.joints.R_EE.setJointValue(e)}function tn(){function t(n,s){for(let o=0;o<rt.length;o++){const r=s[o],a=(r.angle*180/Math.PI).toFixed(1);n[o].angle.innerHTML=`${a}°`,n[o].vel.textContent=r.velocity.toFixed(1),n[o].tau.textContent=r.torque.toFixed(1)}}t(ke,N),t(Me,j),document.getElementById("frameCount").textContent=Et,document.getElementById("bytesReceived").textContent=Le($t);const e=performance.now();e-At>=1e3&&(document.getElementById("canFps").textContent=it,it=0,At=e),document.getElementById("lastUpdate").textContent=new Date().toLocaleTimeString().split(" ")[0]}function Lt(){if(!B)return;const t=Rt.parentElement,e=t.clientWidth,n=t.clientHeight;B.setSize(e,n),U.aspect=e/n,U.updateProjectionMatrix()}window.addEventListener("resize",Lt);requestAnimationFrame(Lt);let z="3d";const Wt=document.getElementById("view3d"),Gt=document.getElementById("viewCamera"),L=document.getElementById("viewToggle"),et=document.getElementById("colorFullCanvas"),nt=document.getElementById("depthFullCanvas"),en=et.getContext("2d"),zt=nt.getContext("2d");L.addEventListener("click",()=>{z==="3d"?(z="camera",Wt.style.display="none",Gt.style.display="block",L.textContent="3D",L.style.background="#00d4ff",L.style.color="#000"):(z="3d",Wt.style.display="",Gt.style.display="none",L.textContent="Camera",L.style.background="#2a2a4a",L.style.color="#aaa",Lt())});function nn(){if(z!=="camera")return;const t=document.getElementById("colorVideo");if(t.videoWidth&&(et.width!==t.videoWidth&&(et.width=t.videoWidth,et.height=t.videoHeight),en.drawImage(t,0,0)),p&&p.latestY){const e=p.latestY,n=p.width,s=p.height;nt.width!==n&&(nt.width=n,nt.height=s);const o=zt.createImageData(n,s),r=o.data;for(let a=0;a<n*s;a++){const l=p.is10bit?e[a]>>2:e[a];r[a*4]=l,r[a*4+1]=l,r[a*4+2]=l,r[a*4+3]=255}zt.putImageData(o,0,0)}}function le(){if(requestAnimationFrame(le),Ke(),z==="camera"){nn();return}B&&(V.update(),Xe(),B.render(F,U))}le();async function Nt(t,e,n){const o=`${Y.value}/${e}`;c(`[${t}] Connecting to ${o}...`);const r=Bt(),a=await Promise.race([It(new URL(o),r),new Promise((d,h)=>setTimeout(()=>h(new Error(`[${t}] Connection timeout`)),8e3))]);at.push(a),c(`[${t}] Connected`,"success");const i=a.consume(bt("")).subscribe("can",0);for(c(`[${t}] Subscribed to 'can' track`,"success");ct;){const d=await i.nextGroup();if(!d){c(`[${t}] Track ended`);break}for(;ct;){const h=await d.readFrame();if(!h)break;const u=new Uint8Array(h);$t+=u.length,Et++,it++;const f=Ae(u);if(!f)continue;const m=rt.findIndex(R=>R.canId===f.canId);if(m<0)continue;const x=_e(f.data);if(x&&(n[m].angle=x.qRad,n[m].velocity=x.vel,n[m].torque=x.tau,n[m].tempMos=x.tempMos,n[m].tempRotor=x.tempRotor,n[m].updated=!0,m===7)){const R=(x.qRad*180/Math.PI).toFixed(1),P=`_lastGripDeg_${t}`;if(!window[P]||Math.abs(parseFloat(R)-window[P])>.5){window[P]=parseFloat(R);const _=t==="left"?"right":"left",gt=((t==="left"?j:N)[7].angle*180/Math.PI).toFixed(1);c(`[GRIP] ${t}=${R}° (${_}=${gt}°) canId=0x${f.canId.toString(16)}`,"data")}}}}}O.addEventListener("click",async()=>{try{const t=ut.value.trim(),e=ht.value.trim(),n=ft.value.trim();if(!t&&!e&&!n){c("No paths configured","error");return}O.disabled=!0,st.disabled=!1,ct=!0,Et=0,$t=0,it=0,at=[],b("Connecting..."),c(`WebTransport: ${typeof WebTransport<"u"?"supported":"NOT supported"}`,"data");const s=Y.value;if(!mt.value.trim())try{const a=await fetch(`${s}/certificate.sha256`);a.ok&&c(`Relay cert: ${(await a.text()).trim().slice(0,32)}...`,"data")}catch{}t&&e&&t===e&&c(`WARNING: Left and Right arms use the same path "${t}" — gripper cross-talk expected!`,"error");const r=[];t&&r.push(Nt("left",t,N)),e&&r.push(Nt("right",e,j));try{await Ue()}catch(a){c(`[depth] ${a.message}`,"error")}g.disabled=!1,b("Streaming"),await Promise.all(r),b("Ended")}catch(t){c(`Error: ${t.message}`,"error"),console.error(t),b("Error")}finally{k&&(Ft(),k=!1,g.classList.remove("active"),g.textContent="Query Motors"),ne(),g.disabled=!0,O.disabled=!1,st.disabled=!0}});st.addEventListener("click",async()=>{ct=!1,k&&(Ft(),k=!1,g.classList.remove("active"),g.textContent="Query Motors"),g.disabled=!0,b("Stopping..."),ne();for(const t of at)try{t.close()}catch{}at=[],O.disabled=!1,st.disabled=!0,b("Disconnected"),c("Disconnected","success")});g.addEventListener("click",async()=>{if(k)Ft(),k=!1,g.classList.remove("active"),g.textContent="Query Motors";else{g.disabled=!0,g.textContent="Starting...";try{await Oe(),k=!0,g.classList.add("active"),g.textContent="Stop Query",g.disabled=!1}catch(t){c(`Query start error: ${t.message}`,"error"),console.error(t),g.textContent="Query Motors",g.disabled=!1}}});setInterval(tn,100);c("Ready. Click Connect to start.","info");($.has("left")||$.has("right")||$.has("path")||$.has("depth"))&&(c("Auto-connecting from query params...","info"),O.click());
|
assets/openarm_v10.urdf
ADDED
|
@@ -0,0 +1,836 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" ?>
|
| 2 |
+
<!-- =================================================================================== -->
|
| 3 |
+
<!-- | This document was autogenerated by xacro from v10.urdf.xacro | -->
|
| 4 |
+
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
|
| 5 |
+
<!-- =================================================================================== -->
|
| 6 |
+
<robot name="openarm">
|
| 7 |
+
<!--
|
| 8 |
+
DEPRECATION NOTICE
|
| 9 |
+
argument arm_type is no longer supported and will be removed in the future.
|
| 10 |
+
This argument is ignored.
|
| 11 |
+
-->
|
| 12 |
+
<!-- Should the robot be spawned in Gazebo with effort interfaces?" -->
|
| 13 |
+
<!-- <xacro:arg name="gazebo_effort" default="false" /> -->
|
| 14 |
+
<!-- ========================================================== -->
|
| 15 |
+
<!-- Adds the required tags to simulate one joint in gazebo -->
|
| 16 |
+
<!-- -->
|
| 17 |
+
<!-- joint - Name of the openarm joint to simulate -->
|
| 18 |
+
<!-- transmission - type of the transmission of the joint -->
|
| 19 |
+
<!-- ========================================================== -->
|
| 20 |
+
<!-- <xacro:macro name="gazebo-joint" params="joint transmission:=hardware_interface/EffortJointInterface">
|
| 21 |
+
<gazebo reference="${joint}">
|
| 22 |
+
<provideFeedback>true</provideFeedback>
|
| 23 |
+
</gazebo>
|
| 24 |
+
<transmission name="${joint}_transmission">
|
| 25 |
+
<type>transmission_interface/SimpleTransmission</type>
|
| 26 |
+
<joint name="${joint}">
|
| 27 |
+
<hardwareInterface>${transmission}</hardwareInterface>
|
| 28 |
+
</joint>
|
| 29 |
+
<actuator name="${joint}_motor">
|
| 30 |
+
<hardwareInterface>${transmission}</hardwareInterface>
|
| 31 |
+
</actuator>
|
| 32 |
+
</transmission>
|
| 33 |
+
</xacro:macro> -->
|
| 34 |
+
<!-- <xacro:macro name="gazebo-friction" params="link mu">
|
| 35 |
+
<gazebo reference="${link}">
|
| 36 |
+
<collision>
|
| 37 |
+
<max_contacts>10</max_contacts>
|
| 38 |
+
<surface>
|
| 39 |
+
<contact>
|
| 40 |
+
<ode>
|
| 41 |
+
<max_vel>0</max_vel>
|
| 42 |
+
<min_depth>0.001</min_depth>
|
| 43 |
+
</ode>
|
| 44 |
+
</contact>
|
| 45 |
+
<friction>
|
| 46 |
+
<ode>
|
| 47 |
+
<mu>${mu}</mu>
|
| 48 |
+
<mu2>${mu}</mu2>
|
| 49 |
+
</ode>
|
| 50 |
+
</friction>
|
| 51 |
+
<bounce/>
|
| 52 |
+
</surface>
|
| 53 |
+
</collision>
|
| 54 |
+
</gazebo>
|
| 55 |
+
</xacro:macro> -->
|
| 56 |
+
<!-- ========================================================== -->
|
| 57 |
+
<!-- Adds the required tags to simulate one joint in gazebo -->
|
| 58 |
+
<!-- -->
|
| 59 |
+
<!-- joint - Name of the openarm joint to simulate -->
|
| 60 |
+
<!-- transmission - type of the transmission of the joint -->
|
| 61 |
+
<!-- ========================================================== -->
|
| 62 |
+
<!-- <xacro:macro name="gazebo-joint" params="joint transmission:=hardware_interface/EffortJointInterface">
|
| 63 |
+
<gazebo reference="${joint}">
|
| 64 |
+
<provideFeedback>true</provideFeedback>
|
| 65 |
+
</gazebo>
|
| 66 |
+
<transmission name="${joint}_transmission">
|
| 67 |
+
<type>transmission_interface/SimpleTransmission</type>
|
| 68 |
+
<joint name="${joint}">
|
| 69 |
+
<hardwareInterface>${transmission}</hardwareInterface>
|
| 70 |
+
</joint>
|
| 71 |
+
<actuator name="${joint}_motor">
|
| 72 |
+
<hardwareInterface>${transmission}</hardwareInterface>
|
| 73 |
+
</actuator>
|
| 74 |
+
</transmission>
|
| 75 |
+
</xacro:macro> -->
|
| 76 |
+
<!-- <xacro:macro name="gazebo-friction" params="link mu">
|
| 77 |
+
<gazebo reference="${link}">
|
| 78 |
+
<collision>
|
| 79 |
+
<max_contacts>10</max_contacts>
|
| 80 |
+
<surface>
|
| 81 |
+
<contact>
|
| 82 |
+
<ode>
|
| 83 |
+
<max_vel>0</max_vel>
|
| 84 |
+
<min_depth>0.001</min_depth>
|
| 85 |
+
</ode>
|
| 86 |
+
</contact>
|
| 87 |
+
<friction>
|
| 88 |
+
<ode>
|
| 89 |
+
<mu>${mu}</mu>
|
| 90 |
+
<mu2>${mu}</mu2>
|
| 91 |
+
</ode>
|
| 92 |
+
</friction>
|
| 93 |
+
<bounce/>
|
| 94 |
+
</surface>
|
| 95 |
+
</collision>
|
| 96 |
+
</gazebo>
|
| 97 |
+
</xacro:macro> -->
|
| 98 |
+
<!-- arm_type: Namespace of the robot arm. Serves to differentiate between arms in case of multiple instances. -->
|
| 99 |
+
<!-- joint_limits: description of the joint limits that comes from a YAML file. Example definition: ${xacro.load_yaml('$(find openarm_description)/robots/fr3/joint_limits.yaml')} -->
|
| 100 |
+
<!-- kinematics: description of the kinematics that comes from a YAML file. Example definition: ${xacro.load_yaml('$(find openarm_description)/robots/fr3/kinematics.yaml')} -->
|
| 101 |
+
<!-- inertials: description of the inertials that comes from a YAML file. Example definition: ${xacro.load_yaml('$(find openarm_description)/robots/fr3/inertials.yaml')} -->
|
| 102 |
+
<!-- Is the robot being simulated in gazebo? -->
|
| 103 |
+
<!-- <xacro:arg name="gazebo" default="false" /> -->
|
| 104 |
+
<material name="light_gray">
|
| 105 |
+
<color rgba="0.4 0.4 0.4 1.0"/>
|
| 106 |
+
</material>
|
| 107 |
+
<material name="gray">
|
| 108 |
+
<color rgba="0.2117647058823529 0.2117647058823529 0.2117647058823529 1.0"/>
|
| 109 |
+
</material>
|
| 110 |
+
<material name="dark_gray">
|
| 111 |
+
<color rgba="0.1607843137254902 0.1607843137254902 0.1607843137254902 1.0"/>
|
| 112 |
+
</material>
|
| 113 |
+
<material name="light_black">
|
| 114 |
+
<color rgba="0.08 0.08 0.08 1.0"/>
|
| 115 |
+
</material>
|
| 116 |
+
<material name="black">
|
| 117 |
+
<color rgba="0.0 0.0 0.0 1.0"/>
|
| 118 |
+
</material>
|
| 119 |
+
<link name="world"/>
|
| 120 |
+
<joint name="openarm_body_world_joint" type="fixed">
|
| 121 |
+
<parent link="world"/>
|
| 122 |
+
<child link="openarm_body_link0"/>
|
| 123 |
+
<origin rpy="0 0 -2.36" xyz="0 0 0"/>
|
| 124 |
+
</joint>
|
| 125 |
+
<link name="openarm_body_link0">
|
| 126 |
+
<visual name="openarm_body_link0_visual">
|
| 127 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 128 |
+
<geometry>
|
| 129 |
+
<mesh filename="./meshes/body/v10/visual/body_link0.stl" scale="0.001 0.001 0.001"/>
|
| 130 |
+
</geometry>
|
| 131 |
+
<material name="light_black"/>
|
| 132 |
+
</visual>
|
| 133 |
+
<collision name="openarm_body_link0_collision">
|
| 134 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 135 |
+
<geometry>
|
| 136 |
+
</geometry>
|
| 137 |
+
</collision>
|
| 138 |
+
<inertial>
|
| 139 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 140 |
+
<mass value="13.89"/>
|
| 141 |
+
<inertia ixx="1.653" ixy="0.0" ixz="0.0" iyy="1.653" iyz="0.0" izz="0.051"/>
|
| 142 |
+
</inertial>
|
| 143 |
+
</link>
|
| 144 |
+
<!-- Define a property that defaults to 'arm_prefix_arm_type' concatenated with an underscore if 'no_prefix' is not set -->
|
| 145 |
+
<!-- <xacro:if value="${gazebo}">
|
| 146 |
+
<xacro:property name="connected_to" value="" />
|
| 147 |
+
</xacro:if> -->
|
| 148 |
+
<!-- <link name="${connected_to}">
|
| 149 |
+
</link> -->
|
| 150 |
+
<joint name="openarm_left_openarm_body_link0_joint" type="fixed">
|
| 151 |
+
<parent link="openarm_body_link0"/>
|
| 152 |
+
<child link="openarm_left_link0"/>
|
| 153 |
+
<origin rpy="-1.5708 0 0" xyz="0.0 0.031 0.698"/>
|
| 154 |
+
</joint>
|
| 155 |
+
<link name="openarm_left_link0">
|
| 156 |
+
<visual name="openarm_left_link0_visual">
|
| 157 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 158 |
+
<geometry>
|
| 159 |
+
<mesh filename="./meshes/arm/v10/visual/link0.stl" scale="0.001 -0.001 0.001"/>
|
| 160 |
+
</geometry>
|
| 161 |
+
<material name="light_black"/>
|
| 162 |
+
</visual>
|
| 163 |
+
<collision name="openarm_left_link0_collision">
|
| 164 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 165 |
+
<geometry>
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
</geometry>
|
| 169 |
+
</collision>
|
| 170 |
+
<inertial>
|
| 171 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0009483362816297526 0.0001580207020448382 0.03076860287587199"/>
|
| 172 |
+
<mass value="1.1432284943239561"/>
|
| 173 |
+
<inertia ixx="0.001128" ixy="-4e-06" ixz="-3.3e-05" iyy="0.000962" iyz="-7e-06" izz="0.00147"/>
|
| 174 |
+
</inertial>
|
| 175 |
+
</link>
|
| 176 |
+
<link name="openarm_left_link1">
|
| 177 |
+
<visual name="openarm_left_link1_visual">
|
| 178 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 0.0 -0.0625"/>
|
| 179 |
+
<geometry>
|
| 180 |
+
<mesh filename="./meshes/arm/v10/visual/link1.stl" scale="0.001 -0.001 0.001"/>
|
| 181 |
+
</geometry>
|
| 182 |
+
<material name="light_black"/>
|
| 183 |
+
</visual>
|
| 184 |
+
<collision name="openarm_left_link1_collision">
|
| 185 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 0.0 -0.0625"/>
|
| 186 |
+
<geometry>
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
</geometry>
|
| 190 |
+
</collision>
|
| 191 |
+
<inertial>
|
| 192 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0011467657911800769 3.319987657026362e-05 0.05395284380736254"/>
|
| 193 |
+
<mass value="1.1416684646202298"/>
|
| 194 |
+
<inertia ixx="0.001567" ixy="-1e-06" ixz="-2.9e-05" iyy="0.001273" iyz="-0.0" izz="0.001016"/>
|
| 195 |
+
</inertial>
|
| 196 |
+
</link>
|
| 197 |
+
<joint name="L_J1" type="revolute">
|
| 198 |
+
<origin rpy="0 0 0" xyz="0.0 0.0 0.0625"/>
|
| 199 |
+
<parent link="openarm_left_link0"/>
|
| 200 |
+
<child link="openarm_left_link1"/>
|
| 201 |
+
<axis xyz="0 0 1"/>
|
| 202 |
+
<limit effort="54" lower="-3.490659" upper="1.3962629999999998" velocity="45"/>
|
| 203 |
+
</joint>
|
| 204 |
+
<link name="openarm_left_link2">
|
| 205 |
+
<visual name="openarm_left_link2_visual">
|
| 206 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0301 0.0 -0.1225"/>
|
| 207 |
+
<geometry>
|
| 208 |
+
<mesh filename="./meshes/arm/v10/visual/link2.stl" scale="0.001 -0.001 0.001"/>
|
| 209 |
+
</geometry>
|
| 210 |
+
<material name="light_black"/>
|
| 211 |
+
</visual>
|
| 212 |
+
<collision name="openarm_left_link2_collision">
|
| 213 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0301 0.0 -0.1225"/>
|
| 214 |
+
<geometry>
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
</geometry>
|
| 218 |
+
</collision>
|
| 219 |
+
<inertial>
|
| 220 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.00839629182351943 -2.0145102027597523e-08 0.03256649300522363"/>
|
| 221 |
+
<mass value="0.2775092746011571"/>
|
| 222 |
+
<inertia ixx="0.000359" ixy="-0.0" ixz="-0.000109" iyy="0.000376" iyz="0.0" izz="0.000232"/>
|
| 223 |
+
</inertial>
|
| 224 |
+
</link>
|
| 225 |
+
<joint name="L_J2" type="revolute">
|
| 226 |
+
<origin rpy="-1.57079632679 0 0" xyz="-0.0301 0.0 0.06"/>
|
| 227 |
+
<parent link="openarm_left_link1"/>
|
| 228 |
+
<child link="openarm_left_link2"/>
|
| 229 |
+
<axis xyz="-1 0 0"/>
|
| 230 |
+
<limit effort="54" lower="-3.3161253267948965" upper="0.17453267320510335" velocity="45"/>
|
| 231 |
+
</joint>
|
| 232 |
+
<link name="openarm_left_link3">
|
| 233 |
+
<visual name="openarm_left_link3_visual">
|
| 234 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.18875"/>
|
| 235 |
+
<geometry>
|
| 236 |
+
<mesh filename="./meshes/arm/v10/visual/link3.stl" scale="0.001 -0.001 0.001"/>
|
| 237 |
+
</geometry>
|
| 238 |
+
<material name="dark_gray"/>
|
| 239 |
+
</visual>
|
| 240 |
+
<collision name="openarm_left_link3_collision">
|
| 241 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.18875"/>
|
| 242 |
+
<geometry>
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
</geometry>
|
| 246 |
+
</collision>
|
| 247 |
+
<inertial>
|
| 248 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.002104752099628911 0.0005549085042607548 0.08847470545721961"/>
|
| 249 |
+
<mass value="1.073863338202347"/>
|
| 250 |
+
<inertia ixx="0.004372" ixy="-0.0" ixz="1.1e-05" iyy="0.004319" iyz="-3.6e-05" izz="0.000661"/>
|
| 251 |
+
</inertial>
|
| 252 |
+
</link>
|
| 253 |
+
<joint name="L_J3" type="revolute">
|
| 254 |
+
<origin rpy="0 0 0" xyz="0.0301 0.0 0.06625"/>
|
| 255 |
+
<parent link="openarm_left_link2"/>
|
| 256 |
+
<child link="openarm_left_link3"/>
|
| 257 |
+
<axis xyz="0 0 1"/>
|
| 258 |
+
<limit effort="28" lower="-1.570796" upper="1.570796" velocity="8"/>
|
| 259 |
+
</joint>
|
| 260 |
+
<link name="openarm_left_link4">
|
| 261 |
+
<visual name="openarm_left_link4_visual">
|
| 262 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0315 -0.3425"/>
|
| 263 |
+
<geometry>
|
| 264 |
+
<mesh filename="./meshes/arm/v10/visual/link4.stl" scale="0.001 0.001 0.001"/>
|
| 265 |
+
</geometry>
|
| 266 |
+
<material name="gray"/>
|
| 267 |
+
</visual>
|
| 268 |
+
<collision name="openarm_left_link4_collision">
|
| 269 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0315 -0.3425"/>
|
| 270 |
+
<geometry>
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
</geometry>
|
| 274 |
+
</collision>
|
| 275 |
+
<inertial>
|
| 276 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0029006831074562967 -0.03030575826634669 0.06339637422196209"/>
|
| 277 |
+
<mass value="1.3699337287025453"/>
|
| 278 |
+
<inertia ixx="0.001577" ixy="-5e-06" ixz="-7.5e-05" iyy="0.001346" iyz="0.000108" izz="0.001104"/>
|
| 279 |
+
</inertial>
|
| 280 |
+
</link>
|
| 281 |
+
<joint name="L_J4" type="revolute">
|
| 282 |
+
<origin rpy="0 0 0" xyz="-0.0 0.0315 0.15375"/>
|
| 283 |
+
<parent link="openarm_left_link3"/>
|
| 284 |
+
<child link="openarm_left_link4"/>
|
| 285 |
+
<axis xyz="0 1 0"/>
|
| 286 |
+
<limit effort="28" lower="0.0" upper="2.443461" velocity="8"/>
|
| 287 |
+
</joint>
|
| 288 |
+
<link name="openarm_left_link5">
|
| 289 |
+
<visual name="openarm_left_link5_visual">
|
| 290 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.438"/>
|
| 291 |
+
<geometry>
|
| 292 |
+
<mesh filename="./meshes/arm/v10/visual/link5.stl" scale="0.001 -0.001 0.001"/>
|
| 293 |
+
</geometry>
|
| 294 |
+
<material name="dark_gray"/>
|
| 295 |
+
</visual>
|
| 296 |
+
<collision name="openarm_left_link5_collision">
|
| 297 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.438"/>
|
| 298 |
+
<geometry>
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
</geometry>
|
| 302 |
+
</collision>
|
| 303 |
+
<inertial>
|
| 304 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.003049665024221911 0.0008866902457326625 0.043079803024980934"/>
|
| 305 |
+
<mass value="0.5506588026168502"/>
|
| 306 |
+
<inertia ixx="0.000423" ixy="-8e-06" ixz="6e-06" iyy="0.000445" iyz="-6e-06" izz="0.000324"/>
|
| 307 |
+
</inertial>
|
| 308 |
+
</link>
|
| 309 |
+
<joint name="L_J5" type="revolute">
|
| 310 |
+
<origin rpy="0 0 0" xyz="0.0 -0.0315 0.0955"/>
|
| 311 |
+
<parent link="openarm_left_link4"/>
|
| 312 |
+
<child link="openarm_left_link5"/>
|
| 313 |
+
<axis xyz="0 0 1"/>
|
| 314 |
+
<limit effort="10" lower="-1.570796" upper="1.570796" velocity="30"/>
|
| 315 |
+
</joint>
|
| 316 |
+
<link name="openarm_left_link6">
|
| 317 |
+
<visual name="openarm_left_link6_visual">
|
| 318 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0375 -0.0 -0.5585"/>
|
| 319 |
+
<geometry>
|
| 320 |
+
<mesh filename="./meshes/arm/v10/visual/link6.stl" scale="0.001 -0.001 0.001"/>
|
| 321 |
+
</geometry>
|
| 322 |
+
<material name="light_black"/>
|
| 323 |
+
</visual>
|
| 324 |
+
<collision name="openarm_left_link6_collision">
|
| 325 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0375 -0.0 -0.5585"/>
|
| 326 |
+
<geometry>
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
</geometry>
|
| 330 |
+
</collision>
|
| 331 |
+
<inertial>
|
| 332 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.037136587005447405 0.00033230528343419053 -9.498374522309838e-05"/>
|
| 333 |
+
<mass value="0.3540202773187987"/>
|
| 334 |
+
<inertia ixx="0.000143" ixy="4e-06" ixz="0.0" iyy="0.000157" iyz="1e-06" izz="0.000159"/>
|
| 335 |
+
</inertial>
|
| 336 |
+
</link>
|
| 337 |
+
<joint name="L_J6" type="revolute">
|
| 338 |
+
<origin rpy="0 0 0" xyz="0.0375 0.0 0.1205"/>
|
| 339 |
+
<parent link="openarm_left_link5"/>
|
| 340 |
+
<child link="openarm_left_link6"/>
|
| 341 |
+
<axis xyz="1 0 0"/>
|
| 342 |
+
<limit effort="10" lower="-0.785398" upper="0.785398" velocity="30"/>
|
| 343 |
+
</joint>
|
| 344 |
+
<link name="openarm_left_link7">
|
| 345 |
+
<visual name="openarm_left_link7_visual">
|
| 346 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0 -0.5585"/>
|
| 347 |
+
<geometry>
|
| 348 |
+
<mesh filename="./meshes/arm/v10/visual/link7.stl" scale="0.001 -0.001 0.001"/>
|
| 349 |
+
</geometry>
|
| 350 |
+
<material name="gray"/>
|
| 351 |
+
</visual>
|
| 352 |
+
<collision name="openarm_left_link7_collision">
|
| 353 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0 -0.5585"/>
|
| 354 |
+
<geometry>
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
</geometry>
|
| 358 |
+
</collision>
|
| 359 |
+
<inertial>
|
| 360 |
+
<origin rpy="0.0 0.0 0.0" xyz="6.875510271106056e-05 -0.01766175250761268 0.06651945409987448"/>
|
| 361 |
+
<mass value="0.5499771327380578"/>
|
| 362 |
+
<inertia ixx="0.000639" ixy="0.0" ixz="-0.0" iyy="0.000497" iyz="8.9e-05" izz="0.000342"/>
|
| 363 |
+
</inertial>
|
| 364 |
+
</link>
|
| 365 |
+
<joint name="L_J7" type="revolute">
|
| 366 |
+
<origin rpy="0 0 0" xyz="-0.0375 0.0 0.0"/>
|
| 367 |
+
<parent link="openarm_left_link6"/>
|
| 368 |
+
<child link="openarm_left_link7"/>
|
| 369 |
+
<axis xyz="0 -1 0"/>
|
| 370 |
+
<limit effort="10" lower="-1.570796" upper="1.570796" velocity="30"/>
|
| 371 |
+
</joint>
|
| 372 |
+
<link name="openarm_left_link8"/>
|
| 373 |
+
<joint name="L_J8" type="fixed">
|
| 374 |
+
<origin rpy="0 0 0" xyz="1e-06 0.0205 0.0"/>
|
| 375 |
+
<parent link="openarm_left_link7"/>
|
| 376 |
+
<child link="openarm_left_link8"/>
|
| 377 |
+
</joint>
|
| 378 |
+
<!-- Define a property that defaults to 'arm_prefix_arm_type' concatenated with an underscore if 'no_prefix' is not set -->
|
| 379 |
+
<!-- <xacro:if value="${gazebo}">
|
| 380 |
+
<xacro:property name="connected_to" value="" />
|
| 381 |
+
</xacro:if> -->
|
| 382 |
+
<!-- <link name="${connected_to}">
|
| 383 |
+
</link> -->
|
| 384 |
+
<joint name="openarm_right_openarm_body_link0_joint" type="fixed">
|
| 385 |
+
<parent link="openarm_body_link0"/>
|
| 386 |
+
<child link="openarm_right_link0"/>
|
| 387 |
+
<origin rpy="1.5708 0 0" xyz="0.0 -0.031 0.698"/>
|
| 388 |
+
</joint>
|
| 389 |
+
<link name="openarm_right_link0">
|
| 390 |
+
<visual name="openarm_right_link0_visual">
|
| 391 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 392 |
+
<geometry>
|
| 393 |
+
<mesh filename="./meshes/arm/v10/visual/link0.stl" scale="0.001 0.001 0.001"/>
|
| 394 |
+
</geometry>
|
| 395 |
+
<material name="light_black"/>
|
| 396 |
+
</visual>
|
| 397 |
+
<collision name="openarm_right_link0_collision">
|
| 398 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
|
| 399 |
+
<geometry>
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
</geometry>
|
| 403 |
+
</collision>
|
| 404 |
+
<inertial>
|
| 405 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0009483362816297526 0.0001580207020448382 0.03076860287587199"/>
|
| 406 |
+
<mass value="1.1432284943239561"/>
|
| 407 |
+
<inertia ixx="0.001128" ixy="-4e-06" ixz="-3.3e-05" iyy="0.000962" iyz="-7e-06" izz="0.00147"/>
|
| 408 |
+
</inertial>
|
| 409 |
+
</link>
|
| 410 |
+
<link name="openarm_right_link1">
|
| 411 |
+
<visual name="openarm_right_link1_visual">
|
| 412 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 0.0 -0.0625"/>
|
| 413 |
+
<geometry>
|
| 414 |
+
<mesh filename="./meshes/arm/v10/visual/link1.stl" scale="0.001 0.001 0.001"/>
|
| 415 |
+
</geometry>
|
| 416 |
+
<material name="light_black"/>
|
| 417 |
+
</visual>
|
| 418 |
+
<collision name="openarm_right_link1_collision">
|
| 419 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 0.0 -0.0625"/>
|
| 420 |
+
<geometry>
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
</geometry>
|
| 424 |
+
</collision>
|
| 425 |
+
<inertial>
|
| 426 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0011467657911800769 3.319987657026362e-05 0.05395284380736254"/>
|
| 427 |
+
<mass value="1.1416684646202298"/>
|
| 428 |
+
<inertia ixx="0.001567" ixy="-1e-06" ixz="-2.9e-05" iyy="0.001273" iyz="-0.0" izz="0.001016"/>
|
| 429 |
+
</inertial>
|
| 430 |
+
</link>
|
| 431 |
+
<joint name="R_J1" type="revolute">
|
| 432 |
+
<origin rpy="0 0 0" xyz="0.0 0.0 0.0625"/>
|
| 433 |
+
<parent link="openarm_right_link0"/>
|
| 434 |
+
<child link="openarm_right_link1"/>
|
| 435 |
+
<axis xyz="0 0 1"/>
|
| 436 |
+
<limit effort="54" lower="-1.396263" upper="3.490659" velocity="45"/>
|
| 437 |
+
</joint>
|
| 438 |
+
<link name="openarm_right_link2">
|
| 439 |
+
<visual name="openarm_right_link2_visual">
|
| 440 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0301 0.0 -0.1225"/>
|
| 441 |
+
<geometry>
|
| 442 |
+
<mesh filename="./meshes/arm/v10/visual/link2.stl" scale="0.001 0.001 0.001"/>
|
| 443 |
+
</geometry>
|
| 444 |
+
<material name="light_black"/>
|
| 445 |
+
</visual>
|
| 446 |
+
<collision name="openarm_right_link2_collision">
|
| 447 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0301 0.0 -0.1225"/>
|
| 448 |
+
<geometry>
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
</geometry>
|
| 452 |
+
</collision>
|
| 453 |
+
<inertial>
|
| 454 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.00839629182351943 -2.0145102027597523e-08 0.03256649300522363"/>
|
| 455 |
+
<mass value="0.2775092746011571"/>
|
| 456 |
+
<inertia ixx="0.000359" ixy="-0.0" ixz="-0.000109" iyy="0.000376" iyz="0.0" izz="0.000232"/>
|
| 457 |
+
</inertial>
|
| 458 |
+
</link>
|
| 459 |
+
<joint name="R_J2" type="revolute">
|
| 460 |
+
<origin rpy="1.57079632679 0 0" xyz="-0.0301 0.0 0.06"/>
|
| 461 |
+
<parent link="openarm_right_link1"/>
|
| 462 |
+
<child link="openarm_right_link2"/>
|
| 463 |
+
<axis xyz="-1 0 0"/>
|
| 464 |
+
<limit effort="54" lower="-0.17453267320510335" upper="3.3161253267948965" velocity="45"/>
|
| 465 |
+
</joint>
|
| 466 |
+
<link name="openarm_right_link3">
|
| 467 |
+
<visual name="openarm_right_link3_visual">
|
| 468 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.18875"/>
|
| 469 |
+
<geometry>
|
| 470 |
+
<mesh filename="./meshes/arm/v10/visual/link3.stl" scale="0.001 0.001 0.001"/>
|
| 471 |
+
</geometry>
|
| 472 |
+
<material name="dark_gray"/>
|
| 473 |
+
</visual>
|
| 474 |
+
<collision name="openarm_right_link3_collision">
|
| 475 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.18875"/>
|
| 476 |
+
<geometry>
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
</geometry>
|
| 480 |
+
</collision>
|
| 481 |
+
<inertial>
|
| 482 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.002104752099628911 0.0005549085042607548 0.08847470545721961"/>
|
| 483 |
+
<mass value="1.073863338202347"/>
|
| 484 |
+
<inertia ixx="0.004372" ixy="-0.0" ixz="1.1e-05" iyy="0.004319" iyz="-3.6e-05" izz="0.000661"/>
|
| 485 |
+
</inertial>
|
| 486 |
+
</link>
|
| 487 |
+
<joint name="R_J3" type="revolute">
|
| 488 |
+
<origin rpy="0 0 0" xyz="0.0301 0.0 0.06625"/>
|
| 489 |
+
<parent link="openarm_right_link2"/>
|
| 490 |
+
<child link="openarm_right_link3"/>
|
| 491 |
+
<axis xyz="0 0 1"/>
|
| 492 |
+
<limit effort="28" lower="-1.570796" upper="1.570796" velocity="8"/>
|
| 493 |
+
</joint>
|
| 494 |
+
<link name="openarm_right_link4">
|
| 495 |
+
<visual name="openarm_right_link4_visual">
|
| 496 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0315 -0.3425"/>
|
| 497 |
+
<geometry>
|
| 498 |
+
<mesh filename="./meshes/arm/v10/visual/link4.stl" scale="0.001 0.001 0.001"/>
|
| 499 |
+
</geometry>
|
| 500 |
+
<material name="gray"/>
|
| 501 |
+
</visual>
|
| 502 |
+
<collision name="openarm_right_link4_collision">
|
| 503 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0315 -0.3425"/>
|
| 504 |
+
<geometry>
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
</geometry>
|
| 508 |
+
</collision>
|
| 509 |
+
<inertial>
|
| 510 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0029006831074562967 -0.03030575826634669 0.06339637422196209"/>
|
| 511 |
+
<mass value="1.3699337287025453"/>
|
| 512 |
+
<inertia ixx="0.001577" ixy="-5e-06" ixz="-7.5e-05" iyy="0.001346" iyz="0.000108" izz="0.001104"/>
|
| 513 |
+
</inertial>
|
| 514 |
+
</link>
|
| 515 |
+
<joint name="R_J4" type="revolute">
|
| 516 |
+
<origin rpy="0 0 0" xyz="-0.0 0.0315 0.15375"/>
|
| 517 |
+
<parent link="openarm_right_link3"/>
|
| 518 |
+
<child link="openarm_right_link4"/>
|
| 519 |
+
<axis xyz="0 1 0"/>
|
| 520 |
+
<limit effort="28" lower="0.0" upper="2.443461" velocity="8"/>
|
| 521 |
+
</joint>
|
| 522 |
+
<link name="openarm_right_link5">
|
| 523 |
+
<visual name="openarm_right_link5_visual">
|
| 524 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.438"/>
|
| 525 |
+
<geometry>
|
| 526 |
+
<mesh filename="./meshes/arm/v10/visual/link5.stl" scale="0.001 0.001 0.001"/>
|
| 527 |
+
</geometry>
|
| 528 |
+
<material name="dark_gray"/>
|
| 529 |
+
</visual>
|
| 530 |
+
<collision name="openarm_right_link5_collision">
|
| 531 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0 -0.0 -0.438"/>
|
| 532 |
+
<geometry>
|
| 533 |
+
|
| 534 |
+
|
| 535 |
+
</geometry>
|
| 536 |
+
</collision>
|
| 537 |
+
<inertial>
|
| 538 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.003049665024221911 0.0008866902457326625 0.043079803024980934"/>
|
| 539 |
+
<mass value="0.5506588026168502"/>
|
| 540 |
+
<inertia ixx="0.000423" ixy="-8e-06" ixz="6e-06" iyy="0.000445" iyz="-6e-06" izz="0.000324"/>
|
| 541 |
+
</inertial>
|
| 542 |
+
</link>
|
| 543 |
+
<joint name="R_J5" type="revolute">
|
| 544 |
+
<origin rpy="0 0 0" xyz="0.0 -0.0315 0.0955"/>
|
| 545 |
+
<parent link="openarm_right_link4"/>
|
| 546 |
+
<child link="openarm_right_link5"/>
|
| 547 |
+
<axis xyz="0 0 1"/>
|
| 548 |
+
<limit effort="10" lower="-1.570796" upper="1.570796" velocity="30"/>
|
| 549 |
+
</joint>
|
| 550 |
+
<link name="openarm_right_link6">
|
| 551 |
+
<visual name="openarm_right_link6_visual">
|
| 552 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0375 -0.0 -0.5585"/>
|
| 553 |
+
<geometry>
|
| 554 |
+
<mesh filename="./meshes/arm/v10/visual/link6.stl" scale="0.001 0.001 0.001"/>
|
| 555 |
+
</geometry>
|
| 556 |
+
<material name="light_black"/>
|
| 557 |
+
</visual>
|
| 558 |
+
<collision name="openarm_right_link6_collision">
|
| 559 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.0375 -0.0 -0.5585"/>
|
| 560 |
+
<geometry>
|
| 561 |
+
|
| 562 |
+
|
| 563 |
+
</geometry>
|
| 564 |
+
</collision>
|
| 565 |
+
<inertial>
|
| 566 |
+
<origin rpy="0.0 0.0 0.0" xyz="-0.037136587005447405 0.00033230528343419053 -9.498374522309838e-05"/>
|
| 567 |
+
<mass value="0.3540202773187987"/>
|
| 568 |
+
<inertia ixx="0.000143" ixy="4e-06" ixz="0.0" iyy="0.000157" iyz="1e-06" izz="0.000159"/>
|
| 569 |
+
</inertial>
|
| 570 |
+
</link>
|
| 571 |
+
<joint name="R_J6" type="revolute">
|
| 572 |
+
<origin rpy="0 0 0" xyz="0.0375 0.0 0.1205"/>
|
| 573 |
+
<parent link="openarm_right_link5"/>
|
| 574 |
+
<child link="openarm_right_link6"/>
|
| 575 |
+
<axis xyz="1 0 0"/>
|
| 576 |
+
<limit effort="10" lower="-0.785398" upper="0.785398" velocity="30"/>
|
| 577 |
+
</joint>
|
| 578 |
+
<link name="openarm_right_link7">
|
| 579 |
+
<visual name="openarm_right_link7_visual">
|
| 580 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0 -0.5585"/>
|
| 581 |
+
<geometry>
|
| 582 |
+
<mesh filename="./meshes/arm/v10/visual/link7.stl" scale="0.001 0.001 0.001"/>
|
| 583 |
+
</geometry>
|
| 584 |
+
<material name="gray"/>
|
| 585 |
+
</visual>
|
| 586 |
+
<collision name="openarm_right_link7_collision">
|
| 587 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.0 -0.5585"/>
|
| 588 |
+
<geometry>
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
</geometry>
|
| 592 |
+
</collision>
|
| 593 |
+
<inertial>
|
| 594 |
+
<origin rpy="0.0 0.0 0.0" xyz="6.875510271106056e-05 -0.01766175250761268 0.06651945409987448"/>
|
| 595 |
+
<mass value="0.5499771327380578"/>
|
| 596 |
+
<inertia ixx="0.000639" ixy="0.0" ixz="-0.0" iyy="0.000497" iyz="8.9e-05" izz="0.000342"/>
|
| 597 |
+
</inertial>
|
| 598 |
+
</link>
|
| 599 |
+
<joint name="R_J7" type="revolute">
|
| 600 |
+
<origin rpy="0 0 0" xyz="-0.0375 0.0 0.0"/>
|
| 601 |
+
<parent link="openarm_right_link6"/>
|
| 602 |
+
<child link="openarm_right_link7"/>
|
| 603 |
+
<axis xyz="0 1 0"/>
|
| 604 |
+
<limit effort="10" lower="-1.570796" upper="1.570796" velocity="30"/>
|
| 605 |
+
</joint>
|
| 606 |
+
<link name="openarm_right_link8"/>
|
| 607 |
+
<joint name="R_J8" type="fixed">
|
| 608 |
+
<origin rpy="0 0 0" xyz="1e-06 0.0205 0.0"/>
|
| 609 |
+
<parent link="openarm_right_link7"/>
|
| 610 |
+
<child link="openarm_right_link8"/>
|
| 611 |
+
</joint>
|
| 612 |
+
<link name="openarm_left_hand">
|
| 613 |
+
<visual name="openarm_left_hand_visual">
|
| 614 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.005 -0.6585"/>
|
| 615 |
+
<geometry>
|
| 616 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/hand.stl" scale="0.001 0.001 0.001"/>
|
| 617 |
+
</geometry>
|
| 618 |
+
<material name="light_gray"/>
|
| 619 |
+
</visual>
|
| 620 |
+
<collision name="openarm_left_hand_collision">
|
| 621 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.005 -0.6585"/>
|
| 622 |
+
<geometry>
|
| 623 |
+
|
| 624 |
+
</geometry>
|
| 625 |
+
</collision>
|
| 626 |
+
<inertial>
|
| 627 |
+
<origin rpy="0 0 0" xyz="0.0 0.002 0.01"/>
|
| 628 |
+
<mass value="0.15"/>
|
| 629 |
+
<inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.00025" iyz="0" izz="0.00017"/>
|
| 630 |
+
</inertial>
|
| 631 |
+
</link>
|
| 632 |
+
<!-- <link name="${ee_prefix}hand"/> -->
|
| 633 |
+
<!-- <joint name="${ee_prefix}hand_joint" type="fixed"> -->
|
| 634 |
+
<joint name="left_openarm_hand_joint" type="fixed">
|
| 635 |
+
<parent link="openarm_left_link8"/>
|
| 636 |
+
<child link="openarm_left_hand"/>
|
| 637 |
+
<origin rpy="0 0 0" xyz="0 -0.025 0.1001"/>
|
| 638 |
+
</joint>
|
| 639 |
+
<!-- Define the hand_tcp frame -->
|
| 640 |
+
<link name="openarm_left_hand_tcp"/>
|
| 641 |
+
<joint name="openarm_left_hand_tcp_joint" type="fixed">
|
| 642 |
+
<origin rpy="0 0 0" xyz="0 -0.0 0.08"/>
|
| 643 |
+
<parent link="openarm_left_hand"/>
|
| 644 |
+
<child link="openarm_left_hand_tcp"/>
|
| 645 |
+
</joint>
|
| 646 |
+
<link name="openarm_left_left_finger">
|
| 647 |
+
<visual name="openarm_left_left_finger_visual">
|
| 648 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.05 -0.673001"/>
|
| 649 |
+
<geometry>
|
| 650 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/finger.stl" scale="0.001 0.001 0.001"/>
|
| 651 |
+
</geometry>
|
| 652 |
+
<material name="light_black"/>
|
| 653 |
+
</visual>
|
| 654 |
+
<collision name="openarm_left_left_finger_collision">
|
| 655 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.05 -0.673001"/>
|
| 656 |
+
<geometry>
|
| 657 |
+
|
| 658 |
+
</geometry>
|
| 659 |
+
</collision>
|
| 660 |
+
<inertial>
|
| 661 |
+
<origin rpy="0 0 0" xyz="0.0064528 0.01702 0.0219685"/>
|
| 662 |
+
<mass value="0.03602545343277134"/>
|
| 663 |
+
<inertia ixx="2.3749999999999997e-06" ixy="0" ixz="0" iyy="2.3749999999999997e-06" iyz="0" izz="7.5e-07"/>
|
| 664 |
+
</inertial>
|
| 665 |
+
</link>
|
| 666 |
+
<link name="openarm_left_right_finger">
|
| 667 |
+
<visual name="openarm_left_right_finger_visual">
|
| 668 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.05 -0.673001"/>
|
| 669 |
+
<geometry>
|
| 670 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/finger.stl" scale="0.001 -0.001 0.001"/>
|
| 671 |
+
</geometry>
|
| 672 |
+
<material name="light_black"/>
|
| 673 |
+
</visual>
|
| 674 |
+
<collision name="openarm_left_right_finger_collision">
|
| 675 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.05 -0.673001"/>
|
| 676 |
+
<geometry>
|
| 677 |
+
|
| 678 |
+
</geometry>
|
| 679 |
+
</collision>
|
| 680 |
+
<inertial>
|
| 681 |
+
<origin rpy="0 0 0" xyz="0.0064528 -0.01702 0.0219685"/>
|
| 682 |
+
<mass value="0.03602545343277134"/>
|
| 683 |
+
<inertia ixx="2.3749999999999997e-06" ixy="0" ixz="0" iyy="2.3749999999999997e-06" iyz="0" izz="7.5e-07"/>
|
| 684 |
+
</inertial>
|
| 685 |
+
</link>
|
| 686 |
+
<joint name="L_EE" type="prismatic">
|
| 687 |
+
<parent link="openarm_left_hand"/>
|
| 688 |
+
<child link="openarm_left_right_finger"/>
|
| 689 |
+
<origin rpy="0 0 0" xyz="0 0.00 0.015"/>
|
| 690 |
+
<axis xyz="0 -1 0"/>
|
| 691 |
+
<limit effort="333" lower="0.0" upper="0.044" velocity="10.0"/>
|
| 692 |
+
</joint>
|
| 693 |
+
<joint name="L_EE2" type="prismatic">
|
| 694 |
+
<parent link="openarm_left_hand"/>
|
| 695 |
+
<child link="openarm_left_left_finger"/>
|
| 696 |
+
<origin rpy="0 0 0" xyz="0 0.012 0.015"/>
|
| 697 |
+
<axis xyz="0 1 0"/>
|
| 698 |
+
<limit effort="333" lower="0.0" upper="0.044" velocity="10.0"/>
|
| 699 |
+
<mimic joint="L_EE"/>
|
| 700 |
+
</joint>
|
| 701 |
+
<link name="openarm_right_hand">
|
| 702 |
+
<visual name="openarm_right_hand_visual">
|
| 703 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.005 -0.6585"/>
|
| 704 |
+
<geometry>
|
| 705 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/hand.stl" scale="0.001 0.001 0.001"/>
|
| 706 |
+
</geometry>
|
| 707 |
+
<material name="light_gray"/>
|
| 708 |
+
</visual>
|
| 709 |
+
<collision name="openarm_right_hand_collision">
|
| 710 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.005 -0.6585"/>
|
| 711 |
+
<geometry>
|
| 712 |
+
|
| 713 |
+
</geometry>
|
| 714 |
+
</collision>
|
| 715 |
+
<inertial>
|
| 716 |
+
<origin rpy="0 0 0" xyz="0.0 0.002 0.01"/>
|
| 717 |
+
<mass value="0.15"/>
|
| 718 |
+
<inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.00025" iyz="0" izz="0.00017"/>
|
| 719 |
+
</inertial>
|
| 720 |
+
</link>
|
| 721 |
+
<!-- <link name="${ee_prefix}hand"/> -->
|
| 722 |
+
<!-- <joint name="${ee_prefix}hand_joint" type="fixed"> -->
|
| 723 |
+
<joint name="right_openarm_hand_joint" type="fixed">
|
| 724 |
+
<parent link="openarm_right_link8"/>
|
| 725 |
+
<child link="openarm_right_hand"/>
|
| 726 |
+
<origin rpy="0 0 0" xyz="0 -0.025 0.1001"/>
|
| 727 |
+
</joint>
|
| 728 |
+
<!-- Define the hand_tcp frame -->
|
| 729 |
+
<link name="openarm_right_hand_tcp"/>
|
| 730 |
+
<joint name="openarm_right_hand_tcp_joint" type="fixed">
|
| 731 |
+
<origin rpy="0 0 0" xyz="0 -0.0 0.08"/>
|
| 732 |
+
<parent link="openarm_right_hand"/>
|
| 733 |
+
<child link="openarm_right_hand_tcp"/>
|
| 734 |
+
</joint>
|
| 735 |
+
<link name="openarm_right_left_finger">
|
| 736 |
+
<visual name="openarm_right_left_finger_visual">
|
| 737 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.05 -0.673001"/>
|
| 738 |
+
<geometry>
|
| 739 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/finger.stl" scale="0.001 0.001 0.001"/>
|
| 740 |
+
</geometry>
|
| 741 |
+
<material name="light_black"/>
|
| 742 |
+
</visual>
|
| 743 |
+
<collision name="openarm_right_left_finger_collision">
|
| 744 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 -0.05 -0.673001"/>
|
| 745 |
+
<geometry>
|
| 746 |
+
|
| 747 |
+
</geometry>
|
| 748 |
+
</collision>
|
| 749 |
+
<inertial>
|
| 750 |
+
<origin rpy="0 0 0" xyz="0.0064528 0.01702 0.0219685"/>
|
| 751 |
+
<mass value="0.03602545343277134"/>
|
| 752 |
+
<inertia ixx="2.3749999999999997e-06" ixy="0" ixz="0" iyy="2.3749999999999997e-06" iyz="0" izz="7.5e-07"/>
|
| 753 |
+
</inertial>
|
| 754 |
+
</link>
|
| 755 |
+
<link name="openarm_right_right_finger">
|
| 756 |
+
<visual name="openarm_right_right_finger_visual">
|
| 757 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.05 -0.673001"/>
|
| 758 |
+
<geometry>
|
| 759 |
+
<mesh filename="./meshes/ee/openarm_hand/visual/finger.stl" scale="0.001 -0.001 0.001"/>
|
| 760 |
+
</geometry>
|
| 761 |
+
<material name="light_black"/>
|
| 762 |
+
</visual>
|
| 763 |
+
<collision name="openarm_right_right_finger_collision">
|
| 764 |
+
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.05 -0.673001"/>
|
| 765 |
+
<geometry>
|
| 766 |
+
|
| 767 |
+
</geometry>
|
| 768 |
+
</collision>
|
| 769 |
+
<inertial>
|
| 770 |
+
<origin rpy="0 0 0" xyz="0.0064528 -0.01702 0.0219685"/>
|
| 771 |
+
<mass value="0.03602545343277134"/>
|
| 772 |
+
<inertia ixx="2.3749999999999997e-06" ixy="0" ixz="0" iyy="2.3749999999999997e-06" iyz="0" izz="7.5e-07"/>
|
| 773 |
+
</inertial>
|
| 774 |
+
</link>
|
| 775 |
+
<joint name="R_EE" type="prismatic">
|
| 776 |
+
<parent link="openarm_right_hand"/>
|
| 777 |
+
<child link="openarm_right_right_finger"/>
|
| 778 |
+
<origin rpy="0 0 0" xyz="0 0.00 0.015"/>
|
| 779 |
+
<axis xyz="0 -1 0"/>
|
| 780 |
+
<limit effort="333" lower="0.0" upper="0.044" velocity="10.0"/>
|
| 781 |
+
</joint>
|
| 782 |
+
<joint name="R_EE2" type="prismatic">
|
| 783 |
+
<parent link="openarm_right_hand"/>
|
| 784 |
+
<child link="openarm_right_left_finger"/>
|
| 785 |
+
<origin rpy="0 0 0" xyz="0 0.012 0.015"/>
|
| 786 |
+
<axis xyz="0 1 0"/>
|
| 787 |
+
<limit effort="333" lower="0.0" upper="0.044" velocity="10.0"/>
|
| 788 |
+
<mimic joint="R_EE"/>
|
| 789 |
+
</joint>
|
| 790 |
+
<!-- <xacro:if value="${gazebo}">
|
| 791 |
+
<xacro:if value="${parent != ''}">
|
| 792 |
+
<xacro:if value="${parent == 'world'}">
|
| 793 |
+
<link name="${parent}" />
|
| 794 |
+
</xacro:if>
|
| 795 |
+
<joint name="${parent}_joint" type="fixed">
|
| 796 |
+
<origin xyz="${xyz}" rpy="${rpy}" />
|
| 797 |
+
<parent link="${parent}" />
|
| 798 |
+
<child link="${arm_type}_link0" />
|
| 799 |
+
</joint>
|
| 800 |
+
</xacro:if> -->
|
| 801 |
+
<!-- <xacro:gazebo-joint joint="${arm_type}_joint1" transmission="hardware_interface/PositionJointInterface" />
|
| 802 |
+
<xacro:gazebo-joint joint="${arm_type}_joint2" transmission="hardware_interface/PositionJointInterface" />
|
| 803 |
+
<xacro:gazebo-joint joint="${arm_type}_joint3" transmission="hardware_interface/PositionJointInterface" />
|
| 804 |
+
<xacro:gazebo-joint joint="${arm_type}_joint4" transmission="hardware_interface/PositionJointInterface" />
|
| 805 |
+
<xacro:gazebo-joint joint="${arm_type}_joint5" transmission="hardware_interface/PositionJointInterface" />
|
| 806 |
+
<xacro:gazebo-joint joint="${arm_type}_joint6" transmission="hardware_interface/PositionJointInterface" />
|
| 807 |
+
<xacro:gazebo-joint joint="${arm_type}_joint7" transmission="hardware_interface/PositionJointInterface" />
|
| 808 |
+
|
| 809 |
+
<xacro:gazebo-joint joint="${arm_type}_joint1" transmission="hardware_interface/VelocityJointInterface" />
|
| 810 |
+
<xacro:gazebo-joint joint="${arm_type}_joint2" transmission="hardware_interface/VelocityJointInterface" />
|
| 811 |
+
<xacro:gazebo-joint joint="${arm_type}_joint3" transmission="hardware_interface/VelocityJointInterface" />
|
| 812 |
+
<xacro:gazebo-joint joint="${arm_type}_joint4" transmission="hardware_interface/VelocityJointInterface" />
|
| 813 |
+
<xacro:gazebo-joint joint="${arm_type}_joint5" transmission="hardware_interface/VelocityJointInterface" />
|
| 814 |
+
<xacro:gazebo-joint joint="${arm_type}_joint6" transmission="hardware_interface/VelocityJointInterface" />
|
| 815 |
+
<xacro:gazebo-joint joint="${arm_type}_joint7" transmission="hardware_interface/VelocityJointInterface" />
|
| 816 |
+
|
| 817 |
+
<xacro:gazebo-joint joint="${arm_type}_joint1" transmission="hardware_interface/EffortJointInterface" />
|
| 818 |
+
<xacro:gazebo-joint joint="${arm_type}_joint2" transmission="hardware_interface/EffortJointInterface" />
|
| 819 |
+
<xacro:gazebo-joint joint="${arm_type}_joint3" transmission="hardware_interface/EffortJointInterface" />
|
| 820 |
+
<xacro:gazebo-joint joint="${arm_type}_joint4" transmission="hardware_interface/EffortJointInterface" />
|
| 821 |
+
<xacro:gazebo-joint joint="${arm_type}_joint5" transmission="hardware_interface/EffortJointInterface" />
|
| 822 |
+
<xacro:gazebo-joint joint="${arm_type}_joint6" transmission="hardware_interface/EffortJointInterface" />
|
| 823 |
+
<xacro:gazebo-joint joint="${arm_type}_joint7" transmission="hardware_interface/EffortJointInterface" /> -->
|
| 824 |
+
<!-- <xacro:transmission-openarm-state arm_type="${arm_type}" />
|
| 825 |
+
<xacro:transmission-openarm-model arm_type="${arm_type}"
|
| 826 |
+
root="${arm_type}_joint1"
|
| 827 |
+
tip="${arm_type}_joint8"
|
| 828 |
+
/> -->
|
| 829 |
+
<!-- <xacro:if value="${ee_type == 'openarm_hand'}">
|
| 830 |
+
<xacro:gazebo-joint joint="${arm_type}_finger_joint1" transmission="hardware_interface/EffortJointInterface" />
|
| 831 |
+
<xacro:gazebo-joint joint="${arm_type}_finger_joint2" transmission="hardware_interface/EffortJointInterface" />
|
| 832 |
+
<xacro:gazebo-friction link="${arm_type}_leftfinger" mu="1.13" />
|
| 833 |
+
<xacro:gazebo-friction link="${arm_type}_rightfinger" mu="1.13" />
|
| 834 |
+
</xacro:if>
|
| 835 |
+
</xacro:if> -->
|
| 836 |
+
</robot>
|
assets/publish-IjwDLK4H.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
var y=Object.defineProperty;var k=(a,t,e)=>t in a?y(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var r=(a,t,e)=>k(a,typeof t!="symbol"?t+"":t,e);import{c as E,B as v,f as T}from"./connect-DkGLCYAo.js";class B{constructor(t){r(this,"config");r(this,"connection",null);r(this,"broadcast",null);r(this,"abortController",null);r(this,"running",!1);r(this,"activeTrack",null);this.config={trackName:"serial",groupSize:1024,...t}}async start(){if(this.running)throw new Error("Publisher is already running");this.running=!0,this.abortController=new AbortController;const{serial:t,url:e,path:l,trackName:i,groupSize:n}=this.config;this.connection=await E(new URL(e)),this.broadcast=new v,this.connection.publish(T(l),this.broadcast),this.handleRequests(i),await this.readSerial(t,i,n)}async handleRequests(t){if(this.broadcast)try{for(;;){const e=await this.broadcast.requested();if(!e||!this.running)break;e.track.name===t?this.publishToTrack(e.track):e.track.close(new Error("track not found"))}}catch{}}publishToTrack(t){this.activeTrack=t}async readSerial(t,e,l){var f,m,p;const i=(f=t.readable)==null?void 0:f.getReader();if(!i)throw new Error("Serial port is not readable");let n=null,h=0;try{for(;this.running;){const{value:b,done:w}=await i.read();if(w||(m=this.abortController)!=null&&m.signal.aborted)break;b&&this.activeTrack&&((!n||h>=l)&&(n==null||n.close(),n=this.activeTrack.appendGroup(),h=0),n.writeFrame(b),h+=b.byteLength)}n==null||n.close(),(p=this.activeTrack)==null||p.close()}finally{i.releaseLock()}}async stop(){var t,e,l;this.running=!1,(t=this.abortController)==null||t.abort(),this.abortController=null,(e=this.broadcast)==null||e.close(),this.broadcast=null,await((l=this.connection)==null?void 0:l.close()),this.connection=null}}const g=document.getElementById("log"),d=document.getElementById("start"),u=document.getElementById("stop");let c=null,s=null;function o(a,t=!1){const e=document.createElement("div");e.textContent=`[${new Date().toLocaleTimeString()}] ${a}`,t&&(e.className="error"),g.appendChild(e),g.scrollTop=g.scrollHeight}d.addEventListener("click",async()=>{try{const a=document.getElementById("url").value,t=document.getElementById("path").value,e=parseInt(document.getElementById("baudRate").value);o("Requesting serial port..."),s=await navigator.serial.requestPort(),await s.open({baudRate:e}),o(`Opened serial port at ${e} baud`),c=new B({url:a,path:t,serial:s}),d.disabled=!0,u.disabled=!1,o(`Connecting to ${a}/${t}...`),await c.start(),o("Publisher stopped")}catch(a){o(`Error: ${a.message}`,!0)}finally{d.disabled=!1,u.disabled=!0}});u.addEventListener("click",async()=>{o("Stopping..."),await(c==null?void 0:c.stop()),await(s==null?void 0:s.close()),c=null,s=null,d.disabled=!1,u.disabled=!0});
|
assets/subscribe-Cz9tf8k2.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{c as g,f as m}from"./connect-DkGLCYAo.js";const d=document.getElementById("log"),r=document.getElementById("start"),c=document.getElementById("stop");let o=null,s=!1;const b=new TextDecoder;function e(t,n=""){const a=document.createElement("div");a.textContent=`[${new Date().toLocaleTimeString()}] ${t}`,n&&(a.className=n),d.appendChild(a),d.scrollTop=d.scrollHeight}r.addEventListener("click",async()=>{try{const t=document.getElementById("url").value,n=document.getElementById("path").value;r.disabled=!0,c.disabled=!1,s=!0,e(`Connecting to ${t}...`),o=await g(new URL(t)),e("Connected!"),e(`Subscribing to broadcast: ${n}`);const a=o.consume(m(n));e("Got broadcast handle"),e("Subscribing to track: serial");const u=a.subscribe("serial",0);for(e("Subscribed to track, waiting for data...");s;){e("Waiting for next group...");const l=await u.nextGroup();if(!l){e("No more groups");break}for(e(`Got group ${l.sequence}`);s;){const i=await l.readFrame();if(!i){e("End of group");break}e(`Data: ${b.decode(i)}`,"data")}}e("Loop ended")}catch(t){e(`Error: ${t.message}`,"error"),console.error(t)}finally{r.disabled=!1,c.disabled=!0}});c.addEventListener("click",async()=>{e("Stopping..."),s=!1,await(o==null?void 0:o.close()),o=null,r.disabled=!1,c.disabled=!0});
|
assets/urdf_viewer-trQNEAhR.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import{c as V,B as he,f as K}from"./connect-DkGLCYAo.js";import{W as ye,S as ve,A as we,D as te,P as xe,O as be,G as Ee,a as Ie,l as Ce,U as Be,m as Se,V as Y}from"./URDFLoader-CL7UVBjw.js";const $=new URLSearchParams(location.search),Le="https://cdn.1ms.ai",je="anon/xoq-serial",$e="urdf/so101/so101.urdf",z=document.getElementById("urdfUrl"),ne=document.getElementById("relayUrl"),oe=document.getElementById("path"),R=document.getElementById("certHash");z.value=$.get("urdf")||$e;ne.value=$.get("relay")||Le;oe.value=$.get("path")||je;R.value=$.get("certHash")||localStorage.getItem("moq-cert-hash")||"";R.addEventListener("input",()=>localStorage.setItem("moq-cert-hash",R.value));const S=document.getElementById("log"),M=document.getElementById("startBtn"),G=document.getElementById("stopBtn"),g=document.getElementById("queryBtn"),Fe=document.getElementById("loadUrdfBtn"),Te=document.getElementById("statusText");let m=null,h=[];const D={};let F=null,T=null,j=null,v=null,P=!1,_=0,Q=0,H=0,X=performance.now(),x=null,k=!1;function r(e,n="info"){const t=document.createElement("div");t.className=`log-entry log-${n}`,t.textContent=`[${new Date().toLocaleTimeString()}] ${e}`,S.appendChild(t),S.children.length>200&&S.removeChild(S.firstChild),S.scrollTop=S.scrollHeight}function ke(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} K`:`${(e/(1024*1024)).toFixed(1)} M`}function L(e){Te.textContent=e}const Re=2,se=56;function Ue(e){let n=0;for(let t=0;t<e.length;t++)n+=e[t];return~n&255}function ae(e,n,t){const o=new Uint8Array([e,4,Re,n,t]),s=Ue(o),a=new Uint8Array(2+o.length+1);return a[0]=255,a[1]=255,a.set(o,2),a[a.length-1]=s,a}function re(e){return(e-2048)*(Math.PI/2048)}const ce="urdf-viewer-joint-mapping";function Ne(){try{const e=localStorage.getItem(ce);if(e)return JSON.parse(e)}catch{}return ie()}function ie(){return{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6"}}function O(e){localStorage.setItem(ce,JSON.stringify(e))}let d=Ne();const Z=document.getElementById("mappingRows"),Pe=document.getElementById("addMappingBtn"),Ae=document.getElementById("resetMappingBtn");function U(){Z.innerHTML="";for(const[e,n]of Object.entries(d)){const t=document.createElement("div");t.className="mapping-row";const o=document.createElement("input");o.type="text",o.value=e,o.title="Servo ID";const s=document.createElement("span");s.textContent="→",s.style.color="#666";const a=document.createElement("select"),c=document.createElement("option");c.value="",c.textContent="(none)",a.appendChild(c);for(const l of h){const y=document.createElement("option");y.value=l,y.textContent=l,l===n&&(y.selected=!0),a.appendChild(y)}if(h.length===0){const l=document.createElement("option");l.value=n,l.textContent=n,l.selected=!0,a.appendChild(l)}const f=document.createElement("button");f.className="remove-btn",f.textContent="×",f.addEventListener("click",()=>{delete d[e],O(d),U()});const w=()=>{const l=e,y=o.value.trim(),q=a.value;l!==y&&delete d[l],y&&(d[y]=q),O(d)};o.addEventListener("change",w),a.addEventListener("change",w),t.appendChild(o),t.appendChild(s),t.appendChild(a),t.appendChild(f),Z.appendChild(t)}}Pe.addEventListener("click",()=>{let e=1;for(;d[String(e)];)e++;d[String(e)]=h[0]||"",O(d),U()});Ae.addEventListener("click",()=>{d=ie(),O(d),U()});U();function Me(){const e=R.value.trim(),n={};if(e){const t=e.replace(/[^0-9a-fA-F]/g,""),o=new Uint8Array(t.length/2);for(let s=0;s<o.length;s++)o[s]=parseInt(t.substr(s*2,2),16);n.webtransport={serverCertificateHashes:[{algorithm:"sha-256",value:o.buffer}]},r(`Using cert hash: ${t.slice(0,16)}...`,"data")}return n}const J=document.getElementById("threeCanvas");let b;try{b=new ye({canvas:J,antialias:!0,preserveDrawingBuffer:!0}),b.setPixelRatio(window.devicePixelRatio),b.setClearColor(1710638)}catch(e){r(`WebGL not available: ${e.message}`,"error"),b=null}const E=new ve,De=new we(16777215,.6);E.add(De);const le=new te(16777215,.8);le.position.set(5,10,7);E.add(le);const de=new te(4491519,.3);de.position.set(-5,3,-5);E.add(de);const I=new xe(50,1,.01,100);I.position.set(.3,.3,.4);I.lookAt(0,.1,0);const C=new be(I,J);C.target.set(0,.1,0);C.enableDamping=!0;C.dampingFactor=.1;C.update();const ue=new Ee(1,20,3355477,2236996);E.add(ue);const He=new Ie(.1);E.add(He);const ee=document.getElementById("jointRows"),A={};function Oe(){ee.innerHTML="";const e=[16739125,16747586,16755021,16765286,448160,1149618,473932,8599788];h.forEach((n,t)=>{const o=e[t%e.length],s=document.createElement("div");s.className="joint-row",s.innerHTML=`
|
| 2 |
+
<span class="joint-label" style="color:#${o.toString(16).padStart(6,"0")}">${n}</span>
|
| 3 |
+
<span class="joint-angle" id="jangle-${t}">0.0°</span>
|
| 4 |
+
<span class="joint-raw" id="jraw-${t}">-</span>
|
| 5 |
+
`,ee.appendChild(s),A[n]={angleEl:s.querySelector(`#jangle-${t}`),rawEl:s.querySelector(`#jraw-${t}`)}})}function qe(){if(!m)return;const e=new Se().setFromObject(m),n=e.getCenter(new Y),t=e.getSize(new Y),s=Math.max(t.x,t.y,t.z)*1.8;I.position.set(n.x+s*.7,n.y+s*.5,n.z+s*.7),I.lookAt(n),C.target.copy(n),C.update();const a=e.min.y;ue.position.y=a,r(`Loaded: bbox size=(${t.x.toFixed(3)}, ${t.y.toFixed(3)}, ${t.z.toFixed(3)})`,"data")}async function me(e){m&&(E.remove(m),m=null,h=[]),r(`Loading URDF: ${e}...`);const n=new Ce,t=new Be(n);return new Promise((o,s)=>{n.onLoad=()=>{r("All meshes loaded","success"),qe()},t.load(e,a=>{m=a,m.rotation.x=-Math.PI/2,E.add(m),h=[];for(const[c,f]of Object.entries(m.joints))(f.jointType==="revolute"||f.jointType==="continuous")&&h.push(c);h.sort((c,f)=>{const w=parseInt(c),l=parseInt(f);return!isNaN(w)&&!isNaN(l)?w-l:c.localeCompare(f)}),r(`Loaded ${m.robotName}: ${h.length} joints [${h.join(", ")}]`,"success"),Oe(),U(),o(m)},void 0,a=>{r(`URDF load error: ${a}`,"error"),s(a)})})}Fe.addEventListener("click",()=>{const e=z.value.trim();e&&me(e)});me(z.value.trim()).catch(()=>{});function ze(){if(m)for(const[e,n]of Object.entries(d)){if(!n||!D[e]||!m.joints[n])continue;const o=re(D[e].position);m.setJointValue(n,o)}}function Ge(){for(const[n,t]of Object.entries(d)){if(!t||!A[t])continue;const o=D[n];if(!o)continue;const s=(re(o.position)*180/Math.PI).toFixed(1);A[t].angleEl.innerHTML=`${s}°`,A[t].rawEl.textContent=o.position}document.getElementById("frameCount").textContent=_,document.getElementById("bytesReceived").textContent=ke(Q);const e=performance.now();e-X>=1e3&&(document.getElementById("canFps").textContent=H,H=0,X=e),document.getElementById("lastUpdate").textContent=new Date().toLocaleTimeString().split(" ")[0]}function pe(){if(!b)return;const e=J.parentElement,n=e.clientWidth,t=e.clientHeight;b.setSize(n,t),I.aspect=n/t,I.updateProjectionMatrix()}window.addEventListener("resize",pe);requestAnimationFrame(pe);function fe(){requestAnimationFrame(fe),b&&(C.update(),ze(),b.render(E,I))}fe();let i=new Uint8Array(0);function _e(e){const n=new Uint8Array(i.length+e.length);n.set(i),n.set(e,i.length),i=n}function Qe(){for(;i.length>=6;){let e=-1;for(let c=0;c<i.length-1;c++)if(i[c]===255&&i[c+1]===255){e=c;break}if(e<0){i=new Uint8Array(0);return}if(e>0&&(i=i.slice(e)),i.length<4)return;const n=i[3],t=4+n;if(i.length<t)return;const o=i[2],s=i[4],a=i.slice(5,3+n);if(s===0&&a.length>=2){const c=a[0]|a[1]<<8;c>=0&&c<=4095&&(D[String(o)]={position:c,updated:!0},_++,H++)}Q+=t,i=i.slice(t)}}M.addEventListener("click",async()=>{try{const e=ne.value,n=oe.value,t=`${e}/${n}/s2c`,o=`${e}/${n}/c2s`;M.disabled=!0,G.disabled=!1,P=!0,_=0,Q=0,H=0,i=new Uint8Array(0),L("Connecting...");const s=Me();if(!R.value.trim())try{const u=`${e}/certificate.sha256`,p=await fetch(u);if(p.ok){const B=await p.text();r(`Relay cert hash: ${B.trim().slice(0,32)}...`,"data")}}catch(u){r(`Cert hash fetch failed: ${u.message}`,"error")}r(`Publishing commands to ${o}...`);const c=new Promise((u,p)=>setTimeout(()=>p(new Error("c2s connection timeout after 8s")),8e3));T=await Promise.race([V(new URL(o),s),c]),j=new he,T.publish(K(""),j),r("c2s broadcast published, waiting for serial server...","data");const f=new Promise((u,p)=>setTimeout(()=>p(new Error("No subscriber after 15s — is moq-serial-server running on this path?")),15e3)),w=await Promise.race([j.requested(),f]);if(!w)throw new Error("Command broadcast closed");v=w.track,r(`Command track "${v.name}" active`,"success"),r(`Subscribing to ${t}...`);const l=new Promise((u,p)=>setTimeout(()=>p(new Error("s2c connection timeout after 8s")),8e3));F=await Promise.race([V(new URL(t),s),l]);const q=F.consume(K("")).subscribe("data",0);r("Subscribed to s2c 'data' track","success");const N=Object.keys(d).map(Number).filter(u=>!isNaN(u)&&u>0);let W=0;for(x=setInterval(()=>{if(!v||N.length===0)return;const u=N[W%N.length],p=ae(u,se,2),B=v.appendGroup();B.writeFrame(p),B.close(),W++},15),k=!0,g.classList.add("active"),g.textContent="Stop Query",g.disabled=!1,r(`Querying servos [${N.join(",")}] at ~${Math.round(1e3/15)}Hz`,"success"),L("Streaming");P;){const u=await q.nextGroup();if(!u){r("Track ended");break}for(;P;){const p=await u.readFrame();if(!p)break;const B=new Uint8Array(p);_e(B),Qe()}}L("Ended")}catch(e){r(`Error: ${e.message}`,"error"),console.error(e),L("Error")}finally{ge()}});function ge(){if(x&&(clearInterval(x),x=null),k=!1,g.classList.remove("active"),g.textContent="Query Servos",g.disabled=!0,M.disabled=!1,G.disabled=!0,v){try{v.close()}catch{}v=null}if(j){try{j.close()}catch{}j=null}if(T){try{T.close()}catch{}T=null}}G.addEventListener("click",async()=>{if(P=!1,ge(),L("Stopping..."),F){try{F.close()}catch{}F=null}L("Disconnected"),r("Disconnected","success")});g.addEventListener("click",()=>{if(k)x&&(clearInterval(x),x=null),k=!1,g.classList.remove("active"),g.textContent="Query Servos",r("Query paused");else{const e=Object.keys(d).map(Number).filter(t=>!isNaN(t)&&t>0);let n=0;x=setInterval(()=>{if(!v||e.length===0)return;const t=e[n%e.length],o=ae(t,se,2),s=v.appendGroup();s.writeFrame(o),s.close(),n++},15),k=!0,g.classList.add("active"),g.textContent="Stop Query",r("Query resumed","success")}});setInterval(Ge,100);r("Ready. Load a URDF and connect to start.","info");($.has("relay")||$.has("path"))&&(r("Auto-connecting from query params...","info"),M.click());
|
assets/video_player-BJSMA0Bo.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{c as x,f as w}from"./connect-DkGLCYAo.js";const o=document.getElementById("video"),b=document.getElementById("log"),p=document.getElementById("startBtn"),y=document.getElementById("stopBtn"),C=document.getElementById("status"),I=document.getElementById("groupCount"),k=document.getElementById("bytesReceived"),R=document.getElementById("bufferLength");let l=null,m=!1,d=null,r=null,g=0,B=0,h=!1,v=[];function t(e,n="info"){const s=document.createElement("div");s.className=`log-entry log-${n}`,s.textContent=`[${new Date().toLocaleTimeString()}] ${e}`,b.appendChild(s),b.scrollTop=b.scrollHeight}function U(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}function $(){if(I.textContent=g,k.textContent=U(B),o.buffered.length>0){const e=o.buffered.end(0)-o.currentTime;R.textContent=`${Math.max(0,e).toFixed(1)}s`}}function i(e){C.textContent=e}function M(){if(v.length>0&&r&&!r.updating){const e=v.shift();try{r.appendBuffer(e)}catch(n){t(`Append error: ${n.message}`,"error")}}}async function T(e){if(!r||r.updating){v.push(e);return}try{r.appendBuffer(e)}catch(n){t(`Append error: ${n.message}`,"error")}}async function A(){return new Promise((e,n)=>{d=new MediaSource,o.src=URL.createObjectURL(d),d.addEventListener("sourceopen",()=>{t("MediaSource opened","success");const s=['video/mp4; codecs="avc1.640028"','video/mp4; codecs="avc1.64001f"','video/mp4; codecs="avc1.4d4028"','video/mp4; codecs="avc1.4d401f"','video/mp4; codecs="avc1.42e01f"','video/mp4; codecs="avc1.640029"'];let f=null;for(const a of s)if(MediaSource.isTypeSupported(a)){f=a;break}if(!f){t("No supported H.264 codec found","error"),n(new Error("No codec supported"));return}t(`Using codec: ${f}`,"success"),r=d.addSourceBuffer(f),r.mode="segments",r.addEventListener("updateend",()=>{M(),$(),o.paused&&o.buffered.length>0&&o.play().catch(()=>{})}),r.addEventListener("error",a=>{t(`SourceBuffer error: ${a.type}`,"error"),console.error("SourceBuffer error:",a)}),e()}),d.addEventListener("error",n)})}p.addEventListener("click",async()=>{try{const e=document.getElementById("relayUrl").value,n=document.getElementById("path").value,s=`${e}/${n}`;p.disabled=!0,y.disabled=!1,m=!0,g=0,B=0,h=!1,v=[],i("Connecting..."),t(`Connecting to ${s}...`),await A(),l=await x(new URL(e)),t("Connected!","success"),i("Subscribing...");const a=l.consume(w(n)).subscribe("video",0);for(t("Subscribed to video track","success"),i("Streaming");m;){const S=await a.nextGroup();if(!S){t("Track ended");break}for(;m;){const u=await S.readFrame();if(!u)break;g++,B+=u.byteLength;const c=new Uint8Array(u),L=Array.from(c.slice(0,8)).map(E=>E.toString(16).padStart(2,"0")).join(" ");if(!h)t(`Init segment: ${u.byteLength} bytes [${L}...]`,"data"),c[4]===102&&c[5]===116&&c[6]===121&&c[7]===112?t("Valid ftyp box detected","success"):t("WARNING: Init segment doesn't start with ftyp!","error"),h=!0;else{t(`Segment ${g-1}: ${u.byteLength} bytes [${L}...]`,"data");const E=String.fromCharCode(c[4],c[5],c[6],c[7]);t(`Box type: ${E}`,"info")}await T(u),$()}}i("Ended")}catch(e){t(`Error: ${e.message}`,"error"),i("Error")}finally{p.disabled=!1,y.disabled=!0}});y.addEventListener("click",async()=>{m=!1,i("Stopping...");try{await(l==null?void 0:l.close())}catch{}if(l=null,(d==null?void 0:d.readyState)==="open")try{d.endOfStream()}catch{}p.disabled=!1,y.disabled=!0,i("Disconnected"),t("Disconnected","success")});o.addEventListener("error",e=>{const n=o.error;t(`Video error: ${(n==null?void 0:n.message)||"unknown"} (code: ${n==null?void 0:n.code})`,"error")});o.addEventListener("loadedmetadata",()=>{t(`Video metadata loaded: ${o.videoWidth}x${o.videoHeight}`,"success")});o.addEventListener("canplay",()=>{t("Video can play!","success")});setInterval($,1e3);t("Ready. Enter relay URL and path, then click Connect.","info");
|
camera.html
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Camera CMAF Player - xoq</title>
|
| 7 |
+
<style>
|
| 8 |
+
* { box-sizing: border-box; }
|
| 9 |
+
body {
|
| 10 |
+
font-family: system-ui, -apple-system, sans-serif;
|
| 11 |
+
max-width: 900px;
|
| 12 |
+
margin: 0 auto;
|
| 13 |
+
padding: 1rem;
|
| 14 |
+
background: #1a1a2e;
|
| 15 |
+
color: #eee;
|
| 16 |
+
}
|
| 17 |
+
h1 { color: #00d4ff; margin-bottom: 0.5rem; }
|
| 18 |
+
.subtitle { color: #888; margin-bottom: 1.5rem; }
|
| 19 |
+
|
| 20 |
+
.controls {
|
| 21 |
+
display: flex;
|
| 22 |
+
gap: 0.5rem;
|
| 23 |
+
flex-wrap: wrap;
|
| 24 |
+
margin-bottom: 1rem;
|
| 25 |
+
align-items: center;
|
| 26 |
+
}
|
| 27 |
+
.controls label {
|
| 28 |
+
display: flex;
|
| 29 |
+
align-items: center;
|
| 30 |
+
gap: 0.5rem;
|
| 31 |
+
}
|
| 32 |
+
.controls input[type="text"] {
|
| 33 |
+
padding: 0.5rem;
|
| 34 |
+
border: 1px solid #444;
|
| 35 |
+
border-radius: 4px;
|
| 36 |
+
background: #2a2a4a;
|
| 37 |
+
color: #fff;
|
| 38 |
+
width: 300px;
|
| 39 |
+
}
|
| 40 |
+
button {
|
| 41 |
+
padding: 0.5rem 1rem;
|
| 42 |
+
border: none;
|
| 43 |
+
border-radius: 4px;
|
| 44 |
+
cursor: pointer;
|
| 45 |
+
font-size: 1rem;
|
| 46 |
+
transition: background 0.2s;
|
| 47 |
+
}
|
| 48 |
+
button:disabled { opacity: 0.5; cursor: not-allowed; }
|
| 49 |
+
#startBtn { background: #00d4ff; color: #000; }
|
| 50 |
+
#startBtn:hover:not(:disabled) { background: #00b8e6; }
|
| 51 |
+
#stopBtn { background: #ff4757; color: #fff; }
|
| 52 |
+
#stopBtn:hover:not(:disabled) { background: #ff3344; }
|
| 53 |
+
|
| 54 |
+
.video-container {
|
| 55 |
+
background: #000;
|
| 56 |
+
border-radius: 8px;
|
| 57 |
+
overflow: hidden;
|
| 58 |
+
margin-bottom: 1rem;
|
| 59 |
+
aspect-ratio: 16/9;
|
| 60 |
+
}
|
| 61 |
+
video { width: 100%; height: 100%; display: block; }
|
| 62 |
+
|
| 63 |
+
.stats {
|
| 64 |
+
display: grid;
|
| 65 |
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
| 66 |
+
gap: 0.5rem;
|
| 67 |
+
margin-bottom: 1rem;
|
| 68 |
+
}
|
| 69 |
+
.stat {
|
| 70 |
+
background: #2a2a4a;
|
| 71 |
+
padding: 0.75rem;
|
| 72 |
+
border-radius: 8px;
|
| 73 |
+
text-align: center;
|
| 74 |
+
}
|
| 75 |
+
.stat-label { color: #888; font-size: 0.75rem; text-transform: uppercase; }
|
| 76 |
+
.stat-value { font-size: 1.2rem; font-weight: bold; color: #00d4ff; }
|
| 77 |
+
|
| 78 |
+
#log {
|
| 79 |
+
background: #0a0a1a;
|
| 80 |
+
border: 1px solid #333;
|
| 81 |
+
border-radius: 8px;
|
| 82 |
+
padding: 1rem;
|
| 83 |
+
height: 200px;
|
| 84 |
+
overflow-y: auto;
|
| 85 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 86 |
+
font-size: 0.8rem;
|
| 87 |
+
}
|
| 88 |
+
.log-entry { margin: 0.2rem 0; }
|
| 89 |
+
.log-info { color: #888; }
|
| 90 |
+
.log-success { color: #2ed573; }
|
| 91 |
+
.log-error { color: #ff4757; }
|
| 92 |
+
.log-data { color: #00d4ff; }
|
| 93 |
+
</style>
|
| 94 |
+
<script type="module" crossorigin src="/assets/camera-M5W9d3UM.js"></script>
|
| 95 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 96 |
+
</head>
|
| 97 |
+
<body>
|
| 98 |
+
<h1>Camera CMAF Player</h1>
|
| 99 |
+
<p class="subtitle">xoq MoQ Video Stream Client</p>
|
| 100 |
+
|
| 101 |
+
<div class="controls">
|
| 102 |
+
<label>
|
| 103 |
+
Relay:
|
| 104 |
+
<input type="text" id="relayUrl" />
|
| 105 |
+
</label>
|
| 106 |
+
<label>
|
| 107 |
+
Path:
|
| 108 |
+
<input type="text" id="path" />
|
| 109 |
+
</label>
|
| 110 |
+
</div>
|
| 111 |
+
<div class="controls">
|
| 112 |
+
<button id="startBtn">Connect</button>
|
| 113 |
+
<button id="stopBtn" disabled>Disconnect</button>
|
| 114 |
+
</div>
|
| 115 |
+
|
| 116 |
+
<div class="video-container">
|
| 117 |
+
<video id="video" autoplay muted playsinline></video>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
<div class="stats">
|
| 121 |
+
<div class="stat">
|
| 122 |
+
<div class="stat-label">Status</div>
|
| 123 |
+
<div class="stat-value" id="status">Idle</div>
|
| 124 |
+
</div>
|
| 125 |
+
<div class="stat">
|
| 126 |
+
<div class="stat-label">Groups</div>
|
| 127 |
+
<div class="stat-value" id="groupCount">0</div>
|
| 128 |
+
</div>
|
| 129 |
+
<div class="stat">
|
| 130 |
+
<div class="stat-label">Received</div>
|
| 131 |
+
<div class="stat-value" id="bytesReceived">0 B</div>
|
| 132 |
+
</div>
|
| 133 |
+
<div class="stat">
|
| 134 |
+
<div class="stat-label">Buffer</div>
|
| 135 |
+
<div class="stat-value" id="bufferLength">0s</div>
|
| 136 |
+
</div>
|
| 137 |
+
</div>
|
| 138 |
+
|
| 139 |
+
<h3>Log</h3>
|
| 140 |
+
<div id="log"></div>
|
| 141 |
+
|
| 142 |
+
</body>
|
| 143 |
+
</html>
|
index.html
CHANGED
|
@@ -1,19 +1,22 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>XoQ Examples</title>
|
| 7 |
+
<style>
|
| 8 |
+
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
|
| 9 |
+
h1 { margin-bottom: 2rem; }
|
| 10 |
+
a { display: block; margin: 1rem 0; font-size: 1.2rem; }
|
| 11 |
+
</style>
|
| 12 |
+
</head>
|
| 13 |
+
<body>
|
| 14 |
+
<h1>XoQ Examples</h1>
|
| 15 |
+
<a href="openarm.html">OpenArm 3D Visualizer</a>
|
| 16 |
+
<a href="camera.html">Camera Viewer</a>
|
| 17 |
+
<a href="publish.html">Publisher (Serial → MoQ)</a>
|
| 18 |
+
<a href="subscribe.html">Subscriber (MoQ → Console)</a>
|
| 19 |
+
<a href="urdf_viewer.html">URDF Robot Viewer</a>
|
| 20 |
+
<a href="video_player.html">Video Player</a>
|
| 21 |
+
</body>
|
| 22 |
</html>
|
openarm.html
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>OpenArm 3D Visualizer - xoq</title>
|
| 7 |
+
<style>
|
| 8 |
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 9 |
+
body {
|
| 10 |
+
font-family: system-ui, -apple-system, sans-serif;
|
| 11 |
+
background: #1a1a2e;
|
| 12 |
+
color: #eee;
|
| 13 |
+
height: 100vh;
|
| 14 |
+
display: flex;
|
| 15 |
+
flex-direction: column;
|
| 16 |
+
overflow: hidden;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
/* Top bar */
|
| 20 |
+
.top-bar {
|
| 21 |
+
padding: 0.5rem 1rem;
|
| 22 |
+
display: flex;
|
| 23 |
+
align-items: center;
|
| 24 |
+
gap: 0.75rem;
|
| 25 |
+
flex-wrap: wrap;
|
| 26 |
+
border-bottom: 1px solid #333;
|
| 27 |
+
background: #16162a;
|
| 28 |
+
}
|
| 29 |
+
.top-bar h1 { color: #00d4ff; font-size: 1.1rem; white-space: nowrap; }
|
| 30 |
+
.top-bar label {
|
| 31 |
+
display: flex;
|
| 32 |
+
align-items: center;
|
| 33 |
+
gap: 0.3rem;
|
| 34 |
+
font-size: 0.85rem;
|
| 35 |
+
color: #aaa;
|
| 36 |
+
}
|
| 37 |
+
.top-bar input[type="text"] {
|
| 38 |
+
padding: 0.35rem 0.5rem;
|
| 39 |
+
border: 1px solid #444;
|
| 40 |
+
border-radius: 4px;
|
| 41 |
+
background: #2a2a4a;
|
| 42 |
+
color: #fff;
|
| 43 |
+
font-size: 0.85rem;
|
| 44 |
+
width: 240px;
|
| 45 |
+
}
|
| 46 |
+
button {
|
| 47 |
+
padding: 0.35rem 0.75rem;
|
| 48 |
+
border: none;
|
| 49 |
+
border-radius: 4px;
|
| 50 |
+
cursor: pointer;
|
| 51 |
+
font-size: 0.85rem;
|
| 52 |
+
transition: background 0.2s;
|
| 53 |
+
}
|
| 54 |
+
button:disabled { opacity: 0.5; cursor: not-allowed; }
|
| 55 |
+
#startBtn { background: #00d4ff; color: #000; }
|
| 56 |
+
#startBtn:hover:not(:disabled) { background: #00b8e6; }
|
| 57 |
+
#stopBtn { background: #ff4757; color: #fff; }
|
| 58 |
+
#stopBtn:hover:not(:disabled) { background: #ff3344; }
|
| 59 |
+
#queryBtn { background: #2a2a4a; color: #888; border: 1px solid #444; }
|
| 60 |
+
#queryBtn.active { background: #2ed573; color: #000; border-color: #2ed573; }
|
| 61 |
+
#queryBtn:hover:not(:disabled) { background: #444; }
|
| 62 |
+
#queryBtn.active:hover:not(:disabled) { background: #26b860; }
|
| 63 |
+
|
| 64 |
+
/* Main layout */
|
| 65 |
+
.main {
|
| 66 |
+
flex: 1;
|
| 67 |
+
display: flex;
|
| 68 |
+
min-height: 0;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
/* 3D canvas */
|
| 72 |
+
.canvas-container {
|
| 73 |
+
flex: 1;
|
| 74 |
+
position: relative;
|
| 75 |
+
min-width: 0;
|
| 76 |
+
}
|
| 77 |
+
#threeCanvas {
|
| 78 |
+
width: 100%;
|
| 79 |
+
height: 100%;
|
| 80 |
+
display: block;
|
| 81 |
+
}
|
| 82 |
+
.canvas-overlay {
|
| 83 |
+
position: absolute;
|
| 84 |
+
top: 0.5rem;
|
| 85 |
+
left: 0.5rem;
|
| 86 |
+
font-size: 0.7rem;
|
| 87 |
+
color: #888;
|
| 88 |
+
pointer-events: none;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
/* Right panel */
|
| 92 |
+
.side-panel {
|
| 93 |
+
width: 280px;
|
| 94 |
+
background: #16162a;
|
| 95 |
+
border-left: 1px solid #333;
|
| 96 |
+
display: flex;
|
| 97 |
+
flex-direction: column;
|
| 98 |
+
overflow-y: auto;
|
| 99 |
+
}
|
| 100 |
+
.panel-section {
|
| 101 |
+
padding: 0.75rem;
|
| 102 |
+
border-bottom: 1px solid #2a2a4a;
|
| 103 |
+
}
|
| 104 |
+
.panel-section h3 {
|
| 105 |
+
font-size: 0.8rem;
|
| 106 |
+
color: #888;
|
| 107 |
+
text-transform: uppercase;
|
| 108 |
+
margin-bottom: 0.5rem;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
/* Joint rows */
|
| 112 |
+
.joint-row {
|
| 113 |
+
display: grid;
|
| 114 |
+
grid-template-columns: 50px 1fr 50px 50px;
|
| 115 |
+
gap: 0.25rem;
|
| 116 |
+
align-items: center;
|
| 117 |
+
padding: 0.3rem 0;
|
| 118 |
+
font-size: 0.8rem;
|
| 119 |
+
border-bottom: 1px solid #1e1e3a;
|
| 120 |
+
}
|
| 121 |
+
.joint-row:last-child { border-bottom: none; }
|
| 122 |
+
.joint-label {
|
| 123 |
+
font-weight: bold;
|
| 124 |
+
white-space: nowrap;
|
| 125 |
+
}
|
| 126 |
+
.joint-angle {
|
| 127 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 128 |
+
text-align: right;
|
| 129 |
+
font-size: 0.85rem;
|
| 130 |
+
}
|
| 131 |
+
.joint-vel, .joint-tau {
|
| 132 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 133 |
+
text-align: right;
|
| 134 |
+
font-size: 0.7rem;
|
| 135 |
+
color: #888;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
/* Stats */
|
| 139 |
+
.stats-grid {
|
| 140 |
+
display: grid;
|
| 141 |
+
grid-template-columns: 1fr 1fr;
|
| 142 |
+
gap: 0.4rem;
|
| 143 |
+
}
|
| 144 |
+
.stat {
|
| 145 |
+
background: #2a2a4a;
|
| 146 |
+
padding: 0.4rem;
|
| 147 |
+
border-radius: 4px;
|
| 148 |
+
text-align: center;
|
| 149 |
+
}
|
| 150 |
+
.stat-label { color: #888; font-size: 0.65rem; text-transform: uppercase; }
|
| 151 |
+
.stat-value { font-size: 0.9rem; font-weight: bold; color: #00d4ff; }
|
| 152 |
+
|
| 153 |
+
/* Log */
|
| 154 |
+
.log-panel {
|
| 155 |
+
height: 120px;
|
| 156 |
+
border-top: 1px solid #333;
|
| 157 |
+
background: #0a0a1a;
|
| 158 |
+
overflow-y: auto;
|
| 159 |
+
padding: 0.5rem;
|
| 160 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 161 |
+
font-size: 0.7rem;
|
| 162 |
+
flex-shrink: 0;
|
| 163 |
+
}
|
| 164 |
+
.log-entry { margin: 0.15rem 0; }
|
| 165 |
+
.log-info { color: #888; }
|
| 166 |
+
.log-success { color: #2ed573; }
|
| 167 |
+
.log-error { color: #ff4757; }
|
| 168 |
+
.log-data { color: #00d4ff; }
|
| 169 |
+
</style>
|
| 170 |
+
<script type="module" crossorigin src="/assets/openarm-DqhZ0Caw.js"></script>
|
| 171 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 172 |
+
<link rel="modulepreload" crossorigin href="/assets/URDFLoader-CL7UVBjw.js">
|
| 173 |
+
</head>
|
| 174 |
+
<body>
|
| 175 |
+
<div class="top-bar">
|
| 176 |
+
<h1>OpenArm 3D</h1>
|
| 177 |
+
<label>
|
| 178 |
+
Relay:
|
| 179 |
+
<input type="text" id="relayUrl" />
|
| 180 |
+
</label>
|
| 181 |
+
<label>
|
| 182 |
+
Left:
|
| 183 |
+
<input type="text" id="leftPath" style="width:200px;" />
|
| 184 |
+
</label>
|
| 185 |
+
<label>
|
| 186 |
+
Right:
|
| 187 |
+
<input type="text" id="rightPath" style="width:200px;" />
|
| 188 |
+
</label>
|
| 189 |
+
<label>
|
| 190 |
+
Depth:
|
| 191 |
+
<input type="text" id="depthPath" style="width:180px;" />
|
| 192 |
+
</label>
|
| 193 |
+
<label>
|
| 194 |
+
Cert hash:
|
| 195 |
+
<input type="text" id="certHash" placeholder="sha256 hex (optional)" style="width:140px;" />
|
| 196 |
+
</label>
|
| 197 |
+
<label>
|
| 198 |
+
Hz:
|
| 199 |
+
<input type="number" id="queryRate" value="100" min="10" max="1000" step="10" style="width:60px; padding:0.35rem 0.3rem; border:1px solid #444; border-radius:4px; background:#2a2a4a; color:#fff; font-size:0.85rem;" />
|
| 200 |
+
</label>
|
| 201 |
+
<button id="startBtn">Connect</button>
|
| 202 |
+
<button id="stopBtn" disabled>Disconnect</button>
|
| 203 |
+
<button id="queryBtn" disabled>Query Motors</button>
|
| 204 |
+
<span id="statusText" style="color:#888; font-size:0.8rem;">Idle</span>
|
| 205 |
+
<span style="border-left:1px solid #444; height:1.2rem;"></span>
|
| 206 |
+
<button id="viewToggle" style="background:#2a2a4a; color:#aaa; border:1px solid #444;">Camera</button>
|
| 207 |
+
<label style="font-size:0.75rem;">Pt size: <input type="range" id="ptSize" min="0.5" max="8" step="0.5" value="2" style="width:60px; vertical-align:middle;" /></label>
|
| 208 |
+
<span style="font-size:0.7rem; color:#666;">depth: 1mm</span>
|
| 209 |
+
<span style="border-left:1px solid #444; height:1.2rem;"></span>
|
| 210 |
+
<label style="font-size:0.75rem;">Cam X:<input type="number" id="camX" value="0" step="0.01" style="width:48px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 211 |
+
<label style="font-size:0.75rem;">Y:<input type="number" id="camY" value="0" step="0.01" style="width:48px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 212 |
+
<label style="font-size:0.75rem;">Z:<input type="number" id="camZ" value="0" step="0.01" style="width:48px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 213 |
+
<label style="font-size:0.75rem;">R:<input type="number" id="camRoll" value="0" step="1" style="width:40px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 214 |
+
<label style="font-size:0.75rem;">P:<input type="number" id="camPitch" value="0" step="1" style="width:40px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 215 |
+
<label style="font-size:0.75rem;">Yw:<input type="number" id="camYaw" value="0" step="1" style="width:40px; padding:0.2rem; border:1px solid #444; border-radius:3px; background:#2a2a4a; color:#fff; font-size:0.75rem;" /></label>
|
| 216 |
+
</div>
|
| 217 |
+
|
| 218 |
+
<div class="main">
|
| 219 |
+
<div class="canvas-container" id="view3d">
|
| 220 |
+
<canvas id="threeCanvas"></canvas>
|
| 221 |
+
<div class="canvas-overlay">
|
| 222 |
+
<span>Drag to orbit / Scroll to zoom / Right-drag to pan</span>
|
| 223 |
+
</div>
|
| 224 |
+
</div>
|
| 225 |
+
<div id="viewCamera" style="display:none; flex:1; min-width:0; background:#000; position:relative;">
|
| 226 |
+
<div style="display:flex; height:100%; gap:2px; padding:2px;">
|
| 227 |
+
<div style="flex:1; display:flex; flex-direction:column; min-width:0;">
|
| 228 |
+
<div style="font-size:0.65rem; color:#666; padding:2px 4px;">Color</div>
|
| 229 |
+
<canvas id="colorFullCanvas" style="flex:1; width:100%; object-fit:contain; background:#111; border-radius:3px;"></canvas>
|
| 230 |
+
</div>
|
| 231 |
+
<div style="flex:1; display:flex; flex-direction:column; min-width:0;">
|
| 232 |
+
<div style="font-size:0.65rem; color:#666; padding:2px 4px;">Depth</div>
|
| 233 |
+
<canvas id="depthFullCanvas" style="flex:1; width:100%; object-fit:contain; background:#111; border-radius:3px;"></canvas>
|
| 234 |
+
</div>
|
| 235 |
+
</div>
|
| 236 |
+
</div>
|
| 237 |
+
|
| 238 |
+
<div class="side-panel">
|
| 239 |
+
<div class="panel-section">
|
| 240 |
+
<h3>Left Arm</h3>
|
| 241 |
+
<div class="joint-row" style="font-size:0.65rem; color:#666;">
|
| 242 |
+
<span>Joint</span><span style="text-align:right;">Angle</span><span style="text-align:right;">Vel</span><span style="text-align:right;">Tau</span>
|
| 243 |
+
</div>
|
| 244 |
+
<div id="leftJointRows"></div>
|
| 245 |
+
</div>
|
| 246 |
+
|
| 247 |
+
<div class="panel-section">
|
| 248 |
+
<h3>Right Arm</h3>
|
| 249 |
+
<div class="joint-row" style="font-size:0.65rem; color:#666;">
|
| 250 |
+
<span>Joint</span><span style="text-align:right;">Angle</span><span style="text-align:right;">Vel</span><span style="text-align:right;">Tau</span>
|
| 251 |
+
</div>
|
| 252 |
+
<div id="rightJointRows"></div>
|
| 253 |
+
</div>
|
| 254 |
+
|
| 255 |
+
<div class="panel-section">
|
| 256 |
+
<h3>Camera</h3>
|
| 257 |
+
<div style="display:flex; gap:4px;">
|
| 258 |
+
<div style="flex:1; text-align:center;">
|
| 259 |
+
<div style="font-size:0.65rem; color:#666; margin-bottom:2px;">Color</div>
|
| 260 |
+
<canvas id="colorPreview" width="128" height="96" style="width:100%; border-radius:3px; background:#000;"></canvas>
|
| 261 |
+
</div>
|
| 262 |
+
<div style="flex:1; text-align:center;">
|
| 263 |
+
<div style="font-size:0.65rem; color:#666; margin-bottom:2px;">Depth</div>
|
| 264 |
+
<canvas id="depthPreview" width="128" height="96" style="width:100%; border-radius:3px; background:#000;"></canvas>
|
| 265 |
+
</div>
|
| 266 |
+
</div>
|
| 267 |
+
<div style="font-size:0.7rem; color:#888; margin-top:4px;" id="pcStats">No depth stream</div>
|
| 268 |
+
</div>
|
| 269 |
+
|
| 270 |
+
<div class="panel-section">
|
| 271 |
+
<h3>Stats</h3>
|
| 272 |
+
<div class="stats-grid">
|
| 273 |
+
<div class="stat">
|
| 274 |
+
<div class="stat-label">Frames</div>
|
| 275 |
+
<div class="stat-value" id="frameCount">0</div>
|
| 276 |
+
</div>
|
| 277 |
+
<div class="stat">
|
| 278 |
+
<div class="stat-label">Bytes</div>
|
| 279 |
+
<div class="stat-value" id="bytesReceived">0 B</div>
|
| 280 |
+
</div>
|
| 281 |
+
<div class="stat">
|
| 282 |
+
<div class="stat-label">FPS</div>
|
| 283 |
+
<div class="stat-value" id="canFps">0</div>
|
| 284 |
+
</div>
|
| 285 |
+
<div class="stat">
|
| 286 |
+
<div class="stat-label">Last</div>
|
| 287 |
+
<div class="stat-value" id="lastUpdate">-</div>
|
| 288 |
+
</div>
|
| 289 |
+
</div>
|
| 290 |
+
</div>
|
| 291 |
+
</div>
|
| 292 |
+
</div>
|
| 293 |
+
|
| 294 |
+
<div class="log-panel" id="log"></div>
|
| 295 |
+
|
| 296 |
+
<div style="position:fixed; top:-9999px;">
|
| 297 |
+
<video id="colorVideo" autoplay muted playsinline></video>
|
| 298 |
+
</div>
|
| 299 |
+
|
| 300 |
+
</body>
|
| 301 |
+
</html>
|
publish.html
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>xoq publisher</title>
|
| 7 |
+
<style>
|
| 8 |
+
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
|
| 9 |
+
button { font-size: 1rem; padding: 0.5rem 1rem; margin: 0.5rem 0; cursor: pointer; }
|
| 10 |
+
#log { background: #1a1a1a; color: #0f0; padding: 1rem; height: 300px; overflow-y: auto; font-family: monospace; font-size: 0.9rem; }
|
| 11 |
+
.error { color: #f00; }
|
| 12 |
+
</style>
|
| 13 |
+
<script type="module" crossorigin src="/assets/publish-IjwDLK4H.js"></script>
|
| 14 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 15 |
+
</head>
|
| 16 |
+
<body>
|
| 17 |
+
<h1>xoq publisher</h1>
|
| 18 |
+
<div>
|
| 19 |
+
<label>URL: <input type="text" id="url" value="https://cdn.moq.dev/anon" /></label>
|
| 20 |
+
</div>
|
| 21 |
+
<div>
|
| 22 |
+
<label>Path: <input type="text" id="path" value="xoq-duplex" /></label>
|
| 23 |
+
</div>
|
| 24 |
+
<div>
|
| 25 |
+
<label>Baud rate: <input type="number" id="baudRate" value="1000000" /></label>
|
| 26 |
+
</div>
|
| 27 |
+
<button id="start">Select Port & Start</button>
|
| 28 |
+
<button id="stop" disabled>Stop</button>
|
| 29 |
+
<h3>Log</h3>
|
| 30 |
+
<div id="log"></div>
|
| 31 |
+
|
| 32 |
+
</body>
|
| 33 |
+
</html>
|
style.css
DELETED
|
@@ -1,28 +0,0 @@
|
|
| 1 |
-
body {
|
| 2 |
-
padding: 2rem;
|
| 3 |
-
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
| 4 |
-
}
|
| 5 |
-
|
| 6 |
-
h1 {
|
| 7 |
-
font-size: 16px;
|
| 8 |
-
margin-top: 0;
|
| 9 |
-
}
|
| 10 |
-
|
| 11 |
-
p {
|
| 12 |
-
color: rgb(107, 114, 128);
|
| 13 |
-
font-size: 15px;
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
.card {
|
| 19 |
-
max-width: 620px;
|
| 20 |
-
margin: 0 auto;
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
-
}
|
| 25 |
-
|
| 26 |
-
.card p:last-child {
|
| 27 |
-
margin-bottom: 0;
|
| 28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subscribe.html
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>xoq subscriber</title>
|
| 7 |
+
<style>
|
| 8 |
+
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
|
| 9 |
+
button { font-size: 1rem; padding: 0.5rem 1rem; margin: 0.5rem 0; cursor: pointer; }
|
| 10 |
+
#log { background: #1a1a1a; color: #0f0; padding: 1rem; height: 300px; overflow-y: auto; font-family: monospace; font-size: 0.9rem; }
|
| 11 |
+
.error { color: #f00; }
|
| 12 |
+
.data { color: #0ff; }
|
| 13 |
+
</style>
|
| 14 |
+
<script type="module" crossorigin src="/assets/subscribe-Cz9tf8k2.js"></script>
|
| 15 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 16 |
+
</head>
|
| 17 |
+
<body>
|
| 18 |
+
<h1>xoq subscriber</h1>
|
| 19 |
+
<div>
|
| 20 |
+
<label>URL: <input type="text" id="url" value="https://cdn.moq.dev/anon" /></label>
|
| 21 |
+
</div>
|
| 22 |
+
<div>
|
| 23 |
+
<label>Path: <input type="text" id="path" value="xoq-duplex" /></label>
|
| 24 |
+
</div>
|
| 25 |
+
<button id="start">Start</button>
|
| 26 |
+
<button id="stop" disabled>Stop</button>
|
| 27 |
+
<h3>Log</h3>
|
| 28 |
+
<div id="log"></div>
|
| 29 |
+
|
| 30 |
+
</body>
|
| 31 |
+
</html>
|
urdf/so101/assets/base_motor_holder_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8cd2f241037ea377af1191fffe0dd9d9006beea6dcc48543660ed41647072424
|
| 3 |
+
size 1877084
|
urdf/so101/assets/base_so101_v2.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bb12b7026575e1f70ccc7240051f9d943553bf34e5128537de6cd86fae33924d
|
| 3 |
+
size 471584
|
urdf/so101/assets/motor_holder_so101_base_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:31242ae6fb59d8b15c66617b88ad8e9bded62d57c35d11c0c43a70d2f4caa95b
|
| 3 |
+
size 1129384
|
urdf/so101/assets/motor_holder_so101_wrist_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:887f92e6013cb64ea3a1ab8675e92da1e0beacfd5e001f972523540545e08011
|
| 3 |
+
size 1052184
|
urdf/so101/assets/moving_jaw_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:785a9dded2f474bc1d869e0d3dae398a3dcd9c0c345640040472210d2861fa9d
|
| 3 |
+
size 1413584
|
urdf/so101/assets/rotation_pitch_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9be900cc2a2bf718102841ef82ef8d2873842427648092c8ed2ca1e2ef4ffa34
|
| 3 |
+
size 883684
|
urdf/so101/assets/sts3215_03a_no_horn_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:75ef3781b752e4065891aea855e34dc161a38a549549cd0970cedd07eae6f887
|
| 3 |
+
size 865884
|
urdf/so101/assets/sts3215_03a_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a37c871fb502483ab96c256baf457d36f2e97afc9205313d9c5ab275ef941cd0
|
| 3 |
+
size 954084
|
urdf/so101/assets/under_arm_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d01d1f2de365651dcad9d6669e94ff87ff7652b5bb2d10752a66a456a86dbc71
|
| 3 |
+
size 1975884
|
urdf/so101/assets/upper_arm_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:475056e03a17e71919b82fd88ab9a0b898ab50164f2a7943652a6b2941bb2d4f
|
| 3 |
+
size 1303484
|
urdf/so101/assets/waveshare_mounting_plate_so101_v2.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e197e24005a07d01bbc06a8c42311664eaeda415bf859f68fa247884d0f1a6e9
|
| 3 |
+
size 62784
|
urdf/so101/assets/wrist_roll_follower_so101_v1.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4b17b410a12d64ec39554abc3e8054d8a97384b2dc4a8d95a5ecb2a93670f5f4
|
| 3 |
+
size 1439884
|
urdf/so101/assets/wrist_roll_pitch_so101_v2.stl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6c7ec5525b4d8b9e397a30ab4bb0037156a5d5f38a4adf2c7d943d6c56eda5ae
|
| 3 |
+
size 2699784
|
urdf/so101/so101.urdf
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" ?>
|
| 2 |
+
<!-- Generated using onshape-to-robot -->
|
| 3 |
+
<!-- Onshape https://cad.onshape.com/documents/7715cc284bb430fe6dab4ffd/w/4fd0791b683777b02f8d975a/e/826c553ede3b7592eb9ca800 -->
|
| 4 |
+
<robot name="so100">
|
| 5 |
+
<!-- Link base -->
|
| 6 |
+
<link name="base">
|
| 7 |
+
<inertial>
|
| 8 |
+
<origin xyz="-0.14932 -0.16812 0.065966" rpy="0 0 0"/>
|
| 9 |
+
<mass value="0.147"/>
|
| 10 |
+
<inertia ixx="0.000114686" ixy="-4.59787e-07" ixz="4.97151e-06" iyy="0.000136117" iyz="9.75275e-08" izz="0.000130364"/>
|
| 11 |
+
</inertial>
|
| 12 |
+
<!-- Part base_motor_holder_so101_v1 -->
|
| 13 |
+
<visual>
|
| 14 |
+
<origin xyz="-0.169402 -0.168167 0.0300817" rpy="1.5708 -1.67685e-15 1.5708"/>
|
| 15 |
+
<geometry>
|
| 16 |
+
<mesh filename="assets/base_motor_holder_so101_v1.stl"/>
|
| 17 |
+
</geometry>
|
| 18 |
+
<material name="base_motor_holder_so101_v1_material">
|
| 19 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 20 |
+
</material>
|
| 21 |
+
</visual>
|
| 22 |
+
<collision>
|
| 23 |
+
<origin xyz="-0.169402 -0.168167 0.0300817" rpy="1.5708 -1.67685e-15 1.5708"/>
|
| 24 |
+
<geometry>
|
| 25 |
+
<mesh filename="assets/base_motor_holder_so101_v1.stl"/>
|
| 26 |
+
</geometry>
|
| 27 |
+
</collision>
|
| 28 |
+
<!-- Part base_so101_v2 -->
|
| 29 |
+
<visual>
|
| 30 |
+
<origin xyz="-0.169402 -0.168068 0.0300817" rpy="1.5708 -1.6144e-15 1.5708"/>
|
| 31 |
+
<geometry>
|
| 32 |
+
<mesh filename="assets/base_so101_v2.stl"/>
|
| 33 |
+
</geometry>
|
| 34 |
+
<material name="base_so101_v2_material">
|
| 35 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 36 |
+
</material>
|
| 37 |
+
</visual>
|
| 38 |
+
<collision>
|
| 39 |
+
<origin xyz="-0.169402 -0.168068 0.0300817" rpy="1.5708 -1.6144e-15 1.5708"/>
|
| 40 |
+
<geometry>
|
| 41 |
+
<mesh filename="assets/base_so101_v2.stl"/>
|
| 42 |
+
</geometry>
|
| 43 |
+
</collision>
|
| 44 |
+
<!-- Part sts3215_03a_v1 -->
|
| 45 |
+
<visual>
|
| 46 |
+
<origin xyz="-0.136702 -0.168068 0.0761817" rpy="-8.21148e-16 7.84513e-18 1.249e-15"/>
|
| 47 |
+
<geometry>
|
| 48 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 49 |
+
</geometry>
|
| 50 |
+
<material name="sts3215_03a_v1_material">
|
| 51 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 52 |
+
</material>
|
| 53 |
+
</visual>
|
| 54 |
+
<collision>
|
| 55 |
+
<origin xyz="-0.136702 -0.168068 0.0761817" rpy="-8.21148e-16 7.84513e-18 1.249e-15"/>
|
| 56 |
+
<geometry>
|
| 57 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 58 |
+
</geometry>
|
| 59 |
+
</collision>
|
| 60 |
+
<!-- Part waveshare_mounting_plate_so101_v2 -->
|
| 61 |
+
<visual>
|
| 62 |
+
<origin xyz="-0.19402 -0.168267 0.0798817" rpy="1.5708 -1.35493e-14 1.5708"/>
|
| 63 |
+
<geometry>
|
| 64 |
+
<mesh filename="assets/waveshare_mounting_plate_so101_v2.stl"/>
|
| 65 |
+
</geometry>
|
| 66 |
+
<material name="waveshare_mounting_plate_so101_v2_material">
|
| 67 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 68 |
+
</material>
|
| 69 |
+
</visual>
|
| 70 |
+
<collision>
|
| 71 |
+
<origin xyz="-0.19402 -0.168267 0.0798817" rpy="1.5708 -1.35493e-14 1.5708"/>
|
| 72 |
+
<geometry>
|
| 73 |
+
<mesh filename="assets/waveshare_mounting_plate_so101_v2.stl"/>
|
| 74 |
+
</geometry>
|
| 75 |
+
</collision>
|
| 76 |
+
</link>
|
| 77 |
+
<!-- Frame baseframe (dummy link + fixed joint) -->
|
| 78 |
+
<link name="baseframe">
|
| 79 |
+
<origin xyz="0 0 0" rpy="0 -0 0"/>
|
| 80 |
+
<inertial>
|
| 81 |
+
<origin xyz="0 0 0" rpy="0 0 0"/>
|
| 82 |
+
<mass value="1e-9"/>
|
| 83 |
+
<inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
|
| 84 |
+
</inertial>
|
| 85 |
+
</link>
|
| 86 |
+
<joint name="baseframe_frame" type="fixed">
|
| 87 |
+
<origin xyz="-0.163038 -0.168068 0.0324817" rpy="1.6144e-15 7.84513e-18 1.33799e-15"/>
|
| 88 |
+
<parent link="base"/>
|
| 89 |
+
<child link="baseframe"/>
|
| 90 |
+
<axis xyz="0 0 0"/>
|
| 91 |
+
</joint>
|
| 92 |
+
<!-- Link shoulder -->
|
| 93 |
+
<link name="shoulder">
|
| 94 |
+
<inertial>
|
| 95 |
+
<origin xyz="-0.0307604 -1.66727e-05 -0.0252713" rpy="0 0 0"/>
|
| 96 |
+
<mass value="0.100006"/>
|
| 97 |
+
<inertia ixx="8.3759e-05" ixy="7.55525e-08" ixz="-1.16342e-06" iyy="8.10403e-05" iyz="1.54663e-07" izz="2.39783e-05"/>
|
| 98 |
+
</inertial>
|
| 99 |
+
<!-- Part sts3215_03a_v1_2 -->
|
| 100 |
+
<visual>
|
| 101 |
+
<origin xyz="-0.0303992 0.000422241 -0.0417" rpy="1.5708 1.5708 0"/>
|
| 102 |
+
<geometry>
|
| 103 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 104 |
+
</geometry>
|
| 105 |
+
<material name="sts3215_03a_v1_2_material">
|
| 106 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 107 |
+
</material>
|
| 108 |
+
</visual>
|
| 109 |
+
<collision>
|
| 110 |
+
<origin xyz="-0.0303992 0.000422241 -0.0417" rpy="1.5708 1.5708 0"/>
|
| 111 |
+
<geometry>
|
| 112 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 113 |
+
</geometry>
|
| 114 |
+
</collision>
|
| 115 |
+
<!-- Part motor_holder_so101_base_v1 -->
|
| 116 |
+
<visual>
|
| 117 |
+
<origin xyz="-0.0675992 -0.000177759 0.0158499" rpy="1.5708 -1.5708 0"/>
|
| 118 |
+
<geometry>
|
| 119 |
+
<mesh filename="assets/motor_holder_so101_base_v1.stl"/>
|
| 120 |
+
</geometry>
|
| 121 |
+
<material name="motor_holder_so101_base_v1_material">
|
| 122 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 123 |
+
</material>
|
| 124 |
+
</visual>
|
| 125 |
+
<collision>
|
| 126 |
+
<origin xyz="-0.0675992 -0.000177759 0.0158499" rpy="1.5708 -1.5708 0"/>
|
| 127 |
+
<geometry>
|
| 128 |
+
<mesh filename="assets/motor_holder_so101_base_v1.stl"/>
|
| 129 |
+
</geometry>
|
| 130 |
+
</collision>
|
| 131 |
+
<!-- Part rotation_pitch_so101_v1 -->
|
| 132 |
+
<visual>
|
| 133 |
+
<origin xyz="0.0122008 2.22413e-05 0.0464" rpy="-1.5708 2.35221e-33 0"/>
|
| 134 |
+
<geometry>
|
| 135 |
+
<mesh filename="assets/rotation_pitch_so101_v1.stl"/>
|
| 136 |
+
</geometry>
|
| 137 |
+
<material name="rotation_pitch_so101_v1_material">
|
| 138 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 139 |
+
</material>
|
| 140 |
+
</visual>
|
| 141 |
+
<collision>
|
| 142 |
+
<origin xyz="0.0122008 2.22413e-05 0.0464" rpy="-1.5708 2.35221e-33 0"/>
|
| 143 |
+
<geometry>
|
| 144 |
+
<mesh filename="assets/rotation_pitch_so101_v1.stl"/>
|
| 145 |
+
</geometry>
|
| 146 |
+
</collision>
|
| 147 |
+
</link>
|
| 148 |
+
<!-- Link upper_arm -->
|
| 149 |
+
<link name="upper_arm">
|
| 150 |
+
<inertial>
|
| 151 |
+
<origin xyz="-0.0898471 -0.00838224 0.0184089" rpy="0 0 0"/>
|
| 152 |
+
<mass value="0.103"/>
|
| 153 |
+
<inertia ixx="4.08002e-05" ixy="-1.97819e-05" ixz="-4.03016e-08" iyy="0.000147318" iyz="8.97326e-09" izz="0.000142487"/>
|
| 154 |
+
</inertial>
|
| 155 |
+
<!-- Part sts3215_03a_v1_3 -->
|
| 156 |
+
<visual>
|
| 157 |
+
<origin xyz="-0.11257 -0.0155 0.0187" rpy="-3.14159 -5.27356e-16 -1.5708"/>
|
| 158 |
+
<geometry>
|
| 159 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 160 |
+
</geometry>
|
| 161 |
+
<material name="sts3215_03a_v1_3_material">
|
| 162 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 163 |
+
</material>
|
| 164 |
+
</visual>
|
| 165 |
+
<collision>
|
| 166 |
+
<origin xyz="-0.11257 -0.0155 0.0187" rpy="-3.14159 -5.27356e-16 -1.5708"/>
|
| 167 |
+
<geometry>
|
| 168 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 169 |
+
</geometry>
|
| 170 |
+
</collision>
|
| 171 |
+
<!-- Part upper_arm_so101_v1 -->
|
| 172 |
+
<visual>
|
| 173 |
+
<origin xyz="-0.065085 0.012 0.0182" rpy="3.14159 -0 -1.30911e-30"/>
|
| 174 |
+
<geometry>
|
| 175 |
+
<mesh filename="assets/upper_arm_so101_v1.stl"/>
|
| 176 |
+
</geometry>
|
| 177 |
+
<material name="upper_arm_so101_v1_material">
|
| 178 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 179 |
+
</material>
|
| 180 |
+
</visual>
|
| 181 |
+
<collision>
|
| 182 |
+
<origin xyz="-0.065085 0.012 0.0182" rpy="3.14159 -0 -1.30911e-30"/>
|
| 183 |
+
<geometry>
|
| 184 |
+
<mesh filename="assets/upper_arm_so101_v1.stl"/>
|
| 185 |
+
</geometry>
|
| 186 |
+
</collision>
|
| 187 |
+
</link>
|
| 188 |
+
<!-- Link lower_arm -->
|
| 189 |
+
<link name="lower_arm">
|
| 190 |
+
<inertial>
|
| 191 |
+
<origin xyz="-0.0980701 0.00324376 0.0182831" rpy="0 0 0"/>
|
| 192 |
+
<mass value="0.104"/>
|
| 193 |
+
<inertia ixx="2.87438e-05" ixy="7.41152e-06" ixz="1.26409e-06" iyy="0.000159844" iyz="-4.90188e-08" izz="0.00014529"/>
|
| 194 |
+
</inertial>
|
| 195 |
+
<!-- Part under_arm_so101_v1 -->
|
| 196 |
+
<visual>
|
| 197 |
+
<origin xyz="-0.0648499 -0.032 0.0182" rpy="3.14159 -0 6.67202e-31"/>
|
| 198 |
+
<geometry>
|
| 199 |
+
<mesh filename="assets/under_arm_so101_v1.stl"/>
|
| 200 |
+
</geometry>
|
| 201 |
+
<material name="under_arm_so101_v1_material">
|
| 202 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 203 |
+
</material>
|
| 204 |
+
</visual>
|
| 205 |
+
<collision>
|
| 206 |
+
<origin xyz="-0.0648499 -0.032 0.0182" rpy="3.14159 -0 6.67202e-31"/>
|
| 207 |
+
<geometry>
|
| 208 |
+
<mesh filename="assets/under_arm_so101_v1.stl"/>
|
| 209 |
+
</geometry>
|
| 210 |
+
</collision>
|
| 211 |
+
<!-- Part motor_holder_so101_wrist_v1 -->
|
| 212 |
+
<visual>
|
| 213 |
+
<origin xyz="-0.0648499 -0.032 0.018" rpy="-3.14159 -2.55351e-15 -2.56146e-31"/>
|
| 214 |
+
<geometry>
|
| 215 |
+
<mesh filename="assets/motor_holder_so101_wrist_v1.stl"/>
|
| 216 |
+
</geometry>
|
| 217 |
+
<material name="motor_holder_so101_wrist_v1_material">
|
| 218 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 219 |
+
</material>
|
| 220 |
+
</visual>
|
| 221 |
+
<collision>
|
| 222 |
+
<origin xyz="-0.0648499 -0.032 0.018" rpy="-3.14159 -2.55351e-15 -2.56146e-31"/>
|
| 223 |
+
<geometry>
|
| 224 |
+
<mesh filename="assets/motor_holder_so101_wrist_v1.stl"/>
|
| 225 |
+
</geometry>
|
| 226 |
+
</collision>
|
| 227 |
+
<!-- Part sts3215_03a_v1_4 -->
|
| 228 |
+
<visual>
|
| 229 |
+
<origin xyz="-0.1224 0.0052 0.0187" rpy="-3.14159 -7.88861e-31 -3.14159"/>
|
| 230 |
+
<geometry>
|
| 231 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 232 |
+
</geometry>
|
| 233 |
+
<material name="sts3215_03a_v1_4_material">
|
| 234 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 235 |
+
</material>
|
| 236 |
+
</visual>
|
| 237 |
+
<collision>
|
| 238 |
+
<origin xyz="-0.1224 0.0052 0.0187" rpy="-3.14159 -7.88861e-31 -3.14159"/>
|
| 239 |
+
<geometry>
|
| 240 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 241 |
+
</geometry>
|
| 242 |
+
</collision>
|
| 243 |
+
</link>
|
| 244 |
+
<!-- Link wrist -->
|
| 245 |
+
<link name="wrist">
|
| 246 |
+
<inertial>
|
| 247 |
+
<origin xyz="-0.000103312 -0.0386143 0.0281156" rpy="0 0 0"/>
|
| 248 |
+
<mass value="0.079"/>
|
| 249 |
+
<inertia ixx="3.68263e-05" ixy="1.7893e-08" ixz="-5.28128e-08" iyy="2.5391e-05" iyz="3.6412e-06" izz="2.1e-05"/>
|
| 250 |
+
</inertial>
|
| 251 |
+
<!-- Part sts3215_03a_no_horn_v1 -->
|
| 252 |
+
<visual>
|
| 253 |
+
<origin xyz="5.55112e-17 -0.0424 0.0306" rpy="1.5708 1.5708 0"/>
|
| 254 |
+
<geometry>
|
| 255 |
+
<mesh filename="assets/sts3215_03a_no_horn_v1.stl"/>
|
| 256 |
+
</geometry>
|
| 257 |
+
<material name="sts3215_03a_no_horn_v1_material">
|
| 258 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 259 |
+
</material>
|
| 260 |
+
</visual>
|
| 261 |
+
<collision>
|
| 262 |
+
<origin xyz="5.55112e-17 -0.0424 0.0306" rpy="1.5708 1.5708 0"/>
|
| 263 |
+
<geometry>
|
| 264 |
+
<mesh filename="assets/sts3215_03a_no_horn_v1.stl"/>
|
| 265 |
+
</geometry>
|
| 266 |
+
</collision>
|
| 267 |
+
<!-- Part wrist_roll_pitch_so101_v2 -->
|
| 268 |
+
<visual>
|
| 269 |
+
<origin xyz="0 -0.028 0.0181" rpy="-1.5708 -1.5708 0"/>
|
| 270 |
+
<geometry>
|
| 271 |
+
<mesh filename="assets/wrist_roll_pitch_so101_v2.stl"/>
|
| 272 |
+
</geometry>
|
| 273 |
+
<material name="wrist_roll_pitch_so101_v2_material">
|
| 274 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 275 |
+
</material>
|
| 276 |
+
</visual>
|
| 277 |
+
<collision>
|
| 278 |
+
<origin xyz="0 -0.028 0.0181" rpy="-1.5708 -1.5708 0"/>
|
| 279 |
+
<geometry>
|
| 280 |
+
<mesh filename="assets/wrist_roll_pitch_so101_v2.stl"/>
|
| 281 |
+
</geometry>
|
| 282 |
+
</collision>
|
| 283 |
+
</link>
|
| 284 |
+
<!-- Link gripper -->
|
| 285 |
+
<link name="gripper">
|
| 286 |
+
<inertial>
|
| 287 |
+
<origin xyz="0.000213627 0.000245138 -0.025187" rpy="0 0 0"/>
|
| 288 |
+
<mass value="0.087"/>
|
| 289 |
+
<inertia ixx="2.75087e-05" ixy="-3.35241e-07" ixz="-5.7352e-06" iyy="4.33657e-05" iyz="-5.17847e-08" izz="3.45059e-05"/>
|
| 290 |
+
</inertial>
|
| 291 |
+
<!-- Part sts3215_03a_v1_5 -->
|
| 292 |
+
<visual>
|
| 293 |
+
<origin xyz="0.0077 0.0001 -0.0234" rpy="-1.5708 -5.19179e-17 -1.66533e-16"/>
|
| 294 |
+
<geometry>
|
| 295 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 296 |
+
</geometry>
|
| 297 |
+
<material name="sts3215_03a_v1_5_material">
|
| 298 |
+
<color rgba="0.627451 0.627451 0.627451 1.0"/>
|
| 299 |
+
</material>
|
| 300 |
+
</visual>
|
| 301 |
+
<collision>
|
| 302 |
+
<origin xyz="0.0077 0.0001 -0.0234" rpy="-1.5708 -5.19179e-17 -1.66533e-16"/>
|
| 303 |
+
<geometry>
|
| 304 |
+
<mesh filename="assets/sts3215_03a_v1.stl"/>
|
| 305 |
+
</geometry>
|
| 306 |
+
</collision>
|
| 307 |
+
<!-- Part wrist_roll_follower_so101_v1 -->
|
| 308 |
+
<visual>
|
| 309 |
+
<origin xyz="0 -0.000218214 0.000949706" rpy="-3.14159 -5.55112e-17 0"/>
|
| 310 |
+
<geometry>
|
| 311 |
+
<mesh filename="assets/wrist_roll_follower_so101_v1.stl"/>
|
| 312 |
+
</geometry>
|
| 313 |
+
<material name="wrist_roll_follower_so101_v1_material">
|
| 314 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 315 |
+
</material>
|
| 316 |
+
</visual>
|
| 317 |
+
<collision>
|
| 318 |
+
<origin xyz="0 -0.000218214 0.000949706" rpy="-3.14159 -5.55112e-17 0"/>
|
| 319 |
+
<geometry>
|
| 320 |
+
<mesh filename="assets/wrist_roll_follower_so101_v1.stl"/>
|
| 321 |
+
</geometry>
|
| 322 |
+
</collision>
|
| 323 |
+
</link>
|
| 324 |
+
<!-- Frame gripperframe (dummy link + fixed joint) -->
|
| 325 |
+
<link name="gripperframe">
|
| 326 |
+
<origin xyz="0 0 0" rpy="0 -0 0"/>
|
| 327 |
+
<inertial>
|
| 328 |
+
<origin xyz="0 0 0" rpy="0 0 0"/>
|
| 329 |
+
<mass value="1e-9"/>
|
| 330 |
+
<inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
|
| 331 |
+
</inertial>
|
| 332 |
+
</link>
|
| 333 |
+
<joint name="gripperframe_frame" type="fixed">
|
| 334 |
+
<origin xyz="-0.0079 -0.000218121 -0.0981274" rpy="-0 1.5708 0"/>
|
| 335 |
+
<parent link="gripper"/>
|
| 336 |
+
<child link="gripperframe"/>
|
| 337 |
+
<axis xyz="0 0 0"/>
|
| 338 |
+
</joint>
|
| 339 |
+
<!-- Link moving_jaw_so101_v1 -->
|
| 340 |
+
<link name="moving_jaw_so101_v1">
|
| 341 |
+
<inertial>
|
| 342 |
+
<origin xyz="-0.00157495 -0.0300244 0.0192755" rpy="0 0 0"/>
|
| 343 |
+
<mass value="0.012"/>
|
| 344 |
+
<inertia ixx="6.61427e-06" ixy="-3.19807e-07" ixz="-5.90717e-09" iyy="1.89032e-06" iyz="-1.09945e-07" izz="5.28738e-06"/>
|
| 345 |
+
</inertial>
|
| 346 |
+
<!-- Part moving_jaw_so101_v1 -->
|
| 347 |
+
<visual>
|
| 348 |
+
<origin xyz="-5.55112e-17 0 0.0189" rpy="9.53145e-17 6.93889e-18 1.24077e-24"/>
|
| 349 |
+
<geometry>
|
| 350 |
+
<mesh filename="assets/moving_jaw_so101_v1.stl"/>
|
| 351 |
+
</geometry>
|
| 352 |
+
<material name="moving_jaw_so101_v1_material">
|
| 353 |
+
<color rgba="0.964706 0.964706 0.952941 1.0"/>
|
| 354 |
+
</material>
|
| 355 |
+
</visual>
|
| 356 |
+
<collision>
|
| 357 |
+
<origin xyz="-5.55112e-17 0 0.0189" rpy="9.53145e-17 6.93889e-18 1.24077e-24"/>
|
| 358 |
+
<geometry>
|
| 359 |
+
<mesh filename="assets/moving_jaw_so101_v1.stl"/>
|
| 360 |
+
</geometry>
|
| 361 |
+
</collision>
|
| 362 |
+
</link>
|
| 363 |
+
<!-- Joint from gripper to moving_jaw_so101_v1 -->
|
| 364 |
+
<joint name="6" type="revolute">
|
| 365 |
+
<origin xyz="0.0202 0.0188 -0.0234" rpy="1.5708 -5.24284e-08 -1.41553e-15"/>
|
| 366 |
+
<parent link="gripper"/>
|
| 367 |
+
<child link="moving_jaw_so101_v1"/>
|
| 368 |
+
<axis xyz="0 0 1"/>
|
| 369 |
+
<limit effort="10" velocity="10" lower="-0.174533" upper="1.74533"/>
|
| 370 |
+
</joint>
|
| 371 |
+
<!-- Joint from wrist to gripper -->
|
| 372 |
+
<joint name="5" type="revolute">
|
| 373 |
+
<origin xyz="2.77556e-16 -0.0611 0.0181" rpy="1.5708 0.0486795 3.14159"/>
|
| 374 |
+
<parent link="wrist"/>
|
| 375 |
+
<child link="gripper"/>
|
| 376 |
+
<axis xyz="0 0 1"/>
|
| 377 |
+
<limit effort="10" velocity="10" lower="-2.74385" upper="2.84121"/>
|
| 378 |
+
</joint>
|
| 379 |
+
<!-- Joint from lower_arm to wrist -->
|
| 380 |
+
<joint name="4" type="revolute">
|
| 381 |
+
<origin xyz="-0.1349 0.0052 8.44651e-17" rpy="4.02456e-15 8.67362e-16 -1.5708"/>
|
| 382 |
+
<parent link="lower_arm"/>
|
| 383 |
+
<child link="wrist"/>
|
| 384 |
+
<axis xyz="0 0 1"/>
|
| 385 |
+
<limit effort="10" velocity="10" lower="-1.65806" upper="1.65806"/>
|
| 386 |
+
</joint>
|
| 387 |
+
<!-- Joint from upper_arm to lower_arm -->
|
| 388 |
+
<joint name="3" type="revolute">
|
| 389 |
+
<origin xyz="-0.11257 -0.028 2.09886e-16" rpy="-3.63608e-16 8.74301e-16 1.5708"/>
|
| 390 |
+
<parent link="upper_arm"/>
|
| 391 |
+
<child link="lower_arm"/>
|
| 392 |
+
<axis xyz="0 0 1"/>
|
| 393 |
+
<limit effort="10" velocity="10" lower="-1.74533" upper="1.5708"/>
|
| 394 |
+
</joint>
|
| 395 |
+
<!-- Joint from shoulder to upper_arm -->
|
| 396 |
+
<joint name="2" type="revolute">
|
| 397 |
+
<origin xyz="-0.0303992 -0.0182778 -0.0542" rpy="-1.5708 -1.5708 0"/>
|
| 398 |
+
<parent link="shoulder"/>
|
| 399 |
+
<child link="upper_arm"/>
|
| 400 |
+
<axis xyz="0 0 1"/>
|
| 401 |
+
<limit effort="10" velocity="10" lower="-1.74533" upper="1.74533"/>
|
| 402 |
+
</joint>
|
| 403 |
+
<!-- Joint from base to shoulder -->
|
| 404 |
+
<joint name="1" type="revolute">
|
| 405 |
+
<origin xyz="-0.124202 -0.168068 0.0948817" rpy="3.14159 4.18253e-17 -3.14159"/>
|
| 406 |
+
<parent link="base"/>
|
| 407 |
+
<child link="shoulder"/>
|
| 408 |
+
<axis xyz="0 0 1"/>
|
| 409 |
+
<limit effort="10" velocity="10" lower="-1.91986" upper="1.91986"/>
|
| 410 |
+
</joint>
|
| 411 |
+
</robot>
|
urdf_viewer.html
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>URDF Robot Viewer - xoq</title>
|
| 7 |
+
<style>
|
| 8 |
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 9 |
+
body {
|
| 10 |
+
font-family: system-ui, -apple-system, sans-serif;
|
| 11 |
+
background: #1a1a2e;
|
| 12 |
+
color: #eee;
|
| 13 |
+
height: 100vh;
|
| 14 |
+
display: flex;
|
| 15 |
+
flex-direction: column;
|
| 16 |
+
overflow: hidden;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
/* Top bar */
|
| 20 |
+
.top-bar {
|
| 21 |
+
padding: 0.5rem 1rem;
|
| 22 |
+
display: flex;
|
| 23 |
+
align-items: center;
|
| 24 |
+
gap: 0.75rem;
|
| 25 |
+
flex-wrap: wrap;
|
| 26 |
+
border-bottom: 1px solid #333;
|
| 27 |
+
background: #16162a;
|
| 28 |
+
}
|
| 29 |
+
.top-bar h1 { color: #00d4ff; font-size: 1.1rem; white-space: nowrap; }
|
| 30 |
+
.top-bar label {
|
| 31 |
+
display: flex;
|
| 32 |
+
align-items: center;
|
| 33 |
+
gap: 0.3rem;
|
| 34 |
+
font-size: 0.85rem;
|
| 35 |
+
color: #aaa;
|
| 36 |
+
}
|
| 37 |
+
.top-bar input[type="text"] {
|
| 38 |
+
padding: 0.35rem 0.5rem;
|
| 39 |
+
border: 1px solid #444;
|
| 40 |
+
border-radius: 4px;
|
| 41 |
+
background: #2a2a4a;
|
| 42 |
+
color: #fff;
|
| 43 |
+
font-size: 0.85rem;
|
| 44 |
+
width: 240px;
|
| 45 |
+
}
|
| 46 |
+
button {
|
| 47 |
+
padding: 0.35rem 0.75rem;
|
| 48 |
+
border: none;
|
| 49 |
+
border-radius: 4px;
|
| 50 |
+
cursor: pointer;
|
| 51 |
+
font-size: 0.85rem;
|
| 52 |
+
transition: background 0.2s;
|
| 53 |
+
}
|
| 54 |
+
button:disabled { opacity: 0.5; cursor: not-allowed; }
|
| 55 |
+
#loadUrdfBtn { background: #a855f7; color: #fff; }
|
| 56 |
+
#loadUrdfBtn:hover:not(:disabled) { background: #9333ea; }
|
| 57 |
+
#startBtn { background: #00d4ff; color: #000; }
|
| 58 |
+
#startBtn:hover:not(:disabled) { background: #00b8e6; }
|
| 59 |
+
#stopBtn { background: #ff4757; color: #fff; }
|
| 60 |
+
#stopBtn:hover:not(:disabled) { background: #ff3344; }
|
| 61 |
+
#queryBtn { background: #2a2a4a; color: #888; border: 1px solid #444; }
|
| 62 |
+
#queryBtn.active { background: #2ed573; color: #000; border-color: #2ed573; }
|
| 63 |
+
#queryBtn:hover:not(:disabled) { background: #444; }
|
| 64 |
+
#queryBtn.active:hover:not(:disabled) { background: #26b860; }
|
| 65 |
+
|
| 66 |
+
/* Main layout */
|
| 67 |
+
.main {
|
| 68 |
+
flex: 1;
|
| 69 |
+
display: flex;
|
| 70 |
+
min-height: 0;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
/* 3D canvas */
|
| 74 |
+
.canvas-container {
|
| 75 |
+
flex: 1;
|
| 76 |
+
position: relative;
|
| 77 |
+
min-width: 0;
|
| 78 |
+
}
|
| 79 |
+
#threeCanvas {
|
| 80 |
+
width: 100%;
|
| 81 |
+
height: 100%;
|
| 82 |
+
display: block;
|
| 83 |
+
}
|
| 84 |
+
.canvas-overlay {
|
| 85 |
+
position: absolute;
|
| 86 |
+
top: 0.5rem;
|
| 87 |
+
left: 0.5rem;
|
| 88 |
+
font-size: 0.7rem;
|
| 89 |
+
color: #888;
|
| 90 |
+
pointer-events: none;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
/* Right panel */
|
| 94 |
+
.side-panel {
|
| 95 |
+
width: 300px;
|
| 96 |
+
background: #16162a;
|
| 97 |
+
border-left: 1px solid #333;
|
| 98 |
+
display: flex;
|
| 99 |
+
flex-direction: column;
|
| 100 |
+
overflow-y: auto;
|
| 101 |
+
}
|
| 102 |
+
.panel-section {
|
| 103 |
+
padding: 0.75rem;
|
| 104 |
+
border-bottom: 1px solid #2a2a4a;
|
| 105 |
+
}
|
| 106 |
+
.panel-section h3 {
|
| 107 |
+
font-size: 0.8rem;
|
| 108 |
+
color: #888;
|
| 109 |
+
text-transform: uppercase;
|
| 110 |
+
margin-bottom: 0.5rem;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
/* Joint rows */
|
| 114 |
+
.joint-row {
|
| 115 |
+
display: grid;
|
| 116 |
+
grid-template-columns: 70px 1fr 50px;
|
| 117 |
+
gap: 0.25rem;
|
| 118 |
+
align-items: center;
|
| 119 |
+
padding: 0.3rem 0;
|
| 120 |
+
font-size: 0.8rem;
|
| 121 |
+
border-bottom: 1px solid #1e1e3a;
|
| 122 |
+
}
|
| 123 |
+
.joint-row:last-child { border-bottom: none; }
|
| 124 |
+
.joint-label {
|
| 125 |
+
font-weight: bold;
|
| 126 |
+
white-space: nowrap;
|
| 127 |
+
overflow: hidden;
|
| 128 |
+
text-overflow: ellipsis;
|
| 129 |
+
}
|
| 130 |
+
.joint-angle {
|
| 131 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 132 |
+
text-align: right;
|
| 133 |
+
font-size: 0.85rem;
|
| 134 |
+
}
|
| 135 |
+
.joint-raw {
|
| 136 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 137 |
+
text-align: right;
|
| 138 |
+
font-size: 0.7rem;
|
| 139 |
+
color: #888;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
/* Mapping rows */
|
| 143 |
+
.mapping-row {
|
| 144 |
+
display: flex;
|
| 145 |
+
align-items: center;
|
| 146 |
+
gap: 0.3rem;
|
| 147 |
+
padding: 0.25rem 0;
|
| 148 |
+
font-size: 0.8rem;
|
| 149 |
+
}
|
| 150 |
+
.mapping-row input {
|
| 151 |
+
width: 40px;
|
| 152 |
+
padding: 0.2rem 0.3rem;
|
| 153 |
+
border: 1px solid #444;
|
| 154 |
+
border-radius: 3px;
|
| 155 |
+
background: #2a2a4a;
|
| 156 |
+
color: #fff;
|
| 157 |
+
font-size: 0.8rem;
|
| 158 |
+
text-align: center;
|
| 159 |
+
}
|
| 160 |
+
.mapping-row select {
|
| 161 |
+
flex: 1;
|
| 162 |
+
padding: 0.2rem 0.3rem;
|
| 163 |
+
border: 1px solid #444;
|
| 164 |
+
border-radius: 3px;
|
| 165 |
+
background: #2a2a4a;
|
| 166 |
+
color: #fff;
|
| 167 |
+
font-size: 0.8rem;
|
| 168 |
+
}
|
| 169 |
+
.mapping-row .remove-btn {
|
| 170 |
+
padding: 0.1rem 0.4rem;
|
| 171 |
+
background: #ff475733;
|
| 172 |
+
color: #ff4757;
|
| 173 |
+
border: 1px solid #ff475744;
|
| 174 |
+
font-size: 0.7rem;
|
| 175 |
+
}
|
| 176 |
+
.mapping-actions {
|
| 177 |
+
display: flex;
|
| 178 |
+
gap: 0.4rem;
|
| 179 |
+
margin-top: 0.4rem;
|
| 180 |
+
}
|
| 181 |
+
.mapping-actions button {
|
| 182 |
+
font-size: 0.7rem;
|
| 183 |
+
padding: 0.2rem 0.5rem;
|
| 184 |
+
background: #2a2a4a;
|
| 185 |
+
color: #aaa;
|
| 186 |
+
border: 1px solid #444;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
/* Stats */
|
| 190 |
+
.stats-grid {
|
| 191 |
+
display: grid;
|
| 192 |
+
grid-template-columns: 1fr 1fr;
|
| 193 |
+
gap: 0.4rem;
|
| 194 |
+
}
|
| 195 |
+
.stat {
|
| 196 |
+
background: #2a2a4a;
|
| 197 |
+
padding: 0.4rem;
|
| 198 |
+
border-radius: 4px;
|
| 199 |
+
text-align: center;
|
| 200 |
+
}
|
| 201 |
+
.stat-label { color: #888; font-size: 0.65rem; text-transform: uppercase; }
|
| 202 |
+
.stat-value { font-size: 0.9rem; font-weight: bold; color: #00d4ff; }
|
| 203 |
+
|
| 204 |
+
/* Log */
|
| 205 |
+
.log-panel {
|
| 206 |
+
height: 120px;
|
| 207 |
+
border-top: 1px solid #333;
|
| 208 |
+
background: #0a0a1a;
|
| 209 |
+
overflow-y: auto;
|
| 210 |
+
padding: 0.5rem;
|
| 211 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 212 |
+
font-size: 0.7rem;
|
| 213 |
+
flex-shrink: 0;
|
| 214 |
+
}
|
| 215 |
+
.log-entry { margin: 0.15rem 0; }
|
| 216 |
+
.log-info { color: #888; }
|
| 217 |
+
.log-success { color: #2ed573; }
|
| 218 |
+
.log-error { color: #ff4757; }
|
| 219 |
+
.log-data { color: #00d4ff; }
|
| 220 |
+
</style>
|
| 221 |
+
<script type="module" crossorigin src="/assets/urdf_viewer-trQNEAhR.js"></script>
|
| 222 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 223 |
+
<link rel="modulepreload" crossorigin href="/assets/URDFLoader-CL7UVBjw.js">
|
| 224 |
+
</head>
|
| 225 |
+
<body>
|
| 226 |
+
<div class="top-bar">
|
| 227 |
+
<h1>URDF Viewer</h1>
|
| 228 |
+
<label>
|
| 229 |
+
URDF:
|
| 230 |
+
<input type="text" id="urdfUrl" style="width:300px;" />
|
| 231 |
+
</label>
|
| 232 |
+
<button id="loadUrdfBtn">Load</button>
|
| 233 |
+
<span style="color:#444;">|</span>
|
| 234 |
+
<label>
|
| 235 |
+
Relay:
|
| 236 |
+
<input type="text" id="relayUrl" />
|
| 237 |
+
</label>
|
| 238 |
+
<label>
|
| 239 |
+
Path:
|
| 240 |
+
<input type="text" id="path" />
|
| 241 |
+
</label>
|
| 242 |
+
<label>
|
| 243 |
+
Cert hash:
|
| 244 |
+
<input type="text" id="certHash" placeholder="sha256 hex (optional)" style="width:180px;" />
|
| 245 |
+
</label>
|
| 246 |
+
<button id="startBtn">Connect</button>
|
| 247 |
+
<button id="stopBtn" disabled>Disconnect</button>
|
| 248 |
+
<button id="queryBtn" disabled>Query Servos</button>
|
| 249 |
+
<span id="statusText" style="color:#888; font-size:0.8rem;">Idle</span>
|
| 250 |
+
</div>
|
| 251 |
+
|
| 252 |
+
<div class="main">
|
| 253 |
+
<div class="canvas-container">
|
| 254 |
+
<canvas id="threeCanvas"></canvas>
|
| 255 |
+
<div class="canvas-overlay">
|
| 256 |
+
<span>Drag to orbit / Scroll to zoom / Right-drag to pan</span>
|
| 257 |
+
</div>
|
| 258 |
+
</div>
|
| 259 |
+
|
| 260 |
+
<div class="side-panel">
|
| 261 |
+
<div class="panel-section">
|
| 262 |
+
<h3>Joint Angles</h3>
|
| 263 |
+
<div class="joint-row" style="font-size:0.65rem; color:#666;">
|
| 264 |
+
<span>Joint</span><span style="text-align:right;">Angle</span><span style="text-align:right;">Raw</span>
|
| 265 |
+
</div>
|
| 266 |
+
<div id="jointRows"><span style="color:#666; font-size:0.75rem;">Load a URDF to see joints</span></div>
|
| 267 |
+
</div>
|
| 268 |
+
|
| 269 |
+
<div class="panel-section">
|
| 270 |
+
<h3>Joint Mapping (Servo ID → Joint)</h3>
|
| 271 |
+
<div id="mappingRows"></div>
|
| 272 |
+
<div class="mapping-actions">
|
| 273 |
+
<button id="addMappingBtn">+ Add</button>
|
| 274 |
+
<button id="resetMappingBtn">Reset</button>
|
| 275 |
+
</div>
|
| 276 |
+
</div>
|
| 277 |
+
|
| 278 |
+
<div class="panel-section">
|
| 279 |
+
<h3>Stats</h3>
|
| 280 |
+
<div class="stats-grid">
|
| 281 |
+
<div class="stat">
|
| 282 |
+
<div class="stat-label">Frames</div>
|
| 283 |
+
<div class="stat-value" id="frameCount">0</div>
|
| 284 |
+
</div>
|
| 285 |
+
<div class="stat">
|
| 286 |
+
<div class="stat-label">Bytes</div>
|
| 287 |
+
<div class="stat-value" id="bytesReceived">0 B</div>
|
| 288 |
+
</div>
|
| 289 |
+
<div class="stat">
|
| 290 |
+
<div class="stat-label">FPS</div>
|
| 291 |
+
<div class="stat-value" id="canFps">0</div>
|
| 292 |
+
</div>
|
| 293 |
+
<div class="stat">
|
| 294 |
+
<div class="stat-label">Last</div>
|
| 295 |
+
<div class="stat-value" id="lastUpdate">-</div>
|
| 296 |
+
</div>
|
| 297 |
+
</div>
|
| 298 |
+
</div>
|
| 299 |
+
</div>
|
| 300 |
+
</div>
|
| 301 |
+
|
| 302 |
+
<div class="log-panel" id="log"></div>
|
| 303 |
+
|
| 304 |
+
</body>
|
| 305 |
+
</html>
|
video_player.html
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Camera CMAF Player - xoq</title>
|
| 7 |
+
|
| 8 |
+
<style>
|
| 9 |
+
* { box-sizing: border-box; }
|
| 10 |
+
body {
|
| 11 |
+
font-family: system-ui, -apple-system, sans-serif;
|
| 12 |
+
max-width: 900px;
|
| 13 |
+
margin: 0 auto;
|
| 14 |
+
padding: 1rem;
|
| 15 |
+
background: #1a1a2e;
|
| 16 |
+
color: #eee;
|
| 17 |
+
}
|
| 18 |
+
h1 { color: #00d4ff; margin-bottom: 0.5rem; }
|
| 19 |
+
.subtitle { color: #888; margin-bottom: 1.5rem; }
|
| 20 |
+
|
| 21 |
+
.controls {
|
| 22 |
+
display: flex;
|
| 23 |
+
gap: 0.5rem;
|
| 24 |
+
flex-wrap: wrap;
|
| 25 |
+
margin-bottom: 1rem;
|
| 26 |
+
align-items: center;
|
| 27 |
+
}
|
| 28 |
+
.controls label {
|
| 29 |
+
display: flex;
|
| 30 |
+
align-items: center;
|
| 31 |
+
gap: 0.5rem;
|
| 32 |
+
}
|
| 33 |
+
.controls input[type="text"] {
|
| 34 |
+
padding: 0.5rem;
|
| 35 |
+
border: 1px solid #444;
|
| 36 |
+
border-radius: 4px;
|
| 37 |
+
background: #2a2a4a;
|
| 38 |
+
color: #fff;
|
| 39 |
+
width: 300px;
|
| 40 |
+
}
|
| 41 |
+
button {
|
| 42 |
+
padding: 0.5rem 1rem;
|
| 43 |
+
border: none;
|
| 44 |
+
border-radius: 4px;
|
| 45 |
+
cursor: pointer;
|
| 46 |
+
font-size: 1rem;
|
| 47 |
+
transition: background 0.2s;
|
| 48 |
+
}
|
| 49 |
+
button:disabled { opacity: 0.5; cursor: not-allowed; }
|
| 50 |
+
#startBtn { background: #00d4ff; color: #000; }
|
| 51 |
+
#startBtn:hover:not(:disabled) { background: #00b8e6; }
|
| 52 |
+
#stopBtn { background: #ff4757; color: #fff; }
|
| 53 |
+
#stopBtn:hover:not(:disabled) { background: #ff3344; }
|
| 54 |
+
|
| 55 |
+
.video-container {
|
| 56 |
+
background: #000;
|
| 57 |
+
border-radius: 8px;
|
| 58 |
+
overflow: hidden;
|
| 59 |
+
margin-bottom: 1rem;
|
| 60 |
+
aspect-ratio: 16/9;
|
| 61 |
+
}
|
| 62 |
+
video { width: 100%; height: 100%; display: block; }
|
| 63 |
+
|
| 64 |
+
.stats {
|
| 65 |
+
display: grid;
|
| 66 |
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
| 67 |
+
gap: 0.5rem;
|
| 68 |
+
margin-bottom: 1rem;
|
| 69 |
+
}
|
| 70 |
+
.stat {
|
| 71 |
+
background: #2a2a4a;
|
| 72 |
+
padding: 0.75rem;
|
| 73 |
+
border-radius: 8px;
|
| 74 |
+
text-align: center;
|
| 75 |
+
}
|
| 76 |
+
.stat-label { color: #888; font-size: 0.75rem; text-transform: uppercase; }
|
| 77 |
+
.stat-value { font-size: 1.2rem; font-weight: bold; color: #00d4ff; }
|
| 78 |
+
|
| 79 |
+
.info-box {
|
| 80 |
+
background: #2a2a4a;
|
| 81 |
+
padding: 1rem;
|
| 82 |
+
border-radius: 8px;
|
| 83 |
+
margin-bottom: 1rem;
|
| 84 |
+
}
|
| 85 |
+
.info-box h3 { margin-top: 0; color: #00d4ff; }
|
| 86 |
+
.info-box pre {
|
| 87 |
+
background: #1a1a2e;
|
| 88 |
+
padding: 1rem;
|
| 89 |
+
border-radius: 4px;
|
| 90 |
+
overflow-x: auto;
|
| 91 |
+
margin: 0.5rem 0;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
#log {
|
| 95 |
+
background: #0a0a1a;
|
| 96 |
+
border: 1px solid #333;
|
| 97 |
+
border-radius: 8px;
|
| 98 |
+
padding: 1rem;
|
| 99 |
+
height: 200px;
|
| 100 |
+
overflow-y: auto;
|
| 101 |
+
font-family: 'Monaco', 'Menlo', monospace;
|
| 102 |
+
font-size: 0.8rem;
|
| 103 |
+
}
|
| 104 |
+
.log-entry { margin: 0.2rem 0; }
|
| 105 |
+
.log-info { color: #888; }
|
| 106 |
+
.log-success { color: #2ed573; }
|
| 107 |
+
.log-error { color: #ff4757; }
|
| 108 |
+
.log-data { color: #00d4ff; }
|
| 109 |
+
</style>
|
| 110 |
+
<script type="importmap">
|
| 111 |
+
{
|
| 112 |
+
"imports": {
|
| 113 |
+
"@moq/lite": "https://esm.sh/@moq/lite@0.1.0"
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
</script>
|
| 117 |
+
<script type="module" crossorigin src="/assets/video_player-BJSMA0Bo.js"></script>
|
| 118 |
+
<link rel="modulepreload" crossorigin href="/assets/connect-DkGLCYAo.js">
|
| 119 |
+
</head>
|
| 120 |
+
<body>
|
| 121 |
+
<h1>Camera CMAF Player</h1>
|
| 122 |
+
<p class="subtitle">xoq MoQ Video Stream Client</p>
|
| 123 |
+
|
| 124 |
+
<div class="controls">
|
| 125 |
+
<label>
|
| 126 |
+
URL:
|
| 127 |
+
<input type="text" id="relayUrl" value="https://cdn.moq.dev/anon" />
|
| 128 |
+
</label>
|
| 129 |
+
<label>
|
| 130 |
+
Path:
|
| 131 |
+
<input type="text" id="path" value="camera" />
|
| 132 |
+
</label>
|
| 133 |
+
</div>
|
| 134 |
+
<div class="controls">
|
| 135 |
+
<button id="startBtn">Connect</button>
|
| 136 |
+
<button id="stopBtn" disabled>Disconnect</button>
|
| 137 |
+
</div>
|
| 138 |
+
|
| 139 |
+
<div class="video-container">
|
| 140 |
+
<video id="video" autoplay muted playsinline></video>
|
| 141 |
+
</div>
|
| 142 |
+
|
| 143 |
+
<div class="stats">
|
| 144 |
+
<div class="stat">
|
| 145 |
+
<div class="stat-label">Status</div>
|
| 146 |
+
<div class="stat-value" id="status">Idle</div>
|
| 147 |
+
</div>
|
| 148 |
+
<div class="stat">
|
| 149 |
+
<div class="stat-label">Groups</div>
|
| 150 |
+
<div class="stat-value" id="groupCount">0</div>
|
| 151 |
+
</div>
|
| 152 |
+
<div class="stat">
|
| 153 |
+
<div class="stat-label">Received</div>
|
| 154 |
+
<div class="stat-value" id="bytesReceived">0 B</div>
|
| 155 |
+
</div>
|
| 156 |
+
<div class="stat">
|
| 157 |
+
<div class="stat-label">Buffer</div>
|
| 158 |
+
<div class="stat-value" id="bufferLength">0s</div>
|
| 159 |
+
</div>
|
| 160 |
+
</div>
|
| 161 |
+
|
| 162 |
+
<h3>Log</h3>
|
| 163 |
+
<div id="log"></div>
|
| 164 |
+
|
| 165 |
+
<div class="info-box">
|
| 166 |
+
<h3>How to Run</h3>
|
| 167 |
+
<p>This player requires running from the xoq JS dev server:</p>
|
| 168 |
+
<pre>cd ../wser/js
|
| 169 |
+
npm install
|
| 170 |
+
npm run examples</pre>
|
| 171 |
+
<p>Or start the camera stream with:</p>
|
| 172 |
+
<pre>cargo run --example camera_xoq_stream --features xoq</pre>
|
| 173 |
+
</div>
|
| 174 |
+
|
| 175 |
+
</body>
|
| 176 |
+
</html>
|