• Dear visitors,

    The email issue has been finally solved.
    Thank you for your patience and happy browsing.

    Team ACM.

How to log data (like live or once session is over to another platform or code of mine)? Assetto Corsa

Unre4alKing!23

New Member
How would I log data from my .py file in Assetto Corsa once the session is over to another like application? I have tried doing it before but it failed and I need some help. When I mean logging I mean like logging data like lap count speed throttle brake gear fuel and normTrackPos logged into a .csv file
Python:
import sys
import os
from third_party import sim_info
import ac
import acsys

# Labels for telemetry data
l_lapcount = 0
l_speed = 0
l_throttle = 0
l_brake = 0
l_gear = 0
l_rpm = 0
l_fuel = 0
l_normalizedTrackPos = 0  # <-- Add this

lapcount = 0  # Stores the current lap count

def acMain(ac_version):
    global l_lapcount, l_speed, l_throttle, l_brake, l_gear, l_rpm, l_fuel, l_normalizedTrackPos

    appWindow = ac.newApp("LapTimeML")
    ac.setSize(appWindow, 250, 220)  # Increased size for extra label

    ac.log("Telemetry App Initialized")
    ac.console("Telemetry App Running...")

    # Lap Count
    l_lapcount = ac.addLabel(appWindow, "Laps: 0")
    ac.setPosition(l_lapcount, 3, 30)

    # Speed (km/h)
    l_speed = ac.addLabel(appWindow, "Speed: 0 km/h")
    ac.setPosition(l_speed, 3, 50)

    # Throttle
    l_throttle = ac.addLabel(appWindow, "Throttle: 0%")
    ac.setPosition(l_throttle, 3, 70)

    # Brake
    l_brake = ac.addLabel(appWindow, "Brake: 0%")
    ac.setPosition(l_brake, 3, 90)

    # Gear
    l_gear = ac.addLabel(appWindow, "Gear: N")
    ac.setPosition(l_gear, 3, 110)

    # RPM
    l_rpm = ac.addLabel(appWindow, "RPM: 0")
    ac.setPosition(l_rpm, 3, 130)

    # Fuel
    l_fuel = ac.addLabel(appWindow, "Fuel: 0L")
    ac.setPosition(l_fuel, 3, 150)

    # Normalized Track Position
    l_normalizedTrackPos = ac.addLabel(appWindow, "Track Pos: 0.000")
    ac.setPosition(l_normalizedTrackPos, 3, 170)  # Position below fuel label

    return "LapTimeML"

def acUpdate(deltaT):
    global l_lapcount, l_speed, l_throttle, l_brake, l_gear, l_rpm, l_fuel, lapcount, l_normalizedTrackPos

    # Fetch data from Assetto Corsa
    laps = ac.getCarState(0, acsys.CS.LapCount)
    speed = ac.getCarState(0, acsys.CS.SpeedKMH)
    throttle = ac.getCarState(0, acsys.CS.Gas) * 100  # Convert to percentage
    brake = ac.getCarState(0, acsys.CS.Brake) * 100  # Convert to percentage
    gear = ac.getCarState(0, acsys.CS.Gear)
    rpm = ac.getCarState(0, acsys.CS.RPM)
    fuele = sim_info.info.physics.fuel

    # Normalized track position (0 to 1)
    track_pos = sim_info.info.graphics.normalizedCarPosition

    # Update labels
    if laps > lapcount:
        lapcount = laps
        ac.setText(l_lapcount, "Laps: {}".format(lapcount))

    ac.setText(l_speed, "Speed: {:.1f} km/h".format(speed))
    ac.setText(l_throttle, "Throttle: {:.0f}%".format(throttle))
    ac.setText(l_brake, "Brake: {:.0f}%".format(brake))
    ac.setText(l_gear, "Gear: {}".format(gear if gear > 0 else "N"))
    ac.setText(l_rpm, "RPM: {}".format(rpm))
    ac.setText(l_fuel, "Fuel: {:.2f}L".format(fuele))  # Display fuel with 2 decimal places
    ac.setText(l_normalizedTrackPos, "Track Pos: {:.3f}".format(track_pos))  # Show track position
 
Last edited:

fughettaboutit

aka leBluem aka Please Stop This
you would need to remember values in acUpdate()
and save either periodically or when AC closes:
Code:
def acShutdown():
    # save into your own file
    pass  # placeholder
...but dont reinvent the wheel, Telemetry was done already multiple times

as i understand, it needs or is based on this:

or use this
 

Unre4alKing!23

New Member
Thanks for responding, but like what code would I use to pass the log to another program how would I implement that. This is for my personal programming gain, I'm just experimenting.
 

fughettaboutit

aka leBluem aka Please Stop This
you prefill a huge enough array
only changing array values on the fly in acUpdate()

Python:
# untested
arraycount = 1000
array = [0.0,0.0,0.0,0.0] * arraycount # 1k entries
arrayi = 0

def acUpdate():
    global arraycount, array, arrayi
    #...
    # Update labels
    if laps > lapcount:
        lapcount = laps
        ac.setText(l_lapcount, "Laps: {}".format(lapcount))
        if lapcount>0:   # idk if wrong
            fp = open("lap" + str(lapcount) + ".csv", "w")
            fp.write('speed;gas;brake;gear\n')
            for i in range(len(array)):
                fp.write(str(array[i][0])+';'+str(array[i][1])+';'+str(array[i][2])+';'+str(array[i][3])+'\n')
            fp.close()
    else:
        array[arrayi][0]=speed
        array[arrayi][1]=throttle
        array[arrayi][2]=brake
        array[arrayi][3]=gear
        # ...
        arrayi+=1
        if arrayi>len(array):
            arrayi=0 # wrap around if too small

Or look at "(ACTI) Assetto Corsa Telemetry Interface"
it has a python app that uses UDP to talk with its parent app

acti_package_v1.1.2.rar ->
acti_trig_cntrl.rar ->
\apps\python\acti\acti.py

edit: changed code
 
Last edited:

Unre4alKing!23

New Member
im doing the array recommendation and I came across it sort of working and it sort of not working.
Python:
import os
import csv
import ac
import acsys
import json
from third_party import sim_info

# Settings
ARRAY_COUNT = 1000  # Circular buffer size
array = [[0.0, 0.0, 0.0, 0.0]] * ARRAY_COUNT  # Buffer for (speed, throttle, brake, gear)
array_index = 0  # Circular index

# Lap Count Tracking
lapcount = 0
log_file = "log.csv"  # Single file for all lap data

# Ensure the CSV file exists with a header
if not os.path.exists(log_file):
    with open(log_file, "w", newline="") as file:
        writer = csv.writer(file, delimiter=";")
        writer.writerow(["Lap", "Speed", "Throttle", "Brake", "Gear"])

def acMain(ac_version):
    global l_lapcount, l_speed, l_throttle, l_brake, l_gear, l_rpm, l_fuel, l_normalizedTrackPos

    appWindow = ac.newApp("LapTimeML")
    ac.setSize(appWindow, 250, 220)

    ac.log("Telemetry App Initialized")
    ac.console("Telemetry App Running...")

    # UI Labels
    l_lapcount = ac.addLabel(appWindow, "Laps: 0")
    ac.setPosition(l_lapcount, 3, 30)

    l_speed = ac.addLabel(appWindow, "Speed: 0 km/h")
    ac.setPosition(l_speed, 3, 50)

    l_throttle = ac.addLabel(appWindow, "Throttle: 0%")
    ac.setPosition(l_throttle, 3, 70)

    l_brake = ac.addLabel(appWindow, "Brake: 0%")
    ac.setPosition(l_brake, 3, 90)

    l_gear = ac.addLabel(appWindow, "Gear: N")
    ac.setPosition(l_gear, 3, 110)

    l_rpm = ac.addLabel(appWindow, "RPM: 0")
    ac.setPosition(l_rpm, 3, 130)

    l_fuel = ac.addLabel(appWindow, "Fuel: 0L")
    ac.setPosition(l_fuel, 3, 150)

    l_normalizedTrackPos = ac.addLabel(appWindow, "Track Pos: 0.000")
    ac.setPosition(l_normalizedTrackPos, 3, 170)

    return "LapTimeML"

def acUpdate(deltaT):
    global lapcount, array, array_index
    global l_lapcount, l_speed, l_throttle, l_brake, l_gear, l_rpm, l_fuel, l_normalizedTrackPos

    # Fetch data from Assetto Corsa
    laps = ac.getCarState(0, acsys.CS.LapCount)
    speed = ac.getCarState(0, acsys.CS.SpeedKMH)
    throttle = ac.getCarState(0, acsys.CS.Gas) * 100
    brake = ac.getCarState(0, acsys.CS.Brake) * 100
    gear = ac.getCarState(0, acsys.CS.Gear)
    rpm = ac.getCarState(0, acsys.CS.RPM)
    fuel = sim_info.info.physics.fuel
    track_pos = sim_info.info.graphics.normalizedCarPosition

    # Circular buffer for telemetry logging
    array[array_index] = [speed, throttle, brake, gear]
    array_index = (array_index + 1) % ARRAY_COUNT  # Wrap around

    # Save lap data when a new lap starts
    if laps > lapcount:
        lapcount = laps
        save_lap_data(lapcount, array)

    # Update UI
    ac.setText(l_lapcount, "Laps: {}".format(lapcount))
    ac.setText(l_speed, "Speed: {:.1f} km/h".format(speed))
    ac.setText(l_throttle, "Throttle: {:.0f}%".format(throttle))
    ac.setText(l_brake, "Brake: {:.0f}%".format(brake))
    ac.setText(l_gear, "Gear: {}".format("R" if gear == -1 else ("N" if gear == 0 else gear)))
    ac.setText(l_rpm, "RPM: {}".format(rpm))
    ac.setText(l_fuel, "Fuel: {:.2f}L".format(fuel))
    ac.setText(l_normalizedTrackPos, "Track Pos: {:.3f}".format(track_pos))

def save_lap_data(lap_num, data):
    with open(log_file, "a", newline="") as file:
        writer = csv.writer(file, delimiter=";")
        for entry in data:
            writer.writerow([lap_num, entry[0], entry[1], entry[2], entry[3]])

def acShutdown():
    save_lap_data(lapcount, array)
So this logs the data in this file called log.csv. There are no errors, but no actual logging is happening.
 
Last edited:

fughettaboutit

aka leBluem aka Please Stop This
Check your pedals? maybe set some deadzone? mine go back to 0
9073

Code:
ac.setText(label,
    '\ngas sharedMem       : '+str(round(siminfo.physics.gas*100.0,1))
    +'\nbrk sharedMem       : '+str(round(siminfo.physics.brake*100.0,1))
    +'\ngas ac.getCarState(): '+str(round(ac.getCarState(0, acsys.CS.Gas)*100.0,1))
    +'\nbrk ac.getCarState(): '+str(round(ac.getCarState(0, acsys.CS.Brake)*100.0,1))
    )
9074
 

vv31212

New Member
Code:
import ac
import acsys
import sys
import os
import time
import math

a=0
b=0
c=0
d=0
f=0
g=0
h=0
j=0

def acMain(ac_version):
   global a,c,f,h
   appWindow = ac.newApp("RPM")
   ac.setSize(appWindow, 110, 130)

   a = ac.addLabel(appWindow, "RPM: 0");
   ac.setPosition(a, 3, 30)
   c = ac.addLabel(appWindow, "SPEED: 0");
   ac.setPosition(c, 3, 60)
   f = ac.addLabel(appWindow, "Gas: 0%");
   ac.setPosition(f, 3, 90)
   h = ac.addLabel(appWindow, "Brake: 0%");
   ac.setPosition(h, 3, 110)
  
   return "RPM"

def acUpdate(deltaT):
   global a,b,c,d,f,g,h,j

   RPM = ac.getCarState(0, acsys.CS.RPM)
   if RPM > 0:
      b = RPM
      ac.setText(a, "RPM: {:.0f}".format(b))

   SPEED = ac.getCarState(0, acsys.CS.SpeedKMH)
   if SPEED > 0:
      d = SPEED
      ac.setText(c, "SPEED: {:.1f}".format(d))

   Gas = ac.getCarState(0, acsys.CS.Gas) * 100
   if Gas > 0:
      g = Gas
      ac.setText(f, "Gas: {:.1f}%".format(g))

   Brake = ac.getCarState(0, acsys.CS.Brake) * 100
   if Brake > 0:
      j = Brake
      ac.setText(h, "Brake: {:.1f}%".format(j))
this is my code, i do set 5% deadzone, it should be follow the default red&green bar, both back to 0%.
and if i delete this judgment sentence brake or gas
" if Brake > 0:
j = Brake"
the app wont work idk why
 

fughettaboutit

aka leBluem aka Please Stop This
you multiply wit 100 before the comparsion
try the other way around
and use not 0, but 0.0001 or something
Code:
   Gas = ac.getCarState(0, acsys.CS.Gas)
   if Gas > 0.0001:
      ac.setText(f, "Gas: {:.1f}%".format(Gas * 100))
 

vv31212

New Member
Thank you! ">" to ">=" it work now

Im a beginner and my goal is to get the exact start time and automatically shift gears, but I didn't find the relevant info from ac python doc. Is this kind of function must done by lua? I read the cmrt and gt7 app lua file and found these
function script.startingSequence(dt)
SIM.timeToSessionStart
function physics.engageGear(carIndex, gearToEngage)
 
Last edited:
Top