Add a base

Add a base to your machine’s configuration to drive a mobile robot with movement commands like “move forward 300mm” or “spin 90 degrees.” A base wraps your robot’s drive system, whatever the motor layout, into a single interface that handles steering and speed for you.

Concepts

A base component gives you a movement API (MoveStraight, Spin, SetVelocity, Stop) regardless of the underlying drive system. The most common model is wheeled, which handles differential steering for robots with left and right motors. Other models exist for different platforms, including sensor-controlled (adds IMU feedback to improve accuracy) and module-based models for specific hardware.

Browse all available base models in the Viam registry.

This page covers the wheeled model. You configure your motors first, then the base references them.

For accurate distance and angle calculations, the wheeled model needs two physical measurements:

  • Wheel circumference: how far the robot travels per wheel revolution.
  • Track width (width_mm in the config): the distance between the left and right wheel centers. Not the outside edges of the wheels, and not the robot’s overall body width.

Built-in models

  • fake — A model used for testing, with no physical hardware.
  • sensor-controlled — Wrap other base models and add feedback control using a movement sensor.
  • wheeled — Supports mobile wheeled robotic bases with motors on both sides for differential steering.

Micro-RDK:

Registry modules

Viam-maintained base modules:

ModuleBases supported
viam:controlled-componentsSensor-controlled base that adds PID feedback from a movement sensor to another base

For bases not covered above, browse all base modules in the Viam registry.

Steps

1. Prerequisites

  • Your machine is online in the Viam app.
  • Left and right motor components are configured and tested.
  • You’ve measured your wheel circumference and track width in millimeters.

2. Add a base component

  1. Click the + button.
  2. Select Configuration block.
  3. Search for the base model that matches your hardware. For a differential-drive robot with left and right motors, search for wheeled.
  4. Name your base (for example, my-base) and click Create.

3. Configure base attributes

{
  "left": ["left-motor"],
  "right": ["right-motor"],
  "wheel_circumference_mm": 220,
  "width_mm": 300
}
AttributeTypeRequiredDescription
leftlist of stringsYesNames of the motors on the left side.
rightlist of stringsYesNames of the motors on the right side.
wheel_circumference_mmintYesOuter circumference of a drive wheel in mm.
width_mmintYesDistance between left and right wheel centers in mm.
spin_slip_factorfloatNoCorrection factor for turning accuracy. Increase if the robot over-rotates during spins; decrease if it under-rotates.

For robots with multiple motors per side (for example, six-wheel drive), list all motor names for that side:

{
  "left": ["front-left-motor", "mid-left-motor", "rear-left-motor"],
  "right": ["front-right-motor", "mid-right-motor", "rear-right-motor"],
  "wheel_circumference_mm": 220,
  "width_mm": 300
}

4. Save and test

Click Save, then expand the Test section.

  • Use the directional controls to drive the base forward, backward, left, and right.
  • Test MoveStraight with a specific distance to verify distance accuracy.
  • Test Spin with a specific angle to verify turning accuracy.

Try it

Drive the base forward, spin it, and stop.

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 API key and API key ID. Copy the machine address from the Connection details section on the same tab. If you’re using real hardware, you’ll see the robot drive forward and spin when you run the code below. With a fake base, the commands complete without physical motion.

pip install viam-sdk

Save this as base_test.py:

import asyncio
from viam.robot.client import RobotClient
from viam.components.base import Base


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)

    base = Base.from_robot(robot, "my-base")

    # Drive forward 300mm at 200mm/s
    print("Driving forward 300mm...")
    await base.move_straight(distance=300, velocity=200)

    # Spin 90 degrees at 45 degrees/s
    print("Spinning 90 degrees...")
    await base.spin(angle=90, velocity=45)

    # Stop
    await base.stop()
    print("Done")

    await robot.close()

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

Run it:

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

Save this as main.go:

package main

import (
    "context"
    "fmt"

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

func main() {
    ctx := context.Background()
    logger := logging.NewLogger("base-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)

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

    // Drive forward 300mm at 200mm/s
    fmt.Println("Driving forward 300mm...")
    if err := b.MoveStraight(ctx, 300, 200, nil); err != nil {
        logger.Fatal(err)
    }

    // Spin 90 degrees at 45 degrees/s
    fmt.Println("Spinning 90 degrees...")
    if err := b.Spin(ctx, 90, 45, nil); err != nil {
        logger.Fatal(err)
    }

    // Stop
    if err := b.Stop(ctx, nil); err != nil {
        logger.Fatal(err)
    }
    fmt.Println("Done")
}

Run it:

go run main.go

Troubleshooting

Robot drives in the wrong direction
  • Swap the left and right motor lists.
  • Or set dir_flip to true on the individual motors that are reversed.
Robot curves instead of driving straight
  • Verify that both motors spin at similar speeds. Different motors or uneven friction can cause drift.
  • Adding encoders to both motors improves straight-line accuracy.
Turns are inaccurate
  • Measure width_mm carefully. It’s the distance between the wheel contact points, not the outside edges of the wheels.
  • Adjust spin_slip_factor up or down until spins land on the correct angle. This compensates for tire grip and surface friction.
Robot doesn't move at all
  • Test each motor individually from its own test panel. If the motors work alone but the base doesn’t, check that the motor names in the base config match exactly (names are case-sensitive).
  1. Check your machine logs on the LOGS tab to check for errors.
  2. Review this base model’s documentation to ensure you have configured all required attributes.
  3. Review your configuration for any motors that are components of the base. Check that the names of the motor components match the list of motors you configured on the base.
  4. If a motor is spinning in an unexpected direction, try using the dir_flip attribute in its config, or try swapping the wires running to the motor to change its direction.
  5. Check that all wires are securely attached to the correct pins.
  6. If you are using a battery to power the base, check that it is adequately charged. If the motors are drawing more power than the battery can supply, the single-board computer may be power cycling. Consider using a wall power supply for testing purposes to rule out this issue.
  7. Click on the TEST panel on the CONFIGURE or CONTROL tab and test if you can use the base there.

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

Related