feat: initial commit - Carinha Control Panel v1.0 com UI glassmorphism, watch-bar, emojis, braco robotico e conversa IA
This commit is contained in:
+158
@@ -0,0 +1,158 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user