feat(BNNBot): 44-bit encoding with sin/cos bearing+heading, distance%, velocity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,42 +1,61 @@
|
||||
## binary_encoding — scan data → binary vector (10-bit per value).
|
||||
|
||||
import std/math
|
||||
|
||||
const
|
||||
BITS_PER_VALUE* = 10
|
||||
NUM_VALUES* = 5
|
||||
TOTAL_BITS* = BITS_PER_VALUE * NUM_VALUES # 50
|
||||
TOTAL_BITS* = 44
|
||||
|
||||
type
|
||||
BinaryVector* = array[TOTAL_BITS, uint8]
|
||||
|
||||
ScanData* = object
|
||||
bearing*: float # 0-360
|
||||
distance*: float # 0-2000
|
||||
velocity*: float # -8 to +8
|
||||
heading*: float # 0-360
|
||||
speed*: float # 0-8
|
||||
bearing*: float # 0-360 degrees
|
||||
distance*: float # 0-1414 pixels (will be converted to 0-100%)
|
||||
velocity*: float # -8 to +8 integer steps
|
||||
heading*: float # 0-360 degrees
|
||||
|
||||
proc toBits(value: float, minVal, maxVal: float): array[BITS_PER_VALUE, uint8] =
|
||||
let clamped = clamp(value, minVal, maxVal)
|
||||
let norm = (clamped - minVal) / (maxVal - minVal)
|
||||
let intVal = int(norm * 1023.0) # 0-1023 fits in 10 bits
|
||||
for i in 0..<BITS_PER_VALUE:
|
||||
result[BITS_PER_VALUE - 1 - i] = uint8((intVal shr i) and 1) # MSB first
|
||||
const MAX_DISTANCE = 1414.0 # diagonal of 1000x1000 arena
|
||||
|
||||
proc toBits(value: int, bits: int): seq[uint8] =
|
||||
result = newSeq[uint8](bits)
|
||||
for i in 0..<bits:
|
||||
result[bits - 1 - i] = uint8((value shr i) and 1)
|
||||
|
||||
proc encode*(scan: ScanData): BinaryVector =
|
||||
let parts = [
|
||||
toBits(scan.bearing, 0.0, 360.0),
|
||||
toBits(scan.distance, 0.0, 2000.0),
|
||||
toBits(scan.velocity, -8.0, 8.0),
|
||||
toBits(scan.heading, 0.0, 360.0),
|
||||
toBits(scan.speed, 0.0, 8.0)
|
||||
]
|
||||
var offset = 0
|
||||
for p in parts:
|
||||
for i in 0..<BITS_PER_VALUE:
|
||||
result[offset + i] = p[i]
|
||||
offset += BITS_PER_VALUE
|
||||
|
||||
# 1. bearing_sin: sin(bearing), -1..+1 → 0..199 → 8 bits
|
||||
let bSin = int((sin(degToRad(scan.bearing)) + 1.0) / 2.0 * 199.0)
|
||||
let bSinBits = toBits(clamp(bSin, 0, 199), 8)
|
||||
for i in 0..<8: result[offset + i] = bSinBits[i]
|
||||
offset += 8
|
||||
|
||||
# 2. bearing_cos: cos(bearing), -1..+1 → 0..199 → 8 bits
|
||||
let bCos = int((cos(degToRad(scan.bearing)) + 1.0) / 2.0 * 199.0)
|
||||
let bCosBits = toBits(clamp(bCos, 0, 199), 8)
|
||||
for i in 0..<8: result[offset + i] = bCosBits[i]
|
||||
offset += 8
|
||||
|
||||
# 3. distance %: 0-100% of max → 0..99 → 7 bits
|
||||
let distPct = int(clamp(scan.distance / MAX_DISTANCE * 99.0, 0.0, 99.0))
|
||||
let distBits = toBits(distPct, 7)
|
||||
for i in 0..<7: result[offset + i] = distBits[i]
|
||||
offset += 7
|
||||
|
||||
# 4. velocity: -8..+8 → 0..16 → 5 bits
|
||||
let vel = int(clamp(scan.velocity + 8.0, 0.0, 16.0))
|
||||
let velBits = toBits(vel, 5)
|
||||
for i in 0..<5: result[offset + i] = velBits[i]
|
||||
offset += 5
|
||||
|
||||
# 5. heading_sin: sin(heading), -1..+1 → 0..199 → 8 bits
|
||||
let hSin = int((sin(degToRad(scan.heading)) + 1.0) / 2.0 * 199.0)
|
||||
let hSinBits = toBits(clamp(hSin, 0, 199), 8)
|
||||
for i in 0..<8: result[offset + i] = hSinBits[i]
|
||||
offset += 8
|
||||
|
||||
# 6. heading_cos: cos(heading), -1..+1 → 0..199 → 8 bits
|
||||
let hCos = int((cos(degToRad(scan.heading)) + 1.0) / 2.0 * 199.0)
|
||||
let hCosBits = toBits(clamp(hCos, 0, 199), 8)
|
||||
for i in 0..<8: result[offset + i] = hCosBits[i]
|
||||
|
||||
proc formatBinary*(vec: BinaryVector): string =
|
||||
for b in vec:
|
||||
|
||||
Reference in New Issue
Block a user