mirror of
https://github.com/IS1DI/x0gp.git
synced 2026-07-16 20:47:55 +00:00
feat: implement WebRTC signaling and UDP-based video streaming and control service
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user