Build a Mock Robot
This tutorial will show you how to build a mock robot using just your personal laptop so you can:
Most Viam components have a fake model that you can use for testing. These fake components interact with Viam like real hardware but do not actually exist.
In this tutorial, you will set up, control, and program a mock robotic arm and a mock sub-part with a motor using fake components.
Requirements
You’ll need the following hardware and software for this tutorial:
- A laptop or desktop running Linux or macOS
- Go or Python 3.9+
- A code editor of your choice
Set up a mock robot
Make an account on the Viam app
The first thing you need to do is set up your account on the Viam app. Go to app.viam.com and sign up for a free account.
Configure your mock robot
Now you’ll configure your robot to represent your robot’s hardware. If you were using actual hardware, this file would tell your code what hardware is attached to it and how to communicate with it.
Since this is an imaginary robot, you will use fake
components so that the Viam software (viam-server
) doesn’t try and fail to connect to physical hardware.
Go to app.viam.com.
Create a new robot.
Go to the new robot’s Config tab.
Configure a fake board component:
- Create a new component called
myBoard
with Typeboard
and Modelfake
. Click Create component.
- Create a new component called
Configure a fake arm component:
Create a new component called
myArm
with Typearm
and Modelfake
. Click Create component.Make your fake arm act like a UR5e by adding the following attribute:
{ "arm-model": "ur5e" }
The config panel should look like this:
- Click Save config.
Configure a fake motor component:
- Create a new component called
myMotor
with Typemotor
and Modelfake
. Click Create component. - Most motors are wired to a board which sends them signals.
Even though your motor is fake, make it more realistic by assigning it a
board
. SelectmyBoard
from the board drop-down.
- Create a new component called
Click Save config.
You will need to reference the component names later when you connect to your mock robot with code.
Install and start viam-server
on your computer
Before you proceed with controlling your mock robot, you need to install viam-server
.
Follow the steps outlined on the Setup tab of the Viam app to install viam-server
on your computer and start viam-server
from a terminal window.
Follow the steps outlined on the Setup tab of the Viam app to install viam-server
on your computer.
The Setup tab steps set it up as a system service which means that viam-server
will automatically start every time you boot your computer.
This is convenient if the computer running viam-server
is a dedicated part of a robot, but it is less practical if you are installing viam-server
on your everyday laptop or desktop.
To disable viam-server
from starting automatically on boot, run the following command:
sudo systemctl disable viam-server
Then start viam-server
:
sudo ./viam-server -config /etc/viam.json
Find more information on running viam-server
in the installation guide.
Control your mock robot using the Viam app
When you add components to your robot, the Viam app automatically generates a UI for them under the Control tab.
You can use the Control tab UI to send commands to your robot. For example, you can control the direction and speed of your motor, or change the joint positions of your robotic arm. You can also see the robot’s reported positions and speeds change. With real physical components, you would not only be able to control and see your robot’s readings on this tab, but you would also see your robot move in the physical world.
Next, install a Viam SDK (software development kit) so you can write custom logic to control the mock robot.
Control your mock robot using a Viam SDK
Install a Viam SDK
In this step, you will install either the Viam Python SDK or the Viam Go SDK. Use which ever programming language you are most comfortable with.
Refer to the appropriate SDK documentation for SDK installation instructions:
Connect to your mock robot with your code
The easiest way to get started writing an application with Viam’s SDKs is to use the boilerplate code on the Code Sample tab.
Navigate to your robot’s page on the Viam app, select the Code Sample tab, and select your SDK language (Python or Golang).
Copy the boilerplate code.
This code snippet imports all the necessary libraries, is pre-populated with your robot credentials, and sets up a connection with the Viam app in the cloud.
Next, paste that boilerplate code into a file named
Caution
Do not share your location secret, robot secret, or robot address publicly. Sharing this information compromises your system security by allowing unauthorized access to the computer running your robot.
You can now run the code.
Doing so verifies that the Viam SDK is properly installed, that the viam-server
instance on your robot is live, and that the computer running the program is able to connect to that instance.
Run your code by entering the following in a new terminal on your computer:
python3 index.py
go run index.go
If you successfully configured your robot and it is able to connect to the Viam app you should see something like this printed to the terminal after running your program. What you see here is a list of the various resources that have been configured on your robot in the Viam app.
Control your mock robot
Now it’s time to write code to control and move your mock robotic arm. Through the following steps, you will write a program that moves the mock robotic arm to a new random position every second. You will be able to verify that your mock robotic arm is working by watching its joint positions change in the Control tab of the Viam app while your code runs.
At the top of your
First, import the arm component from the Viam Python SDK, and the random and async.io libraries.
from viam.components.arm import ArmClient, JointPositions
import random
import asyncio
First, import the arm component from the Viam Go SDK, and the random and time libraries.
import (
"fmt"
"math/rand"
"time"
componentpb "go.viam.com/api/component/arm/v1"
"go.viam.com/rdk/components/arm"
)
Next, you need to initialize your fake robotic arm. In the main function, paste the following. Make sure that the name of your fake arm matches the arm named in your config file.
arm = ArmClient.from_robot(robot=robot, name='myArm')
myArm, err := arm.FromRobot(robot, "myArm")
if err != nil {
logger.Fatalf("cannot get arm: %v", err)
}
Now that your mock arm has been initialized, you can write some code to control it.
# Gets a random position for each servo on the arm that is within the safe range of motion of the arm.
# Returns a new array of safe joint positions.
def getRandoms():
return [random.randint(-90, 90),
random.randint(-120, -45),
random.randint(-45, 45),
random.randint(-45, 45),
random.randint(-45, 45)]
# Moves the arm to a new random position every second
async def randomMovement(arm: ArmClient):
while (True):
randomPositions = getRandoms()
newRandomArmJointPositions = JointPositions(values=randomPositions)
await arm.move_to_joint_positions(newRandomArmJointPositions)
print(await arm.get_joint_positions())
await asyncio.sleep(1)
return
// Returns an array of random floats between two numbers
func getRandoms(min, max float64) []float64 {
res := make([]float64, 5)
for i := range res {
res[i] = min + rand.Float64() * (max - min)
}
return res
}
// Moves the arm to a new random position every second
func randomMovement (ctx context.Context, a arm.Arm ) {
for {
randomPositions := getRandoms(-90, 90)
newRandomArmJointPositions := &componentpb.JointPositions{Values: randomPositions}
a.MoveToJointPositions(ctx, newRandomArmJointPositions, nil)
fmt.Println(a.JointPositions(ctx, nil))
time.Sleep(1 * time.Second)
}
}
You can run this code by invoking this function below your arm initialization in main. Your main function should look like this:
async def main():
robot = await connect()
print('Resources:')
print(robot.resource_names)
arm = ArmClient.from_robot(robot=robot, name='myArm')
await randomMovement(arm)
await robot.close()
func main() {
// Connect to the robot...
myArm, err := arm.FromRobot(robot, "myArm")
if err != nil {
logger.Fatalf("cannot get arm: %v", err)
}
randomMovement(context.Background(), myArm)
}
Now when you run this code, you should see the new mock arm positions listed in the command line. Open the Control tab of your mock robot to see the robot’s arm positions changing in real-time along with the code on your development machine.
Create a mock sub-part
Now that you have your mock robotic arm working, add a mock sub-part to your robot.
What is a part?
A robot in Viam consists of one or more computers combined into one logical unit. The bounds of a robot are usually pretty clear, but can be subjective. However, it’s possible with Viam to create a robot that is made up of multiple computers. Each of these computer-controlled units is referred to as a part. Most simple robots will have only one part, but they can have as many parts as needed.
Parts are organized in a tree, with one of them being the main part, and the others being sub-parts.
You can access any sub-part either directly, or through any part above it in the tree.
Each part runs a single viam-server
instance.
Configure a sub-part in the Viam app
You will be creating a mock sub-part to control a motor. This could be anything, but imagine for the purpose of this tutorial that this motor controls a conveyor belt in front of your mock arm on an assembly line.
On your robot’s page on the Viam app, click on the dropdown next to the main part, name your part and click Add new.
Navigate to your new sub-part’s Config tab and create a new motor using the fake model.
Name it "motor2"
.
Click Create component and then Save config.
Start a new instance of viam-server
for your mock sub-part
Every part needs to run an instance of viam-server
.
Typically, a sub-part would represent a separate computer running viam-server
.
For this tutorial since you are using only one computer, you will need to bind the sub-part to a new port so you can run two servers on your machine at the same time.
The following instructions use port 8081
, but you can use any open port you want.
- Go to the Config tab and then go to the Auth/Network subtab.
- Under Network click Add bind address.
- In the Host field type
localhost
. - In the Port field type
8081
. - Click Save config.
Run a second instance of viam-server
for your sub-part
In the upper right corner of the Setup tab, click Copy viam-server config.
On your local machine, create a new file called viam-server
using this configuration.
viam-server -config viam-sub-part.json
Now that you have two instances of viam-server
running on your local machine, you should be able to see both your main robot arm and your new mock sub motor listed on your main robot’s Control tab.
Control a sub-part using the Viam SDK
Now that you have your mock sub-part connected as a remote to your main mock robot, you can control all of your sub-part’s components and services with Viam’s SDKs.
In fact, if you run your Python or Go script again, and you review the output of print(robot.resource_names)
, you will see that your sub-part’s motor will now be listed as an available resource for you to use.
In your main function, you need to instantiate your mock sub motor. Be sure that your motor’s name matches the one that you have listed in your robot’s resource names.
motor = Motor.from_robot(robot=robot, name='SubPart:motor2')
myMotor, err := motor.FromRobot(robot, "motor2")
if err != nil {
logger.Fatalf("cannot get motor: %v", err)
}
Write a function that toggles your sub-part’s motor on and off every second:
# Toggles the motor on and off every second
async def toggleMotor(motor: MotorClient):
while (True):
await motor.set_power(1)
print("go")
await asyncio.sleep(1)
await motor.stop()
print("stop")
await asyncio.sleep(1)
return
// Toggles the motor on and off every second
func toggleMotor (ctx context.Context, m motor.Motor) {
for {
m.SetPower(ctx, 1, nil)
fmt.Println("go")
time.Sleep(1 * time.Second)
m.Stop(ctx, nil)
fmt.Println("stop")
time.Sleep(1 * time.Second)
}
}
And now, you must invoke your new function. Your main function should look similar to this snippet:
async def main():
robot = await connect()
print('Resources:')
print(robot.resource_names)
arm = Arm.from_robot(robot=robot, name='myArm')
motor = Motor.from_robot(robot=robot, name='SubPart:motor2')
await toggleMotor(motor)
# await randomMovement(arm)
await robot.close()
func main() {
// Connect to the robot...
myMotor, err := motor.FromRobot(robot, "motor2")
if err != nil {
logger.Fatalf("cannot get motor: %v", err)
}
toggleMotor(context.Background(), myMotor)
myArm, err := arm.FromRobot(robot, "myArm")
if err != nil {
logger.Fatalf("cannot get arm: %v", err)
}
randomMovement(context.Background(), myArm)
}
When you run this code, you will see your mock sub motor toggling between running and idle in real time from the Viam app!
Next steps
In this tutorial, we showed you how to set up a mock robot with a sub-part so that you can learn more about using fake components, setting up a local development environment, and writing code using a Viam SDK.
If you’re ready to get started with building robots with real hardware components, pick up a board and try building one of Viam’s introductory robots.
You can also ask questions in the Community Discord and we will be happy to help.
Have questions, or want to meet other people working on robots? Join our Community Discord.
Was this page helpful?
Glad to hear it! If there is anything we could be doing better, please create an issue.
We're sorry about that. If you'd like to talk to us for help, please join the Community Discord. To ensure we know what's wrong with this page, you can also open an issue.