Files
carinha-control-panel/braco.html
T

159 lines
12 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="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Braço Robótico · Carinha</title>
<meta name="description" content="Controle os ângulos, crie coreografias articuladas e coordene 8 canais de movimento do braço robótico.">
<link rel="stylesheet" href="/dashboard.css">
<link rel="stylesheet" href="/braco.css">
<script src="/dashboard.js" defer></script>
</head>
<body>
<!-- Cabeçalho -->
<div style="display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:16px;margin-bottom:12px">
<div>
<h1>Braço Robótico</h1>
<p style="margin:4px 0 0">Posturas e movimentos coordenados para os 8 canais de servo.</p>
</div>
<div style="display:flex;gap:10px;align-items:center">
<span id="connection" class="connection">Verificando conexão…</span>
</div>
</div>
<!-- Aviso de Segurança -->
<div class="card" style="margin-bottom:18px;border-color:rgba(245,158,11,0.35);background:rgba(45,30,6,0.5)">
<div style="display:flex;align-items:center;gap:12px">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--amarelo)" stroke-width="2" style="flex-shrink:0"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
<div>
<p style="margin:0;color:var(--texto-medio);font-weight:600;font-size:14px">Atenção ao usar o braço</p>
<p style="margin:2px 0 0;font-size:13px">Ângulos são comandos nominais, sem medição do eixo. Canais 5 e 6 movem juntos e invertidos. Comece com o braço apoiado e limites calibrados. Ao parar ou perder a conexão, o sinal desliga e o braço pode perder sustentação.</p>
</div>
</div>
<div style="margin-top:12px">
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;margin:0">
<input id="enable" type="checkbox" disabled>
<span style="font-size:14px;font-weight:600">Ativar movimento das articulações — canais 0 a 7</span>
</label>
</div>
</div>
<!-- Workspace Principal: SVG + Sliders + Controles -->
<div class="workspace">
<!-- Painel Esquerdo: Posturas Salvas -->
<aside class="side">
<div class="card" style="padding:18px">
<h2 style="font-size:16px;margin-bottom:14px">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--ciano)" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><line x1="9" y1="15" x2="15" y2="15"/></svg>
Posturas Salvas
</h2>
<span id="count" class="counter" style="display:block;margin-bottom:12px">0 posturas</span>
<div style="display:flex;flex-direction:column;gap:8px">
<button id="savePose" style="width:100%">💾 Salvar postura atual</button>
<select id="poses" aria-label="Postura salva" style="margin:0">
<option>Sem posturas</option>
</select>
<button id="loadPose" disabled style="width:100%">📥 Carregar postura</button>
<button id="deletePose" disabled style="width:100%;background:rgba(60,10,18,0.5);border-color:rgba(244,63,94,0.3)">🗑️ Excluir postura</button>
<hr style="border:none;border-top:1px solid var(--borda);margin:4px 0">
<button id="play" disabled style="width:100%" class="primary">▶️ Reproduzir sequência</button>
<button id="stop" class="danger" style="width:100%">⛔ Parar sinais</button>
</div>
</div>
</aside>
<!-- Diagrama SVG do Braço -->
<svg class="arm" viewBox="0 0 240 530" role="img" aria-label="Ilustração detalhada do braço robótico">
<defs>
<linearGradient id="shell"><stop stop-color="#17191b"/><stop offset=".25" stop-color="#54585b"/><stop offset=".48" stop-color="#303437"/><stop offset=".8" stop-color="#151719"/><stop offset="1" stop-color="#3b3f41"/></linearGradient>
<linearGradient id="edge" x2="0" y2="1"><stop stop-color="#707579"/><stop offset=".18" stop-color="#34383b"/><stop offset=".8" stop-color="#191c1e"/><stop offset="1" stop-color="#464c50"/></linearGradient>
<radialGradient id="hub"><stop stop-color="#646b70"/><stop offset=".4" stop-color="#30363a"/><stop offset=".85" stop-color="#171a1c"/><stop offset="1" stop-color="#5c6267"/></radialGradient>
<g id="bolt"><circle r="3.2" fill="#777e83" stroke="#111" stroke-width="1"/><path d="m-1.5-1.5 3 3m0-3-3 3" stroke="#222" stroke-width=".7"/></g>
</defs>
<g stroke="#151719" stroke-width="2.5">
<path d="M25 512 46 490 73 467h100l18 23 29 22Z" fill="url(#shell)"/><path d="M74 478v-33q0-15 19-22h50q26 6 27 22v33q-47 16-96 0Z" fill="url(#edge)"/>
<rect x="87" y="343" width="70" height="103" rx="23" fill="url(#shell)"/><rect x="96" y="356" width="51" height="76" rx="13" fill="#202426"/>
<rect x="79" y="306" width="87" height="67" rx="24" fill="url(#edge)"/><circle cx="122" cy="339" r="24" fill="url(#hub)"/><circle cx="122" cy="339" r="10" fill="#30383d"/><circle cx="122" cy="339" r="3" fill="#949ba0"/>
<rect x="87" y="213" width="69" height="106" rx="20" fill="url(#shell)"/><path d="M97 224v74M146 224v74" stroke="#686e72" stroke-width="1.2"/>
<rect x="80" y="179" width="85" height="64" rx="20" fill="url(#edge)"/><circle cx="122" cy="211" r="24" fill="url(#hub)"/><circle cx="122" cy="211" r="8" fill="#5b6368"/>
<rect x="94" y="130" width="57" height="67" rx="17" fill="url(#shell)"/><rect x="77" y="96" width="91" height="59" rx="21" fill="url(#edge)"/><circle cx="122" cy="125" r="23" fill="url(#hub)"/><circle cx="122" cy="125" r="7" fill="#656c71"/>
<path d="M50 48h63q12 0 14-13h28q18 0 19 21v37q-3 13-18 14H65q-15 0-15-13Z" fill="url(#shell)"/><path d="M71 99h83q11-1 12-12V55" fill="none" stroke="#73797e" stroke-width="3"/><rect x="43" y="44" width="16" height="64" rx="4" fill="url(#edge)"/>
<path d="M45 57 13 61 2 72l43-6Z M45 92 13 88 2 77l43 6Z" fill="url(#edge)"/><path d="M50 46h7v59" stroke="#92989d" stroke-width="1"/>
</g>
<g><use href="#bolt" x="88" y="192"/><use href="#bolt" x="158" y="192"/><use href="#bolt" x="88" y="234"/><use href="#bolt" x="158" y="234"/><use href="#bolt" x="90" y="316"/><use href="#bolt" x="155" y="316"/><use href="#bolt" x="90" y="362"/><use href="#bolt" x="155" y="362"/><use href="#bolt" x="88" y="110"/><use href="#bolt" x="157" y="110"/><use href="#bolt" x="100" y="449"/><use href="#bolt" x="144" y="449"/></g>
<g fill="none" stroke="#2f3335" stroke-width="2" opacity=".8"><path d="M174 63q25 0 33 16t24 18M164 123q30 0 44 24t25 9M165 188q30 0 43 27t25 10M164 239q24 0 42 28t28 10M160 309q25 0 49 20t24 3M168 364q24 0 40 10t25 8M171 456q20-52 38-41t24 21"/></g>
</svg>
<!-- Coluna de Sliders + Console -->
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:16px">
<div class="card" style="padding:20px">
<h2 style="font-size:16px;margin-bottom:14px">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--ciano)" stroke-width="2"><line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/></svg>
Controle de Canais
</h2>
<div id="sliders" class="sliders"></div>
<div style="display:flex;gap:16px;align-items:center;margin-top:18px;padding-top:14px;border-top:1px solid var(--borda)">
<div style="flex:1">
<label for="speed">Velocidade nominal (graus/s)</label>
<input id="speed" type="range" min="5" max="90" value="25">
</div>
<output id="speedValue" style="font-size:22px;font-weight:700;color:var(--ciano);font-family:'JetBrains Mono',monospace;min-width:36px">25</output>
</div>
<div id="console" role="status" aria-live="polite" style="margin-top:14px;padding:10px 14px;background:rgba(5,9,16,0.6);border:1px solid var(--borda);border-radius:var(--raio-sm);font-family:'JetBrains Mono',monospace;font-size:12.5px;color:var(--ciano)">Carregando configurações…</div>
</div>
</div>
<!-- Painel Direito: Ferramentas -->
<aside class="side right">
<div class="card" style="padding:18px">
<h2 style="font-size:16px;margin-bottom:14px">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--ciano)" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9z"/></svg>
Ferramentas
</h2>
<div style="display:flex;flex-direction:column;gap:8px">
<button id="export" style="width:100%">📤 Exportar JSON</button>
<button id="import" style="width:100%">📥 Importar JSON</button>
<button id="reset" style="width:100%">🎯 Centralizar na tela</button>
<input id="importFile" type="file" accept=".json,application/json">
</div>
</div>
</aside>
</div>
<!-- Calibração de Limites -->
<details style="margin-top:24px">
<summary>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--ciano)" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
Calibrar Limites por Canal
</summary>
<div class="card" style="margin-top:14px">
<p style="margin:0 0 14px">O projeto original usa 500–2500 µs para 0–180°. Isso não confirma o fim de curso do seu servo. Amplie gradualmente os limites com o eixo livre. Os limites desta aba são independentes dos testes individuais.</p>
<div id="calibration" class="calibration"></div>
<button id="saveCalibration" style="margin-top:16px">💾 Salvar calibração</button>
</div>
</details>
<!-- Movimentos Coordenados -->
<section style="margin-top:24px" class="card">
<h2 style="font-size:18px;margin-bottom:8px">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--ciano)" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Movimentos Coordenados
</h2>
<p style="margin:0 0 14px">Prévia é uma simulação dos comandos, sem sensores de posição. Executar envia a sequência aos oito canais dentro dos limites salvos.</p>
<div id="movimentos" style="display:flex;gap:12px;flex-wrap:wrap"></div>
<div style="margin-top:16px;padding-top:14px;border-top:1px solid var(--borda);display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px">
<p id="animationStatus" style="margin:0;font-size:13px;color:var(--fraco)">Representação esquemática · posição nominal</p>
<button id="stopPreview" style="font-size:13px">⛔ Parar prévia e sinais</button>
</div>
</section>
<script src="/braco-calibracao.js" defer></script>
<script src="/braco.js"></script>
<script src="/movimentos-core.js"></script>
<script src="/braco-movimentos.js"></script>
</body>
</html>