Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>RoboRover Commander</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Roboto:wght@300;400;500;700&display=swap'); | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| } | |
| .title-font { | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .control-btn { | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
| } | |
| .control-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
| } | |
| .control-btn:active { | |
| transform: translateY(0); | |
| } | |
| .glow { | |
| box-shadow: 0 0 15px rgba(59, 130, 246, 0.5); | |
| } | |
| .pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { | |
| box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); | |
| } | |
| 70% { | |
| box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); | |
| } | |
| 100% { | |
| box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen text-white overflow-x-hidden"> | |
| <div id="vanta-bg" class="absolute top-0 left-0 w-full h-full z-0"></div> | |
| <div class="relative z-10 container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="text-center mb-12"> | |
| <h1 class="title-font text-4xl md:text-6xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500"> | |
| RoboRover Commander | |
| </h1> | |
| <p class="text-xl text-gray-300 max-w-2xl mx-auto"> | |
| Take control of your robotic companion with this intuitive directional interface. Navigate with precision and style! | |
| </p> | |
| </header> | |
| <!-- Status Panel --> | |
| <div class="bg-gray-800 bg-opacity-70 backdrop-blur-lg rounded-2xl p-6 mb-8 border border-gray-700 max-w-2xl mx-auto"> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="w-3 h-3 rounded-full bg-green-500 pulse"></div> | |
| <span class="text-green-400 font-medium">Connected</span> | |
| </div> | |
| <div class="text-right"> | |
| <p class="text-gray-300">Battery: <span class="text-green-400 font-bold">87%</span></p> | |
| <p class="text-gray-300">Signal: <span class="text-green-400 font-bold">Strong</span></p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Control Interface --> | |
| <div class="max-w-md mx-auto bg-gray-800 bg-opacity-70 backdrop-blur-lg rounded-3xl p-8 border border-gray-700 shadow-2xl"> | |
| <!-- Directional Pad --> | |
| <div class="grid grid-cols-3 gap-4 mb-8"> | |
| <!-- Empty space --> | |
| <div></div> | |
| <!-- Forward Button --> | |
| <button id="forward-btn" class="control-btn bg-blue-600 hover:bg-blue-700 text-white rounded-xl p-6 flex items-center justify-center glow"> | |
| <i data-feather="arrow-up" class="w-8 h-8"></i> | |
| </button> | |
| <!-- Empty space --> | |
| <div></div> | |
| <!-- Left Button --> | |
| <button id="left-btn" class="control-btn bg-blue-600 hover:bg-blue-700 text-white rounded-xl p-6 flex items-center justify-center"> | |
| <i data-feather="arrow-left" class="w-8 h-8"></i> | |
| </button> | |
| <!-- Stop Button --> | |
| <button id="stop-btn" class="control-btn bg-red-600 hover:bg-red-700 text-white rounded-xl p-6 flex items-center justify-center"> | |
| <i data-feather="square" class="w-8 h-8"></i> | |
| </button> | |
| <!-- Right Button --> | |
| <button id="right-btn" class="control-btn bg-blue-600 hover:bg-blue-700 text-white rounded-xl p-6 flex items-center justify-center"> | |
| <i data-feather="arrow-right" class="w-8 h-8"></i> | |
| </button> | |
| <!-- Empty space --> | |
| <div></div> | |
| <!-- Backward Button --> | |
| <button id="backward-btn" class="control-btn bg-blue-600 hover:bg-blue-700 text-white rounded-xl p-6 flex items-center justify-center"> | |
| <i data-feather="arrow-down" class="w-8 h-8"></i> | |
| </button> | |
| <!-- Empty space --> | |
| <div></div> | |
| </div> | |
| <!-- Speed Control --> | |
| <div class="mb-8"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-gray-300">Speed Control</span> | |
| <span id="speed-value" class="text-blue-400 font-bold">50%</span> | |
| </div> | |
| <input id="speed-slider" type="range" min="0" max="100" value="50" class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer slider"> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <button class="control-btn bg-purple-600 hover:bg-purple-700 text-white rounded-xl py-3 flex items-center justify-center"> | |
| <i data-feather="camera" class="w-5 h-5 mr-2"></i> | |
| <span>Camera</span> | |
| </button> | |
| <button class="control-btn bg-green-600 hover:bg-green-700 text-white rounded-xl py-3 flex items-center justify-center"> | |
| <i data-feather="settings" class="w-5 h-5 mr-2"></i> | |
| <span>Settings</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Navigation --> | |
| <div class="mt-8 text-center space-y-4"> | |
| <div class="text-gray-400"> | |
| <p>Tip: Use arrow keys for quick navigation</p> | |
| </div> | |
| <a href="path_planner.html" class="inline-flex items-center bg-purple-600 hover:bg-purple-700 text-white rounded-lg px-6 py-3 control-btn"> | |
| <i data-feather="map" class="w-4 h-4 mr-2"></i> | |
| Go to Path Planner | |
| </a> | |
| </div> | |
| </div> | |
| <script> | |
| // Initialize Vanta.js background | |
| VANTA.GLOBE({ | |
| el: "#vanta-bg", | |
| mouseControls: true, | |
| touchControls: true, | |
| gyroControls: false, | |
| minHeight: 200.00, | |
| minWidth: 200.00, | |
| scale: 1.00, | |
| scaleMobile: 1.00, | |
| color: 0x3b82f6, | |
| backgroundColor: 0x111827, | |
| size: 0.8 | |
| }); | |
| // Initialize Feather Icons | |
| feather.replace(); | |
| // Control button functionality | |
| document.getElementById('forward-btn').addEventListener('click', () => { | |
| sendCommand('forward'); | |
| highlightButton('forward-btn'); | |
| }); | |
| document.getElementById('backward-btn').addEventListener('click', () => { | |
| sendCommand('backward'); | |
| highlightButton('backward-btn'); | |
| }); | |
| document.getElementById('left-btn').addEventListener('click', () => { | |
| sendCommand('left'); | |
| highlightButton('left-btn'); | |
| }); | |
| document.getElementById('right-btn').addEventListener('click', () => { | |
| sendCommand('right'); | |
| highlightButton('right-btn'); | |
| }); | |
| document.getElementById('stop-btn').addEventListener('click', () => { | |
| sendCommand('stop'); | |
| highlightButton('stop-btn'); | |
| }); | |
| // Speed control | |
| const speedSlider = document.getElementById('speed-slider'); | |
| const speedValue = document.getElementById('speed-value'); | |
| speedSlider.addEventListener('input', () => { | |
| const value = speedSlider.value; | |
| speedValue.textContent = `${value}%`; | |
| sendCommand(`speed:${value}`); | |
| }); | |
| // Keyboard controls | |
| document.addEventListener('keydown', (event) => { | |
| switch(event.key) { | |
| case 'ArrowUp': | |
| sendCommand('forward'); | |
| highlightButton('forward-btn'); | |
| break; | |
| case 'ArrowDown': | |
| sendCommand('backward'); | |
| highlightButton('backward-btn'); | |
| break; | |
| case 'ArrowLeft': | |
| sendCommand('left'); | |
| highlightButton('left-btn'); | |
| break; | |
| case 'ArrowRight': | |
| sendCommand('right'); | |
| highlightButton('right-btn'); | |
| break; | |
| case ' ': | |
| sendCommand('stop'); | |
| highlightButton('stop-btn'); | |
| break; | |
| } | |
| }); | |
| // Function to send commands (placeholder for actual implementation) | |
| function sendCommand(command) { | |
| console.log(`Sending command: ${command}`); | |
| // In a real implementation, this would send the command to your Flask backend | |
| // Example: fetch(`/control/${command}`, { method: 'POST' }); | |
| } | |
| // Function to highlight button when pressed | |
| function highlightButton(buttonId) { | |
| const button = document.getElementById(buttonId); | |
| button.classList.add('bg-blue-800'); | |
| setTimeout(() => { | |
| button.classList.remove('bg-blue-800'); | |
| }, 200); | |
| } | |
| </script> | |
| </body> | |
| </html> | |