Skip to content

Vhi.ControlHandSkeleton

VHI_godot

Vhi

ControlHandSkeleton Class

The "control" hand - the ground-truth / cued hand on the left of the scene.

Follows the presence of its vhi.control.pose.* LSL streams, exactly as the predicted hand follows vhi.prediction.*: whichever is live drives the hand, checked fresh every frame rather than switched by a handshake. - Some stream live: ignores its own movement state machine and holds whatever its DOFs were last commanded to, each one applied as it arrived (pushed in by LSLCommunicationController). - Every stream absent (the default at startup, and again once they go stale): plays a named predefined movement through the state machine waiting → closing → holding → opening → resting, and listens for ←/→/↑/↓ keyboard input to cycle/start/stop. Movement poses come from the TOML loaded via MovementConfigLoader; the available set is filtered by Mode (AI vs Classifier).

Frame-by-frame animation logic runs in _Process; the resulting pose is published to the VHI_Control LSL outlet in _PhysicsProcess. Commands originate from the gRPC control services (via the public command API on this class) and from local keyboard input - the same methods are called either way.

public class ControlHandSkeleton : Vhi.HandSkeleton

Inheritance System.Object → Godot.GodotObject → Godot.Node → Godot.Node3D → HandSkeleton → ControlHandSkeleton

Fields

ControlHandSkeleton.ConfigFilePath Field

Godot resource path to the movements TOML config. Defaults to user://movements.toml; auto-generated from the hard-coded poses on first run, and hot-reloaded on change. To load a TOML from elsewhere at runtime, use the control panel's "Load Config File" button or call LoadConfigFile(string).

public string ConfigFilePath;

Field Value

System.String

ControlHandSkeleton.Frequency Field

Movement cycles per second while the control hand is animating its own movements rather than following its pose stream - the closing/opening interpolation speed. Live-adjustable via the control panel, or over gRPC by StartRecordingTrajectory's frequency_hz; there is no SetSpeed RPC.

public float Frequency;

Field Value

System.Single

ControlHandSkeleton.HoldTime Field

Seconds held at max flexion in each movement cycle.

public float HoldTime;

Field Value

System.Single

ControlHandSkeleton.RestTime Field

Seconds held at rest in each movement cycle.

public float RestTime;

Field Value

System.Single

Properties

ControlHandSkeleton.IsFrozen Property

True while the control hand is in the frozen state - set by SetFrozen(bool) with frozen=true, or by SetMovement(string, bool) with cycle=false after reaching the end pose.

public bool IsFrozen { get; }

Property Value

System.Boolean

ControlHandSkeleton.RecordingTrajectoryActive Property

Whether a v2 recording trajectory is cycling this hand right now.

public bool RecordingTrajectoryActive { get; }

Property Value

System.Boolean

Remarks

Tracked here rather than in the gRPC service because the service is constructed per call — grpc-dotnet's activator gives every RPC a fresh instance, so a flag held there would always read false. The hand is the thing that is running a trajectory, so the hand is where the fact belongs.

ControlHandSkeleton.RecordingTrajectoryMovement Property

The movement a running recording trajectory is cycling, or empty.

public string RecordingTrajectoryMovement { get; }

Property Value

System.String

ControlHandSkeleton.SessionActive Property

True when a MyoGestic recording session is currently active. While set, VHI's local keyboard input is gated off so the gRPC client is the sole movement source. Toggled via the RemoteControl.SetRecordingSession RPC.

public bool SessionActive { get; set; }

Property Value

System.Boolean

Methods

ControlHandSkeleton.CycleMovement(int) Method

"AI" or "Classifier".

public void CycleMovement(int delta);

Parameters

delta System.Int32

Direction and magnitude of the cycle step. Pass +1 for the next movement, -1 for the previous; wraps at the ends of the available-movements list.

ControlHandSkeleton.GetAnimationState() Method

public string GetAnimationState();

Returns

System.String

ControlHandSkeleton.GetAvailableMovements() Method

Movement names valid for the current mode.

public string[] GetAvailableMovements();

Returns

System.String[]

ControlHandSkeleton.GetCurrentMovementName() Method

public string GetCurrentMovementName();

Returns

System.String

ControlHandSkeleton.LoadConfigFile(string) Method

Load a new config file, replacing the current one. Updates ConfigFilePath, reloads movements, and re-watches the new file.

public void LoadConfigFile(string absolutePath);

Parameters

absolutePath System.String

Absolute filesystem path to a TOML movement config. If the path is inside Godot's user data directory it is stored back as a user:// path; otherwise the absolute path is kept.

ControlHandSkeleton.SetFrozen(bool) Method

Freeze the control hand at its current pose, or release it back to the resting state.

public void SetFrozen(bool frozen);

Parameters

frozen System.Boolean

true to hold the live pose indefinitely; false to release back to the resting state and resume the normal movement state machine.

ControlHandSkeleton.SetMovement(string, bool) Method

Select a movement by name and start playing it. The name "Rest" returns the hand to its resting state. Returns false if the name is neither a known movement nor "Rest".

public bool SetMovement(string name, bool cycle=false);

Parameters

name System.String

A name from GetAvailableMovements(), or the special value "Rest" to return to the resting state.

cycle System.Boolean

If false (default), snap to the movement's end pose and hold it - the right behaviour for a classifier output. If true, play the open/close cycle in a loop - used when recording regression data so VHI_Control sweeps a continuous kinematic range.

Returns

System.Boolean
true if the command was applied; false if name was rejected.

ControlHandSkeleton.SetSpeed(float, float, float) Method

Set the control-hand animation timing (the UI speed/hold/rest sliders). A non-positive frequency is ignored; negative hold/rest values are ignored.

public void SetSpeed(float frequencyHz, float holdTimeS, float restTimeS);

Parameters

frequencyHz System.Single

Movement cycles per second. Values \<= 0 leave the current frequency unchanged.

holdTimeS System.Single

Seconds to hold at max flexion in each cycle. Negative values are ignored.

restTimeS System.Single

Seconds to hold at rest in each cycle. Negative values are ignored.

ControlHandSkeleton.StartCurrentMovement() Method

Start playing the currently-selected movement from rest.

public void StartCurrentMovement();

ControlHandSkeleton.StartRecordingTrajectory(string, float, float, float) Method

Begin cycling movement to generate a recording trajectory.

public bool StartRecordingTrajectory(string movement, float frequencyHz, float holdTimeS, float restTimeS);

Returns

System.Boolean
false if a control-pose stream is driving the hand or the movement name is unknown — in which case nothing was started.

Remarks

Non-positive frequencyHz and negative hold/rest times leave VHI's current timing alone, matching SetSpeed(float, float, float).

ControlHandSkeleton.StopRecordingTrajectory() Method

Stop a recording trajectory, resting the hand only if one was running. Idempotent.

public void StopRecordingTrajectory();

ControlHandSkeleton.StopToRest() Method

Stop any movement and return the hand to its resting state.

public void StopToRest();

ControlHandSkeleton.ToggleFreeze() Method

Toggle freeze mode (used by keyboard input).

public void ToggleFreeze();

delta System.Double

delta System.Double