Files
RC_WheelLeg/05_software/real/sim2real/web/static/index.html
T

191 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>sim2real 控制台</title>
<link rel="stylesheet" href="/static/style.css">
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/examples/jsm/controls/OrbitControls.js": "https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js",
"three/examples/jsm/loaders/STLLoader.js": "https://unpkg.com/three@0.160.0/examples/jsm/loaders/STLLoader.js"
}
}
</script>
</head>
<body>
<div id="canvas-container">
<canvas id="viewer-canvas"></canvas>
<div id="viewer-status" class="viewer-overlay">加载中...</div>
</div>
<header class="glass-panel top-bar">
<div class="top-bar-left">
<h1>sim2real</h1>
<span class="stage" id="stage">DISCONNECTED</span>
<span id="busy" class="busy-indicator"></span>
<span id="logdir" class="logdir-indicator"></span>
</div>
<div class="top-bar-center">
<label class="toggle-switch">
<input type="checkbox" id="dry-run">
<span class="slider"></span>
<span class="label">Dry-run</span>
</label>
<button class="btn btn-primary" id="btn-connect">连接硬件</button>
<button class="btn btn-secondary" id="btn-disconnect">断开连接</button>
<div class="divider"></div>
<button class="btn btn-success" id="btn-enable">使能电机</button>
<button class="btn btn-warning" id="btn-disable">失能电机</button>
</div>
<div class="top-bar-right">
<button id="btn-reset-camera" class="btn btn-secondary btn-icon" title="重置视角"></button>
<button id="btn-estop" class="btn btn-danger">急停</button>
<button id="btn-reset-estop" class="btn btn-secondary">解除急停</button>
</div>
</header>
<div class="glass-panel side-panel left-panel">
<div class="panel-section">
<h2 class="panel-title">控制流程</h2>
<div class="btn-group-vertical">
<button class="btn btn-action" id="btn-startup">一键起立</button>
<div class="runtime-group">
<input type="text" id="policy-path" class="glass-input" placeholder="策略路径,留空则使用默认 rough">
<div class="btn-row">
<button class="btn btn-success flex-1" id="btn-runtime-start">启动策略</button>
<button class="btn btn-danger flex-1" id="btn-runtime-stop">停止策略</button>
</div>
</div>
</div>
</div>
<div class="panel-section state-section">
<h2 class="panel-title">实时状态</h2>
<div id="state-summary" class="state-grid"></div>
</div>
<div class="panel-section flex-1">
<div class="panel-title-row">
<h2 class="panel-title">Motors / Jog Test</h2>
<span class="hint" style="font-size:10px; color:var(--text-tertiary)">POS | VEL | TAU</span>
</div>
<div class="control-row mt-2 mb-2">
<span class="label">Kp</span><input type="number" id="jt-kp" class="glass-input mini" value="5">
<span class="label">Kd</span><input type="number" id="jt-kd" class="glass-input mini" value="1">
<span class="label">Time</span><input type="number" id="jt-dur" class="glass-input mini" value="1.0">
<span class="label">Δ(rad)</span><input type="number" id="jt-delta" class="glass-input mini" value="0.1" step="0.05">
<span id="jt-delta-v" class="slider-val">0.10</span>
</div>
<div id="motors-grid" class="motors-grid-list"></div>
</div>
</div>
<div class="glass-panel side-panel right-panel">
<div class="panel-section">
<div class="panel-title-row">
<h2 class="panel-title">Diagnostics</h2>
<button class="btn btn-secondary" id="btn-refresh-debug">刷新</button>
</div>
<div class="diag-row"><span class="diag-label">Obs Normalization</span><span class="diag-value success" id="diag-norm">Aligned</span></div>
<div class="diag-row"><span class="diag-label">Control Latency</span><span class="diag-value" id="diag-latency">-- ms</span></div>
<div class="diag-row"><span class="diag-label">Tracking Error</span><span class="diag-value" id="diag-track-err">-- rad</span></div>
<div class="diag-row"><span class="diag-label">Runtime</span><span class="diag-value" id="diag-runtime">--</span></div>
<div class="diag-row"><span class="diag-label">Runtime Age</span><span class="diag-value" id="diag-runtime-age">--</span></div>
<div class="diag-row"><span class="diag-label">Poll Age</span><span class="diag-value" id="diag-poll-age">--</span></div>
<div class="diag-row"><span class="diag-label">Cmd Age</span><span class="diag-value" id="diag-cmd-age">--</span></div>
<div class="diag-row"><span class="diag-label">Poll Errors</span><span class="diag-value" id="diag-poll-errors">0</span></div>
<div class="diag-row"><span class="diag-label">API Errors</span><span class="diag-value" id="diag-api-errors">0</span></div>
<div class="diag-row"><span class="diag-label">Zero-Cmd Suppression</span><span class="diag-value" id="diag-suppression">--</span></div>
<div class="diag-row"><span class="diag-label">Policy</span><span class="diag-value" id="diag-policy">--</span></div>
</div>
<div id="fault-box" class="panel-section hidden">
<h2 class="panel-title">Fault</h2>
<div id="fault-text" class="diag-value danger"></div>
<pre id="traceback-text" style="white-space:pre-wrap; font-size:11px; max-height:160px; overflow:auto;"></pre>
</div>
<div class="panel-section">
<h2 class="panel-title">Command</h2>
<div class="slider-group">
<div class="slider-row">
<span class="slider-label">vx</span>
<input type="range" id="cmd-vx" class="glass-slider" min="-1" max="1" step="0.05" value="0">
<span class="slider-val" id="cmd-vx-v">0.00</span>
</div>
<div class="slider-row">
<span class="slider-label">vy</span>
<input type="range" id="cmd-vy" class="glass-slider" min="-0.5" max="0.5" step="0.05" value="0">
<span class="slider-val" id="cmd-vy-v">0.00</span>
</div>
<div class="slider-row">
<span class="slider-label">yaw</span>
<input type="range" id="cmd-yaw" class="glass-slider" min="-1" max="1" step="0.05" value="0">
<span class="slider-val" id="cmd-yaw-v">0.00</span>
</div>
<button class="btn btn-secondary full-width mt-2" id="btn-cmd-zero">速度归零</button>
</div>
</div>
<div class="panel-section log-section flex-1">
<h2 class="panel-title">事件流</h2>
<div id="events-log" class="log"></div>
</div>
<div class="panel-section">
<h2 class="panel-title">Debug JSON</h2>
<pre id="debug-json" style="white-space:pre-wrap; font-size:11px; max-height:160px; overflow:auto;"></pre>
</div>
<div class="panel-section plots-section">
<h2 class="panel-title">实时曲线</h2>
<div class="plots-container" style="max-height: 200px;">
<canvas id="plot-pos"></canvas>
<canvas id="plot-vel"></canvas>
<canvas id="plot-imu"></canvas>
<canvas id="plot-diag"></canvas>
</div>
</div>
</div>
<div id="logs-modal" class="glass-modal hidden">
<div class="glass-panel modal-content">
<div class="modal-header">
<h2 class="panel-title">日志下载</h2>
<button class="btn-close" id="btn-close-logs">×</button>
</div>
<div class="modal-body">
<table id="logs-table">
<thead><tr><th>会话 ID</th><th>state.csv</th><th>events.jsonl</th><th>大小</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<button id="btn-show-logs" class="btn btn-secondary floating-btn" title="查看日志文件">🗂</button>
<span id="viewer-joint-count" class="viewer-count-indicator"></span>
<script type="module">
import { RobotViewer3D } from '/static/viewer/RobotViewer3D.js';
window.RobotViewer3D = RobotViewer3D;
const canvas = document.getElementById('viewer-canvas');
window.viewer3d = new RobotViewer3D(canvas, { meshBaseUrl: '/meshes/' });
try {
await window.viewer3d.load();
document.getElementById('viewer-status').textContent = '';
document.getElementById('viewer-joint-count').textContent = window.viewer3d.jointMap.size + ' joints';
} catch (error) {
document.getElementById('viewer-status').textContent = '3D 加载失败: ' + error.message;
console.error(error);
}
document.getElementById('btn-reset-camera').onclick = () => window.viewer3d.resetCamera();
window.addEventListener('resize', () => window.viewer3d.resize());
</script>
<script src="/static/app.js"></script>
</body>
</html>