Spaces:
Running
Running
egoSample/faberu: 640-wide previews (~500 kbps, 31 MB), parallel point-cloud fetch, accumulated environment map
Browse files- egoSample/epdata/restock_20260916_ep000.pack +2 -2
- egoSample/faberu.html +17 -10
- egoSample/media/restock_20260916_ep000/head_color.mp4 +2 -2
- egoSample/media/restock_20260916_ep000/head_depth.mp4 +2 -2
- egoSample/media/restock_20260916_ep000/head_left_fisheye.mp4 +2 -2
- egoSample/media/restock_20260916_ep000/head_right_fisheye.mp4 +2 -2
- egoSample/media/restock_20260916_ep000/head_stereo_left.mp4 +2 -2
- egoSample/media/restock_20260916_ep000/head_stereo_right.mp4 +2 -2
egoSample/epdata/restock_20260916_ep000.pack
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f274669a4116fba7779f9f380f9338ec98d475c915385901002d904a615ff12f
|
| 3 |
+
size 5271240
|
egoSample/faberu.html
CHANGED
|
@@ -90,17 +90,17 @@ const fmt=t=>{t=Math.max(0,t);const m=Math.floor(t/60),s=t%60;return m+':'+s.toF
|
|
| 90 |
const skc=s=>SKC[s]||'#666';
|
| 91 |
|
| 92 |
function select(i){ EP=EPS[i]; SIG=null; cancelAnimationFrame(raf); clearInterval(syncT); playing=false; render(); loadSig(EP.slug); }
|
| 93 |
-
function loadSig(slug){ window.EPDATA=window.EPDATA||{};
|
| 94 |
-
const done=()=>{ SIG=window.EPDATA[slug]; if(!SIG) return; sizeCharts(); drawCharts(); init3D();
|
| 95 |
const go=()=>{ if(_toggle&&!playing) _toggle(); }; if(master.readyState>=3) go(); else master.addEventListener('canplay',go,{once:true}); };
|
| 96 |
if(window.EPDATA[slug]){ done(); return; }
|
| 97 |
const s=document.createElement('script'); s.fetchPriority='high'; s.src='epdata/'+slug+'.js'; s.onload=done; document.body.appendChild(s); }
|
| 98 |
|
| 99 |
/* heavy viewer payload (lidar snapshots + depth-hover grid): gzip'd binary, fetched after the page is interactive */
|
| 100 |
-
async function loadPack(
|
| 101 |
const st=()=>document.getElementById('cloudStat');
|
| 102 |
try{
|
| 103 |
-
const res=await fetch('epdata/'+
|
| 104 |
const total=+res.headers.get('content-length')||0, rd=res.body.getReader(), parts=[]; let got=0;
|
| 105 |
for(;;){ const {done,value}=await rd.read(); if(done) break; parts.push(value); got+=value.length;
|
| 106 |
if(st()) st().textContent=`loading point cloud… ${(got/1e6).toFixed(1)}${total?' / '+(total/1e6).toFixed(1):''} MB`; }
|
|
@@ -111,8 +111,9 @@ async function loadPack(sig){
|
|
| 111 |
const ab=buf.buffer;
|
| 112 |
sig.clouds={}; Object.entries(hdr.clouds).forEach(([k,fr])=>{ sig.clouds[k]=fr.map(f=>({t:f.t, q:new Int16Array(ab,base+f.xyz,f.n*3), I:new Uint8Array(ab,base+f.i,f.n)})); });
|
| 113 |
sig.depthGrid=hdr.depth.frames.map(o=>new Uint16Array(ab,base+o,hdr.depth.w*hdr.depth.h));
|
| 114 |
-
if(
|
| 115 |
-
|
|
|
|
| 116 |
}
|
| 117 |
|
| 118 |
function render(){
|
|
@@ -136,7 +137,7 @@ function render(){
|
|
| 136 |
<div class="panel">
|
| 137 |
<div class="vgrid">${CAMS.map(c=>tile(c)).join('')}</div>
|
| 138 |
<div class="chk" id="chk"></div>
|
| 139 |
-
<div class="three" id="three"><span class="lbl">world (odom) · robot links ·
|
| 140 |
</div>
|
| 141 |
<div class="panel">
|
| 142 |
<div class="spans-head">temporal spans (${e.n_segments}) · <b>${esc(e.task_name)}</b></div>
|
|
@@ -290,9 +291,15 @@ async function init3D(){
|
|
| 290 |
['l','r'].forEach(s=>{ bones.push(['arm_base_link',`arm_${s}_link1`]); for(let i=1;i<7;i++) bones.push([`arm_${s}_link${i}`,`arm_${s}_link${i+1}`]); bones.push([`arm_${s}_link7`,`arm_${s}_end_link`],[`arm_${s}_end_link`,`gripper_${s}_center_link`]); });
|
| 291 |
const clouds={}; const CC={lidar_front:[1,.54,.44],lidar_back:[.43,.66,1]};
|
| 292 |
let follow=false;
|
| 293 |
-
const buildChk=()=>{ document.getElementById('chk').innerHTML=Object.keys(clouds).map(k=>`<label><input type="checkbox" data-k="${k}" checked>${k}</label>`).join('')+`<label><input type="checkbox" data-k="__path" checked>base path</label><label><input type="checkbox" data-k="__follow">camera follows robot</label>`;
|
| 294 |
document.querySelectorAll('#chk input').forEach(i=>i.onchange=()=>{ const k=i.dataset.k; if(k==='__path') path.visible=i.checked; else if(k==='__follow') follow=i.checked; else clouds[k].p.visible=i.checked; }); };
|
| 295 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
buildChk(); if(setCloudT) setCloudT(master.currentTime||0); };
|
| 297 |
buildChk();
|
| 298 |
let last=null;
|
|
@@ -302,7 +309,7 @@ async function init3D(){
|
|
| 302 |
const lt=SIG.link_t; let li=0; while(li<lt.length-1&<[li+1]<=t) li++; const P=SIG.link_p[li];
|
| 303 |
const seg=[]; bones.forEach(([a,c])=>{ const ia=idx(a), ic=idx(c); if(ia>=0&&ic>=0) seg.push(...P[ia],...P[ic]); });
|
| 304 |
body.geometry.setAttribute('position',new THREE.Float32BufferAttribute(seg,3)); joints.geometry.setAttribute('position',new THREE.Float32BufferAttribute(P.flat(),3));
|
| 305 |
-
Object.entries(clouds).forEach(([k,C])=>{ const fr=SIG.clouds&&SIG.clouds[k]; if(!fr) return; let i=0; while(i<fr.length-1&&fr[i+1].t<=t) i++; if(i===C.cur) return; C.cur=i;
|
| 306 |
const f=fr[i], q=f.q, I=f.I, n=I.length, bj=Math.max(0,Math.min(SIG.n-1,Math.round(f.t*SIG.fps))), bb=SIG.base[bj], cs=Math.cos(bb[2]), sn=Math.sin(bb[2]);
|
| 307 |
const pos=new Float32Array(n*3), col=new Float32Array(n*3), base=CC[k]||[.8,.8,.8];
|
| 308 |
for(let m=0;m<n;m++){ const x=q[3*m]/100,y=q[3*m+1]/100,z=q[3*m+2]/100; pos[3*m]=bb[0]+cs*x-sn*y; pos[3*m+1]=bb[1]+sn*x+cs*y; pos[3*m+2]=z;
|
|
|
|
| 90 |
const skc=s=>SKC[s]||'#666';
|
| 91 |
|
| 92 |
function select(i){ EP=EPS[i]; SIG=null; cancelAnimationFrame(raf); clearInterval(syncT); playing=false; render(); loadSig(EP.slug); }
|
| 93 |
+
function loadSig(slug){ window.EPDATA=window.EPDATA||{}; const packP=loadPack(slug+'.pack');
|
| 94 |
+
const done=()=>{ SIG=window.EPDATA[slug]; if(!SIG) return; sizeCharts(); drawCharts(); init3D(); packP.then(pk=>{ if(!pk) return; Object.assign(SIG,pk); if(window._addClouds) window._addClouds(); }); updateUI(master.currentTime||0);
|
| 95 |
const go=()=>{ if(_toggle&&!playing) _toggle(); }; if(master.readyState>=3) go(); else master.addEventListener('canplay',go,{once:true}); };
|
| 96 |
if(window.EPDATA[slug]){ done(); return; }
|
| 97 |
const s=document.createElement('script'); s.fetchPriority='high'; s.src='epdata/'+slug+'.js'; s.onload=done; document.body.appendChild(s); }
|
| 98 |
|
| 99 |
/* heavy viewer payload (lidar snapshots + depth-hover grid): gzip'd binary, fetched after the page is interactive */
|
| 100 |
+
async function loadPack(name){ const sig={};
|
| 101 |
const st=()=>document.getElementById('cloudStat');
|
| 102 |
try{
|
| 103 |
+
const res=await fetch('epdata/'+name,{priority:'high'}); if(!res.ok) throw new Error('HTTP '+res.status);
|
| 104 |
const total=+res.headers.get('content-length')||0, rd=res.body.getReader(), parts=[]; let got=0;
|
| 105 |
for(;;){ const {done,value}=await rd.read(); if(done) break; parts.push(value); got+=value.length;
|
| 106 |
if(st()) st().textContent=`loading point cloud… ${(got/1e6).toFixed(1)}${total?' / '+(total/1e6).toFixed(1):''} MB`; }
|
|
|
|
| 111 |
const ab=buf.buffer;
|
| 112 |
sig.clouds={}; Object.entries(hdr.clouds).forEach(([k,fr])=>{ sig.clouds[k]=fr.map(f=>({t:f.t, q:new Int16Array(ab,base+f.xyz,f.n*3), I:new Uint8Array(ab,base+f.i,f.n)})); });
|
| 113 |
sig.depthGrid=hdr.depth.frames.map(o=>new Uint16Array(ab,base+o,hdr.depth.w*hdr.depth.h));
|
| 114 |
+
if(hdr.map) sig.map={q:new Int16Array(ab,base+hdr.map.xyz,hdr.map.n*3), I:new Uint8Array(ab,base+hdr.map.i,hdr.map.n)};
|
| 115 |
+
if(st()) st().textContent=''; return sig;
|
| 116 |
+
}catch(e){ if(st()) st().textContent='point cloud failed to load: '+e.message; return null; }
|
| 117 |
}
|
| 118 |
|
| 119 |
function render(){
|
|
|
|
| 137 |
<div class="panel">
|
| 138 |
<div class="vgrid">${CAMS.map(c=>tile(c)).join('')}</div>
|
| 139 |
<div class="chk" id="chk"></div>
|
| 140 |
+
<div class="three" id="three"><span class="lbl">world (odom) · robot links · map (all scans, dim) · current scan front <span style="color:#ff8a70">■</span> back <span style="color:#6ea8ff">■</span> · base path · ceiling (>2.3 m) and >10 m hidden</span><span class="hint">drag to orbit · scroll to zoom</span><span id="cloudStat" style="position:absolute;top:26px;left:9px;font:11px ui-monospace,monospace;color:#e0a33a;z-index:1">loading point cloud…</span></div>
|
| 141 |
</div>
|
| 142 |
<div class="panel">
|
| 143 |
<div class="spans-head">temporal spans (${e.n_segments}) · <b>${esc(e.task_name)}</b></div>
|
|
|
|
| 291 |
['l','r'].forEach(s=>{ bones.push(['arm_base_link',`arm_${s}_link1`]); for(let i=1;i<7;i++) bones.push([`arm_${s}_link${i}`,`arm_${s}_link${i+1}`]); bones.push([`arm_${s}_link7`,`arm_${s}_end_link`],[`arm_${s}_end_link`,`gripper_${s}_center_link`]); });
|
| 292 |
const clouds={}; const CC={lidar_front:[1,.54,.44],lidar_back:[.43,.66,1]};
|
| 293 |
let follow=false;
|
| 294 |
+
const buildChk=()=>{ document.getElementById('chk').innerHTML=Object.keys(clouds).map(k=>`<label><input type="checkbox" data-k="${k}" checked>${k==='__map'?'environment map (all scans)':k+' (current scan)'}</label>`).join('')+`<label><input type="checkbox" data-k="__path" checked>base path</label><label><input type="checkbox" data-k="__follow">camera follows robot</label>`;
|
| 295 |
document.querySelectorAll('#chk input').forEach(i=>i.onchange=()=>{ const k=i.dataset.k; if(k==='__path') path.visible=i.checked; else if(k==='__follow') follow=i.checked; else clouds[k].p.visible=i.checked; }); };
|
| 296 |
+
let mapPts=null;
|
| 297 |
+
window._addClouds=()=>{ if(!SIG.clouds) return;
|
| 298 |
+
if(SIG.map&&!mapPts){ const q=SIG.map.q, I=SIG.map.I, n=I.length, pos=new Float32Array(n*3), col=new Float32Array(n*3);
|
| 299 |
+
for(let m=0;m<n;m++){ pos[3*m]=q[3*m]/100; pos[3*m+1]=q[3*m+1]/100; const z=q[3*m+2]/100; pos[3*m+2]=z;
|
| 300 |
+
const h=Math.max(0,Math.min(1,z/2.3)), s=.30+.35*I[m]/255; col[3*m]=(.35+.25*h)*s*1.6; col[3*m+1]=(.45+.2*h)*s*1.6; col[3*m+2]=(.6+.15*h)*s*1.6; }
|
| 301 |
+
const g=new THREE.BufferGeometry(); g.setAttribute('position',new THREE.BufferAttribute(pos,3)); g.setAttribute('color',new THREE.BufferAttribute(col,3));
|
| 302 |
+
mapPts=new THREE.Points(g,new THREE.PointsMaterial({size:.03,vertexColors:true,transparent:true,opacity:.35})); scene.add(mapPts); clouds.__map={p:mapPts,cur:0,static:true}; } Object.keys(SIG.clouds).forEach(k=>{ if(clouds[k]) return; const p=new THREE.Points(new THREE.BufferGeometry(),new THREE.PointsMaterial({size:.05,vertexColors:true})); scene.add(p); clouds[k]={p,cur:-1}; });
|
| 303 |
buildChk(); if(setCloudT) setCloudT(master.currentTime||0); };
|
| 304 |
buildChk();
|
| 305 |
let last=null;
|
|
|
|
| 309 |
const lt=SIG.link_t; let li=0; while(li<lt.length-1&<[li+1]<=t) li++; const P=SIG.link_p[li];
|
| 310 |
const seg=[]; bones.forEach(([a,c])=>{ const ia=idx(a), ic=idx(c); if(ia>=0&&ic>=0) seg.push(...P[ia],...P[ic]); });
|
| 311 |
body.geometry.setAttribute('position',new THREE.Float32BufferAttribute(seg,3)); joints.geometry.setAttribute('position',new THREE.Float32BufferAttribute(P.flat(),3));
|
| 312 |
+
Object.entries(clouds).forEach(([k,C])=>{ if(C.static) return; const fr=SIG.clouds&&SIG.clouds[k]; if(!fr) return; let i=0; while(i<fr.length-1&&fr[i+1].t<=t) i++; if(i===C.cur) return; C.cur=i;
|
| 313 |
const f=fr[i], q=f.q, I=f.I, n=I.length, bj=Math.max(0,Math.min(SIG.n-1,Math.round(f.t*SIG.fps))), bb=SIG.base[bj], cs=Math.cos(bb[2]), sn=Math.sin(bb[2]);
|
| 314 |
const pos=new Float32Array(n*3), col=new Float32Array(n*3), base=CC[k]||[.8,.8,.8];
|
| 315 |
for(let m=0;m<n;m++){ const x=q[3*m]/100,y=q[3*m+1]/100,z=q[3*m+2]/100; pos[3*m]=bb[0]+cs*x-sn*y; pos[3*m+1]=bb[1]+sn*x+cs*y; pos[3*m+2]=z;
|
egoSample/media/restock_20260916_ep000/head_color.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:44136e675c3e213e8ebfbcadaf82da129e0078b80a31ac06a2084d1597852f8a
|
| 3 |
+
size 5169484
|
egoSample/media/restock_20260916_ep000/head_depth.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d9fabd8eaff1de40b6779b5a42931f0d5cc002352634053d1c057180b2fb26a3
|
| 3 |
+
size 5425020
|
egoSample/media/restock_20260916_ep000/head_left_fisheye.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bc042a345524b0536767c319efb81e081cdd46aea47b89d743c94ff583e51117
|
| 3 |
+
size 4991258
|
egoSample/media/restock_20260916_ep000/head_right_fisheye.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1500eafe778c86e93440291f26205d55fa3c49edab17e8ed768b9978a9bf1fc0
|
| 3 |
+
size 5126456
|
egoSample/media/restock_20260916_ep000/head_stereo_left.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d10b14c302b25ee87e3083e8aca46e04b10ba90a2bda8cc2c591af09832c1d46
|
| 3 |
+
size 5146427
|
egoSample/media/restock_20260916_ep000/head_stereo_right.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8ed5c46b10a7d3ac29b559257505da235609c6615a7550e668b8f60e70f7853b
|
| 3 |
+
size 5164276
|