Skip to content

Commit c0e79a9

Browse files
committed
Merge remote-tracking branch 'upstream/main' into RSDK-10618
2 parents e59d45e + 34ea115 commit c0e79a9

File tree

113 files changed

+2260
-1002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+2260
-1002
lines changed

.github/workflows/motion-tests.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,11 @@ jobs:
5555

5656
- name: Run motion tests on PR branch
5757
shell: bash
58-
env:
58+
env:
5959
URL: ${{ github.event.pull_request.head.repo.html_url }}
6060
SHA: ${{ github.event.pull_request.head.sha }}
6161
run: |
62-
cd motion-testing
63-
go mod edit -replace go.viam.com/rdk=${URL#"https://"}@$SHA
64-
sudo -Hu testbot bash -lc "go mod tidy && go test ./... -v -run TestMotionExtended"
62+
echo "Skipping actual running of extended motion tests until RSDK-10651 has been resolved"
63+
# cd motion-testing
64+
# go mod edit -replace go.viam.com/rdk=${URL#"https://"}@$SHA
65+
# sudo -Hu testbot bash -lc "go mod tidy && go test ./... -v -run TestMotionExtended"

Makefile

+2-4
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,11 @@ build: build-go
2222
build-go:
2323
go build ./...
2424

25-
.PHONY: rm-cli
26-
rm-cli:
27-
rm -f ./bin/$(GOOS)-$(GOARCH)/viam-cli
25+
GO_FILES=$(shell find . -name "*.go")
2826

2927
GOOS ?= $(shell go env GOOS)
3028
GOARCH ?= $(shell go env GOARCH)
31-
bin/$(GOOS)-$(GOARCH)/viam-cli: rm-cli
29+
bin/$(GOOS)-$(GOARCH)/viam-cli: $(GO_FILES) Makefile go.mod go.sum
3230
# no_cgo necessary here because of motionplan -> nlopt dependency.
3331
# can be removed if you can run CGO_ENABLED=0 go build ./cli/viam on your local machine.
3432
go build $(LDFLAGS) -tags osusergo,netgo,no_cgo -o $@ ./cli/viam

cli/app.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -2367,6 +2367,17 @@ Copy multiple files from the machine to a local destination with recursion and k
23672367
{
23682368
Name: "motion",
23692369
Subcommands: []*cli.Command{
2370+
{
2371+
Name: "print-config",
2372+
Flags: commonPartFlags,
2373+
Action: createCommandWithT[motionPrintArgs](motionPrintConfigAction),
2374+
},
2375+
{
2376+
Name: "print-status",
2377+
Flags: commonPartFlags,
2378+
Action: createCommandWithT[motionPrintArgs](motionPrintStatusAction),
2379+
},
2380+
23702381
{
23712382
Name: "get-pose",
23722383
Flags: append(commonPartFlags, []cli.Flag{
@@ -2377,6 +2388,23 @@ Copy multiple files from the machine to a local destination with recursion and k
23772388
}...),
23782389
Action: createCommandWithT[motionGetPoseArgs](motionGetPoseAction),
23792390
},
2391+
{
2392+
Name: "set-pose",
2393+
Flags: append(commonPartFlags, []cli.Flag{
2394+
&cli.StringFlag{
2395+
Name: "component",
2396+
Required: true,
2397+
},
2398+
&cli.Float64SliceFlag{Name: "x"},
2399+
&cli.Float64SliceFlag{Name: "y"},
2400+
&cli.Float64SliceFlag{Name: "z"},
2401+
&cli.Float64SliceFlag{Name: "ox"},
2402+
&cli.Float64SliceFlag{Name: "oy"},
2403+
&cli.Float64SliceFlag{Name: "oz"},
2404+
&cli.Float64SliceFlag{Name: "theta"},
2405+
}...),
2406+
Action: createCommandWithT[motionSetPoseArgs](motionSetPoseAction),
2407+
},
23802408
},
23812409
},
23822410
},
@@ -2790,7 +2818,7 @@ This won't work unless you have an existing installation of our GitHub app on yo
27902818
&cli.StringFlag{
27912819
Name: moduleFlagHomeDir,
27922820
Usage: "remote user's home directory. only necessary if you're targeting a remote machine where $HOME is not /root",
2793-
Value: "/root",
2821+
Value: "~",
27942822
},
27952823
},
27962824
Action: createCommandWithT[reloadModuleArgs](ReloadModuleAction),

cli/module_generate/_templates/go/tmpl-module.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ type Config struct {
3838
// Returns implicit dependencies based on the config.
3939
// The path is the JSON path in your robot's config (not the `Config` struct) to the
4040
// resource being validated; e.g. "components.0".
41-
func (cfg *Config) Validate(path string) ([]string, error) {
41+
func (cfg *Config) Validate(path string) ([]string, []string, error) {
4242
// Add config validation code here
43-
return nil, nil
43+
return nil, nil, nil
4444
}
4545

4646
type {{.ModuleCamel}}{{.ModelPascal}} struct {

cli/module_generate/_templates/python/src/models/tmpl-resource.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, Mapping, Sequence, Self
1+
from typing import ClassVar, Mapping, Sequence, Self, Tuple
22
from viam.proto.app.robot import ComponentConfig
33
from viam.proto.common import ResourceName
44
from viam.resource.base import ResourceBase
@@ -25,17 +25,19 @@ def new(cls, config: ComponentConfig, dependencies: Mapping[ResourceName, Resour
2525
return super().new(config, dependencies)
2626

2727
@classmethod
28-
def validate_config(cls, config: ComponentConfig) -> Sequence[str]:
28+
def validate_config(cls, config: ComponentConfig) -> Tuple[Sequence[str], Sequence[str]]:
2929
"""This method allows you to validate the configuration object received from the machine,
30-
as well as to return any implicit dependencies based on that `config`.
30+
as well as to return any required dependencies or optional dependencies based on that `config`.
3131
3232
Args:
3333
config (ComponentConfig): The configuration for this resource
3434
3535
Returns:
36-
Sequence[str]: A list of implicit dependencies
36+
Tuple[Sequence[str], Sequence[str]]: A tuple where the
37+
first element is a list of required dependencies and the
38+
second element is a list of optional dependencies
3739
"""
38-
return []
40+
return [], []
3941

4042
def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]):
4143
"""This method allows you to dynamically update your service when it receives a new `config` object.

cli/module_generate/scripts/generate_stubs.py

+54-60
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ def return_attribute(value: str, attr: str) -> ast.Attribute:
1010
return ast.Attribute(
1111
value=ast.Name(id=value, ctx=ast.Load()),
1212
attr=attr,
13-
ctx=ast.Load())
13+
ctx=ast.Load(),
14+
)
1415

1516

1617
def update_annotation(
1718
resource_name: str,
1819
annotation: Union[ast.Name, ast.Subscript],
1920
nodes: Set[str],
20-
parent: str
21+
parent: str,
2122
) -> Union[ast.Attribute, ast.Subscript]:
2223
if isinstance(annotation, ast.Name) and annotation.id in nodes:
2324
value = parent if parent else resource_name
@@ -27,48 +28,43 @@ def update_annotation(
2728
resource_name,
2829
annotation.slice,
2930
nodes,
30-
parent)
31+
parent,
32+
)
3133
return annotation
3234

3335

3436
def replace_async_func(
35-
resource_name: str,
36-
func: ast.AsyncFunctionDef,
37-
nodes: Set[str],
38-
parent: str = ""
37+
resource_name: str, func: ast.AsyncFunctionDef, nodes: Set[str], parent: str = ""
3938
) -> None:
4039
for arg in func.args.args:
41-
arg.annotation = update_annotation(
42-
resource_name,
43-
arg.annotation,
44-
nodes,
45-
parent)
40+
arg.annotation = update_annotation(resource_name, arg.annotation, nodes, parent)
4641
func.body = [
47-
ast.Expr(ast.Call(
48-
func=ast.Attribute(
49-
value=ast.Attribute(
50-
ast.Name(id="self"),
51-
attr="logger"),
52-
attr="error",
53-
),
54-
args=[ast.Constant(value=f"`{func.name}` is not implemented")],
55-
keywords=[])),
42+
ast.Expr(
43+
ast.Call(
44+
func=ast.Attribute(
45+
value=ast.Attribute(ast.Name(id="self"), attr="logger"),
46+
attr="error",
47+
),
48+
args=[ast.Constant(value=f"`{func.name}` is not implemented")],
49+
keywords=[],
50+
)
51+
),
5652
ast.Raise(
57-
exc=ast.Call(func=ast.Name(id='NotImplementedError',
58-
ctx=ast.Load()),
59-
args=[],
60-
keywords=[]),
61-
cause=None)
53+
exc=ast.Call(
54+
func=ast.Name(id="NotImplementedError", ctx=ast.Load()),
55+
args=[],
56+
keywords=[],
57+
),
58+
cause=None,
59+
),
6260
]
6361
func.decorator_list = []
6462
if isinstance(func.returns, (ast.Name, ast.Subscript)):
65-
func.returns = update_annotation(
66-
resource_name, func.returns, nodes, parent
67-
)
63+
func.returns = update_annotation(resource_name, func.returns, nodes, parent)
6864

6965

7066
def return_subclass(
71-
resource_name: str, stmt: ast.ClassDef, parent: str = ""
67+
resource_name: str, stmt: ast.ClassDef, parent: str = ""
7268
) -> List[str]:
7369
def parse_subclass(resource_name: str, stmt: ast.ClassDef, parent: str):
7470
nodes = set()
@@ -93,9 +89,7 @@ def parse_subclass(resource_name: str, stmt: ast.ClassDef, parent: str):
9389
stmt.body = [ast.Pass()]
9490

9591
parse_subclass(resource_name, stmt, parent)
96-
return '\n'.join(
97-
[' ' + line for line in ast.unparse(stmt).splitlines()]
98-
)
92+
return "\n".join([" " + line for line in ast.unparse(stmt).splitlines()])
9993

10094

10195
def main(
@@ -108,14 +102,12 @@ def main(
108102
import isort
109103
from slugify import slugify
110104

111-
module_name = (
112-
f"viam.{resource_type}s.{resource_subtype}.{resource_subtype}"
113-
)
105+
module_name = f"viam.{resource_type}s.{resource_subtype}.{resource_subtype}"
114106
module = import_module(module_name)
115-
resource_name = {
116-
"input": "Controller", "slam": "SLAM", "mlmodel": "MLModel"
117-
}.get(resource_subtype, "".join(word.capitalize()
118-
for word in resource_subtype.split("_")))
107+
resource_name = {"input": "Controller", "slam": "SLAM", "mlmodel": "MLModel"}.get(
108+
resource_subtype,
109+
"".join(word.capitalize() for word in resource_subtype.split("_")),
110+
)
119111

120112
imports, subclasses, abstract_methods = [], [], []
121113
nodes = set()
@@ -132,8 +124,11 @@ def main(
132124
for imp in stmt.names:
133125
if imp.name in modules_to_ignore:
134126
continue
135-
imports.append(f"import {imp.name} as {imp.asname}"
136-
if imp.asname else f"import {imp.name}")
127+
imports.append(
128+
f"import {imp.name} as {imp.asname}"
129+
if imp.asname
130+
else f"import {imp.name}"
131+
)
137132
elif (
138133
isinstance(stmt, ast.ImportFrom)
139134
and stmt.module
@@ -159,8 +154,8 @@ def main(
159154
nodes.add(cstmt.target.id)
160155
elif isinstance(cstmt, ast.AsyncFunctionDef):
161156
replace_async_func(resource_name, cstmt, nodes)
162-
indented_code = '\n'.join(
163-
[' ' + line for line in ast.unparse(cstmt).splitlines()]
157+
indented_code = "\n".join(
158+
[" " + line for line in ast.unparse(cstmt).splitlines()]
164159
)
165160
abstract_methods.append(indented_code)
166161

@@ -172,22 +167,24 @@ def main(
172167
for cstmt in stmt.body:
173168
if isinstance(cstmt, ast.AsyncFunctionDef):
174169
replace_async_func("", cstmt, [])
175-
indented_code = '\n'.join(
176-
[' ' + line for line in ast.unparse(cstmt).splitlines()]
170+
indented_code = "\n".join(
171+
[" " + line for line in ast.unparse(cstmt).splitlines()]
177172
)
178173
abstract_methods.append(indented_code)
179174
if cstmt.name == "do_command":
180175
imports.append("from typing import Optional")
181176
imports.append("from viam.utils import ValueTypes")
182177
elif cstmt.name == "get_geometries":
183-
imports.append("from typing import Any, Dict, List, Optional")
178+
imports.append(
179+
"from typing import Any, Dict, List, Optional"
180+
)
184181
imports.append("from viam.proto.common import Geometry")
185182

186183
model_name_pascal = "".join(
187184
[word.capitalize() for word in slugify(model_name).split("-")]
188185
)
189186
resource_file = '''
190-
from typing import ClassVar, Mapping, Sequence
187+
from typing import ClassVar, Mapping, Sequence, Tuple
191188
from typing_extensions import Self
192189
from viam.proto.app.robot import ComponentConfig
193190
from viam.proto.common import ResourceName
@@ -218,17 +215,19 @@ def new(cls, config: ComponentConfig, dependencies: Mapping[ResourceName, Resour
218215
return super().new(config, dependencies)
219216
220217
@classmethod
221-
def validate_config(cls, config: ComponentConfig) -> Sequence[str]:
218+
def validate_config(cls, config: ComponentConfig) -> Tuple[Sequence[str], Sequence[str]]:
222219
"""This method allows you to validate the configuration object received from the machine,
223-
as well as to return any implicit dependencies based on that `config`.
220+
as well as to return any required dependencies or optional dependencies based on that `config`.
224221
225222
Args:
226223
config (ComponentConfig): The configuration for this resource
227224
228225
Returns:
229-
Sequence[str]: A list of implicit dependencies
226+
Tuple[Sequence[str], Sequence[str]]: A tuple where the
227+
first element is a list of required dependencies and the
228+
second element is a list of optional dependencies
230229
"""
231-
return []
230+
return [], []
232231
233232
def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]):
234233
"""This method allows you to dynamically update your service when it receives a new `config` object.
@@ -250,8 +249,8 @@ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceNam
250249
namespace,
251250
mod_name,
252251
model_name,
253-
'\n\n'.join([subclass for subclass in subclasses]),
254-
'\n\n'.join([f'{method}' for method in abstract_methods]),
252+
"\n\n".join([subclass for subclass in subclasses]),
253+
"\n\n".join([f"{method}" for method in abstract_methods]),
255254
)
256255
f_name = os.path.join(mod_name, "src", "models", "resource.py")
257256
with open(f_name, "w+") as f:
@@ -274,12 +273,7 @@ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceNam
274273
if sys.argv[2] == "mlmodel":
275274
packages.append("numpy")
276275
install_res = subprocess.run(
277-
[
278-
sys.executable,
279-
"-m",
280-
"pip",
281-
"install"
282-
] + packages,
276+
[sys.executable, "-m", "pip", "install"] + packages,
283277
capture_output=True,
284278
)
285279
if install_res.returncode != 0:

cli/module_registry.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ func UploadModuleAction(c *cli.Context, args uploadModuleArgs) error {
356356
if !forceUploadArg {
357357
if err := validateModuleFile(client, c, moduleID, tarballPath, versionArg, platformArg); err != nil {
358358
return fmt.Errorf(
359-
"error validating module: %w. For more details, please visit: https://docs.viam.com/cli/#module ",
359+
"error validating module: %w. For more details, please visit: https://docs.viam.com/dev/tools/cli#module ",
360360
err)
361361
}
362362
}

0 commit comments

Comments
 (0)