Skip to content

Commit e09e7e3

Browse files
authored
Merge pull request #153 from NavAbility/23Q2/enh/gqlinstallissues
fix sdkCommonGQL install copy
2 parents f2e130d + 5bb210d commit e09e7e3

File tree

10 files changed

+76
-155
lines changed

10 files changed

+76
-155
lines changed

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
recursive-include sdkCommonGQL *

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ release: $(VIRTUAL_ENV_DIR)
1414
$(VIRTUAL_ENV_DIR)/bin/$(PYTHON_VERSION) setup.py sdist
1515
# Assuming you have twine already in the sdist
1616
$(VIRTUAL_ENV_DIR)/bin/pip install twine
17-
$(VIRTUAL_ENV_DIR)/bin/twine upload dist/*
17+
$(VIRTUAL_ENV_DIR)/bin/twine upload dist/*.tar.gz
1818

1919
docs_cicd:
2020
$(PYTHON_VERSION) -m venv venv_docs

docs/_toc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ parts:
1919
- file: solvers
2020
- caption: Tutorials
2121
chapters:
22-
- file: nvatutorials
2322
- file: bigexample
23+
- file: nvatutorials
2424
- caption: Notes and FAQ
2525
chapters:
2626
- file: notesfaq

docs/bigexample.md

+26-112
Original file line numberDiff line numberDiff line change
@@ -5,132 +5,46 @@
55
```python
66
from navability.entities import *
77
from navability.services import *
8-
import asyncio
98
from uuid import uuid4
109
import numpy as np
10+
# import asyncio
1111

1212

1313
userLabel = "guest@navability.io"
1414
robotLabel = "TestRobot"
1515
sessionLabel = "TestHex"
16-
fgclient = DFGClient(userLabel, robotLabel, sessionLabel)
1716

18-
variables = await listVariablesAsync(fgclient)
17+
# for private (non-guest) use, get a token after login at app.navability.io, Connect page.
18+
auth_token = ''
1919

20-
entries = await listBlobEntriesAsync(fgclient, "x1")
20+
fgclient = DFGClient(userLabel, robotLabel, sessionLabel, auth_token=auth_token)
2121

22-
```
23-
24-
## Legacy Example
25-
26-
This script will create variables and factors, list the graph, and solve the session for SLAM estimates.
27-
28-
> NOTES:
29-
> * You'll need to start Python using `python -m asyncio` to support the `await` command.
30-
> * You'll need numpy to run the example.
31-
32-
```python
33-
from uuid import uuid4
34-
import numpy as np
35-
import json
36-
from navability.entities import (
37-
Client,
38-
Factor,
39-
FactorData,
40-
FullNormal,
41-
NavAbilityHttpsClient,
42-
Pose2Pose2,
43-
PriorPose2,
44-
Variable,
45-
VariableType,
46-
)
47-
from navability.services import (
48-
addFactor,
49-
addVariable,
50-
solveSession,
51-
ls,
52-
lsf,
53-
waitForCompletion,
54-
getVariable
55-
)
22+
variables = listVariables(fgclient)
23+
# variables = await listVariablesAsync(fgclient)
5624

57-
navability_client = NavAbilityHttpsClient()
58-
client = Client("Guest", "MyUser", "Session_" + str(uuid4())[0:8])
25+
# get one of the variables from the graph
26+
x1 = getVariable(fgclient, 'x1')
27+
# xl1 = await getVariableAsync(fgclient, 'x1')
28+
print('The tags on this variable are', x1.tags)
5929

60-
# Create variables x0, x1, and x2
61-
variables = [
62-
Variable("x0", VariableType.Pose2.value),
63-
Variable("x1", VariableType.Pose2.value),
64-
Variable("x2", VariableType.Pose2.value),
65-
]
30+
# which blob entries (list of labels) are there on this variable
31+
be_labels = listBlobEntries(fgclient, "x1")
32+
# be_labels = await listBlobEntriesAsync(fgclient, "x1")
6633

67-
# Create factors between them
68-
factors = [
69-
Factor(
70-
"x0f1",
71-
"PriorPose2",
72-
["x0"],
73-
FactorData(
74-
fnc=PriorPose2(
75-
Z=FullNormal(mu=np.zeros(3), cov=np.diag([0.1, 0.1, 0.1]))
76-
).dump() # This is a generator for a PriorPose2
77-
),
78-
),
79-
Factor(
80-
"x0x1f1",
81-
"Pose2Pose2",
82-
["x0", "x1"],
83-
FactorData(
84-
fnc=Pose2Pose2(
85-
Z=FullNormal(
86-
mu=[1, 1, np.pi / 3], cov=np.diag([0.1, 0.1, 0.1])
87-
)
88-
).dump() # This is a generator for a PriorPose2
89-
),
90-
),
91-
Factor(
92-
"x1x2f1",
93-
"Pose2Pose2",
94-
["x1", "x2"],
95-
FactorData(
96-
fnc=Pose2Pose2(
97-
Z=FullNormal(
98-
mu=[1, 1, np.pi / 3], cov=np.diag([0.1, 0.1, 0.1])
99-
)
100-
).dump() # This is a generator for a PriorPose2
101-
),
102-
),
103-
]
34+
# fetch fetch one of the blob entries (note not the blob itself yet)
35+
entry = getBlobEntry(fgclient, "x1", be_labels[0])
10436

105-
# Get the result IDs so we can check on their completion
106-
print("Adding variables and factors..\r\n")
107-
variable_results = [await addVariable(navability_client, client, v) for v in variables]
108-
factor_results = [await addFactor(navability_client, client, f) for f in factors]
109-
result_ids = variable_results + factor_results
37+
## fetch binary data blob from one of the blobstores
38+
store = NavAbilityBlobStore(fgclient.client, userLabel)
39+
blob = getBlob(store, str(entry.blobId))
40+
# blob = await getBlobAsync(store, entry.id)
11041

111-
# Wait for them to be inserted if they havent already
112-
print("Waiting for them to be loaded..\r\n")
113-
await waitForCompletion(navability_client, result_ids, maxSeconds=120)
42+
## which neighbors does this variable have
43+
x1_nei = listNeighbors(fgclient, 'x1')
11444

115-
# Interrogate the graph
116-
# Get the variables
117-
print("Listing all the variables and factors in the session:\r\n")
118-
vs = await ls(navability_client, client)
119-
print("Variables: " + json.dumps(vs, indent=4, sort_keys=True))
120-
# Get the factors
121-
fs = await lsf(navability_client, client)
122-
print("Factors: " + json.dumps(fs, indent=4, sort_keys=True))
123-
# There's some pretty neat functionality with searching, but we'll save that for more comprehensive tutorials
45+
## which factors are there
46+
fcts = listFactors(fgclient)
12447

125-
# Request a SLAM multimodal solve and wait for the response
126-
# Note: Guest sessions solve a little slower than usual because they're using some small hardware we put down for community use. Feel free to reach out if you want faster solving.
127-
print("Requesting that the graph be solved to determine the positions of the variables (poses)...")
128-
request_id = await solveSession(navability_client, client)
129-
await waitForCompletion(navability_client, [request_id], maxSeconds=120)
130-
131-
# Get the solves positions of the variables (these are stores in the PPEs structure)
132-
print("Getting the estimates of the variables (poses)...")
133-
estimates = {v.label: (await getVariable(navability_client, client, v.label)).ppes['default'].suggested for v in variables}
134-
print("Solved estimates for the positions:\r\n")
135-
print(json.dumps(estimates, indent=4, sort_keys=True))
136-
```
48+
## get a specific factor
49+
fc = getFactor(fgclient, 'x1x2f1')
50+
```

docs/blobs.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,11 @@ Adding `Blob` or `BlobEntry`s from the Python SDK are under construction and [ex
8383

8484
It is also possible to push data blobs:
8585
```python
86-
client = NavAbilityHttpsClient()
87-
blobId = await addBlob(fgclient.client, "testimage.png", imgblob)
86+
blobId = addBlob(fgclient, "testimage.png", imgblob)
8887
```
8988

9089
Remember to add at least one BlobEntry somewhere in your session so that you might find it again in the future, see `addBlobEntry` above.
9190

92-
:::{eval-rst}
93-
.. autofunction:: navability.entities.NavAbilityHttpsClient
94-
:::
9591

9692
:::{seealso}
9793
See [Tutorial 5 from ICRA 2022 for a more in-depth example of working with data blobs](sdkpynb:python/navability-sdk/icra-5-marineexample).

docs/buildgraph.md

+14-28
Original file line numberDiff line numberDiff line change
@@ -64,53 +64,39 @@ Let's create a `PriorPose2` unary factor with zero mean and a covariance matrix
6464
```python
6565
prior_distribution = FullNormal(mu=np.zeros(3), cov=np.power(np.diag([0.1, 0.1, 0.1]),2))
6666
result_f0 = addFactor(fgclient, ["x0"], PriorPose2(Z=prior_distribution))
67-
result_f0 = await addFactorAsync(fgclient, ["x0"], PriorPose2(Z=prior_distribution))
67+
# result_f0 = await addFactorAsync(fgclient, ["x0"], PriorPose2(Z=prior_distribution))
6868
```
6969

7070
## Odometry Factor
7171

7272
An odometry factor connects two consecutive robot poses `x0` and `x1` together to form a chain. Here we use a relative factor of type `Pose2Pose2` with a measurement from pose `x0` to `x1` of `(x=1.0,y=0.0,θ=pi/2)`; the robot drove 1 unit forward (in the x direction). Similarly to the prior we added above, we use a `FullNormal` distribution to represent the odometry with mean and covariance:
7373
```python
74-
result_v = await addVariable(client, context, "x1", VariableType.Pose2)
74+
result_v = addVariable(fgclient, "x1", VariableType.Pose2)
7575
print(f"Added x1 with result ID {result_v}")
76+
7677
odo_distribution = FullNormal(mu=[1.0, 0.0, np.pi/2], cov=np.power(np.diag([0.1, 0.1, 0.01]),2))
77-
result_fac_1 = await addFactor(client, context, ["x0", "x1"], Pose2Pose2(Z=odo_distribution))
78+
result_fac_1 = addFactor(fgclient, ["x0", "x1"], Pose2Pose2(Z=odo_distribution))
7879
print(f"Added factor with result ID {result_fac_1}")
79-
80-
# Wait for it to be loaded.
81-
await waitForCompletion(client, [result_v, result_fac_1])
8280
```
8381

8482
## Adding Different Sensors
8583

8684
So far we worked with the `Pose2` factor type. Among others, `NavAbilitySDK` also provides the `Point2` variable and `Pose2Point2BearingRange` factor types, which we will use to represent a landmark sighting in our factor graph. We will add a landmark `l1` with bearing range measurement of bearing=`(mu=0,sigma=0.03)` `range=(mu=0.5,sigma=0.1)` and continue our robot trajectory by driving around in a square.
8785
```python
88-
results_variables = [
89-
await addVariable(client, context, "l1", VariableType.Point2),
90-
await addVariable(client, context, "x2", VariableType.Pose2),
91-
await addVariable(client, context, "x3", VariableType.Pose2),
92-
await addVariable(client, context, "x4", VariableType.Pose2)]
93-
results_variables
94-
95-
results_factors = [
96-
await addFactor(client, context, ["x0", "l1"], Pose2Point2BearingRange(Normal(0.0,0.03), Normal(0.5,0.1))),
97-
await addFactor(client, context, ["x1", "x2"], Pose2Pose2(odo_distribution)),
98-
await addFactor(client, context, ["x2", "x3"], Pose2Pose2(odo_distribution)),
99-
await addFactor(client, context, ["x3", "x4"], Pose2Pose2(odo_distribution)),
100-
]
101-
await waitForCompletion(client, results_variables + results_factors)
86+
addVariable(fgclient, "l1", VariableType.Point2)
87+
addVariable(fgclient, "x2", VariableType.Pose2)
88+
addVariable(fgclient, "x3", VariableType.Pose2)
89+
addVariable(fgclient, "x4", VariableType.Pose2)
90+
91+
addFactor(fgclient, ["x0", "l1"], Pose2Point2BearingRange(Normal(0.0,0.03), Normal(0.5,0.1)))
92+
addFactor(fgclient, ["x1", "x2"], Pose2Pose2(odo_distribution))
93+
addFactor(fgclient, ["x2", "x3"], Pose2Pose2(odo_distribution))
94+
addFactor(fgclient, ["x3", "x4"], Pose2Pose2(odo_distribution))
10295
```
10396

10497
## One Loop-Closure Example
10598

10699
The robot continued its square trajectory to end off where it started. To illustrate a loop closure, we add another bearing range sighting to from pose `x4` to landmark `l1`, solve the graph and plot the new results:
107100
```python
108-
result_factor = await addFactor(client, context, ["x4", "l1"], Pose2Point2BearingRange(Normal(0.0,0.03), Normal(0.5,0.1)))
109-
110-
await waitForCompletion(client, [result_factor])
101+
result_factor = addFactor(fgclient, ["x4", "l1"], Pose2Point2BearingRange(Normal(0.0,0.03), Normal(0.5,0.1)))
111102
```
112-
113-
<!-- ```@docs
114-
waitForCompletion
115-
NvaSDK.waitForCompletion2
116-
``` -->

docs/developer.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,15 @@ make docs
1818
make docs_firefox
1919
```
2020

21-
The latter also builds the docs.
21+
The latter also builds the docs.
22+
23+
## Release to PyPi
24+
25+
Have login credentials and push access to pypi.org.
26+
27+
Run
28+
```
29+
make release
30+
```
31+
32+
Do manual release tag on Github.com/NavAbility/NavAbilitySDK.py.

docs/getting-started.md

+12-5
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,33 @@ Installing from within a Python kernel can also be done using:
4343

4444
# Starting a Python REPL and Importing
4545

46-
To use the NavAbility SDK example in a REPL you need to start it with `asyncio`, i.e. run `python -m asyncio`. Together with a [virtual environment][py-venv], the entire call becomes:
46+
To use the NavAbility SDK example in a REPL, together with a [virtual environment][py-venv]
4747
```python
48-
python3 -m asyncio venv /path/to/user/venv
48+
python3 venv /path/to/user/venv
4949
```
5050

51-
If you don't, you'll see `SyntaxError: 'await' outside function`.
52-
5351
Loading the SDK module:
5452
```python
5553
from navability.entities import *
5654
from navability.services import *
57-
import asyncio
5855
from uuid import uuid4
5956
import numpy as np
57+
# import asyncio
6058
```
6159

6260
:::{seealso}
6361
The NavAbility and [Caesar.jl][cjl-docs] design promote distributed factor graph workflows for both edge and cloud usage. The NavAbilitySDK is part of a larger architecture where both client and server side computations are used. The rest of this page illustrates usage against the server side data and computations. Reach out to NavAbility via Slack [![](https://img.shields.io/badge/Invite-Slack-green.svg?style=popout)][slack-invite] or <info@navability.io> for more help.
6462
:::
6563

64+
:::{warning}
65+
Earlier versions of NavAbilitySDK.py had to be started with `python -m asyncio`, otherwise you'd see `SyntaxError: 'await' outside function`:
66+
```python
67+
# earlier versions of sdk had to be started with asyncio
68+
python3 -m asyncio venv /path/to/user/venv
69+
```
70+
:::
71+
72+
6673
[sdk-py]: https://github.com/NavAbility/NavAbilitySDK.py/issues
6774
[cjl-docs]: https://juliarobotics.org/Caesar.jl/latest/
6875
[slack-invite]: https://join.slack.com/t/caesarjl/shared_invite/zt-ucs06bwg-y2tEbddwX1vR18MASnOLsw

docs/nvatutorials.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NavAbility Tutorials
22

3-
These Tutorials can be read as static pages or be run live via Binder. Either of the options below should work.
3+
These Tutorials can be read as static pages, be run live via Binder / locally, or watched through via the YouTube walkthrough videos.
44
<!-- ## Run Via NavAbility App
55
66
A free tier access to NavAbility servers is provided through the user `guest@navability.io`. To learn more about using the guest user, consider trying the [NavAbility Tutorials](https://app.navability.io/get-started/tutorials).
@@ -20,3 +20,7 @@ On the notebook pages, use the Rocket icon in the top right menu bar to launch a
2020
- [Tutorial 3: Insufficient Data (3D Range-only)](sdkpynb:python/navability-sdk/icra-3-rangeonly)
2121
- [Tutorial 4: Leveraging (Contradictory) Prior Data](sdkpynb:python/navability-sdk/icra-4-contradictorydata)
2222
- [Tutorial 5: Marine Data: Entries and Blobs](sdkpynb:python/navability-sdk/icra-5-marineexample)
23+
24+
:::{tip}
25+
These notebooks are kept in the {NavAbility/Notebooks repo](https://github.com/NavAbility/BinderNotebooks).
26+
:::

src/navability/services/loader.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import toml
44
import re
5+
import pathlib
56

67
from gql import gql # used to parse GraphQL queries
78
from graphql import GraphQLSyntaxError # used to handle GraphQL errors
@@ -160,4 +161,5 @@ def detect_cycle(
160161

161162

162163
# Load all GraphQL operations from the "sdkCommonGQL" folder and export them
163-
GQL_FRAGMENTS, GQL_OPERATIONS = get_operations(os.path.join(".", "sdkCommonGQL"))
164+
GQL_FRAGMENTS, GQL_OPERATIONS = get_operations(os.path.join(pathlib.Path(__file__).parent.parent.parent.parent,"sdkCommonGQL"))
165+
# (os.path.join(".", "sdkCommonGQL"))

0 commit comments

Comments
 (0)