Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@
<td><progress id="brake-progress" max="1"></progress></td>
<td><progress id="throttle-progress" max="1"></progress></td>
</tr>
<tr>
<td colspan="3">
<canvas id="input-graph" width="100" height="40"></canvas>
</td>
</tr>
</table>

<div id="steering-wheel-container">
Expand Down
6 changes: 6 additions & 0 deletions wwwroot/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,12 @@ progress#revs::-webkit-progress-value {
padding: 0px;
}

#input-graph {
background-color: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.2);
display: block;
}

#steering-wheel {
width: 90px;
}
Expand Down
14 changes: 14 additions & 0 deletions wwwroot/ts/hudElements/DriverInputs.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import HudElement from "./HudElement.js";
import {validNumberOrDefault, valueIsValidAssertUndefined} from "../consts.js";
import {SharedMemoryKey} from '../SharedMemoryConsumer.js';
import {InputGraph} from "./InputGraph.js";

export default class DriverInputs extends HudElement {
override sharedMemoryKeys: SharedMemoryKey[] = ['throttleRaw', 'throttle', 'brakeRaw', 'brake', 'clutchRaw', 'clutch', 'steerInputRaw', 'steerWheelRangeDegrees'];

private inputGraph: InputGraph | null = null;

private static rawOrReal(n: number, r: number): number {
return validNumberOrDefault(n, validNumberOrDefault(r, 0));
}
Expand All @@ -19,6 +22,13 @@ export default class DriverInputs extends HudElement {

const steer = document.getElementById('steering-wheel');

if (!this.inputGraph) {
const canvas = document.getElementById('input-graph') as HTMLCanvasElement;
if (canvas) {
this.inputGraph = new InputGraph(canvas, 100);
}
}

tRaw = DriverInputs.rawOrReal(tRaw, t);
bRaw = DriverInputs.rawOrReal(bRaw, b);
cRaw = DriverInputs.rawOrReal(cRaw, c);
Expand All @@ -33,6 +43,10 @@ export default class DriverInputs extends HudElement {
brakeProgress.value = bRaw.toString();
clutchProgress.value = cRaw.toString();

if (this.inputGraph) {
this.inputGraph.update(tRaw, bRaw);
}

const steerAngle = sRaw * sRange / 2;
steer.style.transform = `rotate(${steerAngle}deg)`;

Expand Down
76 changes: 76 additions & 0 deletions wwwroot/ts/hudElements/InputGraph.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
export class InputHistory {
private history: number[] = [];
private readonly maxSize: number;

constructor(maxSize: number) {
this.maxSize = maxSize;
}

public add(value: number): void {
this.history.push(value);
if (this.history.length > this.maxSize) {
this.history.shift();
}
}

public getHistory(): number[] {
return this.history;
}
}

export class InputGraph {
private readonly canvas: HTMLCanvasElement;
private readonly ctx: CanvasRenderingContext2D;
private readonly throttleHistory: InputHistory;
private readonly brakeHistory: InputHistory;

constructor(canvas: HTMLCanvasElement, historySize: number) {
this.canvas = canvas;
const context = canvas.getContext('2d');
if (!context) {
throw new Error('Could not get 2d context');
}
this.ctx = context;
this.throttleHistory = new InputHistory(historySize);
this.brakeHistory = new InputHistory(historySize);
}

public update(throttle: number, brake: number): void {
this.throttleHistory.add(throttle);
this.brakeHistory.add(brake);
this.render();
}

private render(): void {
const width = this.canvas.width;
const height = this.canvas.height;
this.ctx.clearRect(0, 0, width, height);

this.drawCurve(this.throttleHistory.getHistory(), '#00ff00'); // Green for throttle
this.drawCurve(this.brakeHistory.getHistory(), '#ff0000'); // Red for brake
}

private drawCurve(history: number[], color: string): void {
const historyLength = history.length;
if (historyLength < 2) return;

this.ctx.strokeStyle = color;
this.ctx.lineWidth = 2;
this.ctx.beginPath();

const width = this.canvas.width;
const height = this.canvas.height;
const step = width / (historyLength - 1);

for (let i = 0; i < historyLength; i++) {
const x = i * step;
const y = height - (history[i] * height);
if (i === 0) {
this.ctx.moveTo(x, y);
} else {
this.ctx.lineTo(x, y);
}
}
this.ctx.stroke();
}
}