Rally Geometry
Early work-in-progress rally co-driver system. Generates pacenotes from a route by analyzing road geometry - computing turn radius, velocity, severity, and direction for each node, then splitting and
Early work-in-progress rally co-driver system. Generates pacenotes from a route by analyzing road geometry - computing turn radius, velocity, severity, and direction for each node, then splitting and simplifying into human-readable pacenote calls (e.g., "3 left long"). Renders pacenotes as colored 3D overlays in the world.
Public API
| Function | Signature | Returns | Description |
|---|---|---|---|
M.onUpdate | (dt, dtSim) | nil | Per-frame update: generates/loads pacenotes, renders them based on vehicle state |
Internals
Key Local Functions
| Function | Description |
|---|---|
circleDist1Dist2CenterAngleFromPoints(p1,p2,p3) | Fits a circle through 3 points; returns distances, center, and arc angle |
getTurnVelocityWithSlickTires(radius) | Calculates max cornering speed from radius using v = sqrt(μ·g·r) with μ=1.7 |
computeNodeData(route) | Annotates each route node with center, radius, velocity, severity, direction, angle |
computePacenoteData(pacenote) | Aggregates node data into a pacenote (time, length, angle, name) |
splitRouteIntoPacenotes(route) | Splits route at direction changes into raw pacenote segments |
simplifyPacenotes(pacenotes) | Iteratively merges straights by extending next/prev and combining consecutive |
getPacenotesFromRoute(route) | Full pipeline: computeNodeData → split → simplify |
renderNode(node, renderLine, renderText) | Debug-draws a single route node with sphere, cylinder, and text |
renderPacenote(pacenote, txt) | Draws a pacenote as colored cylinders with label at the start |
renderNextPacenotes(...) | Shows upcoming pacenotes based on time/distance prediction |
renderAllPacenotes(pacenotes, showNodes) | Draws all pacenotes; optionally shows individual nodes |
getPacenoteText(pacenote) | Formats pacenote into text like "3 left long tightens" |
getPacenoteCall(txt, pacenote, pacenoteNext) | Appends link text ("into", distance) between consecutive pacenotes |
Severity Table
Pacenotes are classified by max cornering velocity:
| Name | Max Velocity (km/h) | Color |
|---|---|---|
| Hairpin / K | 50 | dark violet |
| 2 | 80 | dark red |
| 3 | 110 | dark orange |
| 4 | 150 | dark green |
| 5 | 200 | dark cyan |
| 6 | 300 | dark blue |
| (straight) | ∞ | white |
Route Sources
- Ground markers: Uses
core_groundMarkers.routePlanner.pathto get A→B route, optimized viamap.optimizePath - File cache: Falls back to
temp/rally_route_{level}.jsonencoded withlpack
Pacenote Name Logic
- Hairpin: angle < 60° → "Slow", < 120° → "K", else "Hairpin"
- Straight: length < 10m → "into", < 20m → "then", else rounded distance (e.g., "50")
- Modifiers: "long" (>3s), "short" (<0.7s), "tightens" (60%+ speed drop), "opens" (inverse)
How It Works
- On update, checks if ground markers target exists
- Generates route from A→B using
map.getGraphpath+map.optimizePath - Computes per-node geometry (circle fitting, radius, velocity, severity)
- Splits into pacenotes at direction changes, then simplifies by merging straights
- At standstill: renders all pacenotes; while moving: renders upcoming pacenotes by predicted time window (4 seconds ahead)
- Displays current pacenote call via
ScenarioRealtimeDisplayGUI hook
Usage Example
-- This module runs automatically via onUpdate when ground markers are active
-- No direct API calls needed; pacenotes appear as 3D overlays on the routeSee Also
- Rally Audio Manager - Related reference
- Rally Camera Path Player - Related reference
- Rally Client - Related reference
- Gameplay Systems Guide - Guide
Rally Extension Helper
Stub extension for rally gameplay. Provides empty `load` and `unload` lifecycle hooks. Currently contains no functional logic - serves as a placeholder for future rally extension management.
Rally Manager
Central runtime manager for a rally stage. Coordinates the notebook, driveline route, audio manager, vehicle tracker, and pacenote queue during gameplay.