Previous
Gripper
Add an input controller to your machine’s configuration so you can use a gamepad, joystick, or other input device to control your machine.
An input controller component reads events from human input devices: button presses, joystick axis movements, and trigger pulls. Your code registers callbacks for these events and translates them into machine actions.
| Model | Use case |
|---|---|
gamepad | USB gamepad or joystick. Works with most HID-compatible controllers. |
webgamepad | Browser-based gamepad input in the Viam app’s CONTROL tab. No physical controller needed. |
gpio | Buttons and switches wired to GPIO pins on a board. |
mux | Multiplexes multiple input controllers, allowing one to override another (for example, safety controller overrides gamepad). |
Browse all available input controller models in the Viam registry.
my-gamepad) and click Create.The gamepad model typically needs no attributes. It auto-detects the
connected controller.
If you have multiple controllers, specify which one:
{
"dev_file": "/dev/input/event0"
}
web-controller) and click Create.No attributes needed. The web gamepad appears in the Viam app’s CONTROL tab and works with browser-compatible game controllers or on-screen controls.
{
"board": "my-board",
"buttons": {
"ButtonNorth": "11",
"ButtonSouth": "13"
}
}
Click Save, then expand the TEST section.
List available controls and print events as they happen.
To get the credentials for the code below, go to your machine’s page in the Viam app, click the CONNECT tab, and select SDK code sample. Toggle Include API key on. Copy the machine address, API key, and API key ID from the code sample. When you run the code below, press buttons on your gamepad and watch the events print in real time.
pip install viam-sdk
Save this as input_test.py:
import asyncio
from viam.robot.client import RobotClient
from viam.components.input import Controller, Control, EventType
async def main():
opts = RobotClient.Options.with_api_key(
api_key="YOUR-API-KEY",
api_key_id="YOUR-API-KEY-ID"
)
robot = await RobotClient.at_address("YOUR-MACHINE-ADDRESS", opts)
controller = Controller.from_robot(robot, "my-gamepad")
# List available controls
controls = await controller.get_controls()
print(f"Available controls: {controls}")
# Get current state of all events
events = await controller.get_events()
for control, event in events.items():
print(f" {control}: {event.value}")
# Register a callback for button presses
def handle_press(event):
print(f"Button {event.control} {event.event}: value={event.value}")
controller.register_control_callback(
Control.BUTTON_START,
[EventType.BUTTON_PRESS, EventType.BUTTON_RELEASE],
handle_press,
)
print("\nPress buttons on the gamepad (Ctrl+C to stop)...")
# Keep running to receive callbacks
await asyncio.sleep(30)
await robot.close()
if __name__ == "__main__":
asyncio.run(main())
Run it:
python input_test.py
Press buttons on your gamepad and watch the events print.
mkdir input-test && cd input-test
go mod init input-test
go get go.viam.com/rdk
Save this as main.go:
package main
import (
"context"
"fmt"
"time"
"go.viam.com/rdk/components/input"
"go.viam.com/rdk/logging"
"go.viam.com/rdk/robot/client"
"go.viam.com/rdk/utils"
)
func main() {
ctx := context.Background()
logger := logging.NewLogger("input-test")
robot, err := client.New(ctx, "YOUR-MACHINE-ADDRESS", logger,
client.WithCredentials(utils.Credentials{
Type: utils.CredentialsTypeAPIKey,
Payload: "YOUR-API-KEY",
}),
client.WithAPIKeyID("YOUR-API-KEY-ID"),
)
if err != nil {
logger.Fatal(err)
}
defer robot.Close(ctx)
controller, err := input.FromProvider(robot, "my-gamepad")
if err != nil {
logger.Fatal(err)
}
// List available controls
controls, err := controller.Controls(ctx, nil)
if err != nil {
logger.Fatal(err)
}
fmt.Printf("Available controls: %v\n", controls)
// Get current state
events, err := controller.Events(ctx, nil)
if err != nil {
logger.Fatal(err)
}
for control, event := range events {
fmt.Printf(" %s: %.2f\n", control, event.Value)
}
// Register a callback for the Start button
err = controller.RegisterControlCallback(
ctx,
input.ButtonStart,
[]input.EventType{input.ButtonPress, input.ButtonRelease},
func(ctx context.Context, event input.Event) {
fmt.Printf("Button %s %s: value=%.2f\n",
event.Control, event.Event, event.Value)
},
nil,
)
if err != nil {
logger.Fatal(err)
}
fmt.Println("\nPress buttons on the gamepad (waiting 30s)...")
time.Sleep(30 * time.Second)
}
Run it:
go run main.go
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!