added ability to read speed from forza
This commit is contained in:
@@ -1 +1,177 @@
|
|||||||
FROZA_DATA_FORMAT = '<iIfffffffffffffffffffffffffffffffffffffffffffffffffffiiiiifffffffffffffffffHBBBBBBbbb'
|
import struct
|
||||||
|
#####FROZA_DATA_FORMAT = '<iIfffffffffffffffffffffffffffffffffffffffffffffffffffiiiiifffffffffffffffffHBBBBBBbbb'
|
||||||
|
FORZA_DATA_FORMAT = '<lL27f4l20f5lL27f4l20f5l3l17fH9b'
|
||||||
|
####FORZA_DATA_FORMAT = '<iI27f4i20f5i17fH6B3bi19fH6B4b'
|
||||||
|
|
||||||
|
def unpackData(unpackedData):
|
||||||
|
carData = {
|
||||||
|
"IsRaceOn":unpackedData[0], #// = 1 when race is on. = 0 when in menus/race stopped …
|
||||||
|
#// Can overflow to 0 eventually
|
||||||
|
"TimestampMS": unpackedData[1],
|
||||||
|
"EngineMaxRpm": unpackedData[2],
|
||||||
|
"EngineIdleRpm": unpackedData[3],
|
||||||
|
"CurrentEngineRpm": unpackedData[4],
|
||||||
|
#// In the car's local space; X = right, Y = up, Z = forward
|
||||||
|
"AccelerationX": unpackedData[5],
|
||||||
|
"AccelerationY": unpackedData[6],
|
||||||
|
"AccelerationZ": unpackedData[7],
|
||||||
|
#// In the car's local space; X = right, Y = up, Z = forward
|
||||||
|
"VelocityX": unpackedData[8],
|
||||||
|
"VelocityY": unpackedData[9],
|
||||||
|
"VelocityZ": unpackedData[10],
|
||||||
|
#// In the car's local space; X = pitch, Y = yaw, Z = roll
|
||||||
|
"AngularVelocityX": unpackedData[11],
|
||||||
|
"AngularVelocityY": unpackedData[12],
|
||||||
|
"AngularVelocityZ": unpackedData[13],
|
||||||
|
"Yaw": unpackedData[14],
|
||||||
|
"Pitch": unpackedData[15],
|
||||||
|
"Roll": unpackedData[16],
|
||||||
|
#// Suspension travel normalized: 0.0f = max stretch; 1.0 = max compression
|
||||||
|
"NormalizedSuspensionTravelFrontLeft": unpackedData[17],
|
||||||
|
"NormalizedSuspensionTravelFrontRight": unpackedData[18],
|
||||||
|
"NormalizedSuspensionTravelRearLeft": unpackedData[19],
|
||||||
|
"NormalizedSuspensionTravelRearRight": unpackedData[20],
|
||||||
|
#// Tire normalized slip ratio, = 0 means 100% grip and |ratio| > 1.0 means loss of grip.
|
||||||
|
"TireSlipRatioFrontLeft": unpackedData[21],
|
||||||
|
"TireSlipRatioFrontRight": unpackedData[22],
|
||||||
|
"TireSlipRatioRearLeft": unpackedData[23],
|
||||||
|
"TireSlipRatioRearRight": unpackedData[24],
|
||||||
|
#// Wheels rotation speed radians/sec.
|
||||||
|
"WheelRotationSpeedFrontLeft": unpackedData[25],
|
||||||
|
"WheelRotationSpeedFrontRight": unpackedData[26],
|
||||||
|
"WheelRotationSpeedRearLeft": unpackedData[27],
|
||||||
|
"WheelRotationSpeedRearRight": unpackedData[28],
|
||||||
|
#// = 1 when wheel is on rumble strip, = 0 when off.
|
||||||
|
"WheelOnRumbleStripFrontLeft": unpackedData[29],
|
||||||
|
"WheelOnRumbleStripFrontRight": unpackedData[30],
|
||||||
|
"WheelOnRumbleStripRearLeft": unpackedData[31],
|
||||||
|
"WheelOnRumbleStripRearRight": unpackedData[32],
|
||||||
|
#// = from 0 to 1, where 1 is the deepest puddle
|
||||||
|
"WheelInPuddleDepthFrontLeft": unpackedData[33],
|
||||||
|
"WheelInPuddleDepthFrontRight": unpackedData[34],
|
||||||
|
"WheelInPuddleDepthRearLeft": unpackedData[35],
|
||||||
|
"WheelInPuddleDepthRearRight": unpackedData[35],
|
||||||
|
#// Non-dimensional surface rumble values passed to controller force feedback
|
||||||
|
"SurfaceRumbleFrontLeft": unpackedData[36],
|
||||||
|
"SurfaceRumbleFrontRight": unpackedData[37],
|
||||||
|
"SurfaceRumbleRearLeft": unpackedData[38],
|
||||||
|
"SurfaceRumbleRearRight": unpackedData[39],
|
||||||
|
#// Tire normalized slip angle, = 0 means 100% grip and |angle| > 1.0 means loss of grip.
|
||||||
|
"TireSlipAngleFrontLeft": unpackedData[40],
|
||||||
|
"TireSlipAngleFrontRight": unpackedData[41],
|
||||||
|
"TireSlipAngleRearLeft": unpackedData[42],
|
||||||
|
"TireSlipAngleRearRight": unpackedData[43],
|
||||||
|
#// Tire normalized combined slip, = 0 means 100% grip and |slip| > 1.0 means loss of grip.
|
||||||
|
"TireCombinedSlipFrontLeft": unpackedData[44],
|
||||||
|
"TireCombinedSlipFrontRight": unpackedData[45],
|
||||||
|
"TireCombinedSlipRearLeft": unpackedData[46],
|
||||||
|
"TireCombinedSlipRearRight": unpackedData[47],
|
||||||
|
#// Actual suspension travel in meters
|
||||||
|
"SuspensionTravelMetersFrontLeft": unpackedData[48],
|
||||||
|
"SuspensionTravelMetersFrontRight": unpackedData[49],
|
||||||
|
"SuspensionTravelMetersRearLeft": unpackedData[50],
|
||||||
|
"SuspensionTravelMetersRearRight": unpackedData[51],
|
||||||
|
#// Unique ID of the car make/model
|
||||||
|
"CarOrdinal": unpackedData[52],
|
||||||
|
#// Between 0 (D -- worst cars) and 7 (X class -- best cars) inclusive
|
||||||
|
"CarClass": unpackedData[53],
|
||||||
|
#// Between 100 (worst car) and 999 (best car) inclusive
|
||||||
|
"CarPerformanceIndex": unpackedData[54],
|
||||||
|
#// 0 = FWD, 1 = RWD, 2 = AWD
|
||||||
|
"DrivetrainType": unpackedData[55],
|
||||||
|
#// Number of cylinders in the engine
|
||||||
|
"NumCylinders": unpackedData[56],
|
||||||
|
"PositionX": unpackedData[57],
|
||||||
|
"PositionY": unpackedData[58],
|
||||||
|
"PositionZ": unpackedData[59],
|
||||||
|
"Speed": unpackedData[60],
|
||||||
|
"Power": unpackedData[61],
|
||||||
|
"Torque": unpackedData[62],
|
||||||
|
"TireTempFrontLeft": unpackedData[63],
|
||||||
|
"TireTempFrontRight": unpackedData[64],
|
||||||
|
"TireTempRearLeft": unpackedData[65],
|
||||||
|
"TireTempRearRight": unpackedData[66],
|
||||||
|
"Boost": unpackedData[67],
|
||||||
|
"Fuel": unpackedData[68],
|
||||||
|
"DistanceTraveled": unpackedData[69],
|
||||||
|
"BestLap": unpackedData[70],
|
||||||
|
"LastLap": unpackedData[71],
|
||||||
|
"CurrentLap": unpackedData[72],
|
||||||
|
"CurrentRaceTime": unpackedData[73],
|
||||||
|
"LapNumber": unpackedData[74],
|
||||||
|
"RacePosition": unpackedData[75],
|
||||||
|
"Accel": unpackedData[76],
|
||||||
|
"Brake": unpackedData[77],
|
||||||
|
"Clutch": unpackedData[78],
|
||||||
|
"HandBrake": unpackedData[79],
|
||||||
|
"Gear": unpackedData[80],
|
||||||
|
"Steer": unpackedData[81],
|
||||||
|
"NormalizedDrivingLine": unpackedData[82],
|
||||||
|
"NormalizedAIBrakeDifference": unpackedData[83],
|
||||||
|
"TireWearFrontLeft": unpackedData[84],
|
||||||
|
"TireWearFrontRight": unpackedData[85],
|
||||||
|
"TireWearRearLeft": unpackedData[86],
|
||||||
|
"TireWearRearRight": unpackedData[87],
|
||||||
|
#// ID for track
|
||||||
|
"TrackOrdinal": unpackedData[88]
|
||||||
|
}
|
||||||
|
return carData
|
||||||
|
|
||||||
|
data_types = {}
|
||||||
|
with open('data_format.txt', 'r') as f:
|
||||||
|
lines = f.read().split('\n')
|
||||||
|
for line in lines:
|
||||||
|
data_types[line.split()[1]] = line.split()[0]
|
||||||
|
|
||||||
|
|
||||||
|
#assigning sizes in bytes to each variable type
|
||||||
|
jumps={
|
||||||
|
's32': 4, #Signed 32bit int, 4 bytes of size
|
||||||
|
'u32': 4, #Unsigned 32bit int
|
||||||
|
'f32': 4, #Floating point 32bit
|
||||||
|
'u16': 2, #Unsigned 16bit int
|
||||||
|
'u8': 1, #Unsigned 8bit int
|
||||||
|
's8': 1, #Signed 8bit int
|
||||||
|
'hzn': 12 #Unknown, 12 bytes of.. something
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(data):
|
||||||
|
return_dict={}
|
||||||
|
|
||||||
|
#additional var
|
||||||
|
passed_data = data
|
||||||
|
|
||||||
|
for i in data_types:
|
||||||
|
d_type = data_types[i]#checks data type (s32, u32 etc.)
|
||||||
|
jump=jumps[d_type]#gets size of data
|
||||||
|
current = passed_data[:jump]#gets data
|
||||||
|
|
||||||
|
decoded = 0
|
||||||
|
#complicated decoding for each type of data
|
||||||
|
if d_type == 's32':
|
||||||
|
decoded = int.from_bytes(current, byteorder='little', signed = True)
|
||||||
|
elif d_type == 'u32':
|
||||||
|
decoded = int.from_bytes(current, byteorder='little', signed=False)
|
||||||
|
elif d_type == 'f32':
|
||||||
|
decoded = struct.unpack('f', current)[0]
|
||||||
|
elif d_type == 'u16':
|
||||||
|
decoded = struct.unpack('H', current)[0]
|
||||||
|
elif d_type == 'u8':
|
||||||
|
decoded = struct.unpack('B', current)[0]
|
||||||
|
elif d_type == 's8':
|
||||||
|
decoded = struct.unpack('b', current)[0]
|
||||||
|
|
||||||
|
#adds decoded data to the dict
|
||||||
|
return_dict[i] = decoded
|
||||||
|
|
||||||
|
|
||||||
|
#removes already read bytes from the variable
|
||||||
|
passed_data = passed_data[jump:]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#returns the dict
|
||||||
|
return return_dict
|
||||||
Binary file not shown.
Binary file not shown.
@@ -2,36 +2,47 @@ import socket
|
|||||||
import struct
|
import struct
|
||||||
import serial
|
import serial
|
||||||
import time
|
import time
|
||||||
|
from enum import Enum
|
||||||
from GAME_METHODS import *
|
from GAME_METHODS import *
|
||||||
##import BEAMNG_FILES as BEAM
|
|
||||||
|
|
||||||
COM_PORT = 'COM5'
|
COM_PORT = 'COM5'
|
||||||
UDP_IP = "127.0.0.1"
|
UDP_IP = "127.0.0.1"
|
||||||
BEAMNG_UDP_PORT = 4444
|
BEAMNG_UDP_PORT = 4444
|
||||||
FORZA_UDP_PORT= 4843
|
FORZA_UDP_PORT= 4843
|
||||||
|
|
||||||
|
class GameType(Enum):
|
||||||
|
NONE=0,
|
||||||
|
BEAMNG = 1,
|
||||||
|
FORZA = 2
|
||||||
|
|
||||||
connectedArduino = False
|
connectedArduino = False
|
||||||
connectedWebSocket = False
|
connectedWebSocket = False
|
||||||
gameSelected = False
|
gameSelected = False
|
||||||
portToConnect= 0
|
portToConnect= 0
|
||||||
dataFormat = ""
|
gameType= GameType.NONE
|
||||||
|
carData = 0
|
||||||
|
|
||||||
|
#code runs from here<-----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#select game
|
||||||
while gameSelected == False:
|
while gameSelected == False:
|
||||||
gameNo = input("1:BEAMNG\n2:FORZA\n")
|
gameNo = input("1:BEAMNG\n2:FORZA\n")
|
||||||
if gameNo == "1":
|
if gameNo == "1":
|
||||||
portToConnect = BEAMNG_UDP_PORT
|
portToConnect = BEAMNG_UDP_PORT
|
||||||
dataFormat =BEAMNG_METHODS.BEAMNG_DATA_FORMAT
|
|
||||||
gameSelected = True
|
gameSelected = True
|
||||||
|
gameType=GameType.BEAMNG
|
||||||
print("BeamNG Selected")
|
print("BeamNG Selected")
|
||||||
elif gameNo == "2":
|
elif gameNo == "2":
|
||||||
portToConnect = FORZA_UDP_PORT
|
portToConnect = FORZA_UDP_PORT
|
||||||
dataFormat = FORZA_METHODS.FROZA_DATA_FORMAT
|
gameType=GameType.FORZA
|
||||||
print("Forza Selected")
|
|
||||||
gameSelected=True
|
gameSelected=True
|
||||||
|
print("Forza Selected")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("please select a number from the list")
|
print("please select a number from the list")
|
||||||
|
|
||||||
|
#check everything is connected
|
||||||
while connectedWebSocket == False:
|
while connectedWebSocket == False:
|
||||||
try:
|
try:
|
||||||
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
|
||||||
@@ -49,12 +60,18 @@ while connectedArduino == False:
|
|||||||
print("please check connection to arduino and verify the correct COM port")
|
print("please check connection to arduino and verify the correct COM port")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
print("ready:\n")
|
|
||||||
|
|
||||||
|
print(struct.calcsize(FORZA_METHODS.FORZA_DATA_FORMAT))
|
||||||
|
print("ready:\n")
|
||||||
while True:
|
while True:
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
unpackedData = struct.unpack(dataFormat,data)
|
if gameType == GameType.BEAMNG:
|
||||||
|
unpackedData = struct.unpack(BEAMNG_METHODS.BEAMNG_DATA_FORMAT,data)
|
||||||
carData = BEAMNG_METHODS.unpackData(unpackedData)
|
carData = BEAMNG_METHODS.unpackData(unpackedData)
|
||||||
kmh=carData["speed"]*3.6
|
kmh=carData["speed"]*3.6
|
||||||
|
elif gameType == GameType.FORZA:
|
||||||
|
# unpackedData = struct.unpack(FORZA_METHODS.FORZA_DATA_FORMAT,data)
|
||||||
|
carData = FORZA_METHODS.get_data(data)
|
||||||
|
kmh = carData["Speed"]*3.6
|
||||||
toPi.write(str(kmh).encode()+":".encode())
|
toPi.write(str(kmh).encode()+":".encode())
|
||||||
|
|
||||||
|
|||||||
85
data_format.txt
Normal file
85
data_format.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
s32 IsRaceOn
|
||||||
|
u32 TimestampMS
|
||||||
|
f32 EngineMaxRpm
|
||||||
|
f32 EngineIdleRpm
|
||||||
|
f32 CurrentEngineRpm
|
||||||
|
f32 AccelerationX
|
||||||
|
f32 AccelerationY
|
||||||
|
f32 AccelerationZ
|
||||||
|
f32 VelocityX
|
||||||
|
f32 VelocityY
|
||||||
|
f32 VelocityZ
|
||||||
|
f32 AngularVelocityX
|
||||||
|
f32 AngularVelocityY
|
||||||
|
f32 AngularVelocityZ
|
||||||
|
f32 Yaw
|
||||||
|
f32 Pitch
|
||||||
|
f32 Roll
|
||||||
|
f32 NormalizedSuspensionTravelFrontLeft
|
||||||
|
f32 NormalizedSuspensionTravelFrontRight
|
||||||
|
f32 NormalizedSuspensionTravelRearLeft
|
||||||
|
f32 NormalizedSuspensionTravelRearRight
|
||||||
|
f32 TireSlipRatioFrontLeft
|
||||||
|
f32 TireSlipRatioFrontRight
|
||||||
|
f32 TireSlipRatioRearLeft
|
||||||
|
f32 TireSlipRatioRearRight
|
||||||
|
f32 WheelRotationSpeedFrontLeft
|
||||||
|
f32 WheelRotationSpeedFrontRight
|
||||||
|
f32 WheelRotationSpeedRearLeft
|
||||||
|
f32 WheelRotationSpeedRearRight
|
||||||
|
s32 WheelOnRumbleStripFrontLeft
|
||||||
|
s32 WheelOnRumbleStripFrontRight
|
||||||
|
s32 WheelOnRumbleStripRearLeft
|
||||||
|
s32 WheelOnRumbleStripRearRight
|
||||||
|
f32 WheelInPuddleDepthFrontLeft
|
||||||
|
f32 WheelInPuddleDepthFrontRight
|
||||||
|
f32 WheelInPuddleDepthRearLeft
|
||||||
|
f32 WheelInPuddleDepthRearRight
|
||||||
|
f32 SurfaceRumbleFrontLeft
|
||||||
|
f32 SurfaceRumbleFrontRight
|
||||||
|
f32 SurfaceRumbleRearLeft
|
||||||
|
f32 SurfaceRumbleRearRight
|
||||||
|
f32 TireSlipAngleFrontLeft
|
||||||
|
f32 TireSlipAngleFrontRight
|
||||||
|
f32 TireSlipAngleRearLeft
|
||||||
|
f32 TireSlipAngleRearRight
|
||||||
|
f32 TireCombinedSlipFrontLeft
|
||||||
|
f32 TireCombinedSlipFrontRight
|
||||||
|
f32 TireCombinedSlipRearLeft
|
||||||
|
f32 TireCombinedSlipRearRight
|
||||||
|
f32 SuspensionTravelMetersFrontLeft
|
||||||
|
f32 SuspensionTravelMetersFrontRight
|
||||||
|
f32 SuspensionTravelMetersRearLeft
|
||||||
|
f32 SuspensionTravelMetersRearRight
|
||||||
|
s32 CarOrdinal
|
||||||
|
s32 CarClass
|
||||||
|
s32 CarPerformanceIndex
|
||||||
|
s32 DrivetrainType
|
||||||
|
s32 NumCylinders
|
||||||
|
f32 PositionX
|
||||||
|
f32 PositionY
|
||||||
|
f32 PositionZ
|
||||||
|
f32 Speed
|
||||||
|
f32 Power
|
||||||
|
f32 Torque
|
||||||
|
f32 TireTempFrontLeft
|
||||||
|
f32 TireTempFrontRight
|
||||||
|
f32 TireTempRearLeft
|
||||||
|
f32 TireTempRearRight
|
||||||
|
f32 Boost
|
||||||
|
f32 Fuel
|
||||||
|
f32 DistanceTraveled
|
||||||
|
f32 BestLap
|
||||||
|
f32 LastLap
|
||||||
|
f32 CurrentLap
|
||||||
|
f32 CurrentRaceTime
|
||||||
|
u16 LapNumber
|
||||||
|
u8 RacePosition
|
||||||
|
u8 Accel
|
||||||
|
u8 Brake
|
||||||
|
u8 Clutch
|
||||||
|
u8 HandBrake
|
||||||
|
u8 Gear
|
||||||
|
s8 Steer
|
||||||
|
s8 NormalizedDrivingLine
|
||||||
|
s8 NormalizedAIBrakeDifference
|
||||||
Reference in New Issue
Block a user