Build a Mock Robot
In this tutorial you will build a mock robot to learn how to configure smart machines with Viam. You do not need any hardware to do this tutorial.
Follow this tutorial to set up and control a robot with a fake
arm, board, and motor, and an additional mock sub-part with a motor.
These fake
components interact with Viam like real hardware but do not physically exist.
Set up a mock robot
Install and start viam-server
on your computer
You’ll need the following hardware and software for this tutorial:
- A computer running Linux or macOS
- Go or Python 3.9+
If you don’t already have a Viam account, sign up for one on the Viam app.
Add a new machine in the Viam app.
On the machine’s page, follow the setup instructions to install viam-server
on the computer you’re using for your project.
Wait until your machine has successfully connected to the Viam app.
Configure your mock robot
Configure your mock robot to represent a physical machine with robotic board, arm, and motor hardware.
If you were using physical hardware, this process would provide viam-server
with information about what hardware is attached to it and how to communicate with it.
For this robot, you configure viam-server
to use fake
components that emulate physical hardware.
Navigate to the CONFIGURE tab of your machine’s page in the Viam app.
Configure a fake board component:
- Click the + (Create) icon next to your machine part in the left-hand menu and select Component.
- Select the
board
type, then select thefake
model. - Enter the name
myBoard
for your board and click Create. - Leave the attribute
fail_new
set to false.
Configure a fake arm component:
Click the + (Create) icon next to your machine part in the left-hand menu and select Component.
Select the
arm
type, then select thefake
model.Enter the name
myArm
for your arm and click Create.Make your fake arm act like a UR5e by setting the attribute arm-model to
ur5e
. The config panel should look like this:Click Save in the top right of the window to save your config.
Configure a fake motor component:
- Click the + (Create) icon next to your machine part in the left-hand menu and select Component.
- Select the
motor
type, then select thefake
model. - Enter the name
myMotor
for your motor and click Create. - 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 dropdown.
Click Save.
You will need to reference the component names later when you connect to your mock robot with code.
Control your mock robot using the Viam app
When you add components to your machine, 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 machine.
For example, you can control the direction and speed of your motor, or change the joint positions of your machineic arm. You can also see the machine’s reported positions and speeds change. With real physical components, you would not only be able to control and see your machine’s readings on this tab, but you would also see your machine move in the physical world.
Control your mock robot using a Viam SDK
Install a Viam SDK
Install a Viam SDK (software development kit) so you can write custom logic to control the mock machine. Use the 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 sample code on the CONNECT tab.
Navigate to your machine’s page on the Viam app, select the Code sample page on the CONNECT tab, select your SDK language (this tutorial uses Python or Go), and copy the sample code.
To show your machine’s API key in the sample code, toggle Include API key.
Caution: Keep your API key and machine address safe
We strongly recommend that you add your API key and machine address as an environment variable. Anyone with these secrets can access your machine, and the computer running your machine.
This code snippet imports all the necessary libraries, is pre-populated with your machine cloud credentials, and sets up a connection with the Viam app in the cloud.
Next, paste that sample code into a file named
You can now run the code.
Doing so verifies that the Viam SDK is properly installed, that the viam-server
instance on your machine 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 machine and it is able to connect to the Viam app you should see the program print a list of the various resources that have been configured on your machine in the Viam app:
Control your mock robot
Now, write a program that moves the mock robotic arm to a new random position every second.
First, import the arm component from the Viam Python SDK, and the random library.
At the top of your
from viam.components.arm import Arm, JointPositions
import random
At the top of your
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, initialize your fake robotic arm. In the main function, paste the following. Make sure that the name of your fake arm matches the arm name you configured earlier.
arm = Arm.from_robot(machine, name='myArm')
myArm, err := arm.FromRobot(machine, "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: Arm):
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)
// 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():
machine = await connect()
print('Resources:')
print(machine.resource_names)
arm = Arm.from_robot(machine, 'myArm')
await randomMovement(arm)
await machine.close()
func main() {
// Connect to the machine...
myArm, err := arm.FromRobot(machine, "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.
Verify that your mock robotic arm is working in the CONTROL tab of the Viam app.
Watch the robotic arm’s JointPositions()
changing in real-time along with the code on your development machine.
Configure your machine’s mock sub-part
Now that you have your fake
robotic arm, board, and motor working, add a fake
motor sub-part to your machine.
Imagine for the purpose of this tutorial that the fake
motor we are adding controls a conveyor belt in front of your mock arm on an assembly line.
What is a sub-part?
Usually, when building a machine, you pick out a single-board computer like the Jetson Nano or Raspberry Pi.
You follow the setup instructions to install viam-server
on your board, and you start operating your machine with that computer, adding the components and services you want to use to that viam-server
instance.
By utilizing parts, you can expand upon this, chaining multiple computers together to build a complex robot with Viam:
- Each individual computer-controlled unit of a machine is called a “part” in Viam.
- Typically, simple robots have just one part, but you can have as many parts as your project requires.
- 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.
Add a new sub-part in the Viam app
Navigate to the CONFIGURE tab of your machine’s page on the Viam app.
Click the + (Create) icon next to your main machine part in the left-hand menu and select Sub-part.
Your sub-part will automatically be created with a name like your-machine-name-1
:
Configure your machine’s new sub-part with a fake motor:
Click the + (Create) icon next to your sub-part in the left-hand menu and select Component.
Select the
motor
type, then select thefake
model.Enter the name
motor2
for your motor and click Create:Click Save.
Start a new instance of viam-server
for your mock sub-part
Every sub-part of a machine needs to run an instance of viam-server
.
Since you are using only one computer, you 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 CONFIGURE tab and find the sub-part’s card. Expand the card to view the NETWORK configuration section for the sub-part.
- Click Set bind address.
- In the Host field type
localhost
. - In the Port field type
8081
. - Click Save.
Your NETWORK configuration appears as follows:
Run a second instance of viam-server
for your sub-part
Now, it’s time to run viam-server
on your sub-part.
This instance of viam-server
will work with the main part’s instance of viam-server
as two parts of one machine.
Stay on the CONFIGURE tab.
Click the … (Actions) icon on the right side of the sub-part’s card and select View setup instructions to open the sub-part’s setup instructions.
Select the platform you want to run viam-server
on and follow the instructions until you receive confirmation that your sub-part has connected.
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 machine’s CONTROL tab.
To test that your motor sub-part has been added to your machine, run your Python or Go script again. Review the output of your program that prints the machine’s resources to see your sub-part’s motor’s name listed.
Control a sub-part using the Viam SDK
Now that you have your mock sub-part connected to your main part under your mock robot, you can control all of your sub-part’s components and services with Viam’s SDKs.
In your main function, you need to instantiate your mock sub motor.
Make sure your sub-part’s name and motor’s name matches what you have configured.
This code uses the name SubPart
as a placeholder.
motor = Motor.from_robot(robot=machine, name='SubPart:motor2')
myMotor, err := motor.FromRobot(machine, "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: Motor):
while (True):
await motor.set_power(1)
print("go")
await asyncio.sleep(1)
await motor.stop()
print("stop")
await asyncio.sleep(1)
// 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)
}
}
Now, invoke your new function in main()
.
Comment out invoking randomMovement()
to focus on testing the sub-part.
Your main function should look similar to this snippet:
async def main():
machine = await connect()
print('Resources:')
print(machine.resource_names)
arm = Arm.from_robot(machine, name='myArm')
motor = Motor.from_robot(machine, name='SubPart:motor2')
await toggleMotor(motor)
# await randomMovement(arm)
await machine.close()
func main() {
// Connect to the machine...
myMotor, err := motor.FromRobot(machine, "motor2")
if err != nil {
logger.Fatalf("cannot get motor: %v", err)
}
toggleMotor(context.Background(), myMotor)
myArm, err := arm.FromRobot(machine, "myArm")
if err != nil {
logger.Fatalf("cannot get arm: %v", err)
}
// randomMovement(context.Background(), myArm)
}
Run this code to see your mock sub-part’s 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 following another tutorial.
Have questions, or want to meet other people working on robots? Join our Community Discord.
If you notice any issues with the documentation, feel free to file an issue or edit this file.
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!