<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Robot Control</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
#joysticks {
display: flex;
gap: 20px;
}
.joystick {
width: 150px;
height: 150px;
position: relative;
}
.nipple {
width: 100%;
height: 100%;
}
</style>
<script src="static/nipplejs.min.js"></script>
<script src="static/control.js"></script>
</head>
<body>
<h1>Robot Control</h1>
<p id="controlStatus" role="status" aria-live="polite">Connecting…</p>
<div id="joysticks">
<div id="leftJoystick" class="joystick"></div>
<div id="rightJoystick" class="joystick"></div>
</div>
<script>
const leftJoystick = document.getElementById('leftJoystick');
const rightJoystick = document.getElementById('rightJoystick');
const { sendDriveCommand } = connectRobot(
WebSocket, location,
(message) => { document.getElementById('controlStatus').textContent = message; },
() => { leftJoystick.value = 0; rightJoystick.value = 0; }
);
const leftNipple = nipplejs.create({
zone: leftJoystick,
mode: 'static',
position: { left: '50%', top: '50%' },
color: 'blue'
});
const rightNipple = nipplejs.create({
zone: rightJoystick,
mode: 'static',
position: { left: '50%', top: '50%' },
color: 'red'
});
leftNipple.on('move', (evt, data) => {
const value = Math.max(-1, Math.min(1, data.vector.y));
sendDriveCommand(value, rightJoystick.value || 0);
leftJoystick.value = value;
});
rightNipple.on('move', (evt, data) => {
const value = Math.max(-1, Math.min(1, data.vector.y));
sendDriveCommand(leftJoystick.value || 0, value);
rightJoystick.value = value;
});
leftNipple.on('end', () => {
leftJoystick.value = 0;
sendDriveCommand(0, rightJoystick.value || 0);
});
rightNipple.on('end', () => {
rightJoystick.value = 0;
sendDriveCommand(leftJoystick.value || 0, 0);
});
</script>
</body>
</html>