standardbots 2.0.0.dev1737492400__tar.gz → 2.0.0.dev1740502639__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of standardbots might be problematic. Click here for more details.
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/PKG-INFO +1 -1
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/README.md +16 -4
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/setup.py +1 -1
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/apis.py +185 -14
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/models.py +393 -45
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/PKG-INFO +1 -1
- standardbots-2.0.0.dev1740502639/tests/test_apis.py +2994 -0
- standardbots-2.0.0.dev1737492400/tests/test_apis.py +0 -1294
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/setup.cfg +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots/__init__.py +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/__init__.py +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/SOURCES.txt +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/dependency_links.txt +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/requires.txt +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/top_level.txt +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/tests/fixtures/__init__.py +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/tests/fixtures/client_fixt.py +0 -0
- {standardbots-2.0.0.dev1737492400 → standardbots-2.0.0.dev1740502639}/tests/fixtures/routines_fixt.py +0 -0
|
@@ -26,9 +26,14 @@ To set up tests:
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
cd sdks/python
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Note: Make sure to select proper python interpreter.
|
|
32
|
+
Sometimes there is an error related to missing "dotenv" module, to solve this install it separately
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
pip install -
|
|
34
|
+
```
|
|
35
|
+
python3 -m pip install python-dotenv
|
|
36
|
+
python3 -m pip install -r requirements-dev.txt
|
|
32
37
|
```
|
|
33
38
|
|
|
34
39
|
### Create sample data
|
|
@@ -71,7 +76,7 @@ python3 -m pytest ./tests --cov=standardbots
|
|
|
71
76
|
|
|
72
77
|
### Robot state and testing (Markers)
|
|
73
78
|
|
|
74
|
-
We need the bot to be in a certain state to run certain tests. For example, we need a routine to be running in order to stop the routine.
|
|
79
|
+
We need the bot to be in a certain state to run certain tests. For example, we need a routine to be running in order to stop the routine. Camera should be connected by default.
|
|
75
80
|
|
|
76
81
|
At start of testing, robot should:
|
|
77
82
|
|
|
@@ -82,7 +87,14 @@ The basic idea here is:
|
|
|
82
87
|
|
|
83
88
|
- These special tests will not be run by default.
|
|
84
89
|
- You may pass a flag (e.g. `--routine-running`) when the bot is in the correct state to run the tests.
|
|
85
|
-
-
|
|
90
|
+
- Markers usage:
|
|
91
|
+
- When `--routine-running` flag is passed:
|
|
92
|
+
1. Tests with the flag are run.
|
|
93
|
+
2. Tests without the flag are not run.
|
|
94
|
+
- When `--gripper=<type>` flag is passed(`type` is value from `GripperKindEnum` enum):
|
|
95
|
+
1. Tests expect that this specific gripper is connected
|
|
96
|
+
2. Tests without the flag are not run.
|
|
97
|
+
- When `--camera-disconnected` flag is passed:
|
|
86
98
|
1. Tests with the flag are run.
|
|
87
99
|
2. Tests without the flag are not run.
|
|
88
100
|
|
|
@@ -76,6 +76,95 @@ class RequestManager:
|
|
|
76
76
|
|
|
77
77
|
class Default:
|
|
78
78
|
_request_manager: RequestManager
|
|
79
|
+
class Calibration:
|
|
80
|
+
def __init__(self, request_manager: RequestManager):
|
|
81
|
+
self._request_manager = request_manager
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_active_calibration(
|
|
85
|
+
self,
|
|
86
|
+
) -> Response[
|
|
87
|
+
Union[
|
|
88
|
+
models.ActiveCalibrationContainer,
|
|
89
|
+
models.ErrorResponse,
|
|
90
|
+
None
|
|
91
|
+
],
|
|
92
|
+
models.ActiveCalibrationContainer
|
|
93
|
+
]:
|
|
94
|
+
"""
|
|
95
|
+
Get the active calibration for the robot.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
path = "/api/v1/calibration/active"
|
|
99
|
+
try:
|
|
100
|
+
response = self._request_manager.request(
|
|
101
|
+
"GET",
|
|
102
|
+
path,
|
|
103
|
+
headers=self._request_manager.json_headers(),
|
|
104
|
+
)
|
|
105
|
+
parsed = None
|
|
106
|
+
if response.status == 200:
|
|
107
|
+
parsed = models.parse_active_calibration_container(json.loads(response.data))
|
|
108
|
+
|
|
109
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
110
|
+
is_unavailable = response.status == 503
|
|
111
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
112
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
113
|
+
|
|
114
|
+
return Response(
|
|
115
|
+
parsed,
|
|
116
|
+
response.status,
|
|
117
|
+
response
|
|
118
|
+
)
|
|
119
|
+
except urllib3.exceptions.MaxRetryError:
|
|
120
|
+
return Response(
|
|
121
|
+
models.ErrorResponse(
|
|
122
|
+
error=models.ErrorEnum.InternalServerError,
|
|
123
|
+
message="Connection Refused"
|
|
124
|
+
),
|
|
125
|
+
503,
|
|
126
|
+
None
|
|
127
|
+
)
|
|
128
|
+
def set_active_calibration(
|
|
129
|
+
self,
|
|
130
|
+
body: models.ActiveCalibrationContainer,
|
|
131
|
+
) -> Response[
|
|
132
|
+
None,
|
|
133
|
+
None
|
|
134
|
+
]:
|
|
135
|
+
"""
|
|
136
|
+
Set the active calibration for the robot.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
path = "/api/v1/calibration/active"
|
|
140
|
+
try:
|
|
141
|
+
response = self._request_manager.request(
|
|
142
|
+
"POST",
|
|
143
|
+
path,
|
|
144
|
+
headers=self._request_manager.json_headers(),
|
|
145
|
+
body=json.dumps(models.serialize_active_calibration_container(body)),
|
|
146
|
+
)
|
|
147
|
+
parsed = None
|
|
148
|
+
|
|
149
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
150
|
+
is_unavailable = response.status == 503
|
|
151
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
152
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
153
|
+
|
|
154
|
+
return Response(
|
|
155
|
+
parsed,
|
|
156
|
+
response.status,
|
|
157
|
+
response
|
|
158
|
+
)
|
|
159
|
+
except urllib3.exceptions.MaxRetryError:
|
|
160
|
+
return Response(
|
|
161
|
+
models.ErrorResponse(
|
|
162
|
+
error=models.ErrorEnum.InternalServerError,
|
|
163
|
+
message="Connection Refused"
|
|
164
|
+
),
|
|
165
|
+
503,
|
|
166
|
+
None
|
|
167
|
+
)
|
|
79
168
|
class Equipment:
|
|
80
169
|
def __init__(self, request_manager: RequestManager):
|
|
81
170
|
self._request_manager = request_manager
|
|
@@ -83,7 +172,7 @@ class Default:
|
|
|
83
172
|
def onrobot_2fg7_move(
|
|
84
173
|
self,
|
|
85
174
|
value: Union[int, float],
|
|
86
|
-
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.
|
|
175
|
+
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.Internal,
|
|
87
176
|
unit_kind: Union[str, models.LinearUnitKind] = models.LinearUnitKind.Millimeters
|
|
88
177
|
):
|
|
89
178
|
"""Move the robot to the onrobot_2fg7 position.
|
|
@@ -105,7 +194,7 @@ class Default:
|
|
|
105
194
|
def onrobot_2fg7_grip(
|
|
106
195
|
self,
|
|
107
196
|
value: Union[int, float],
|
|
108
|
-
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.
|
|
197
|
+
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.Internal,
|
|
109
198
|
unit_kind: Union[str, models.LinearUnitKind] = models.LinearUnitKind.Millimeters,
|
|
110
199
|
force: Union[int, float] = 0.0,
|
|
111
200
|
force_unit: Union[str, models.ForceUnitKind] = models.ForceUnitKind.Newtons
|
|
@@ -382,12 +471,14 @@ class Default:
|
|
|
382
471
|
None
|
|
383
472
|
)
|
|
384
473
|
|
|
474
|
+
calibration: Calibration
|
|
385
475
|
equipment: Equipment
|
|
386
476
|
sensors: Sensors
|
|
387
477
|
space: Space
|
|
388
478
|
|
|
389
479
|
def __init__(self, request_manager: RequestManager):
|
|
390
480
|
self._request_manager = request_manager
|
|
481
|
+
self.calibration = Default.Calibration(request_manager)
|
|
391
482
|
self.equipment = Default.Equipment(request_manager)
|
|
392
483
|
self.sensors = Default.Sensors(request_manager)
|
|
393
484
|
self.space = Default.Space(request_manager)
|
|
@@ -425,6 +516,7 @@ class Movement:
|
|
|
425
516
|
Union[
|
|
426
517
|
models.BrakesState,
|
|
427
518
|
models.ErrorResponse,
|
|
519
|
+
models.ErrorResponse,
|
|
428
520
|
None
|
|
429
521
|
],
|
|
430
522
|
models.BrakesState
|
|
@@ -444,6 +536,8 @@ class Movement:
|
|
|
444
536
|
parsed = None
|
|
445
537
|
if response.status == 200:
|
|
446
538
|
parsed = models.parse_brakes_state(json.loads(response.data))
|
|
539
|
+
if response.status == 500:
|
|
540
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
447
541
|
|
|
448
542
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
449
543
|
is_unavailable = response.status == 503
|
|
@@ -713,7 +807,7 @@ class Camera:
|
|
|
713
807
|
None
|
|
714
808
|
]:
|
|
715
809
|
"""
|
|
716
|
-
Retrieve the latest RGB frame from the camera. In JPEG format.
|
|
810
|
+
Retrieve the latest RGB frame from the camera as base64 string. In JPEG format.
|
|
717
811
|
"""
|
|
718
812
|
path = "/api/v1/camera/frame/rgb"
|
|
719
813
|
try:
|
|
@@ -747,8 +841,12 @@ class Camera:
|
|
|
747
841
|
def get_camera_intrinsics_color(
|
|
748
842
|
self,
|
|
749
843
|
) -> Response[
|
|
750
|
-
|
|
751
|
-
|
|
844
|
+
Union[
|
|
845
|
+
models.CameraIntrinsics,
|
|
846
|
+
models.ErrorResponse,
|
|
847
|
+
None
|
|
848
|
+
],
|
|
849
|
+
models.CameraIntrinsics
|
|
752
850
|
]:
|
|
753
851
|
"""
|
|
754
852
|
Retrieve the intrinsic parameters for the color camera.
|
|
@@ -761,6 +859,8 @@ class Camera:
|
|
|
761
859
|
headers=self._request_manager.json_headers(),
|
|
762
860
|
)
|
|
763
861
|
parsed = None
|
|
862
|
+
if response.status == 200:
|
|
863
|
+
parsed = models.parse_camera_intrinsics(json.loads(response.data))
|
|
764
864
|
|
|
765
865
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
766
866
|
is_unavailable = response.status == 503
|
|
@@ -788,7 +888,7 @@ class Camera:
|
|
|
788
888
|
None
|
|
789
889
|
]:
|
|
790
890
|
"""
|
|
791
|
-
Retrieve the latest RGB frame from the camera.
|
|
891
|
+
Retrieve the latest RGB frame from the camera as base64 string. In JPEG format.
|
|
792
892
|
"""
|
|
793
893
|
path = "/api/v1/camera/stream/rgb"
|
|
794
894
|
try:
|
|
@@ -863,14 +963,64 @@ class Camera:
|
|
|
863
963
|
503,
|
|
864
964
|
None
|
|
865
965
|
)
|
|
966
|
+
class Status:
|
|
967
|
+
def __init__(self, request_manager: RequestManager):
|
|
968
|
+
self._request_manager = request_manager
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
def get_camera_status(
|
|
972
|
+
self,
|
|
973
|
+
) -> Response[
|
|
974
|
+
Union[
|
|
975
|
+
models.CameraStatus,
|
|
976
|
+
models.ErrorResponse,
|
|
977
|
+
None
|
|
978
|
+
],
|
|
979
|
+
models.CameraStatus
|
|
980
|
+
]:
|
|
981
|
+
"""
|
|
982
|
+
Retrieve the current status of the camera.
|
|
983
|
+
"""
|
|
984
|
+
path = "/api/v1/camera/status"
|
|
985
|
+
try:
|
|
986
|
+
response = self._request_manager.request(
|
|
987
|
+
"GET",
|
|
988
|
+
path,
|
|
989
|
+
headers=self._request_manager.json_headers(),
|
|
990
|
+
)
|
|
991
|
+
parsed = None
|
|
992
|
+
if response.status == 200:
|
|
993
|
+
parsed = models.parse_camera_status(json.loads(response.data))
|
|
994
|
+
|
|
995
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
996
|
+
is_unavailable = response.status == 503
|
|
997
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
998
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
999
|
+
|
|
1000
|
+
return Response(
|
|
1001
|
+
parsed,
|
|
1002
|
+
response.status,
|
|
1003
|
+
response
|
|
1004
|
+
)
|
|
1005
|
+
except urllib3.exceptions.MaxRetryError:
|
|
1006
|
+
return Response(
|
|
1007
|
+
models.ErrorResponse(
|
|
1008
|
+
error=models.ErrorEnum.InternalServerError,
|
|
1009
|
+
message="Connection Refused"
|
|
1010
|
+
),
|
|
1011
|
+
503,
|
|
1012
|
+
None
|
|
1013
|
+
)
|
|
866
1014
|
|
|
867
1015
|
data: Data
|
|
868
1016
|
settings: Settings
|
|
1017
|
+
status: Status
|
|
869
1018
|
|
|
870
1019
|
def __init__(self, request_manager: RequestManager):
|
|
871
1020
|
self._request_manager = request_manager
|
|
872
1021
|
self.data = Camera.Data(request_manager)
|
|
873
1022
|
self.settings = Camera.Settings(request_manager)
|
|
1023
|
+
self.status = Camera.Status(request_manager)
|
|
874
1024
|
|
|
875
1025
|
class Faults:
|
|
876
1026
|
_request_manager: RequestManager
|
|
@@ -1927,8 +2077,13 @@ class RoutineEditor:
|
|
|
1927
2077
|
body: models.PlayRoutineRequest,
|
|
1928
2078
|
routine_id: str,
|
|
1929
2079
|
) -> Response[
|
|
1930
|
-
|
|
1931
|
-
|
|
2080
|
+
Union[
|
|
2081
|
+
models.PlayRoutineResponse,
|
|
2082
|
+
models.ErrorResponse,
|
|
2083
|
+
models.ErrorResponse,
|
|
2084
|
+
None
|
|
2085
|
+
],
|
|
2086
|
+
models.PlayRoutineResponse
|
|
1932
2087
|
]:
|
|
1933
2088
|
"""
|
|
1934
2089
|
Play a routine
|
|
@@ -1943,6 +2098,10 @@ class RoutineEditor:
|
|
|
1943
2098
|
body=json.dumps(models.serialize_play_routine_request(body)),
|
|
1944
2099
|
)
|
|
1945
2100
|
parsed = None
|
|
2101
|
+
if response.status == 200:
|
|
2102
|
+
parsed = models.parse_play_routine_response(json.loads(response.data))
|
|
2103
|
+
if response.status == 400:
|
|
2104
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
1946
2105
|
|
|
1947
2106
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
1948
2107
|
is_unavailable = response.status == 503
|
|
@@ -1967,11 +2126,15 @@ class RoutineEditor:
|
|
|
1967
2126
|
self,
|
|
1968
2127
|
routine_id: str,
|
|
1969
2128
|
) -> Response[
|
|
1970
|
-
|
|
2129
|
+
Union[
|
|
2130
|
+
models.ErrorResponse,
|
|
2131
|
+
models.ErrorResponse,
|
|
2132
|
+
None
|
|
2133
|
+
],
|
|
1971
2134
|
None
|
|
1972
2135
|
]:
|
|
1973
2136
|
"""
|
|
1974
|
-
Pause a routine
|
|
2137
|
+
Pause a routine. Routine must be running.
|
|
1975
2138
|
"""
|
|
1976
2139
|
path = "/api/v1/routine-editor/routines/{routine_id}/pause"
|
|
1977
2140
|
path = path.replace("{routine_id}", str(routine_id))
|
|
@@ -1982,6 +2145,8 @@ class RoutineEditor:
|
|
|
1982
2145
|
headers=self._request_manager.json_headers(),
|
|
1983
2146
|
)
|
|
1984
2147
|
parsed = None
|
|
2148
|
+
if response.status == 400:
|
|
2149
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
1985
2150
|
|
|
1986
2151
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
1987
2152
|
is_unavailable = response.status == 503
|
|
@@ -2005,11 +2170,15 @@ class RoutineEditor:
|
|
|
2005
2170
|
def stop(
|
|
2006
2171
|
self,
|
|
2007
2172
|
) -> Response[
|
|
2008
|
-
|
|
2173
|
+
Union[
|
|
2174
|
+
models.ErrorResponse,
|
|
2175
|
+
models.ErrorResponse,
|
|
2176
|
+
None
|
|
2177
|
+
],
|
|
2009
2178
|
None
|
|
2010
2179
|
]:
|
|
2011
2180
|
"""
|
|
2012
|
-
Stop running routine and all ongoing motions
|
|
2181
|
+
Stop running routine and all ongoing motions. Routine must be running.
|
|
2013
2182
|
"""
|
|
2014
2183
|
path = "/api/v1/routine-editor/stop"
|
|
2015
2184
|
try:
|
|
@@ -2019,6 +2188,8 @@ class RoutineEditor:
|
|
|
2019
2188
|
headers=self._request_manager.json_headers(),
|
|
2020
2189
|
)
|
|
2021
2190
|
parsed = None
|
|
2191
|
+
if response.status == 400:
|
|
2192
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
2022
2193
|
|
|
2023
2194
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
2024
2195
|
is_unavailable = response.status == 503
|
|
@@ -2293,7 +2464,7 @@ class RoutineEditor:
|
|
|
2293
2464
|
models.RuntimeVariable
|
|
2294
2465
|
]:
|
|
2295
2466
|
"""
|
|
2296
|
-
Returns current state of a variable
|
|
2467
|
+
Returns current state of a variable. Routine must be running.
|
|
2297
2468
|
"""
|
|
2298
2469
|
path = "/api/v1/routine-editor/variables/{variable_name}"
|
|
2299
2470
|
path = path.replace("{variable_name}", str(variable_name))
|
|
@@ -2339,7 +2510,7 @@ class RoutineEditor:
|
|
|
2339
2510
|
models.RuntimeVariable
|
|
2340
2511
|
]:
|
|
2341
2512
|
"""
|
|
2342
|
-
Update the value of a variable
|
|
2513
|
+
Update the value of a variable. Routine must be running.
|
|
2343
2514
|
"""
|
|
2344
2515
|
path = "/api/v1/routine-editor/variables/{variable_name}"
|
|
2345
2516
|
path = path.replace("{variable_name}", str(variable_name))
|