Add a gantry | Add a component

Add a gantry

Add a gantry to your machine’s configuration so you can control linear positioning along one or more axes from the Viam app and from code.

Concepts

A gantry component controls linear motion along one or more axes. The API provides:

Viam includes two built-in gantry models:

Model What it does
single-axis Controls one linear rail driven by a motor.
multi-axis Composes multiple single-axis gantries into a coordinated system.

The fake built-in model is useful for testing without hardware. Search for gantry in the Viam registry to see available models.

Built-in models

Registry modules

Viam-maintained gantry modules:

Module Gantries supported
viam:generic-gantry Single- and multi-axis gantries with motor control, limit switches, and encoder homing

For gantries not covered above, search for gantry in the Viam registry. Each module’s configuration is documented on its registry page.

Steps

1. Prerequisites

2. Add a gantry component

  1. Click the + button.
  2. Select Blocks.
  3. Search for the gantry model that matches your setup:
    • For a single linear rail driven by a motor, search for single-axis.
    • For a multi-axis system composed of multiple single-axis gantries, search for multi-axis.
  4. Name your gantry (for example, my-gantry) and click Add to machine.

3. Configure gantry attributes

Single-axis gantry:

{
  "motor": "my-motor",
  "length_mm": 500,
  "mm_per_rev": 8
}
Attribute Type Required Description
motor string Yes Name of the motor that drives this axis.
length_mm int Yes Total travel length of the axis in mm.
mm_per_rev int Yes Distance traveled per motor revolution in mm (for example, lead screw pitch).
board string No Board with limit switches, if using them.
limit_pins object No Pin names for limit switches at each end of travel.
gantry_mm_per_sec int No Default speed in mm/s. Defaults to 100.

Multi-axis gantry:

First configure each axis as a separate single-axis gantry, then compose them:

{
  "subaxes_list": ["x-axis", "y-axis", "z-axis"],
  "move_simultaneously": true
}
Attribute Type Required Description
subaxes_list list of strings Yes Names of the single-axis gantry components.
move_simultaneously bool No Whether to move all axes at the same time. Defaults to false.

4. Save and test

Click Save, then expand the Test section.

Try it

Read the gantry’s position and move it along the axis.

To get the credentials for the code below, go to your machine’s page in the Viam app, click the CONNECT tab, and select API keys. Copy the Key and ID. Then click the CONFIGURE tab, and click Details, and copy the Remote address. If you’re using real hardware, you’ll see the gantry move along its axis when you run the code below. With a fake gantry, position values update without physical motion.

Install the Viam Python SDK in a virtual environment by following Install the Python SDK.

Save this as gantry_test.py:

import asyncio
from viam.robot.client import RobotClient
from viam.components.gantry import Gantry

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)

gantry = Gantry.from_robot(robot, "my-gantry")

# Get axis lengths
    lengths = await gantry.get_lengths()
    print(f"Axis lengths (mm): {lengths}")

# Get current position
    position = await gantry.get_position()
    print(f"Current position (mm): {position}")

# Move to 100mm at 50mm/s
    print("Moving to 100mm...")
    await gantry.move_to_position(
        positions=[100.0],
        speeds=[50.0]
    )

# Verify new position
    position = await gantry.get_position()
    print(f"New position (mm): {position}")

await robot.close()

if __name__ == "__main__":
    asyncio.run(main())

Run it:

python gantry_test.py
mkdir gantry-test && cd gantry-test
go mod init gantry-test
go get go.viam.com/rdk

Save this as main.go:

package main

import (
    "context"
    "fmt"

"go.viam.com/rdk/components/gantry"
    "go.viam.com/rdk/logging"
    "go.viam.com/rdk/robot/client"
)

func main() {
    ctx := context.Background()
    logger := logging.NewLogger("gantry-test")

robot, err := client.New(ctx, "YOUR-MACHINE-ADDRESS", logger,
        client.WithDialOptions(client.WithEntityCredentials(
            "YOUR-API-KEY-ID",
            client.Credentials{
                Type:    client.CredentialsTypeAPIKey,
                Payload: "YOUR-API-KEY",
            })),
    )
    if err != nil {
        logger.Fatal(err)
    }
    defer robot.Close(ctx)

g, err := gantry.FromProvider(robot, "my-gantry")
    if err != nil {
        logger.Fatal(err)
    }

// Get axis lengths
    lengths, err := g.Lengths(ctx, nil)
    if err != nil {
        logger.Fatal(err)
    }
    fmt.Printf("Axis lengths (mm): %v\n", lengths)

// Get current position
    position, err := g.Position(ctx, nil)
    if err != nil {
        logger.Fatal(err)
    }
    fmt.Printf("Current position (mm): %v\n", position)

// Move to 100mm at 50mm/s
    fmt.Println("Moving to 100mm...")
    if err := g.MoveToPosition(ctx, []float64{100.0}, []float64{50.0}, nil); err != nil {
        logger.Fatal(err)
    }

// Verify new position
    position, err = g.Position(ctx, nil)
    if err != nil {
        logger.Fatal(err)
    }
    fmt.Printf("New position (mm): %v\n", position)
}

Run it:

go run main.go

Troubleshooting

Gantry doesn't move
Position readings are inaccurate
Homing fails or limit switches don't trigger

If your gantry is not working as expected, follow these steps:

  1. Check your machine logs on the LOGS tab to check for errors.
  2. Review this gantry model’s documentation to ensure you have configured all required attributes.
  3. Click on the TEST panel on the CONFIGURE or CONTROL tab and test if you can use the gantry there.

If none of these steps work, reach out to us on the Community Discord and we will be happy to help.