robot-folding / app /src /content /embeds /folding /action-representations.html
pepijn223's picture
pepijn223 HF Staff
Improve DAgger explainer, add conclusion and expand references
f0f3d44 unverified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: transparent; font-family: system-ui, sans-serif; color: #e8eaf0; }
svg text { font-family: system-ui, sans-serif; }
</style>
</head>
<body>
<svg id="action-rep" style="overflow:visible"></svg>
<script>
function _initActionRep() {
const svgEl = document.getElementById('action-rep');
const W = Math.min(svgEl.parentElement.clientWidth || 700, 720);
const H = 310;
svgEl.setAttribute('width', W);
svgEl.setAttribute('height', H);
const svg = d3.select('#action-rep').attr('width', W).attr('height', H);
svg.selectAll('*').remove();
const m = { top: 30, right: 24, bottom: 64, left: 48 };
const w = W - m.left - m.right;
const h = H - m.top - m.bottom;
const g = svg.append('g').attr('transform', `translate(${m.left},${m.top})`);
const SUB = '#8b8fa8';
const COL_REL = '#3b82f6';
const COL_DELTA = '#f59e0b';
const COL_ABS = '#ef4444';
// Arrowhead markers
[['rel', COL_REL], ['delta', COL_DELTA]].forEach(([id, col]) => {
svg.append('defs').append('marker')
.attr('id', `ah-${id}`).attr('viewBox', '0 0 8 6').attr('refX', 7).attr('refY', 3)
.attr('markerWidth', 8).attr('markerHeight', 6).attr('orient', 'auto')
.append('path').attr('d', 'M0,0.5 L7,3 L0,5.5 Z').attr('fill', col);
});
const poses = [
{t:0, p:0.8}, {t:1, p:1.5}, {t:2, p:2.1}, {t:3, p:2.9}, {t:4, p:3.3},
{t:5, p:4.0}, {t:6, p:4.5}, {t:7, p:5.1}, {t:8, p:5.6}
];
const x = d3.scaleLinear().domain([-0.3, 8.5]).range([0, w]);
const y = d3.scaleLinear().domain([0, 6.5]).range([h, 0]);
// Faint ground-truth path
const line = d3.line().x(d => x(d.t)).y(d => y(d.p)).curve(d3.curveMonotoneX);
g.append('path').datum(poses).attr('d', line)
.attr('fill', 'none').attr('stroke', '#3a3d4a').attr('stroke-width', 1.5).attr('stroke-dasharray', '4,4');
// Inference boundary
[0, 4].forEach(t => {
g.append('line').attr('x1', x(t)).attr('x2', x(t)).attr('y1', -14).attr('y2', h + 4)
.attr('stroke', '#444').attr('stroke-dasharray', '5,4').attr('stroke-width', 0.8);
});
g.append('text').attr('x', x(2)).attr('y', -4).attr('text-anchor', 'middle')
.attr('fill', SUB).attr('font-size', 11).text('Inference start at t=0');
g.append('text').attr('x', x(6)).attr('y', -4).attr('text-anchor', 'middle')
.attr('fill', SUB).attr('font-size', 11).text('Inference start at t=4');
// Axes
g.append('line').attr('x1', x(0)).attr('x2', x(8.3)).attr('y1', h).attr('y2', h).attr('stroke', '#444');
g.append('line').attr('x1', x(0)).attr('x2', x(0)).attr('y1', h).attr('y2', y(6.2)).attr('stroke', '#444');
for (let t = 0; t <= 8; t++) {
g.append('text').attr('x', x(t)).attr('y', h + 14).attr('text-anchor', 'middle')
.attr('fill', SUB).attr('font-size', 12).text(t);
}
g.append('text').attr('x', x(8.4)).attr('y', h + 4).attr('fill', SUB).attr('font-size', 12).text('Time');
g.append('text').attr('x', x(-0.1)).attr('y', y(6.4)).attr('text-anchor', 'end')
.attr('fill', SUB).attr('font-size', 12).text('Pose');
// --- DELTA (yellow): straight arrows, offset below trajectory ---
const dOff = 14;
for (let i = 0; i < poses.length - 1; i++) {
g.append('line')
.attr('x1', x(poses[i].t) + 3).attr('y1', y(poses[i].p) + dOff)
.attr('x2', x(poses[i+1].t) - 3).attr('y2', y(poses[i+1].p) + dOff)
.attr('stroke', COL_DELTA).attr('stroke-width', 2).attr('opacity', 0.8)
.attr('marker-end', 'url(#ah-delta)');
}
// --- RELATIVE (blue): curved arrows above trajectory ---
function curvedArrow(x1, y1, x2, y2) {
const cpY = Math.min(y1, y2) - 20 - Math.abs(x2 - x1) * 0.08;
const cpX = (x1 + x2) / 2;
g.append('path')
.attr('d', `M${x1},${y1 - 4} Q${cpX},${cpY} ${x2},${y2 - 4}`)
.attr('fill', 'none').attr('stroke', COL_REL).attr('stroke-width', 2).attr('opacity', 0.85)
.attr('marker-end', 'url(#ah-rel)');
}
// Chunk 1: t=0 → t=1,2,3,4
for (let i = 1; i <= 4; i++) curvedArrow(x(0), y(poses[0].p), x(i), y(poses[i].p));
// Chunk 2: t=4 → t=5,6,7,8
for (let i = 5; i <= 8; i++) curvedArrow(x(4), y(poses[4].p), x(i), y(poses[i].p));
// --- ABSOLUTE (red): dots on trajectory ---
poses.forEach(d => {
g.append('circle').attr('cx', x(d.t)).attr('cy', y(d.p)).attr('r', 5)
.attr('fill', COL_ABS).attr('stroke', '#fff').attr('stroke-width', 1.5);
});
// Chunk brackets
const bY = h + 22;
[{t0:0, t1:4}, {t0:4, t1:8}].forEach(({t0, t1}) => {
g.append('path')
.attr('d', `M${x(t0)},${bY-3} L${x(t0)},${bY} L${x(t1)},${bY} L${x(t1)},${bY-3}`)
.attr('fill', 'none').attr('stroke', COL_REL).attr('stroke-width', 1.2).attr('opacity', 0.5);
g.append('text').attr('x', (x(t0) + x(t1)) / 2).attr('y', bY + 12)
.attr('text-anchor', 'middle').attr('fill', COL_REL).attr('font-size', 11).attr('opacity', 0.7)
.text('chunk = 4');
});
// Legend (bottom)
const legY = h + 44;
const legItems = [
{ col: COL_REL, label: 'Relative trajectory (used here)', type: 'curve' },
{ col: COL_DELTA, label: 'Delta (accumulates error)', type: 'line' },
{ col: COL_ABS, label: 'Absolute', type: 'dot' },
];
let lx = 0;
legItems.forEach(item => {
const sw = 14;
if (item.type === 'curve') {
g.append('line').attr('x1', lx).attr('x2', lx + sw).attr('y1', legY + 2).attr('y2', legY + 2)
.attr('stroke', item.col).attr('stroke-width', 2.5);
} else if (item.type === 'line') {
g.append('line').attr('x1', lx).attr('x2', lx + sw).attr('y1', legY + 2).attr('y2', legY + 2)
.attr('stroke', item.col).attr('stroke-width', 2.5);
} else {
g.append('circle').attr('cx', lx + sw / 2).attr('cy', legY + 2).attr('r', 4.5)
.attr('fill', item.col).attr('stroke', '#fff').attr('stroke-width', 1.2);
}
lx += sw + 6;
const t = g.append('text').attr('x', lx).attr('y', legY + 6)
.attr('fill', item.col).attr('font-size', 12).attr('font-weight', 500).text(item.label);
lx += t.node().getComputedTextLength() + 16;
});
}
if (typeof d3 !== "undefined") { _initActionRep(); }
else { var s=document.createElement("script"); s.src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"; s.onload=_initActionRep; document.head.appendChild(s); }
window.addEventListener('resize', _initActionRep);
</script>
</body>
</html>