TiGa-RCE commited on
Commit
c2215d3
·
verified ·
1 Parent(s): 857589b

Replace synthetic viewer telemetry with recorded native drives

Browse files

The current viewer derives motion and HUD values from aggregate results, which creates off-track starting poses, discontinuous movement and unsupported telemetry.

This change replaces that reconstruction with an explicit recorded CPU drive. The native engine supplies position, velocity, heading and contact samples for one unchanged policy; the viewer keeps native track curves, validates the track/policy identities, interpolates only between recorded poses and stops at the final sample. Unavailable controls, sensor rays and neural activity are removed.

The new recording endpoint is bounded to 15 seconds of simulation with a 30-second wall deadline, shares CPU admission with training and uses the existing binary. Physics and control stay at 60 Hz; samples are captured every six ticks. These are fresh drives with wall-hit and idle elimination off, clearly distinguished from historical training results.

Validation: 36 focused checks pass (14 recorder contract, 9 geometry/playback, 5 client lifecycle/integration and 8 existing tutorial/recipe/batch workflows). JavaScript and Python syntax checks pass. Hosted native recording and final visual inspection will follow the complete package update.

Files changed (1) hide show
  1. server.py +40 -0
server.py CHANGED
@@ -4,6 +4,7 @@ import hashlib
4
  import json
5
  from pathlib import Path
6
  import re
 
7
  import threading
8
  from fastapi import HTTPException, Request
9
  from fastapi.responses import FileResponse, Response, HTMLResponse, JSONResponse
@@ -363,6 +364,45 @@ def create_app(worker=run_reported,store=None,gpu_worker=None,track_library=None
363
  except InvalidAnalysisOutput: raise HTTPException(422,'Processing failed; complete analysis could not be verified.') from None
364
  except Exception: raise HTTPException(422,'Processing failed; no result published. Cleanup status requires verification.') from None
365
  finally: admission.release()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  return app
367
 
368
  app=create_app()
 
4
  import json
5
  from pathlib import Path
6
  import re
7
+ import subprocess
8
  import threading
9
  from fastapi import HTTPException, Request
10
  from fastapi.responses import FileResponse, Response, HTMLResponse, JSONResponse
 
364
  except InvalidAnalysisOutput: raise HTTPException(422,'Processing failed; complete analysis could not be verified.') from None
365
  except Exception: raise HTTPException(422,'Processing failed; no result published. Cleanup status requires verification.') from None
366
  finally: admission.release()
367
+ @app.post('/api/replay')
368
+ async def recorded_replay(request:Request):
369
+ # Share CPU admission with training; recordings never allocate a GPU.
370
+ if not admission.acquire(blocking=False):
371
+ raise HTTPException(429,'Worker busy; finish the current run before recording a drive')
372
+ data=bytearray()
373
+ try:
374
+ async for chunk in request.stream():
375
+ if len(data)+len(chunk)>3*1024*1024:
376
+ raise HTTPException(413,'Replay input exceeds the upload limit')
377
+ data.extend(chunk)
378
+ try:
379
+ body=json.loads(data)
380
+ if not isinstance(body,dict) or set(body)!={'track','network','ticks'}:
381
+ raise ValueError()
382
+ if type(body['ticks']) is not int or not 1<=body['ticks']<=900:
383
+ raise ValueError()
384
+ track=base64.b64decode(body['track'],validate=True)
385
+ network=base64.b64decode(body['network'],validate=True)
386
+ if not track or not network or max(len(track),len(network))>1024*1024:
387
+ raise ValueError()
388
+ except Exception:
389
+ raise HTTPException(400,'Invalid replay input; select a track, a network and up to 15 seconds') from None
390
+ finally:
391
+ data.clear()
392
+ from replay import record_replay, ReplayError
393
+ try:
394
+ recording=await run_in_threadpool(record_replay,track,network,
395
+ binary=ROOT/'bin/altd-sim',importer=ROOT/'bin/extract_saved_track',
396
+ scene_template=ROOT/'assets/formula_template.json',ticks=body['ticks'])
397
+ recording['build']=build_identity()
398
+ return JSONResponse(recording,headers={'Cache-Control':'no-store','X-Content-Type-Options':'nosniff'})
399
+ except (TimeoutError,subprocess.TimeoutExpired):
400
+ raise HTTPException(504,'Recording reached its time limit. Try a 5-second drive.') from None
401
+ except (ReplayError,OSError,ValueError,KeyError,TypeError,subprocess.CalledProcessError):
402
+ raise HTTPException(422,'The engine could not produce a complete recorded drive. No estimated playback was substituted.') from None
403
+ finally:
404
+ data.clear()
405
+ admission.release()
406
  return app
407
 
408
  app=create_app()