From 8e68988074cfd3211be3711e117c409184dfb065 Mon Sep 17 00:00:00 2001
From: Naomi Pentrel <5212232+npentrel@users.noreply.github.com>
Date: Mon, 23 Sep 2024 13:02:16 +0200
Subject: [PATCH] Draft: Drive rover and celebrate
---
docs/get-started/drive-rover.md | 1146 ++-----------------------------
1 file changed, 59 insertions(+), 1087 deletions(-)
diff --git a/docs/get-started/drive-rover.md b/docs/get-started/drive-rover.md
index 0cfde46f27..333c24cecf 100644
--- a/docs/get-started/drive-rover.md
+++ b/docs/get-started/drive-rover.md
@@ -32,8 +32,6 @@ date: "2022-12-08"
cost: "0"
---
-If you haven't read through [Learn Viam](/get-started/), we recommend you do so, to get an overview of the Viam platform.
-
This is the first of a few quickstarts which will guide you through the concepts you need to know to get started with Viam.
In this guide you'll write code that makes a rover drive in a square.
@@ -41,6 +39,7 @@ In this guide you'll write code that makes a rover drive in a square.
- How to run SDK code
- How to use the base API to move a rover in a square
+- How to use a vision service to find a color with your rover
{{< /alert >}}
@@ -60,8 +59,6 @@ You only need the following:
Follow these steps to get your rover ready inside the Viam app and write code to control it:
-{{< tabs >}}
-{{% tab name="Borrowed Try Viam Rover" %}}
{{< expand "Step 1: Borrow a Viam Rover" >}}
Go to [Try Viam](https://app.viam.com/try) and borrow a rover.
@@ -72,73 +69,7 @@ If you are running out of time during your session, you can [extend your rover s
{{< /alert >}}
{{< /expand >}}
-
-{{% /tab %}}
-{{% tab name="Other Rover" %}}
-
-{{% alert title="Important" color="note" %}}
-If you are using your own robot for this tutorial instead of [borrowing one](https://app.viam.com/try), be sure to [install `viam-server`](/installation/#install-viam-server) on it and [configure](/tutorials/configure/configure-rover/) its hardware before proceeding with this tutorial.
-{{% /alert %}}
-
-{{% /tab %}}
-{{< /tabs >}}
-
-{{< expand "Step 2: Install an SDK" >}}
-
-Navigate to your machine's **CONNECT** tab.
-Click on any of the listed languages and follow the instructions to install the SDK.
-
-To install your preferred Viam SDK on your Linux or macOS development machine or [single-board computer](/components/board/), run one of the following commands in your terminal:
-
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-If you are using the Python SDK, [set up a virtual environment](/sdks/python/python-venv/) to package the SDK inside before running your code, avoiding conflicts with other projects or your system.
-
-For macOS (both Intel `x86_64` and Apple Silicon) or Linux (`x86`, `aarch64`, `armv6l`), run the following commands:
-
-```sh {class="command-line" data-prompt="$"}
-python3 -m venv .venv
-source .venv/bin/activate
-pip install viam-sdk
-```
-
-Windows is not supported.
-If you are using Windows, use the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) and install the Python SDK using the preceding instructions for Linux.
-For other unsupported systems, see [Installing from source](https://python.viam.dev/#installing-from-source).
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-```sh {class="command-line" data-prompt="$"}
-go get go.viam.com/rdk/robot/client
-```
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-```sh {class="command-line" data-prompt="$"}
-npm install @viamrobotics/sdk
-```
-
-{{% /tab %}}
-{{% tab name="Flutter" %}}
-
-```sh {class="command-line" data-prompt="$"}
-flutter pub add viam_sdk
-```
-
-{{% /tab %}}
-{{% tab name="C++" %}}
-
-Follow the [instructions on the GitHub repository](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/BUILDING.md).
-
-{{% /tab %}}
-
-{{< /tabs >}}
-
-{{< /expand >}}
-{{< expand "Step 3: Copy and run the sample code" >}}
+{{< expand "Step 2: Copy and run the sample code" >}}
The sample code on the **CONNECT** tab will show you how to authenticate and connect to a machine, as well as some of the methods you can use on your configured components and services.
@@ -148,8 +79,6 @@ The sample code on the **CONNECT** tab will show you how to authenticate and con
Go to the **CONNECT** tab and select **Python**.
Save your API key and API key ID as environment variables or include them in the code:
-{{% snippet "show-secret.md" %}}
-
Copy the code into a file called square.py and run the sample code to connect to your machine:
```sh {class="command-line" data-prompt="$"}
@@ -167,173 +96,10 @@ Resources:
```
{{% /tab %}}
-{{% tab name="Go" %}}
-
-Go to the **CONNECT** tab and select **Golang**.
-Save your API key and API key ID as environment variables or include them in the code:
-
-{{% snippet "show-secret.md" %}}
-
-Copy the code into a file called square.go.
-Initialize your project, and install the necessary libraries, and then run the program to verify that the Viam SDK is properly installed and that the `viam-server` instance on your machine is live:
-
-```sh {class="command-line" data-prompt="$"}
-go mod init square
-go mod tidy
-go run square.go
-```
-
-The program prints an array of resources.
-These are the components and services that the machine is configured with in the Viam app.
-
-```sh {class="command-line" data-prompt="$" data-output="2-10"}
-go run square.go
-2024-08-09T11:27:05.034Z DEBUG client.webrtc rpc/wrtc_client.go:111 connecting to signaling server {"signaling_server":"app.viam.com:443","host":"muddy-snow-main.7kp7y4p393.viam.cloud"}
-2024-08-09T11:27:05.314Z DEBUG client.webrtc rpc/wrtc_client.go:125 connected to signaling server {"signaling_server":"app.viam.com:443"}
-...
-2024-08-09T11:27:08.916Z INFO client test-rover/square.go:33 Resources:
-2024-08-09T11:27:08.916Z INFO client test-rover/square.go:34 [rdk:component:board/local rdk:component:base/viam_base rdk:service:motion/builtin rdk:component:motor/right rdk:component:encoder/Renc rdk:component:encoder/Lenc rdk:service:sensors/builtin rdk:component:motor/left rdk:component:camera/cam]
-```
-
-{{% /tab %}}
-{{< tab name="TypeScript" >}}
-
-{{< alert title="Fast track" color="note" >}}
-
-If you want to get the full sample code now, run the following command which will set up the files for you:
-
-```sh {class="command-line" data-prompt="$"}
-npm create robot-app
-```
-
-Then, copy and paste your API key and API key ID, and machine address into the .env file.
-If you have run this command and added your environment variables, skip ahead to running the program.
-
-{{< /alert >}}
-
-Go to the **CONNECT** tab and select **TypeScript**.
-Save your API key and API key ID as environment variables or include them in the code:
-
-{{% snippet "show-secret.md" %}}
-
-Copy the code into a file called main.ts.
-
-Create another file named package.json with the following contents:
-
-```json {class="line-numbers linkable-line-numbers"}
-{
- "name": "test-rover",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "start": "esbuild ./main.ts --bundle --outfile=static/main.js --servedir=static",
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": "Viam Docs Team",
- "license": "ISC",
- "devDependencies": {
- "esbuild": "*"
- },
- "dependencies": {
- "@viamrobotics/sdk": "*"
- }
-}
-```
-
-Create a folder static and inside it another file named index.html.
-Add the following markup:
-
-```html {class="line-numbers linkable-line-numbers"}
-
-
-
- Drive a Rover
-
-
-
-
-
Drive a rover in a square
-
- We recommend you open the developer tools in your browser to see logs.
-
-
- Also open a second window with the
- Viam app and navigate to your rover's
- CONTROL tab, which allows you to interact with your rover's
- resources. Click on one of the camera panels and toggle the camera
- stream on so you can observe the rover's movements.
-
-
-
-
-
-
-```
-
-Run the following commands to install the necessary libraries, and then run the program to verify that the Viam SDK is properly installed and that the `viam-server` instance on your machine is live:
-
-```sh {class="command-line" data-prompt="$"}
-npm install
-npm start
-```
-
-Open a web browser and visit `localhost:8000`.
-You should see a disabled button that says `Click me to drive rover in square`.
-Open the developer console to see the console output.
-If you successfully configured your machine and it is able to connect to the Viam app, you will see some output including the names of your rover's resources.
-These are the components and services that the machine is configured with in the Viam app.
-
-{{< /tab >}}
-{{% tab name="Flutter" %}}
-
-Flutter code must be launched from inside a running Flutter application.
-To get started programming your rover with Flutter, follow the instructions to [Build a Flutter App that Integrates with Viam](/tutorials/control/flutter-app/).
-
-{{% /tab %}}
-{{% tab name="C++" %}}
-
-Go to the **CONNECT** tab and select **C++**.
-Save your API key and API key ID as environment variables or include them in the code:
-
-{{% snippet "show-secret.md" %}}
-
-Copy the code into a file called drive_in_square.cpp.
-
-Compile your code, and then run the program to verify that the Viam SDK is properly installed and that the `viam-server` instance on your machine is live:
-
-```sh {class="command-line" data-prompt="$"}
-cmake . -G Ninja
-ninja all
-./drive_in_square
-```
-
-The program prints an array of resources.
-These are the components and services that the machine is configured with in the Viam app.
-
-```sh {class="command-line" data-prompt="$" data-output="2-20"}
-./src/viam/examples/camera/example_camera
-Resources:
- rdk:component:motor/right
- rdk:component:encoder/Renc
- rdk:component:encoder/Lenc
- rdk:service:sensors/builtin
- rdk:component:motor/left
- rdk:component:camera/cam
- rdk:component:board/local
- rdk:component:base/viam_base
- rdk:service:motion/builtin
- ...
-```
-
-{{% /tab %}}
-
{{< /tabs >}}
{{< /expand >}}
-{{< expand "Step 4: Drive a rover in a square" >}}
+{{< expand "Step 3: Drive a rover in a square" >}}
Now that you have connected the rover to Viam with the SDK, you can write code to move the rover in a square:
@@ -351,15 +117,20 @@ Then paste this snippet above your `main()` function, it will move any base pass
```python
async def moveInSquare(base):
- for _ in range(4):
+ for _ in range(5):
# moves the rover forward 500mm at 500mm/s
- await base.move_straight(velocity=500, distance=500)
+ await base.move_straight(velocity=500)
print("move straight")
- # spins the rover 90 degrees at 100 degrees per second
- await base.spin(velocity=100, angle=90)
+ # spins the rover 90 degrees at 120 degrees per second
+ await base.spins(velocity=100, angle=90)
print("spin 90 degrees")
```
+{{% alert title="Tip" color="tip" %}}
+
+If you are interested to learn about what other commands you can give to a base, see the standardized [base API](/components/base/#api) for a full list of available API methods.
+{{% /alert %}}
+
Next, remove all the code in the `main()` function between where the machine connection is established and closed and instead initialize your `base` and invoke the `moveInSquare()` function.
On the Try Viam rovers, the default base name is `viam_base`.
@@ -373,9 +144,9 @@ async def main():
roverBase = Base.from_robot(machine, 'viam_base')
# Move the rover in a square
- await moveInSquare(roverBase)
+ await moveInASquare("roverBase")
- await machine.close()
+ # await machine.close()
```
If you have a borrowed Try Viam rover, navigate to your machine's **CONTROL** tab, which allows you to interact with your machine's {{< glossary_tooltip term_id="resource" text="resources" >}}.
@@ -388,876 +159,77 @@ Then run your code and watch your rover move in a square.
{{}}
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-The base is responsible for controlling the motors attached to the base of the rover.
-Ensure that the `Base` class is being imported:
-
-```go {class="line-numbers linkable-line-numbers" data-line="3"}
-import (
- // Be sure to keep all of the other imported libraries
- "go.viam.com/rdk/components/base"
-)
-```
-
-Then paste this snippet above your `main()` function, it will move any base passed to it in a square:
-
-```go
-func moveInSquare(ctx context.Context, base base.Base, logger logging.Logger) {
- for i := 0; i < 4; i++ {
- // moves the rover forward 600mm at 500mm/s
- base.MoveStraight(ctx, 600, 500.0, nil)
- logger.Info("move straight")
- // spins the rover 90 degrees at 100 degrees per second
- base.Spin(ctx, 90, 100.0, nil)
- logger.Info("spin 90 degrees")
- }
-}
-```
-
-Next, remove all the code in the `main()` function after the machine connection is established and instead initialize your `base` and invoke the `moveInSquare()` function.
-
-Also remove any unused imports.
-
-On the Try Viam rovers, the default base name is `viam_base`.
-If you have a different base name, update the name in your code.
-
-```go {class="line-numbers linkable-line-numbers" data-line="22-29"}
-func main() {
- logger := logging.NewLogger("client")
- machine, err := client.New(
- context.Background(),
- "ADDRESS FROM THE VIAM APP",
- logger,
- client.WithDialOptions(rpc.WithEntityCredentials(
- /* Replace "" (including brackets) with your machine's api key id */
- "",
- rpc.Credentials{
- Type: rpc.CredentialsTypeAPIKey,
- /* Replace "" (including brackets) with your machine's api key */
- Payload: "",
- })),
- )
- if err != nil {
- logger.Fatal(err)
- }
-
- defer machine.Close(context.Background())
-
- // Get the base from the rover
- roverBase, err := base.FromRobot(machine, "viam_base")
- if err != nil {
- logger.Fatalf("cannot get base: %v", err)
- }
-
- // Move the rover in a square
- moveInSquare(context.Background(), roverBase, logger)
-}
-```
-
-If you have a borrowed Try Viam rover, navigate to your machine's **CONTROL** tab, which allows you to interact with your machine's {{< glossary_tooltip term_id="resource" text="resources" >}}.
-
-Click on one of the camera panels and toggle the camera stream on so you can observe the rover's movements.
-
-Then run your code and watch your rover move in a square.
-
-
-{{}}
-
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-Above the `main` function, add the following function that initializes your rover base client and drives it in a square.
-
-On the Try Viam rovers, the default base name is `viam_base`.
-If you have a different base name, update the name in your code.
-
-```ts {class="line-numbers linkable-line-numbers"}
-// This function moves a base component in a square.
-async function moveInSquare(client: VIAM.RobotClient) {
- // Replace with the name of the base on your machine.
- const name = "viam_base";
- const baseClient = new VIAM.BaseClient(client, name);
-
- try {
- button().disabled = true;
- for (let i = 0; i < 4; i++) {
- console.log("move straight");
- await baseClient.moveStraight(500, 500);
- console.log("spin 90 degrees");
- await baseClient.spin(90, 100);
- }
- } finally {
- button().disabled = false;
- }
-}
-```
-
-Underneath the `moveInSquare` function, add this `button` function which gets the `main-button` button from the page loaded from `index.html`:
-
-```ts {class="line-numbers linkable-line-numbers"}
-// This function gets the button element
-function button() {
- return document.getElementById("main-button");
-}
-```
-
-Next, register a listener on the button you obtain from the `button` function and make it invoke the `moveInSquare` function.
-Place this code after the rover connection code:
-
-```ts {class="line-numbers linkable-line-numbers"}
-button().onclick = async () => {
- await moveInSquare(machine);
-};
-button().disabled = false;
-```
-
-Your main function should now look like this:
-
-```ts {class="line-numbers linkable-line-numbers" data-line="16-19"}
-async function main() {
- const host = "ADDRESS_FROM_VIAM_APP";
-
- const machine = await VIAM.createRobotClient({
- host,
- credential: {
- type: "api-key",
- // Replace "" (including brackets) with your machine's API key
- payload: "",
- },
- // Replace "" (including brackets) with your machine's API key ID
- authEntity: "",
- signalingAddress: "https://app.viam.com:443",
- });
-
- button().onclick = async () => {
- await moveInSquare(machine);
- };
- button().disabled = false;
-}
-```
-
-Save your code and refresh the browser page.
-When the connection to the rover is established, the `Click me to drive rover in square` button will become enabled.
-
-If you have a borrowed Try Viam rover, open a tab and navigate to your machine's **CONTROL** tab, which allows you to interact with your rover's {{< glossary_tooltip term_id="resource" text="resources" >}}.
-
-Click on one of the camera panels and toggle the camera stream on so you can observe the rover's movements.
-
-Go back to the `Click me to drive rover in square` button and click the button to run your code and switch back to the **CONTROL** tab to watch your rover move in a square.
-
-
-{{}}
-
-
-{{% /tab %}}
-{{% tab name="Flutter" %}}
-
-Add a new file to your application in /lib called base_screen.dart.
-Paste this code into your file:
-
-```dart {class="line-numbers linkable-line-numbers"}
-/// This is the BaseScreen, which allows us to control a Base.
-
-import 'package:flutter/material.dart';
-import 'package:viam_sdk/viam_sdk.dart';
-import 'package:viam_sdk/widgets.dart';
-
-class BaseScreen extends StatelessWidget {
- final Base base;
-
- const BaseScreen(this.base, {super.key});
-
- Future moveSquare() async {
- for (var i=0; i<4; i++) {
- await base.moveStraight(500, 500);
- await base.spin(90, 100);
- }
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text(base.name)),
- body: Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- ElevatedButton(
- onPressed: moveSquare,
- child: const Text('Move Base in Square'),
- ),
- ]))
- ,);}}
-```
-
-This code creates a screen with a singular centered button that, when pressed, calls on the `moveSquare()` method to drive the base in a square.
-
-Then, replace the contents of robot_screen.dart with the following file, or add the highlighted lines of code to your program in the locations indicated:
-
-```dart {class="line-numbers linkable-line-numbers" data-line="11, 73-85, 101-102"}
-/// This is the screen that shows the resources available on a robot (or smart machine).
-/// It takes in a Viam app client instance, as well as a robot client.
-/// It then uses the Viam client instance to create a connection to that robot client.
-/// Once the connection is established, you can view the resources available
-/// and send commands to them.
-
-import 'package:flutter/material.dart';
-import 'package:viam_sdk/protos/app/app.dart';
-import 'package:viam_sdk/viam_sdk.dart';
-
-import 'base_screen.dart';
-
-class RobotScreen extends StatefulWidget {
- final Viam _viam;
- final Robot robot;
-
- const RobotScreen(this._viam, this.robot, {super.key});
-
- @override
- State createState() => _RobotScreenState();
-}
-
-class _RobotScreenState extends State {
- /// Similar to previous screens, start with [_isLoading] to true.
- bool _isLoading = true;
-
- /// This is the [RobotClient], which allows you to access
- /// all the resources of a Viam Smart Machine.
- /// This differs from the [Robot] provided to us in the widget constructor
- /// in that the [RobotClient] contains a direct connection to the Smart Machine
- /// and its resources. The [Robot] object simply contains information about
- /// the Smart Machine, but is not actually connected to the machine itself.
- ///
- /// This is initialized late because it requires an asynchronous
- /// network call to establish the connection.
- late RobotClient client;
-
- @override
- void initState() {
- super.initState();
- // Call our own _initState method to initialize our state.
- _initState();
- }
-
- @override
- void dispose() {
- // You should always close the [RobotClient] to free up resources.
- // Calling [RobotClient.close] will clean up any tasks and
- // resources created by Viam.
- if (_isLoading == false) {
- client.close();
- }
- super.dispose();
- }
-
- /// This method will get called when the widget initializes its state.
- /// It exists outside the overridden [initState] function since it's async.
- Future _initState() async {
- // Using the authenticated [Viam] the received as a parameter,
- // the app can obtain a connection to the Robot.
- // There is a helpful convenience method on the [Viam] instance for this.
- final robotClient = await widget._viam.getRobotClient(widget.robot);
- setState(() {
- client = robotClient;
- _isLoading = false;
- });
- }
-
- /// A computed variable that returns the available [ResourceName]s of
- /// this robot in an alphabetically sorted list.
- List get _sortedResourceNames {
- return client.resourceNames..sort((a, b) => a.name.compareTo(b.name));
- }
-
- bool _isNavigable(ResourceName rn) {
- if (rn.subtype == Base.subtype.resourceSubtype) {
- return true;
- }
- return false;
- }
-
- void _navigate(ResourceName rn) {
- if (rn.subtype == Base.subtype.resourceSubtype) {
- final base = Base.fromRobot(client, rn.name);
- Navigator.of(context).push(MaterialPageRoute(builder: (_) => BaseScreen(base)));
- }
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text(widget.robot.name)),
- body: _isLoading
- ? const Center(child: CircularProgressIndicator.adaptive())
- : ListView.builder(
- itemCount: client.resourceNames.length,
- itemBuilder: (_, index) {
- final resourceName = _sortedResourceNames[index];
- return ListTile(
- title: Text(resourceName.name),
- subtitle: Text(
- '${resourceName.namespace}:${resourceName.type}:${resourceName.subtype}'),
- onTap: () => _navigate(resourceName),
- trailing: _isNavigable(resourceName) ? Icon(Icons.chevron_right) : SizedBox.shrink(),
- );
- }));
- }
-}
-```
-
-This imports the base_screen.dart file into the program and adds logic to check if a {{< glossary_tooltip term_id="resource" text="resource" >}} is "navigable", or, has a screen made for it.
-Base is the only resource that is navigable.
-
-To navigate to the base screen, save your code and launch your simulator.
-Navigate to the robot screen of a (live) machine with a base resource configured, and see the resources displayed like the following:
-
-{{}}
-
-Then, click on the base to display the base screen.
-You may need to scroll to the bottom of the list of resources.
-
-{{}}
-
-Click on the button to move your rover in a square:
-
-{{