Getting Started¶
This walks you from a fresh clone to a running VHI window with a hand moving.
Prerequisites¶
| Tool | Version | Notes |
|---|---|---|
| Godot | 4.6 .NET build | The Mono/.NET edition - not the standard build. C# won't load otherwise. |
| .NET SDK | 8.0 | The project targets net8.0 to match Godot 4.6's runtime. A .NET 8 SDK is also required for exporting. |
| Python 3 | 3.x | Only for the LSL test scripts in tests/ (pip install pylsl numpy). Optional. |
Use the .NET build of Godot
On macOS the .NET build is Godot.app reported as …mono… by
Godot --version. The standard (non-.NET) build cannot run VHI.
Restore and run¶
# 1. Restore NuGet packages (SharpLSL, Grpc.AspNetCore, Tomlyn)
dotnet restore
# 2. Open the project in the Godot editor and press F5 - or run headless:
godot --path .
On first run VHI:
- builds the C# assembly,
- opens the main scene (
scenes/HandMain.tscn) with the control and predicted hands, - starts the gRPC control server on
127.0.0.1:50051, - begins resolving its LSL inlets - one per DOF,
named
vhi.prediction.*andvhi.control.pose.*.
You should see a console line like:
See a hand move¶
Out of the box both hands sit at rest - VHI is waiting for input. Two quick ways to get motion:
With the window focused, the control hand responds to:
| Key | Action |
|---|---|
| / | cycle the selected movement (wraps around at both ends) |
| start the movement | |
| stop, return to rest | |
| Space | freeze / unfreeze at the current pose |
Cycling is the keyboard equivalent of a discrete DOF - both pick a movement by
name from the same available_movements list. The programmatic path is a discrete
control, commanded by name (see gRPC control).
Publish the nine vhi.prediction.* streams - one per DOF, one channel each -
and the predicted hand follows them:
A real client publishes only the DOFs it drives; this script publishes all nine so the patterns have a whole hand to animate. See LSL streams for the names.
Command the control hand by name. VHI declares vhi.control.gesture as a
discrete control, so you map a name of your own onto it and select a state:
from myogestic.controls import ControlBus, load_control_map, resolve
from myogestic.remote import RemoteTarget
from myogestic.vhi import virtual_hand
vhi = virtual_hand()
client = vhi.control_client()
controls = resolve(
load_control_map({"dofs": {"gesture": "vhi.control.gesture"}}),
client.capabilities(), # needs VHI running
)
bus = ControlBus(controls, targets=[RemoteTarget(client=client, interface=vhi)])
bus.select("gesture", "Fist") # control hand snaps to the Fist pose
The states come from VHI's own manifest, so "Fist" is a name it reported rather
than one hard-coded here. See
Drive VHI from MyoGestic.
Next steps¶
- Understand the moving parts → Concepts
- Wire it to MyoGestic → Drive VHI from MyoGestic
- Ship a build → Build and export