feat: implement WebRTC signaling and UDP-based video streaming and control service

This commit is contained in:
2026-07-16 14:55:14 +04:00
parent 53288ea670
commit 41eaf49bb2
11 changed files with 614 additions and 108 deletions
+41 -14
View File
@@ -27,11 +27,13 @@ package main
import (
"bufio"
"context"
"encoding/hex"
"encoding/json"
"errors"
"flag"
"fmt"
"log/slog"
"math"
"net"
"net/http"
"os"
@@ -685,6 +687,9 @@ func handleInput(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service,
if v, ok := payload["gear"].(float64); ok {
in.Gear = int(v)
}
if v, ok := payload["buttons"].(float64); ok {
in.Buttons = uint32(v)
}
car := e.GetCarByDriver(c.ID)
if car == nil {
return
@@ -693,21 +698,43 @@ func handleInput(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service,
// Forward command transitions to ESP32 physical car if car has a device_id assigned
if car.DeviceID != nil {
var cmd string
if in.Throttle > 0.1 {
cmd = "start"
} else {
cmd = "stop"
}
if in.Steering < -0.2 {
cmd = "left"
} else if in.Steering > 0.2 {
cmd = "right"
}
var packet [5]byte
if cmd != "" && cmd != c.LastUDPCommand {
c.LastUDPCommand = cmd
_ = videoSvc.SendCommand(uint8(*car.DeviceID), cmd)
// 1. Steer: mapping float64 [-1.0, 1.0] to [0..200] (100 is center)
steerVal := int(math.Round((in.Steering + 1.0) * 100.0))
if steerVal < 0 { steerVal = 0 }
if steerVal > 200 { steerVal = 200 }
packet[0] = uint8(steerVal)
// 2. Throttle: mapping float64 [0.0, 1.0] to [0..100]
throttleVal := int(math.Round(in.Throttle * 100.0))
if throttleVal < 0 { throttleVal = 0 }
if throttleVal > 100 { throttleVal = 100 }
packet[1] = uint8(throttleVal)
// 3. Brake: mapping float64 [0.0, 1.0] to [0..100]
brakeVal := int(math.Round(in.Brake * 100.0))
if brakeVal < 0 { brakeVal = 0 }
if brakeVal > 100 { brakeVal = 100 }
packet[2] = uint8(brakeVal)
// 4. Gear: map -1 to 0 (R), 0 to 1 (N), >=1 to 2 (D)
gearVal := 1 // Neutral by default
if in.Gear < 0 {
gearVal = 0 // R
} else if in.Gear > 0 {
gearVal = 2 // D
}
packet[3] = uint8(gearVal)
// 5. Flags: bit 0 (DRS), bit 1 (Pit Limiter)
packet[4] = uint8(in.Buttons & 0x03)
// Deduplicate UDP transmissions
hexCmd := hex.EncodeToString(packet[:])
if hexCmd != c.LastUDPCommand {
c.LastUDPCommand = hexCmd
_ = videoSvc.SendControlPacket(uint8(*car.DeviceID), packet)
}
}