-
Notifications
You must be signed in to change notification settings - Fork 64
RSDK-4033, RSDK-4043 - Add simple module example, streamline arm example + other updates #369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
629229b
f9ce328
c435077
875f3a9
9c006d4
cf958f8
03836a0
23cdb49
26ffe36
77efe96
a826928
c3ba6c5
8671b0c
69e768d
1d665f2
2ce1d3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# add a version if viam should be pinned to a specific version | ||
viam-sdk |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh | ||
cd `dirname $0` | ||
|
||
# Create a virtual environment to run our code | ||
VENV_NAME="venv" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this not assume you have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. venv is baked into python 3.4 and up, so should be good for the versions of python we support. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AH sorry this is creating a virtual env. I guess then it assumes that there isn't already a virtual env named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NVM, it creates it in this directory, so there should be no collisions. |
||
PYTHON="$VENV_NAME/bin/python" | ||
|
||
python3 -m venv $VENV_NAME | ||
$PYTHON -m pip install -r requirements.txt -U # remove -U if viam-sdk should not be upgraded whenever possible | ||
|
||
# Be sure to use `exec` so that termination signals reach the python process, | ||
# or handle forwarding termination signals manually | ||
exec $PYTHON -m src.main $@ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"name": "xArm6", | ||
"name": "MyArm", | ||
"links": [ | ||
{ | ||
"id": "base", | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# VIAM Simple Module Example | ||
This example goes through how to create custom modular resources using Viam's python SDK, and how to connect it to a Robot. | ||
|
||
This is a limited document. For a more in-depth understanding of modules, see the [documentation](https://docs.viam.com/program/extend/modular-resources/). | ||
|
||
## Purpose | ||
Modular resources allow you to define custom components and services, and add them to your robot. Viam ships with many component types, but you're not limited to only using those types -- you can create your own using modules. | ||
|
||
For more information, see the [documentation](https://docs.viam.com/program/extend/modular-resources/). For a more complex example, take a look at the [complex module example](https://github.com/viamrobotics/viam-python-sdk/tree/main/examples/complex_module), which contains multiple new APIs and custom resource models. | ||
|
||
## Project structure | ||
The definition of the new resources are in the `main` file of the `src` directory. | ||
|
||
The `run.sh` script is the entrypoint for a module and calls the `main.py` file. The `main.py` file contains the definition of a new sensor model and code to register it. When called, the program creates and starts the module. Read further to learn how to connect this module to your robot. | ||
|
||
Outside the `src` directory, there is a `client.py` file. You can use this file to test the module once you have connected to your robot and configured the module. You will have to update the credentials and robot address in that file. | ||
|
||
## Configuring and using the module | ||
These steps assume that you have a robot available at [app.viam.com](app.viam.com). | ||
|
||
The `run.sh` script is the entrypoint for this module. To connect this module with your robot, you must add this module's entrypoint to the robot's config. For example, the entrypoint file may be at `/home/viam-python-sdk/examples/simple_module/run.sh` and you must add this file path to your configuration. See the [documentation](https://docs.viam.com/program/extend/modular-resources/#use-a-modular-resource-with-your-robot) for more details. | ||
|
||
Once the module has been added to your robot, add a new component that uses the `MySensor` model. See the [documentation](https://docs.viam.com/program/extend/modular-resources/#configure-a-component-instance-for-a-modular-resource) for more details. | ||
|
||
An example configuration for a Sensor component could look like this: | ||
```json | ||
{ | ||
"components": [ | ||
{ | ||
"name": "sensor1", | ||
"type": "sensor", | ||
"model": "acme:demo:mysensor", | ||
"attributes": {}, | ||
"depends_on": [] | ||
} | ||
], | ||
"modules": [ | ||
{ | ||
"name": "my-module", | ||
"executable_path": "/home/viam-python-sdk/examples/simple_module/run.sh" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
After the robot has started and connected to the module, you can use the provided `client.py` to connect to your robot and make calls to your custom, modular resources. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import asyncio | ||
|
||
from viam import logging | ||
from viam.robot.client import RobotClient | ||
from viam.rpc.dial import Credentials, DialOptions | ||
from viam.components.sensor import Sensor | ||
|
||
|
||
async def connect(): | ||
creds = Credentials(type="<your authentication type here>", payload="<your authentication payload here>") | ||
opts = RobotClient.Options(refresh_interval=0, dial_options=DialOptions(credentials=creds), log_level=logging.DEBUG) | ||
return await RobotClient.at_address("<your robot uri here>", opts) | ||
|
||
|
||
async def main(): | ||
robot = await connect() | ||
|
||
print("Resources:") | ||
print(robot.resource_names) | ||
|
||
sensor = Sensor.from_robot(robot, name="sensor1") | ||
reading = await sensor.get_readings() | ||
print(f"The reading is {reading}") | ||
|
||
await robot.close() | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# add a version if viam should be pinned to a specific version | ||
viam-sdk |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh | ||
cd `dirname $0` | ||
|
||
# Create a virtual environment to run our code | ||
VENV_NAME="venv" | ||
PYTHON="$VENV_NAME/bin/python" | ||
|
||
python3 -m venv $VENV_NAME | ||
$PYTHON -m pip install -r requirements.txt -U # remove -U if viam-sdk should not be upgraded whenever possible | ||
|
||
# Be sure to use `exec` so that termination signals reach the python process, | ||
# or handle forwarding termination signals manually | ||
exec $PYTHON src/main.py $@ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import asyncio | ||
from typing import Any, ClassVar, Dict, Mapping, Optional | ||
|
||
from typing_extensions import Self | ||
|
||
from viam.components.sensor import Sensor | ||
from viam.module.module import Module | ||
from viam.proto.app.robot import ComponentConfig | ||
from viam.proto.common import ResourceName | ||
from viam.resource.base import ResourceBase | ||
from viam.resource.registry import Registry, ResourceCreatorRegistration | ||
from viam.resource.types import Model, ModelFamily | ||
from viam.utils import ValueTypes | ||
|
||
|
||
class MySensor(Sensor): | ||
# Subclass the Viam Sensor component and implement the required functions | ||
MODEL: ClassVar[Model] = Model(ModelFamily("acme", "demo"), "mysensor") | ||
|
||
def __init__(self, name: str): | ||
super().__init__(name) | ||
|
||
@classmethod | ||
def new(cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]) -> Self: | ||
sensor = cls(config.name) | ||
return sensor | ||
|
||
async def get_readings(self, extra: Optional[Dict[str, Any]] = None, **kwargs) -> Mapping[str, Any]: | ||
return {"signal": 1} | ||
|
||
async def do_command(self, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs) -> Mapping[str, ValueTypes]: | ||
return command | ||
|
||
|
||
async def main(): | ||
"""This function creates and starts a new module, after adding all desired resource models. | ||
Resource creators must be registered to the resource registry before the module adds the resource model. | ||
""" | ||
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new)) | ||
|
||
module = Module.from_args() | ||
module.add_model_from_registry(Sensor.SUBTYPE, MySensor.MODEL) | ||
await module.start() | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may be good to start with simple and then offer the grander example with custom proto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the readme here is part of the complex_module example folder, so I feel like unless we want to restructure the examples even more, it's the user's choice as to which example they start with (the line here is just to remind them there's something simpler)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh. sorry. i'd misunderstood. thanks