Fixed the controls and cleaned up some lookup tables

This commit is contained in:
Niklas Jensen
2026-01-01 23:32:11 +01:00
committed by nikguin04
parent 1117666f26
commit f25aba5f29
4 changed files with 228 additions and 56 deletions
@@ -67,6 +67,39 @@ export function modesEnumToJSON(object: ModesEnum): string {
}
}
export enum WalkGaits {
TROT = 0,
CRAWL = 1,
UNRECOGNIZED = -1,
}
export function walkGaitsFromJSON(object: any): WalkGaits {
switch (object) {
case 0:
case "TROT":
return WalkGaits.TROT;
case 1:
case "CRAWL":
return WalkGaits.CRAWL;
case -1:
case "UNRECOGNIZED":
default:
return WalkGaits.UNRECOGNIZED;
}
}
export function walkGaitsToJSON(object: WalkGaits): string {
switch (object) {
case WalkGaits.TROT:
return "TROT";
case WalkGaits.CRAWL:
return "CRAWL";
case WalkGaits.UNRECOGNIZED:
default:
return "UNRECOGNIZED";
}
}
export interface Vector {
x: number;
y: number;
@@ -200,6 +233,10 @@ export interface SystemInformation {
staticSystemInformation: StaticSystemInformation | undefined;
}
export interface WalkGaitData {
gait: WalkGaits;
}
export interface SubscribeNotification {
tag: number;
}
@@ -2326,6 +2363,64 @@ export const SystemInformation: MessageFns<SystemInformation> = {
},
};
function createBaseWalkGaitData(): WalkGaitData {
return { gait: 0 };
}
export const WalkGaitData: MessageFns<WalkGaitData> = {
encode(message: WalkGaitData, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.gait !== 0) {
writer.uint32(8).int32(message.gait);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): WalkGaitData {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseWalkGaitData();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.gait = reader.int32() as any;
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): WalkGaitData {
return { gait: isSet(object.gait) ? walkGaitsFromJSON(object.gait) : 0 };
},
toJSON(message: WalkGaitData): unknown {
const obj: any = {};
if (message.gait !== 0) {
obj.gait = walkGaitsToJSON(message.gait);
}
return obj;
},
create<I extends Exact<DeepPartial<WalkGaitData>, I>>(base?: I): WalkGaitData {
return WalkGaitData.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<WalkGaitData>, I>>(object: I): WalkGaitData {
const message = createBaseWalkGaitData();
message.gait = object.gait ?? 0;
return message;
},
};
function createBaseSubscribeNotification(): SubscribeNotification {
return { tag: 0 };
}
@@ -4017,6 +4112,30 @@ export const protoMetadata: ProtoMetadata = {
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}, {
"name": "WalkGaitData",
"field": [{
"name": "gait",
"number": 1,
"label": 1,
"type": 14,
"typeName": ".WalkGaits",
"extendee": "",
"defaultValue": "",
"oneofIndex": 0,
"jsonName": "gait",
"options": undefined,
"proto3Optional": false,
}],
"extension": [],
"nestedType": [],
"enumType": [],
"extensionRange": [],
"oneofDecl": [],
"options": undefined,
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}, {
"name": "SubscribeNotification",
"field": [{
@@ -4296,6 +4415,17 @@ export const protoMetadata: ProtoMetadata = {
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}, {
"name": "WalkGaits",
"value": [{ "name": "TROT", "number": 0, "options": undefined }, {
"name": "CRAWL",
"number": 1,
"options": undefined,
}],
"options": undefined,
"reservedRange": [],
"reservedName": [],
"visibility": 0,
}],
"service": [],
"extension": [],
@@ -4308,8 +4438,8 @@ export const protoMetadata: ProtoMetadata = {
"trailingComments": "",
"leadingDetachedComments": [],
}, {
"path": [4, 23],
"span": [87, 0, 105, 1],
"path": [4, 24],
"span": [94, 0, 112, 1],
"leadingComments": " WebSocket message wrapper\n Only ONE field will be set at a time (oneof ensures this)\n",
"trailingComments": "",
"leadingDetachedComments": [],
@@ -4320,6 +4450,7 @@ export const protoMetadata: ProtoMetadata = {
},
references: {
".ModesEnum": ModesEnum,
".WalkGaits": WalkGaits,
".Vector": Vector,
".I2CDevice": I2CDevice,
".PinConfig": PinConfig,
@@ -4339,6 +4470,7 @@ export const protoMetadata: ProtoMetadata = {
".SonarData": SonarData,
".HumanInputData": HumanInputData,
".SystemInformation": SystemInformation,
".WalkGaitData": WalkGaitData,
".SubscribeNotification": SubscribeNotification,
".UnsubscribeNotification": UnsubscribeNotification,
".PingMsg": PingMsg,
+28 -24
View File
@@ -1,4 +1,4 @@
import { HumanInputData, ModeData, ModesEnum } from '$lib/platform_shared/websocket_message'
import { HumanInputData, ModeData, ModesEnum, WalkGaitData, WalkGaits } from '$lib/platform_shared/websocket_message'
import { persistentStore } from '$lib/utilities/svelte-utilities'
import { writable, type Writable } from 'svelte/store'
@@ -8,34 +8,38 @@ export const jointNames = persistentStore('joint_names', <string[]>[])
export const model = writable()
export const modes = ['deactivated', 'idle', 'calibration', 'rest', 'stand', 'walk'] as const
export type Modes = (typeof modes)[number]
export enum WalkGaits {
Trot = 0,
Crawl = 1
}
export const walkGaits = ['trot', 'crawl'] as const
export const walkGaitLabels: Record<WalkGaits, string> = {
[WalkGaits.Trot]: 'Trot',
[WalkGaits.Crawl]: 'Crawl'
}
export const walkGaitToMode = (gait: WalkGaits): 'trot' | 'crawl' => {
return gait === WalkGaits.Trot ? 'trot' : 'crawl'
}
export const mode: Writable<ModeData> = writable(ModeData.create({ mode: ModesEnum.DEACTIVATED }))
export const walkGait: Writable<WalkGaits> = writable(WalkGaits.Trot)
export const walkGait: Writable<WalkGaitData> = writable( WalkGaitData.create({gait: WalkGaits.TROT }) )
export const outControllerData = writable( HumanInputData.create( {left: {x:0,y:0}, right: {x:0,y:0}, height:0, s1:0, speed:0} ) )
export const kinematicData = writable([0, 0, 0, 0, 1, 0])
export const input: Writable<HumanInputData> = writable( HumanInputData.create( {left: {x:0,y:0}, right: {x:0,y:0}, height:0, s1:0, speed:0} ) )
// Following code is generated from CLAUDE CODE
// Auto-generate modes array from ModesEnum (excluding UNRECOGNIZED)
export const modes = Object.values(ModesEnum)
.filter((v): v is ModesEnum => typeof v === 'number' && v !== ModesEnum.UNRECOGNIZED)
// Auto-generate mode labels from enum keys
export const modeLabels: Record<ModesEnum, string> = Object.entries(ModesEnum)
.filter(([_, v]) => typeof v === 'number' && v !== ModesEnum.UNRECOGNIZED)
.reduce((acc, [key, value]) => {
acc[value as ModesEnum] = key.charAt(0) + key.slice(1).toLowerCase()
return acc
}, {} as Record<ModesEnum, string>)
// Auto-generate walk gaits array from WalkGaits enum (excluding UNRECOGNIZED)
export const walkGaits = Object.values(WalkGaits)
.filter((v): v is WalkGaits => typeof v === 'number' && v !== WalkGaits.UNRECOGNIZED)
// Auto-generate walk gait labels from enum keys
export const walkGaitLabels: Record<WalkGaits, string> = Object.entries(WalkGaits)
.filter(([_, v]) => typeof v === 'number' && v !== WalkGaits.UNRECOGNIZED)
.reduce((acc, [key, value]) => {
acc[value as WalkGaits] = key.charAt(0) + key.slice(1).toLowerCase()
return acc
}, {} as Record<WalkGaits, string>)
+39 -29
View File
@@ -1,27 +1,37 @@
<script lang="ts">
import nipplejs from 'nipplejs'
import { onMount } from 'svelte'
import { capitalize } from '$lib/utilities'
import {
input,
mode,
modes,
type Modes,
ModesEnum,
WalkGaits,
walkGait,
modes,
modeLabels,
walkGaits,
walkGaitLabels
} from '$lib/stores'
import type { vector } from '$lib/types/models'
import { VerticalSlider } from '$lib/components/input'
import { gamepadAxes, gamepadButtonsEdges, hasGamepad } from '$lib/stores/gamepad'
import { notifications } from '$lib/components/toasts/notifications'
import { HumanInputData } from '$lib/platform_shared/websocket_message'
import {
HumanInputData,
ModeData,
ModesEnum,
WalkGaitData,
WalkGaits
} from '$lib/platform_shared/websocket_message'
let left: nipplejs.JoystickManager
let right: nipplejs.JoystickManager
let data: HumanInputData = HumanInputData.create( {left: {x:0,y:0}, right: {x:0,y:0}, height:0, s1:0, speed:0} )
let data: HumanInputData = HumanInputData.create({
left: { x: 0, y: 0 },
right: { x: 0, y: 0 },
height: 0,
s1: 0,
speed: 0
})
$effect(() => {
if ($hasGamepad) {
@@ -38,10 +48,10 @@
if (!$hasGamepad) return
const b = $gamepadButtonsEdges
if (!b.length) return
if (b[0]?.justPressed) mode.set(5)
if (b[1]?.justPressed) mode.set(4)
if (b[2]?.justPressed) mode.set(3)
if (b[3]?.justPressed) mode.set(0)
if (b[0]?.justPressed) mode.set(ModeData.create({ mode: ModesEnum.WALK }))
if (b[1]?.justPressed) mode.set(ModeData.create({ mode: ModesEnum.STAND }))
if (b[2]?.justPressed) mode.set(ModeData.create({ mode: ModesEnum.REST }))
if (b[3]?.justPressed) mode.set(ModeData.create({ mode: ModesEnum.DEACTIVATED }))
if (b[12]?.justPressed)
input.update(inputData => {
inputData.height = Math.min(inputData.height + 0.1, 1)
@@ -104,12 +114,12 @@
})
}
const changeMode = (modeValue: Modes) => {
mode.set(modes.indexOf(modeValue))
const changeMode = (modeValue: ModesEnum) => {
mode.set(ModeData.create({ mode: modeValue }))
}
const changeWalkGait = (walkGaitValue: WalkGaits) => {
walkGait.set(walkGaitValue)
walkGait.set(WalkGaitData.create({ gait: walkGaitValue }))
}
</script>
@@ -150,26 +160,24 @@
{#each modes as modeValue (modeValue)}
<button
class="btn join-item btn-sm transition-all duration-200"
class:btn-primary={$mode === modes.indexOf(modeValue)}
class:btn-primary={$mode.mode === modeValue}
onclick={() => changeMode(modeValue)}
>
{capitalize(modeValue)}
{modeLabels[modeValue]}
</button>
{/each}
</div>
{#if $mode === ModesEnum.Walk}
{#if $mode.mode === ModesEnum.WALK}
<div class="join shadow-md">
{#each Object.values(WalkGaits) as gaitValue (gaitValue)}
{#if typeof gaitValue === 'number'}
<button
class="btn join-item btn-xs transition-all duration-200"
class:btn-secondary={$walkGait === gaitValue}
onclick={() => changeWalkGait(gaitValue)}
>
{walkGaitLabels[gaitValue]}
</button>
{/if}
{#each walkGaits as gaitValue (gaitValue)}
<button
class="btn join-item btn-xs transition-all duration-200"
class:btn-secondary={$walkGait.gait === gaitValue}
onclick={() => changeWalkGait(gaitValue)}
>
{walkGaitLabels[gaitValue]}
</button>
{/each}
</div>
@@ -182,7 +190,8 @@
min="0"
step="0.01"
max="1"
oninput={e => handleRange(Number((e.target as HTMLInputElement).value), 's1')}
oninput={e =>
handleRange(Number((e.target as HTMLInputElement).value), 's1')}
class="range range-xs range-primary"
/>
</div>
@@ -194,7 +203,8 @@
min="0"
step="0.01"
max="1"
oninput={e => handleRange(Number((e.target as HTMLInputElement).value), 'speed')}
oninput={e =>
handleRange(Number((e.target as HTMLInputElement).value), 'speed')}
class="range range-xs range-primary"
/>
</div>