diff --git a/docs/build-apps/concepts/how-apps-connect.md b/docs/build-apps/concepts/how-apps-connect.md index 21340d39eb..4e36a1c719 100644 --- a/docs/build-apps/concepts/how-apps-connect.md +++ b/docs/build-apps/concepts/how-apps-connect.md @@ -6,6 +6,8 @@ layout: "docs" type: "docs" description: "The transport paths the SDK uses, the session safety mechanism, and what the SDK reconnects automatically." date: "2026-04-10" +aliases: + - /operate/reference/sessions/ --- A Viam client application needs to reach a machine that may be on a different network, behind a NAT, or both. This page describes the transport paths the SDK uses, the session safety mechanism, and how the SDK reconnects when the network drops. diff --git a/docs/build-apps/overview.md b/docs/build-apps/overview.md index f0349089ed..2b21293dd2 100644 --- a/docs/build-apps/overview.md +++ b/docs/build-apps/overview.md @@ -7,6 +7,7 @@ type: "docs" description: "Build software that uses a Viam SDK to talk to your machines and the Viam cloud, from web dashboards to long-running backend services." date: "2026-04-10" aliases: + - /operate/control/ - /operate/control/headless-app/ - /product-overviews/sdk-as-client/ - /program/sdk-as-client/ diff --git a/docs/build-modules/advanced-patterns.md b/docs/build-modules/advanced-patterns.md new file mode 100644 index 0000000000..c623191a28 --- /dev/null +++ b/docs/build-modules/advanced-patterns.md @@ -0,0 +1,175 @@ +--- +linkTitle: "Advanced patterns" +title: "Advanced module patterns" +weight: 38 +layout: "docs" +type: "docs" +description: "Define new resource APIs, deploy custom components as remote parts, and package modules with Docker." +date: "2026-04-20" +aliases: + - /operate/reference/advanced-modules/ + - /operate/reference/advanced-modules/create-subtype/ + - /operate/reference/advanced-modules/custom-components-remotes/ + - /operate/reference/advanced-modules/docker-modules/ + - /program/extend/ + - /modular-resources/advanced/ + - /registry/advanced/ + - /extend/modular-resources/create/create-subtype/ + - /modular-resources/advanced/create-subtype/ + - /registry/advanced/create-subtype/ + - /program/extend/sdk-as-server/ + - /program/extend/custom-components-remotes/ + - /extend/custom-components-remotes/ + - /modular-resources/advanced/custom-components-remotes/ + - /registry/advanced/custom-components-remotes/ +--- + +Some use cases require approaches beyond the standard module workflow. This page covers three advanced patterns: defining a new resource API, deploying custom components as remote parts, and packaging modules with Docker. + +## Define a new resource API + +You can define a new, custom resource API if: + +- You have a resource that does not fit into any of the existing [component](/reference/apis/#component-apis) or [service](/reference/apis/#service-apis) APIs. +- You have a resource that could fit into an existing API, but you want different methods and messages. + +{{% alert title="Tip" color="tip" %}} + +Defining a new resource API is significantly more complex than using an existing API. In most cases, use an existing API instead. + +If you want to use most of an existing API but need a few additional functions, use the `DoCommand` endpoint with [extra parameters](/reference/sdks/use-extra-params/) to add custom functionality. + +If your use case uses only `DoCommand` and no other API methods, define a new model of [generic component](/reference/components/generic/) or [generic service](/reference/services/generic/). + +{{% /alert %}} + +### Steps to define a new API + +Viam uses [protocol buffers](https://protobuf.dev/) for API definition. To define a new API: + +1. Decide whether your custom API is a component (interfaces with hardware) or a service (provides higher-level functionality). + +2. Choose a name for your API (called the subtype). Determine a valid API namespace triplet. For example, `your-org-namespace:component:gizmo`. + +3. Create a directory for your module with a `src` subdirectory. + + {{% alert title="Tip" color="tip" %}} + If you are writing your module in Python, you can use this [module generator tool](https://github.com/viam-labs/generator-viam-module) to generate stub files for the new API and a module that implements it. + {{% /alert %}} + +4. Write the proto methods in a `.proto` file inside `src/proto/`. For reference: + + - [Example modular component proto file](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/proto/gizmo.proto) + - [Example modular service proto file](https://github.com/viam-labs/speech-service-api/blob/main/src/proto/speech.proto) + - [Built-in Viam resource proto files](https://github.com/viamrobotics/api/tree/main/proto/viam) + +5. Define the proto methods in Python or Go in a file called `api.py` or `api.go`: + + - [Example component in Python](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/gizmo/api.py) + - [Example service in Python](https://github.com/viam-labs/speech-service-api/blob/main/src/speech_service_api/api.py) + +6. Generate the required configuration files (`buf.yaml`, `buf.gen.yaml`, `buf.lock`). See the [Buf documentation](https://buf.build/docs/generate/usage/). + +7. Use the protobuf compiler to [generate](https://buf.build/docs/tutorials/getting-started-with-buf-cli/#generate-code) all other necessary protocol buffer code from your `.proto` file. + +### After defining your API + +Once your API is defined, [create a model that implements it](/build-modules/write-a-driver-module/). + +Keep in mind: + +- You cannot use [SDKs](/reference/sdks/) to call your new API unless you build out the client to support it. Write code against the API in the language you used to define it. +- You need a local copy of the module code on whatever machine runs client code against it. +- Import the API definition from the module directory. For example, in Python: `from path.to.module.src.gizmo import Gizmo`. + +## Custom components as remote parts + +Running modular resources on the computer directly connected to your components is the preferred approach. However, if you cannot use modular resources because you need to host `viam-server` on a non-Linux system or have a compilation issue, you can code a custom resource implementation, host it on a server, and add it as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine. + +Once configured, you control the custom component with the Viam SDKs like any other component. + +### Steps + +{{< tabs >}} +{{% tab name="Go" %}} + +1. Code a new model of a built-in resource type by creating a new interface that implements the required methods from its [API definition](/reference/apis/). +2. Register the custom component on a new gRPC server instance and start the server. +3. Add the server as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine. +4. (Optional) Ensure the remote server automatically starts when the machine boots. + +Each remote server can host one or many custom components. + +{{% /tab %}} +{{% tab name="Python" %}} + +{{< alert title="Tip" color="tip" >}} +For detailed instructions, see the full example in the [Python SDK documentation](https://python.viam.dev/examples/example.html#subclass-a-component). +{{< /alert >}} + +1. Code a new model of a built-in resource type by subclassing it (for example, `sensor` or `arm`). Implement any required methods from its [API definition](/reference/apis/). +2. Register the custom component on a new gRPC server instance using the [`viam.rpc` library](https://python.viam.dev/autoapi/viam/rpc/index.html). +3. Add the server as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine. +4. (Optional) Ensure the remote server automatically starts when the machine boots. + +Each remote server can host one or many custom components. + +{{% /tab %}} +{{< /tabs >}} + +{{% alert title="Important" color="note" %}} + +You must define all methods belonging to a built-in resource type when defining a new model. Otherwise, the class will not instantiate. + +- In Python, raise `NotImplementedError()` or use `pass` in methods you do not want to implement. +- In Go, return `errUnimplemented`. + +{{% /alert %}} + +## Deploy a module using Docker + +In rare cases, you may need to package and deploy a module using Docker. Use cases include: + +- Your module has complex system dependencies that cannot be easily installed on a machine. +- You use a large container image and some layers are already cached on the machine. +- You have specific security requirements. + +If you deploy using Docker, create a "first run" script to handle setup. This is not recommended for modules that do not use Docker. + +### Use a `first_run` script + +1. Create a tarball containing: + + - The module's entrypoint script or binary: + + ```sh {class="command-line" data-prompt="$"} + #!/bin/bash + exec docker run + ``` + + - A [meta.json](/build-modules/module-reference/#metajson-schema) file. + + - A first-run script that runs during setup: + + ```sh {class="command-line" data-prompt="$"} + #!/usr/bin/env bash + docker pull mongo:6 + echo "Setup complete." + exit 0 + ``` + + [This example Makefile](https://github.com/viam-labs/wifi-sensor/blob/7823b6ad3edcbbbf20b06c34b3181453f5f3f078/Makefile) builds a module binary and bundles it with a meta.json and first-run script. + +2. Edit meta.json to include the `first_run` field: + + ```json + { + "first_run": "first_run.sh" + } + ``` + +3. Configure the module on your machine normally. The first-run script executes once when `viam-server` receives a new configuration, and once per version update. + +4. (Optional) To force the first-run script to run again without changing the module version, delete the marker file at `.viam/packages/data/module//bin.first_run_succeeded`. + +5. (Optional) The default first-run timeout is 1 hour. Adjust with `"first_run_timeout": "5m"` in the module configuration. diff --git a/docs/build-modules/deploy-a-module.md b/docs/build-modules/deploy-a-module.md index 0aa5c7c3b3..31b8503020 100644 --- a/docs/build-modules/deploy-a-module.md +++ b/docs/build-modules/deploy-a-module.md @@ -7,6 +7,7 @@ type: "docs" description: "Package, upload, and distribute a module through the Viam registry." date: "2025-01-30" aliases: + - /operate/modules/deploy-a-module/ - /build/development/deploy-a-module/ - /development/deploy-a-module/ - /extend/modular-resources/upload/ diff --git a/docs/build-modules/manage-modules.md b/docs/build-modules/manage-modules.md index d13e9d127a..5f3efbdf00 100644 --- a/docs/build-modules/manage-modules.md +++ b/docs/build-modules/manage-modules.md @@ -8,6 +8,7 @@ icon: true tags: ["modular resources", "components", "services", "registry"] description: "Update or delete your existing modules, or change their privacy settings." aliases: + - /operate/modules/advanced/manage-modules/ - /use-cases/deploy-code/ - /use-cases/manage-modules/ - /how-tos/manage-modules/ diff --git a/docs/build-modules/module-reference.md b/docs/build-modules/module-reference.md index 89d6867f57..31bd9bc895 100644 --- a/docs/build-modules/module-reference.md +++ b/docs/build-modules/module-reference.md @@ -7,6 +7,9 @@ type: "docs" description: "Reference for module developers: lifecycle, interfaces, meta.json schema, CLI commands, environment variables, and registry rules." date: "2025-03-05" aliases: + - /operate/modules/advanced/logging/ + - /operate/modules/advanced/metajson/ + - /operate/modules/advanced/module-configuration/ - /development/module-reference/ - /operate/modules/lifecycle-module/ - /operate/modules/lifecycle-of-a-module/ @@ -17,6 +20,14 @@ This page is a reference for module developers. For step-by-step instructions, see [Write a Module](/build-modules/write-a-driver-module/) and [Deploy a Module](/build-modules/deploy-a-module/). +## Module configuration {#module-configuration} + +For details on configuring modules and modular resources on a machine: + +- [Environment variables](#environment-variables) — custom env vars passed to your module +- [Registry validation rules](#registry-validation-rules) — valid API and model identifier formats +- [meta.json schema](#metajson-schema) — module metadata including visibility settings + ## Module lifecycle Every module, local or registry, runs as a separate child process alongside diff --git a/docs/build-modules/overview.md b/docs/build-modules/overview.md index ca9b4c71fe..bda49d4b44 100644 --- a/docs/build-modules/overview.md +++ b/docs/build-modules/overview.md @@ -6,6 +6,8 @@ layout: "docs" type: "docs" description: "Understand the two kinds of modules and how to extend your machine with custom hardware drivers and application logic." aliases: + - /operate/modules/ + - /operate/modules/advanced/ - /build-modules/from-hardware-to-logic/ --- diff --git a/docs/build-modules/platform-apis.md b/docs/build-modules/platform-apis.md index 76a04e5643..a26f723f34 100644 --- a/docs/build-modules/platform-apis.md +++ b/docs/build-modules/platform-apis.md @@ -6,6 +6,7 @@ layout: "docs" type: "docs" description: "Write your validate and reconfigure functions to handle dependencies in your custom modular resource." aliases: + - /operate/modules/advanced/platform-apis/ date: "2025-11-05" --- diff --git a/docs/build-modules/use-registry-modules.md b/docs/build-modules/use-registry-modules.md index 5555a8bb84..fe5399db85 100644 --- a/docs/build-modules/use-registry-modules.md +++ b/docs/build-modules/use-registry-modules.md @@ -6,6 +6,8 @@ layout: "docs" type: "docs" description: "Before writing a module, check whether one already exists. The registry has more than hardware drivers." date: "2026-04-17" +aliases: + - /registry/ --- Before you write a module, check whether one already exists. The Viam registry contains more than hardware drivers. Many software capabilities you might want to build are already published as modules you can configure and use directly. diff --git a/docs/build-modules/write-a-cpp-module.md b/docs/build-modules/write-a-cpp-module.md index 4dfe684bb5..0b310ba439 100644 --- a/docs/build-modules/write-a-cpp-module.md +++ b/docs/build-modules/write-a-cpp-module.md @@ -61,7 +61,7 @@ For example, the [sensor API](/reference/apis/components/sensor/) has a `GetRead If instead of just getting readings, you actually have an encoder and need to be able to reset the zero position, use the [encoder API](/reference/apis/components/encoder/) so you can define functionality behind the `GetPosition` and `ResetPosition` methods. In addition to the list of methods, another reason to choose one API over another is how certain APIs fit into the Viam ecosystem. -For example, though you could technically implement a GPS as a sensor with just the `GetReadings` method, if you implement it as a movement sensor then you have access to methods like `GetCompassHeading` which allow you to use your GPS module with the [navigation service](/operate/reference/services/navigation/). +For example, though you could technically implement a GPS as a sensor with just the `GetReadings` method, if you implement it as a movement sensor then you have access to methods like `GetCompassHeading` which allow you to use your GPS module with the [navigation service](/reference/services/navigation/). For this reason, it's generally best to choose the API that most closely matches your hardware or software. {{< /expand >}} diff --git a/docs/build-modules/write-a-driver-module.md b/docs/build-modules/write-a-driver-module.md index 91d8004460..7eaf692b56 100644 --- a/docs/build-modules/write-a-driver-module.md +++ b/docs/build-modules/write-a-driver-module.md @@ -7,6 +7,7 @@ type: "docs" description: "Build a module that implements a resource API and runs as a separate process." date: "2025-01-30" aliases: + - /operate/modules/write-a-driver-module/ - /build/development/write-a-module/ - /development/write-a-module/ - /development/write-a-driver-module/ diff --git a/docs/hardware/common-components/add-a-base.md b/docs/hardware/common-components/add-a-base.md index 084e84c690..3793edb89b 100644 --- a/docs/hardware/common-components/add-a-base.md +++ b/docs/hardware/common-components/add-a-base.md @@ -7,6 +7,8 @@ type: "docs" description: "Add and configure a base to drive a mobile robot with movement commands." date: "2025-03-07" aliases: + - /operate/reference/components/base/ + - /operate/reference/components/base/boat/ - /hardware-components/add-a-base/ --- diff --git a/docs/hardware/common-components/add-a-board.md b/docs/hardware/common-components/add-a-board.md index f676b2dd4c..33c48f3c2f 100644 --- a/docs/hardware/common-components/add-a-board.md +++ b/docs/hardware/common-components/add-a-board.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a board component to expose GPIO pins, analog readers, and digital interrupts." date: "2025-03-07" aliases: + - /operate/reference/components/board/ - /hardware-components/add-a-board/ --- diff --git a/docs/hardware/common-components/add-a-button.md b/docs/hardware/common-components/add-a-button.md index 73f2930202..41996c815e 100644 --- a/docs/hardware/common-components/add-a-button.md +++ b/docs/hardware/common-components/add-a-button.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a button component to detect presses from a physical button." date: "2025-03-07" aliases: + - /operate/reference/components/button/ - /hardware-components/add-a-button/ --- diff --git a/docs/hardware/common-components/add-a-camera.md b/docs/hardware/common-components/add-a-camera.md index cb3d39bb79..a61af3a261 100644 --- a/docs/hardware/common-components/add-a-camera.md +++ b/docs/hardware/common-components/add-a-camera.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a camera component, verify the feed, and capture an image programmatically." date: "2025-01-30" aliases: + - /operate/reference/components/camera/ - /build/foundation/add-a-camera/ - /foundation/add-a-camera/ - /hardware-components/add-a-camera/ @@ -332,6 +333,10 @@ Camera streams use a significant amount of CPU resources. The more CPU resources {{< /expand >}} +## Camera calibration + +If you are using a camera with the motion service for arm movement or pick-and-place, you may need to calibrate it. Calibration computes the camera's intrinsic and distortion parameters so the motion service can project 2D image coordinates into 3D workspace coordinates accurately. See [Calibrate a camera for motion planning](/motion-planning/frame-system/camera-calibration/). + ## Related - [Camera API reference](/reference/apis/components/camera/): full method documentation. diff --git a/docs/hardware/common-components/add-a-gantry.md b/docs/hardware/common-components/add-a-gantry.md index deafcaa0ab..4b757960ae 100644 --- a/docs/hardware/common-components/add-a-gantry.md +++ b/docs/hardware/common-components/add-a-gantry.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a gantry component for precise linear positioning along one or more axes." date: "2025-03-07" aliases: + - /operate/reference/components/gantry/ - /hardware-components/add-a-gantry/ --- diff --git a/docs/hardware/common-components/add-a-generic.md b/docs/hardware/common-components/add-a-generic.md index 4273ecf4c2..ad2c95bc6b 100644 --- a/docs/hardware/common-components/add-a-generic.md +++ b/docs/hardware/common-components/add-a-generic.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a generic component for hardware that doesn't fit any other component type." date: "2025-03-07" aliases: + - /operate/reference/components/generic/ - /hardware-components/add-a-generic/ --- diff --git a/docs/hardware/common-components/add-a-gripper.md b/docs/hardware/common-components/add-a-gripper.md index a212ac17b7..21144699fb 100644 --- a/docs/hardware/common-components/add-a-gripper.md +++ b/docs/hardware/common-components/add-a-gripper.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a gripper component to open, close, and grasp objects." date: "2025-03-07" aliases: + - /operate/reference/components/gripper/ - /hardware-components/add-a-gripper/ --- diff --git a/docs/hardware/common-components/add-a-motor.md b/docs/hardware/common-components/add-a-motor.md index 4e1c736a50..1ee617340f 100644 --- a/docs/hardware/common-components/add-a-motor.md +++ b/docs/hardware/common-components/add-a-motor.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a motor component and test it from the Viam app." date: "2025-03-07" aliases: + - /operate/reference/components/motor/ - /hardware-components/add-a-motor/ --- diff --git a/docs/hardware/common-components/add-a-movement-sensor.md b/docs/hardware/common-components/add-a-movement-sensor.md index 3d0867f3d0..5a930caee0 100644 --- a/docs/hardware/common-components/add-a-movement-sensor.md +++ b/docs/hardware/common-components/add-a-movement-sensor.md @@ -7,6 +7,8 @@ type: "docs" description: "Add and configure a movement sensor like a GPS, IMU, or odometry source." date: "2025-03-07" aliases: + - /operate/reference/components/movement-sensor/ + - /operate/reference/components/movement-sensor/set-up-base-station/ - /hardware-components/add-a-movement-sensor/ --- diff --git a/docs/hardware/common-components/add-a-power-sensor.md b/docs/hardware/common-components/add-a-power-sensor.md index df1219b740..ae1e090933 100644 --- a/docs/hardware/common-components/add-a-power-sensor.md +++ b/docs/hardware/common-components/add-a-power-sensor.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a power sensor to monitor voltage, current, and power consumption." date: "2025-03-07" aliases: + - /operate/reference/components/power-sensor/ - /hardware-components/add-a-power-sensor/ --- diff --git a/docs/hardware/common-components/add-a-sensor.md b/docs/hardware/common-components/add-a-sensor.md index 75c64af9f2..fcc5c1983f 100644 --- a/docs/hardware/common-components/add-a-sensor.md +++ b/docs/hardware/common-components/add-a-sensor.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a sensor to read environmental data like temperature, humidity, or distance." date: "2025-03-07" aliases: + - /operate/reference/components/sensor/ - /hardware-components/add-a-sensor/ --- diff --git a/docs/hardware/common-components/add-a-switch.md b/docs/hardware/common-components/add-a-switch.md index 04ecddb97d..86578dbb5b 100644 --- a/docs/hardware/common-components/add-a-switch.md +++ b/docs/hardware/common-components/add-a-switch.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a switch component to read and set the position of a multi-position switch." date: "2025-03-07" aliases: + - /operate/reference/components/switch/ - /hardware-components/add-a-switch/ --- diff --git a/docs/hardware/common-components/add-an-arm.md b/docs/hardware/common-components/add-an-arm.md index 2ece18425e..a3a29ccc1c 100644 --- a/docs/hardware/common-components/add-an-arm.md +++ b/docs/hardware/common-components/add-an-arm.md @@ -7,6 +7,9 @@ type: "docs" description: "Add and configure a robotic arm, verify joint motion, and test end-effector positioning." date: "2025-03-07" aliases: + - /operate/reference/components/arm/ + - /operate/reference/components/arm/eva/ + - /operate/reference/components/arm/yahboom-dofbot/ - /hardware-components/add-an-arm/ --- diff --git a/docs/hardware/common-components/add-an-encoder.md b/docs/hardware/common-components/add-an-encoder.md index d7e37a1e9f..d357cde70a 100644 --- a/docs/hardware/common-components/add-an-encoder.md +++ b/docs/hardware/common-components/add-an-encoder.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure an encoder to track motor position and direction." date: "2025-03-07" aliases: + - /operate/reference/components/encoder/ - /hardware-components/add-an-encoder/ --- diff --git a/docs/hardware/common-components/add-an-input-controller.md b/docs/hardware/common-components/add-an-input-controller.md index ddc874763f..fa70452901 100644 --- a/docs/hardware/common-components/add-an-input-controller.md +++ b/docs/hardware/common-components/add-an-input-controller.md @@ -7,6 +7,7 @@ type: "docs" description: "Add and configure a gamepad, joystick, or other input device for manual machine control." date: "2025-03-07" aliases: + - /operate/reference/components/input-controller/ - /hardware-components/add-an-input-controller/ --- diff --git a/docs/hardware/configure-hardware.md b/docs/hardware/configure-hardware.md index e3c8bf8742..bc03007dcc 100644 --- a/docs/hardware/configure-hardware.md +++ b/docs/hardware/configure-hardware.md @@ -7,6 +7,17 @@ type: "docs" description: "Understand how Viam represents hardware, add components to your machine, and configure them." date: "2025-03-07" aliases: + - /program/extend/modular-resources/configure/ + - /extend/modular-resources/configure/ + - /modular-resources/configure/ + - /registry/configure/ + - /registry/modular-resources/ + - /configure/ + - /manage/configuration/ + - /build/configure/ + - /registry/program/extend/modular-resources/configure/ + - /how-tos/use-cases/configure/ + - /use-cases/configure/ - /hardware-components/add-a-component/ - /hardware/add-a-component/ - /operate/modules/configure-modules/ @@ -58,7 +69,7 @@ If no model exists for your hardware, you can [write your own module](/build-mod -Browse all available components and services in the [Viam registry](https://app.viam.com/registry). +Browse all available components and services in the [Viam registry](https://app.viam.com/registry). The registry also contains software modules that add capabilities beyond hardware drivers: vision and ML services, conversational and audio processing, device discovery, custom logic, and external integrations. ## Switching hardware without changing code diff --git a/docs/hardware/multi-machine/overview.md b/docs/hardware/multi-machine/overview.md index 6a98116615..88cf7df628 100644 --- a/docs/hardware/multi-machine/overview.md +++ b/docs/hardware/multi-machine/overview.md @@ -7,6 +7,13 @@ type: "docs" description: "Connect multiple computers so one machine can access another's components and services." date: "2026-04-16" aliases: + - /manage/parts-and-remotes/ + - /build/configure/parts-and-remotes/ + - /configure/parts/ + - /build/configure/parts/ + - /architecture/parts/ + - /operate/reference/architecture/ + - /operate/reference/architecture/machine-to-machine-comms/ - /operate/reference/architecture/parts/ --- diff --git a/docs/motion-planning/frame-system/camera-calibration.md b/docs/motion-planning/frame-system/camera-calibration.md index a9e8da0122..23e741ab1a 100644 --- a/docs/motion-planning/frame-system/camera-calibration.md +++ b/docs/motion-planning/frame-system/camera-calibration.md @@ -9,6 +9,7 @@ aliases: - /work-cell-layout/calibrate-camera-to-robot/ - /build/work-cell-layout/calibrate-camera-to-robot/ - /motion-planning/camera-calibration/ + - /operate/reference/components/camera/calibrate/ --- Configuring a camera's frame tells the motion service where the camera diff --git a/docs/motion-planning/frame-system/overview.md b/docs/motion-planning/frame-system/overview.md index 821cc5d8cc..913f09a2aa 100644 --- a/docs/motion-planning/frame-system/overview.md +++ b/docs/motion-planning/frame-system/overview.md @@ -6,6 +6,7 @@ layout: "docs" type: "docs" description: "Build a unified coordinate tree so all components agree on where things are in physical space." aliases: + - /operate/reference/kinematic-chain-config/ - /work-cell-layout/define-your-frame-system/ - /build/work-cell-layout/define-your-frame-system/ - /operate/mobility/move-arm/frame-how-to/ diff --git a/docs/operate/_index.md b/docs/operate/_index.md deleted file mode 100644 index 358d33009e..0000000000 --- a/docs/operate/_index.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -linkTitle: "Build and Integrate" -title: "Build and Integrate" -weight: 150 -layout: "docs" -toc_hide: true -type: "docs" -no_list: true -noedit: true -open_on_desktop: true -overview: true -description: "Install Viam on any device and integrate your hardware. Then you can control your device and attached physical hardware securely from anywhere in the world." -notoc: true -aliases: - - /build/ - - /operate/mobility/use-input-to-act/ ---- - -To get started, install Viam on any device and integrate your hardware. Then you can control your device and any attached physical hardware securely from anywhere in the world. - - -
- Platform diagram - Platform diagram with connect elements highlighted - Platform diagram with apps element highlighted - Platform diagram with motion elements highlighted -
- -
- -{{< how-to-expand "Learn Viam & Installation" "4" "BEGINNER-FRIENDLY" "" "build-platform-connect" >}} -{{< cards >}} -{{% card link="/operate/hello-world/what-is-viam/" noimage="true" %}} -{{% card link="/operate/hello-world/tutorial-desk-safari/" noimage="true" %}} -{{% card link="/operate/install/setup/" noimage="true" %}} -{{% card link="/operate/hello-world/building/" noimage="true" %}} - -{{< /cards >}} -{{< /how-to-expand >}} - -{{< how-to-expand "Modules" "3" "BEGINNER-FRIENDLY" "" "build-platform-connect" >}} -{{< cards >}} -{{% card link="/operate/modules/configure-modules/" noimage="true" %}} -{{% card link="/operate/modules/write-a-driver-module/" noimage="true" %}} -{{% card link="/operate/modules/write-a-logic-module/" noimage="true" %}} -{{< /cards >}} -{{< /how-to-expand >}} - -{{< how-to-expand "Build apps" "4" "BEGINNER-FRIENDLY" "" "build-platform-apps" >}} -{{< cards >}} -{{% card link="/operate/control/viam-applications/" noimage="true" %}} -{{% card link="/operate/control/web-app/" noimage="true" %}} -{{% card link="/operate/control/mobile-app/" noimage="true" %}} -{{% card link="/operate/control/headless-app/" noimage="true" %}} -{{< /cards >}} -{{< /how-to-expand >}} - -{{< how-to-expand "Intelligent actuation and motion planning" "4" "INTERMEDIATE" "" "build-platform-motion" >}} -{{< cards >}} -{{% card link="/motion-planning/" noimage="true" %}} -{{% card link="/motion-planning/move-an-arm/move-to-pose/" noimage="true" %}} -{{% card link="/navigation/how-to/drive-a-base/" noimage="true" %}} -{{% card link="/motion-planning/move-gantry/" noimage="true" %}} -{{< /cards >}} -{{< /how-to-expand >}} - -
diff --git a/docs/operate/control/_index.md b/docs/operate/control/_index.md deleted file mode 100644 index 58f211c015..0000000000 --- a/docs/operate/control/_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: "Build apps" -weight: 200 -layout: "empty" -type: "docs" -empty_node: true -open_on_desktop: true -header_only: true -canonical: "/operate/control/web-app/" ---- diff --git a/docs/operate/control/api-keys.md b/docs/operate/control/api-keys.md deleted file mode 100644 index 8e6a708765..0000000000 --- a/docs/operate/control/api-keys.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Viam API keys" -linkTitle: "API keys" -weight: 50 -layout: "docs" -type: "docs" -description: "Run control logic on a machine." -images: ["/general/code.png"] -date: "2025-01-15" ---- - -API keys grant access to organizations, locations, and machines. - -To view all API keys in use for your organization and the locations and machines inside it, click on the organization dropdown in the top navigation bar and click on **Settings**. - -{{}} - -## Add an API key - -On your organization's page, click **Generate key** to generate a new key. -Optionally, give the key a name. -Click on the **Entity** menu and choose what organization, location, or machine you want the key to grant access to. -If you select organization, your key grants access to all locations and machines contained within that organization. -If you select location, your key grants access to all of the machines contained within that location. - -For **Role**, assign either an **Owner** or **Operator** role. -See [Permissions](/manage/manage/rbac/) for information about the privilege each role entails at each resource level. - -## Change an API key's access - -To edit an API key, click on **Show details** in the key's row of the key table's **Entities** column. - -{{}} - -To edit the role, click on the dropdown menu next to the role and select **Owner** or **Operator**. -See [Permissions](/manage/manage/rbac/) for information about the privilege each role entails at each resource level. - -To change the entities it is able to access, click **+ Grant additional access**. -Select which organization, location, or machine you want the key to grant access to. -Click **Choose** to confirm your selection. - -## Rotate an API key - -Viam supports flexible key rotation with up to two keys in use at one time. -If you ever need to rotate an API key you can use the web UI: - -1. On [Viam](https://app.viam.com/), click on the organization dropdown in the top navigation bar. -1. Click on **Settings and invites**. -1. Click the **Generate Key** button on the organization setting page to generate a new key. -1. Update all code and integrations that use the key. -1. Find the old API key on the page and click on **Show details**. -1. Then click **Remove API key**. - -Alternatively, you can use the [`RotateKey`](/reference/apis/fleet/#rotatekey) API method. diff --git a/docs/operate/control/headless-app.md b/docs/operate/control/headless-app.md deleted file mode 100644 index 27d3bc5361..0000000000 --- a/docs/operate/control/headless-app.md +++ /dev/null @@ -1,411 +0,0 @@ ---- -linkTitle: "Create a headless app" -title: "Create a headless app" -weight: 30 -layout: "docs" -type: "docs" -description: "Run control logic on a machine." -images: ["/general/code.png"] -aliases: - - /product-overviews/sdk-as-client/ - - /program/sdk-as-client/ - - /program/sdks/ - - /program/ - - /program/run/ - - /program/debug/ - - /how-tos/develop-app/ - - /use-cases/develop-app/ - - /product-overviews/sdk-as-client/ ---- - -To write control logic for your machine that will run without a user interface, you can use the Python, Go, or C++ SDK. -The SDKs each include similar methods to hit Viam's [gRPC API](https://github.com/viamrobotics/api) endpoints. - -## Decide where to run your code - -You can run your code directly on the [machine's](/operate/install/setup/) single-board computer (SBC), or you can run it from a separate computer connected to the internet or to the same local network as your machine's SBC or microcontroller. - -### On a separate computer - -We recommend running your code on a laptop, desktop, or server if: - -- You are using computationally-intensive programs involving, for example, computer vision or motion planning, and -- You have a stable internet connection - -The client code will establish a connection to the instance of `viam-server` on your machine's SBC over [LAN or WAN](/reference/sdks/connectivity/). - -### On the machine itself - -We recommend running your code on the SBC that directly controls your hardware if: - -- Your machines have intermittent or no network connectivity, or -- You want to reduce latency, for example for running [PID control loops](https://en.wikipedia.org/wiki/Proportional%E2%80%93integral%E2%80%93derivative_controller), or -- Your machine runs continuously (for example, an air quality sensor) and it is impractical to constantly run a client from your development computer - -## Install an SDK - -Install your preferred Viam SDK on the computer or SBC where you plan to run the control script. - -{{< tabs >}} -{{% tab name="Python" %}} - -If you are using the Python SDK, [set up a virtual environment](/reference/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). - -If you intend to use the [ML (machine learning) model service](/vision/configure/), use the following command instead, which installs additional required dependencies along with the Python SDK: - -```sh {class="command-line" data-prompt="$"} -pip install 'viam-sdk[mlmodel]' -``` - -{{% /tab %}} -{{% tab name="Go" %}} - -Run the following command to install the [Viam Go SDK](https://pkg.go.dev/go.viam.com/rdk): - -```sh {class="command-line" data-prompt="$"} -go get go.viam.com/rdk/robot/client -``` - -{{% /tab %}} -{{% tab name="C++" %}} - -Follow the [instructions on the GitHub repository](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/BUILDING.md). - -{{% /tab %}} -{{< /tabs >}} - -## Authenticate - -You can find sample connection code on each [machine's](/operate/install/setup/) **CONNECT** tab. -Select your preferred **Language** to display a code snippet, with connection code as well as some calls to the APIs of the resources you've configured on your machine. - -You can use the toggle to include the machine API key and API key ID, though we strongly recommend storing your API keys in environment variables to reduce the risk of accidentally sharing your API key and granting access to your machines. - -If your code will connect to multiple machines or use [Platform APIs](/reference/apis/#platform-apis) you can create an API key with broader access. - -## Write your control code - -For API reference including code snippets for each method, see [Viam's Client APIs](/reference/apis/). - -{{< expand "Example code for moving a rover in a square" >}} - -The following code moves a mobile robot base in a square using the [base API](/reference/apis/components/base/). - -{{< tabs >}} -{{% tab name="Python" %}} - -```python {class="line-numbers linkable-line-numbers"} -import asyncio - -from viam.components.base import Base -from viam.robot.client import RobotClient -from viam.rpc.dial import Credentials, DialOptions - - -async def connect(): - opts = RobotClient.Options.with_api_key( - # TODO: Replace "" (including brackets) with your - # machine's API key - api_key='', - # TODO: Replace "" (including brackets) with your machine's - # API key ID - api_key_id='' - ) - # TODO: Replace "" with address from the CONNECT tab. - return await RobotClient.at_address('', opts) - - -async def moveInSquare(base): - for _ in range(4): - # moves the rover forward 500mm at 500mm/s - await base.move_straight(velocity=500, distance=500) - print("move straight") - # spins the rover 90 degrees at 100 degrees per second - await base.spin(velocity=100, angle=90) - print("spin 90 degrees") - - -async def main(): - async with connect() as machine: - roverBase = Base.from_robot(machine, 'viam_base') - - # Move the rover in a square - await moveInSquare(roverBase) - - -if __name__ == '__main__': - asyncio.run(main()) -``` - -{{% /tab %}} -{{% tab name="Go" %}} - -```go {class="line-numbers linkable-line-numbers"} -package main - -import ( - "context" - - "go.viam.com/rdk/components/base" - "go.viam.com/rdk/logging" - "go.viam.com/rdk/robot/client" - "go.viam.com/rdk/utils") - -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") - } -} - -func main() { - logger := logging.NewLogger("client") - machine, err := client.New( - context.Background(), - // TODO: Replace "" with address from the CONNECT tab. - "", - logger, - client.WithDialOptions(utils.WithEntityCredentials( - // TODO: Replace "" (including brackets) with your machine's - // API key ID - "", - utils.Credentials{ - Type: utils.CredentialsTypeAPIKey, - // TODO: 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.FromProvider(machine, "viam_base") - if err != nil { - logger.Fatalf("cannot get base: %v", err) - } - - // Move the rover in a square - moveInSquare(context.Background(), roverBase, logger) -} -``` - -{{% /tab %}} -{{% tab name="C++" %}} - -```cpp {class="line-numbers linkable-line-numbers"} -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace viam::sdk; -using std::cerr; -using std::cout; -using std::endl; - -void move_in_square(std::shared_ptr base) { - for (int i = 0; i < 4; ++i) { - cout << "Move straight" << endl; - // Move the base forward 600mm at 500mm/s - base->move_straight(500, 500); - cout << "Spin" << endl; - // Spin the base by 90 degree at 100 degrees per second - base->spin(90, 100); - } -} - -int main() { - // Every Viam C++ SDK program must have one and only one Instance object which is created - // before - // any other C++ SDK objects and stays alive until all Viam C++ SDK objects are destroyed. - Instance inst; - - // TODO: Replace "" with address from the CONNECT tab. - std::string host(""); - DialOptions dial_opts; - // TODO: Replace "" with your machine's API key ID - dial_opts.set_entity(std::string("")); - // TODO: Replace "" with your machine's API key - Credentials credentials("api-key", ""); - dial_opts.set_credentials(credentials); - boost::optional opts(dial_opts); - Options options(0, opts); - - auto machine = RobotClient::at_address(host, options); - - std::cout << "Resources:\n"; - for (const Name& resource : machine->resource_names()) { - std::cout << "\t" << resource << "\n"; - } - - std::string base_name("viam_base"); - - cout << "Getting base: " << base_name << endl; - std::shared_ptr base; - try { - base = machine->resource_by_name(base_name); - - move_in_square(base); - - } catch (const std::exception& e) { - cerr << "Failed to find " << base_name << ". Exiting." << endl; - throw; - } - return EXIT_SUCCESS; -} -``` - -{{% /tab %}} -{{< /tabs >}} - -{{< /expand >}} - -{{< expand "Example Python code for turning on a fan based on sensor readings" >}} - -The following example from [Automate air filtration with air quality sensors](https://codelabs.viam.com/guide/air-quality/index.html?index=..%2F..index#0) uses both the sensor API's [GetReadings](/reference/apis/components/sensor/#getreadings) command as well as custom functionality with the generic [DoCommand](/reference/apis/components/generic/#docommand). - -```python {class="line-numbers linkable-line-numbers"} -import asyncio -import os -from dotenv import load_dotenv -from viam.logging import getLogger -from viam.robot.client import RobotClient -from viam.components.sensor import Sensor -from viam.components.generic import Generic - -load_dotenv() -LOGGER = getLogger(__name__) - -robot_api_key = os.getenv('MACHINE_API_KEY') or '' -robot_api_key_id = os.getenv('MACHINE_API_KEY_ID') or '' -robot_address = os.getenv('MACHINE_ADDRESS') or '' - -# Define the sensor and plug names on the CONFIGURE tab -sensor_name = os.getenv("SENSOR_NAME", "") -plug_name = os.getenv("PLUG_NAME", "") - - -async def connect(): - opts = RobotClient.Options.with_api_key( - api_key=robot_api_key, - api_key_id=robot_api_key_id - ) - return await RobotClient.at_address(robot_address, opts) - - -async def main(): - async with connect() as machine: - pms_7003 = Sensor.from_robot(machine, sensor_name) - kasa_plug = Generic.from_robot(machine, plug_name) - - # Define unhealthy thresholds - unhealthy_thresholds = { - 'pm2_5_atm': 35.4, - 'pm10_atm': 150 - } - - while True: - readings = await pms_7003.get_readings() - # Check if any of the PM values exceed the unhealthy thresholds - if any(readings.get(pm_type, 0) > threshold for pm_type, - threshold in unhealthy_thresholds.items()): - LOGGER.info('UNHEALTHY.') - await kasa_plug.do_command({"toggle_on": []}) - else: - LOGGER.info('HEALTHY!') - await kasa_plug.do_command({"toggle_off": []}) - - # wait before checking again - await asyncio.sleep(10) - -if __name__ == '__main__': - asyncio.run(main()) -``` - -{{< /expand >}} - -## Run your code - -You can run your code manually from your terminal, or you can automatically run it each time your machine starts. - -### Run your code manually - -To run your code on a laptop or desktop, or to run it on your machine's SBC manually for testing purposes, execute the following command in a terminal: - -{{< tabs >}} -{{% tab name="Python" %}} - -```sh {id="terminal-prompt" class="command-line" data-prompt="$"} -python3 /home/myName/project/my_cool_script.py -``` - -{{% /tab %}} -{{% tab name="Go" %}} - -```sh {id="terminal-prompt" class="command-line" data-prompt="$"} -go run /home/myName/project/my_cool_script.go -``` - -{{% /tab %}} -{{% tab name="C++" %}} - -For information on running C++ code see [the instructions on GitHub](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/BUILDING.md). - -{{% /tab %}} -{{< /tabs >}} - -### Run your control code in a module - -To run your control code on your machine, create a {{< glossary_tooltip term_id="module" text="module" >}} and deploy it to your machine. -You can add functionality to the `DoCommand()` method to, for example, start and stop the control code. - -For more information, see [Create a module with machine control logic](/operate/modules/write-a-logic-module/#5-implement-docommand). - -## Debug - -Read and filter a machine's logs to view updates from your machine's `viam-server` instance and troubleshoot issues with your program. - -{{< tabs >}} -{{% tab name="App UI" %}} - -Navigate to the **LOGS** tab of your machine's page. - -Select from the **Levels** dropdown menu to filter the logs by severity level: - -![Filtering by log level of info in the logs tab.](/build/program/sdks/log-level-info.png) - -{{% /tab %}} -{{% tab name="Command line" %}} - -```sh {class="command-line" data-prompt="$"} -viam machines part logs --part= --tail=true -``` - -{{% /tab %}} -{{< /tabs >}} diff --git a/docs/operate/control/kiosk-app.md b/docs/operate/control/kiosk-app.md deleted file mode 100644 index e77f552493..0000000000 --- a/docs/operate/control/kiosk-app.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: "Create a kiosk app" -title: "Create a kiosk app" -weight: 40 -layout: "docs" -type: "docs" -no_list: true -description: "TODO" -draft: true ---- diff --git a/docs/operate/control/mobile-app.md b/docs/operate/control/mobile-app.md deleted file mode 100644 index 2606ce0618..0000000000 --- a/docs/operate/control/mobile-app.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -linkTitle: "Create a mobile app" -title: "Create a mobile app" -weight: 20 -layout: "docs" -type: "docs" -description: "Create a custom user interface for interacting with machines from a mobile device." ---- - -You can use Viam's [Flutter SDK](https://flutter.viam.dev/) to create a custom mobile application to interact with your devices. -The Flutter SDK includes: - -- Implementation of the standard component and service APIs to control your hardware and software -- Widgets to ease the development process -- Authentication tools so users can log in securely - -## Install the Flutter SDK - -Run the following command in your terminal to install the Viam Flutter SDK: - -```sh {id="terminal-prompt" class="command-line" data-prompt="$"} -flutter pub add viam_sdk -``` - -## Connect to your machine - -You can find sample connection code on each [machine's](/operate/install/setup/) **CONNECT** tab. -Select **Flutter** to display a code snippet with connection code as well as some calls to the APIs of the resources you've configured on your machine. - -You can use the toggle to include the machine API key and API key ID, though we strongly recommend storing your API keys in environment variables to reduce the risk of accidentally sharing your API key and granting access to your machines. - -If your code will connect to multiple machines or use [Platform APIs](/reference/apis/#platform-apis) you can create an API key with broader access. - -## Write your app - -Refer to the [Viam Flutter SDK](https://flutter.viam.dev/) documentation for available methods and widgets. - -### Example usage - -The following code, part of [Drive a rover in a square in 2 minutes](/tutorials/control/drive-rover/), shows how you could move a robotic rover base in a square using the base API's [`moveStraight`](https://flutter.viam.dev/viam_sdk/Base/moveStraight.html) and [`spin`](https://flutter.viam.dev/viam_sdk/Base/spin.html) methods: - -```dart {class="line-numbers linkable-line-numbers"} -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'), - ), - ])) - ,);}} -``` - -{{