Program your Robot with Viam's SDKs

Viam offers software development kits (SDKs) in popular languages which

  • Streamline connection, authentication, and encryption against a server using WebRTC
  • Enable you to interface with robots without calling the viam-server gRPC APIs for robot controls directly

Diagram showing how a client connects to a robot with Viam. Diagram shows a client as a computer sending commands to a robot. Robot 1 then communicates with other robotic parts over gRPC and WebRTC and communicating that information back to the client.

Use the SDK of your preferred language to write code to control your robots.

Viam currently offers SDKs for the following languages:

Click on the links above to read more about installation and usage of each SDK.

Install an SDK

pip install viam-sdk
go install go.viam.com/rdk/robot/client@latest
npm install --save @viamrobotics/sdk

Connect to your robot

The easiest way to get started is to navigate to your robot’s page on the Viam app, select the Code Sample tab, select your preferred SDK, and copy the code generated for you.

These boilerplate code samples import all of the necessary libraries and set up a client connection to your robot whether your code runs on your robot or on a different machine. This connection is established through the Viam app in the cloud.

Your boilerplate code sample should look similar to this:

import asyncio

from viam.robot.client import RobotClient
from viam.rpc.dial import Credentials, DialOptions

async def connect():
    creds = Credentials(
        type='robot-location-secret',
        payload='SECRET FROM THE VIAM APP')
    opts = RobotClient.Options(
        refresh_interval=0,
        dial_options=DialOptions(credentials=creds)
    )
    return await RobotClient.at_address('ADDRESS FROM THE VIAM APP', opts)

async def main():
    robot = await connect()

    print('Resources:')
    print(robot.resource_names)

    await robot.close()

if __name__ == '__main__':
    asyncio.run(main())
package main

import (
  "context"

  "github.com/edaniels/golog"
  "go.viam.com/rdk/robot/client"
  "go.viam.com/rdk/utils"
  "go.viam.com/utils/rpc"
)

func main() {
  logger := golog.NewDevelopmentLogger("client")
  robot, err := client.New(
      context.Background(),
      "ADDRESS FROM THE VIAM APP",
      logger,
      client.WithDialOptions(rpc.WithCredentials(rpc.Credentials{
          Type:    utils.CredentialsTypeRobotLocationSecret,
          Payload: "SECRET FROM THE VIAM APP",
      })),
  )
  if err != nil {
      logger.Fatal(err)
  }
  defer robot.Close(context.Background())
  logger.Info("Resources:")
  logger.Info(robot.ResourceNames())
}
import { Client, createRobotClient, RobotClient } from '@viamrobotics/sdk';

async function connect() {
  // You can remove this block entirely if your robot is not authenticated.
  // Otherwise, replace with an actual secret.
  const secret = '<SECRET>';
  const credential = {
    payload: secret,
    type: 'robot-location-secret',
  };

  // Replace with the host of your actual robot running Viam.
  const host = "<HOST>";

  // Replace with the signaling address. If you are running your robot on Viam,
  // it is most likely https://app.viam.com:443.
  const signalingAddress = 'https://app.viam.com:443';

  const iceServers = [{ urls: 'stun:global.stun.twilio.com:3478' }];

  return createRobotClient({
    host,
    credential,
    authEntity: host,
    signalingAddress,
    iceServers
  });
}

async function main() {
  // Connect to client
  let client: Client;
  try {
    client = await connect();
    console.log('connected!');

    let resources = await client.resourceNames();
    console.log('Resources:');
    console.log(resources);
  } catch (error) {
    console.log(error);
    return;
  }
}

main();
# include <string>
# include <vector>

# include <boost/optional.hpp>

# include <viam/api/common/v1/common.pb.h>
# include <viam/api/robot/v1/robot.grpc.pb.h>

# include <viam/sdk/robot/client.hpp>
# include <viam/sdk/components/camera/client.hpp>

using namespace viam::sdk;

int main() {
  std::string host("ADDRESS FROM THE VIAM APP");
  DialOptions dial_opts;
  Credentials credentials("SECRET FROM THE VIAM APP");
  dial_opts.set_credentials(credentials);
  boost::optional<DialOptions> opts(dial_opts);
  Options options(0, opts);

  auto robot = RobotClient::at_address(host, options);

  std::cout << "Resources:\n";
  for (const ResourceName& resource: *robot->resource_names()) {
    std::cout << resource.namespace_() << ":" << resource.type() << ":"
              << resource.subtype() << ":" << resource.name() << "\n";
  }

  return 0;
}

Add Control Logic

You can add control logic for each component of your robot by using the built-in component methods.

Find documentation on how to use these methods here:

Run Your Code

After saving your boilerplate code sample and adding control logic with Viam’s API methods, run your program to control your Viam-connected robot.

For example:

python3 ~/myCode/myViamFile.py
go run ~/myCode/myViamFile.py

For an example, see this execution demo.

For information on running C++ code see here.

Run Code Locally

If you need to run PID control loops or other on-robot code, you can run control code on the same board that is running viam-server.

To ensure intermittent internet connectivity does not interfere with the code’s execution, there are some special steps you need to follow:

  1. Change the connect() method to disable WebRTC and add the auth_entity in the DialOptions and use localhost:8080:

    async def connect():
      creds = Credentials(type='robot-location-secret', payload=PAYLOAD_SECRET)
      opts = RobotClient.Options(
        refresh_interval=0,
        dial_options=DialOptions(
            credentials=creds,
            disable_webrtc=True,
            auth_entity=ROBOT_NAME
        )
      )
      return await RobotClient.at_address('localhost:8080', opts)
    
  2. Replace the ROBOT_NAME with your robot’s Viam cloud address and the PAYLOAD_SECRET with your robot secret. Your localhost can now make a secure connection to viam-server locally. SSL will now check the server hostname against the auth_entity required by gRPC from the auth_entity dial options.

    This ensures that you can send commands to the robot through localhost without internet connectivity. Note that all commands will be sent using gRPC only without WebRTC.

Next Steps