bosdyn-mission 3.3.2__py3-none-any.whl → 4.0.1__py3-none-any.whl
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.
- bosdyn/mission/client.py +35 -8
- bosdyn/mission/remote_client.py +2 -2
- bosdyn/mission/server_util.py +2 -4
- bosdyn/mission/util.py +57 -11
- {bosdyn_mission-3.3.2.dist-info → bosdyn_mission-4.0.1.dist-info}/METADATA +4 -5
- bosdyn_mission-4.0.1.dist-info/RECORD +12 -0
- {bosdyn_mission-3.3.2.dist-info → bosdyn_mission-4.0.1.dist-info}/WHEEL +1 -1
- bosdyn_mission-3.3.2.dist-info/RECORD +0 -12
- {bosdyn_mission-3.3.2.dist-info → bosdyn_mission-4.0.1.dist-info}/top_level.txt +0 -0
bosdyn/mission/client.py
CHANGED
|
@@ -36,6 +36,14 @@ class QuestionAlreadyAnswered(MissionResponseError):
|
|
|
36
36
|
"""The indicated question was already answered."""
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
class CustomParamsError(MissionResponseError):
|
|
40
|
+
"""The indicated answer does not match the spec for the indicated answer"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class IncompatibleAnswer(MissionResponseError):
|
|
44
|
+
"""The indicated answer is not in a format expected by the indicated question."""
|
|
45
|
+
|
|
46
|
+
|
|
39
47
|
class CompilationError(MissionResponseError):
|
|
40
48
|
"""Mission could not be compiled."""
|
|
41
49
|
|
|
@@ -105,25 +113,28 @@ class MissionClient(BaseClient):
|
|
|
105
113
|
return self.call_async(self._stub.GetState, req, _get_state_value, common_header_errors,
|
|
106
114
|
copy_request=False, **kwargs)
|
|
107
115
|
|
|
108
|
-
def answer_question(self, question_id, code, **kwargs):
|
|
116
|
+
def answer_question(self, question_id, code=None, custom_params=None, **kwargs):
|
|
109
117
|
"""Specify an answer to the question asked by the mission.
|
|
110
118
|
Args:
|
|
111
119
|
question_id (int): ID of the question to answer.
|
|
112
120
|
code (int): Answer code.
|
|
121
|
+
custom_params (DictParam): Answer to a custom params prompt.
|
|
113
122
|
|
|
114
123
|
Raises:
|
|
115
124
|
RpcError: Problem communicating with the robot.
|
|
116
125
|
InvalidQuestionId: question_id was not a valid id.
|
|
117
126
|
InvalidAnswerCode: code was not valid for the question.
|
|
118
127
|
QuestionAlreadyAnswered: The question for question_id was already answered.
|
|
128
|
+
CustomParamsError: The answer did not match the spec for the question.
|
|
129
|
+
IncompatibleAnswer: The answer did not match a type expected for the question.
|
|
119
130
|
"""
|
|
120
|
-
req = self._answer_question_request(question_id, code)
|
|
131
|
+
req = self._answer_question_request(question_id, code, custom_params)
|
|
121
132
|
return self.call(self._stub.AnswerQuestion, req, None, _answer_question_error_from_response,
|
|
122
133
|
copy_request=False, **kwargs)
|
|
123
134
|
|
|
124
|
-
def answer_question_async(self, question_id, code, **kwargs):
|
|
135
|
+
def answer_question_async(self, question_id, code=None, custom_params=None, **kwargs):
|
|
125
136
|
"""Async version of answer_question()"""
|
|
126
|
-
req = self._answer_question_request(question_id, code)
|
|
137
|
+
req = self._answer_question_request(question_id, code, custom_params)
|
|
127
138
|
return self.call_async(self._stub.AnswerQuestion, req, None,
|
|
128
139
|
_answer_question_error_from_response, copy_request=False, **kwargs)
|
|
129
140
|
|
|
@@ -287,8 +298,19 @@ class MissionClient(BaseClient):
|
|
|
287
298
|
RpcError: Problem communicating with the robot.
|
|
288
299
|
"""
|
|
289
300
|
req = self._get_info_request()
|
|
290
|
-
|
|
291
|
-
|
|
301
|
+
try:
|
|
302
|
+
return self._get_info_as_chunks_call(req)
|
|
303
|
+
except UnimplementedError as err:
|
|
304
|
+
# This indicates that the software release running on robot does not yet have
|
|
305
|
+
# the implementation for the streaming response of GetInfo.
|
|
306
|
+
return self.call(self._stub.GetInfo, req, _get_info_value, common_header_errors,
|
|
307
|
+
copy_request=False, **kwargs)
|
|
308
|
+
|
|
309
|
+
def _get_info_as_chunks_call(self, req, **kwargs):
|
|
310
|
+
"""Issues the GetInfoAsChunks RPC to the mission service."""
|
|
311
|
+
return self.call(self._stub.GetInfoAsChunks, req, _get_info_value,
|
|
312
|
+
error_from_response=common_header_errors,
|
|
313
|
+
assemble_type=mission_pb2.GetInfoResponse, copy_request=False, **kwargs)
|
|
292
314
|
|
|
293
315
|
def get_info_async(self, **kwargs):
|
|
294
316
|
"""Async version of get_info."""
|
|
@@ -334,8 +356,9 @@ class MissionClient(BaseClient):
|
|
|
334
356
|
return request
|
|
335
357
|
|
|
336
358
|
@staticmethod
|
|
337
|
-
def _answer_question_request(question_id, code):
|
|
338
|
-
return mission_pb2.AnswerQuestionRequest(question_id=question_id, code=code
|
|
359
|
+
def _answer_question_request(question_id, code, custom_params):
|
|
360
|
+
return mission_pb2.AnswerQuestionRequest(question_id=question_id, code=code,
|
|
361
|
+
custom_params=custom_params)
|
|
339
362
|
|
|
340
363
|
@staticmethod
|
|
341
364
|
def _load_mission_request(root, leases):
|
|
@@ -400,6 +423,10 @@ _ANSWER_QUESTION_STATUS_TO_ERROR.update({
|
|
|
400
423
|
(InvalidAnswerCode, InvalidAnswerCode.__doc__),
|
|
401
424
|
mission_pb2.AnswerQuestionResponse.STATUS_ALREADY_ANSWERED:
|
|
402
425
|
(QuestionAlreadyAnswered, QuestionAlreadyAnswered.__doc__),
|
|
426
|
+
mission_pb2.AnswerQuestionResponse.STATUS_CUSTOM_PARAMS_ERROR:
|
|
427
|
+
(CustomParamsError, CustomParamsError.__doc__),
|
|
428
|
+
mission_pb2.AnswerQuestionResponse.STATUS_INCOMPATIBLE_ANSWER:
|
|
429
|
+
(IncompatibleAnswer, IncompatibleAnswer.__doc__),
|
|
403
430
|
})
|
|
404
431
|
|
|
405
432
|
|
bosdyn/mission/remote_client.py
CHANGED
|
@@ -64,7 +64,7 @@ class RemoteClient(BaseClient):
|
|
|
64
64
|
|
|
65
65
|
Args:
|
|
66
66
|
leases (Iterable[Lease]): List of lease protobufs to establish session with.
|
|
67
|
-
inputs (Iterable[bosdyn.api.mission.KeyValue]): any inputs needed by
|
|
67
|
+
inputs (Iterable[bosdyn.api.mission.KeyValue]): any inputs needed by the remote node.
|
|
68
68
|
lease_resources (Iterable[str]): List of resource names to use from the lease wallet.
|
|
69
69
|
Only applied if no leases are provided.
|
|
70
70
|
"""
|
|
@@ -92,7 +92,7 @@ class RemoteClient(BaseClient):
|
|
|
92
92
|
Args:
|
|
93
93
|
session_id: session
|
|
94
94
|
leases (Iterable[Lease]): List of lease protobufs to use during the tick.
|
|
95
|
-
inputs (Iterable[bosdyn.api.mission.KeyValue]): any inputs needed by
|
|
95
|
+
inputs (Iterable[bosdyn.api.mission.KeyValue]): any inputs needed by the remote node.
|
|
96
96
|
lease_resources (Iterable[str]): List of resource names to use from the lease wallet.
|
|
97
97
|
Only applied if no leases are provided.
|
|
98
98
|
"""
|
bosdyn/mission/server_util.py
CHANGED
|
@@ -8,6 +8,7 @@ from deprecated.sphinx import deprecated
|
|
|
8
8
|
|
|
9
9
|
import bosdyn.util
|
|
10
10
|
from bosdyn.api import header_pb2
|
|
11
|
+
from bosdyn.deprecated import moved_to
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
@@ -34,7 +35,4 @@ class ResponseContext(object):
|
|
|
34
35
|
self.rpc_logger.add_protobuf_async(self.response)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
set_response_header =
|
|
38
|
-
reason='The bosdyn.mission.set_response_header helper class has moved to a common '
|
|
39
|
-
'location. Please use bosdyn.client.server_util.populate_response_header.', version='3.0.0',
|
|
40
|
-
action="always")(bosdyn.client.server_util.populate_response_header)
|
|
38
|
+
set_response_header = moved_to(bosdyn.client.server_util.populate_response_header, version='3.0.0')
|
bosdyn/mission/util.py
CHANGED
|
@@ -9,16 +9,21 @@ import json
|
|
|
9
9
|
import operator
|
|
10
10
|
import re
|
|
11
11
|
from builtins import str as text
|
|
12
|
+
from typing import Dict, Union
|
|
12
13
|
|
|
13
14
|
import google.protobuf.message
|
|
14
15
|
import google.protobuf.struct_pb2
|
|
15
16
|
import google.protobuf.text_format
|
|
17
|
+
from deprecated.sphinx import deprecated
|
|
18
|
+
from google.protobuf import message_factory
|
|
16
19
|
|
|
17
20
|
from bosdyn.api import data_acquisition_pb2, geometry_pb2, gripper_camera_param_pb2
|
|
18
21
|
from bosdyn.api.autowalk import walks_pb2
|
|
19
22
|
from bosdyn.api.docking import docking_pb2
|
|
20
23
|
from bosdyn.api.graph_nav import graph_nav_pb2, map_pb2
|
|
21
24
|
from bosdyn.api.mission import mission_pb2, nodes_pb2, util_pb2
|
|
25
|
+
from bosdyn.client.util import safe_pb_enum_to_string as _bosdyn_client_safe_pb_enum_to_string
|
|
26
|
+
from bosdyn.deprecated import moved_to
|
|
22
27
|
from bosdyn.mission import constants
|
|
23
28
|
|
|
24
29
|
# This is a special dummy message we'll use for TYPE_MESSAGE parameters.
|
|
@@ -61,7 +66,24 @@ def tree_to_string(root, start_level=0, include_status=False):
|
|
|
61
66
|
return string
|
|
62
67
|
|
|
63
68
|
|
|
64
|
-
def
|
|
69
|
+
def type_to_field_name(type_name):
|
|
70
|
+
"""Use type name to reconstruct field name of bosdyn.api.mission.Node.type
|
|
71
|
+
Example: SimpleParallel becomes simple_parallel"""
|
|
72
|
+
node_type = str(type_name).split('.')[-1]
|
|
73
|
+
field_name = node_type[0].lower()
|
|
74
|
+
for char in node_type[1:]:
|
|
75
|
+
if char.isupper():
|
|
76
|
+
field_name += f'_{char.lower()}'
|
|
77
|
+
else:
|
|
78
|
+
field_name += char
|
|
79
|
+
|
|
80
|
+
oneof_field_names = [x.name for x in nodes_pb2.Node.DESCRIPTOR.oneofs_by_name['type'].fields]
|
|
81
|
+
assert field_name in oneof_field_names, f'{field_name} is not a field name in bosdyn.api.mission.Node.type'
|
|
82
|
+
|
|
83
|
+
return field_name
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def proto_from_tuple(tup, pack_nodes=True):
|
|
65
87
|
"""Return a bosdyn.api.mission Node from a tuple. EXPERIMENTAL.
|
|
66
88
|
|
|
67
89
|
Example:
|
|
@@ -81,7 +103,7 @@ def proto_from_tuple(tup):
|
|
|
81
103
|
tup: (Name of node, Instantiated implementation of node protobuf, List of children tuples)
|
|
82
104
|
"""
|
|
83
105
|
if isinstance(tup, nodes_pb2.Node):
|
|
84
|
-
# Sometimes the
|
|
106
|
+
# Sometimes the shorthand doesn't work nicely, and in those cases we allow setting
|
|
85
107
|
# The node itself.
|
|
86
108
|
return tup
|
|
87
109
|
|
|
@@ -148,11 +170,15 @@ def proto_from_tuple(tup):
|
|
|
148
170
|
elif num_children != 0:
|
|
149
171
|
raise Error('Proto "{}" of type "{}" was given {} children, but I do not know how to add'
|
|
150
172
|
' them!'.format(node.name, inner_type, num_children))
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
if pack_nodes:
|
|
174
|
+
node.impl.Pack(inner_proto)
|
|
175
|
+
else:
|
|
176
|
+
getattr(node, type_to_field_name(inner_type)).CopyFrom(inner_proto)
|
|
153
177
|
return node
|
|
154
178
|
|
|
155
179
|
|
|
180
|
+
|
|
181
|
+
|
|
156
182
|
def python_var_to_value(var):
|
|
157
183
|
"""Returns a ConstantValue with the appropriate oneof set."""
|
|
158
184
|
value = util_pb2.ConstantValue()
|
|
@@ -318,7 +344,7 @@ def get_value_from_constant_value_message(const_proto):
|
|
|
318
344
|
return value
|
|
319
345
|
|
|
320
346
|
|
|
321
|
-
def get_value_from_value_message(node, blackboard, value_msg):
|
|
347
|
+
def get_value_from_value_message(node, blackboard, value_msg, is_validation=False):
|
|
322
348
|
if value_msg.HasField(text("constant")):
|
|
323
349
|
constant = value_msg.constant
|
|
324
350
|
return get_value_from_constant_value_message(constant)
|
|
@@ -328,11 +354,31 @@ def get_value_from_value_message(node, blackboard, value_msg):
|
|
|
328
354
|
raise AttributeError("Value must be a runtime variable or constant.")
|
|
329
355
|
|
|
330
356
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
357
|
+
safe_pb_enum_to_string = moved_to(_bosdyn_client_safe_pb_enum_to_string, version='4.0.0')
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def create_value(
|
|
361
|
+
var: Union[bool, int, float, str, google.protobuf.message.Message]) -> util_pb2.Value:
|
|
362
|
+
"""Returns a Value message containing a ConstantValue with the appropriate oneof set.
|
|
363
|
+
"""
|
|
364
|
+
return util_pb2.Value(constant=python_var_to_value(var))
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def define_blackboard(dict_values: Dict[str, util_pb2.Value]) -> nodes_pb2.DefineBlackboard:
|
|
368
|
+
"""Returns a DefineBlackboard protobuf message for the key-value pairs in `dict_values`.
|
|
369
|
+
"""
|
|
370
|
+
node_to_return = nodes_pb2.DefineBlackboard()
|
|
371
|
+
for (key, value) in dict_values.items():
|
|
372
|
+
node_to_return.blackboard_variables.add().CopyFrom(util_pb2.KeyValue(key=key, value=value))
|
|
373
|
+
return node_to_return
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def set_blackboard(dict_values: Dict[str, util_pb2.Value]) -> nodes_pb2.SetBlackboard:
|
|
377
|
+
"""Returns a SetBlackboard protobuf message for the key-value pairs in `dict_values`.
|
|
378
|
+
"""
|
|
379
|
+
node_to_return = nodes_pb2.SetBlackboard()
|
|
380
|
+
for (key, value) in dict_values.items():
|
|
381
|
+
node_to_return.blackboard_variables.add().CopyFrom(util_pb2.KeyValue(key=key, value=value))
|
|
382
|
+
return node_to_return
|
|
337
383
|
|
|
338
384
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bosdyn-mission
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.1
|
|
4
4
|
Summary: Boston Dynamics mission code
|
|
5
5
|
Home-page: https://dev.bostondynamics.com/
|
|
6
6
|
Author: Boston Dynamics
|
|
@@ -15,8 +15,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
15
15
|
Classifier: License :: Other/Proprietary License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: bosdyn-client (==
|
|
19
|
-
Requires-Dist: bosdyn-api (==
|
|
18
|
+
Requires-Dist: bosdyn-client (==4.0.1)
|
|
19
|
+
Requires-Dist: bosdyn-api (==4.0.1)
|
|
20
20
|
|
|
21
21
|
<!--
|
|
22
22
|
Copyright (c) 2023 Boston Dynamics, Inc. All rights reserved.
|
|
@@ -37,5 +37,4 @@ missions, which are part of the Boston Dynamics Spot API. The client interfaces
|
|
|
37
37
|
implement the mission-related Remote Procedure Calls (RPCs) defined in
|
|
38
38
|
[bosdyn-api wheel](https://pypi.org/project/bosdyn-api/) and they utilize code included in the
|
|
39
39
|
[bosdyn-client wheel](https://pypi.org/project/bosdyn-client/). Full design documentation for the
|
|
40
|
-
functionality included in this wheel can be found
|
|
41
|
-
[here](https://dev.bostondynamics.com/docs/concepts/autonomy/missions_service).
|
|
40
|
+
functionality included in this wheel can be found [here](../../docs/concepts/autonomy/missions_service.md).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
bosdyn/__init__.py,sha256=CMQioQKK1NlMk3kZuY49b_Aw-JyvDeOtuqOCAul1I0s,330
|
|
2
|
+
bosdyn/mission/__init__.py,sha256=_BpC0ZVGQ5yH5S8rt_DrTMQkAuxzTn5YlPvwDzeFXdQ,483
|
|
3
|
+
bosdyn/mission/client.py,sha256=_jjFZ1FCDNaKKcJ0pzHZ6suADTKcaaXHqp0GV5691M8,22437
|
|
4
|
+
bosdyn/mission/constants.py,sha256=oSsl0XR1-fNzHASGNqs541YEO8qi64eewvbY9ICKaxE,435
|
|
5
|
+
bosdyn/mission/exceptions.py,sha256=UqGT0XK3zA6Bgwo_7KNC44yi_MvW9h3c8_pHKML8ELQ,3941
|
|
6
|
+
bosdyn/mission/remote_client.py,sha256=quGWyqLzpASgrR6MlnEPoRFCmnTMSBZ6tmr-Wyy9YW0,12190
|
|
7
|
+
bosdyn/mission/server_util.py,sha256=_ts77W8yGq9BXhgOWwtMCXaxDjUxoorEPk1-YooEUNA,1508
|
|
8
|
+
bosdyn/mission/util.py,sha256=30_LIam0ve6JTXZfXmZyza0Vey1FC3LHln81rUeAm_w,15616
|
|
9
|
+
bosdyn_mission-4.0.1.dist-info/METADATA,sha256=foyspudk4oRuRkFkE5T6MklXqahIP4E2_c9GTSx48Wo,1760
|
|
10
|
+
bosdyn_mission-4.0.1.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
|
11
|
+
bosdyn_mission-4.0.1.dist-info/top_level.txt,sha256=an2OWgx1ej2jFjmBjPWNQ68ZglvUfKhmXWW-WhTtDmA,7
|
|
12
|
+
bosdyn_mission-4.0.1.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
bosdyn/__init__.py,sha256=CMQioQKK1NlMk3kZuY49b_Aw-JyvDeOtuqOCAul1I0s,330
|
|
2
|
-
bosdyn/mission/__init__.py,sha256=_BpC0ZVGQ5yH5S8rt_DrTMQkAuxzTn5YlPvwDzeFXdQ,483
|
|
3
|
-
bosdyn/mission/client.py,sha256=UeVysD0UBU3sV1DFBZF3K5dvfGbLqcDKWe9zjytqEec,20860
|
|
4
|
-
bosdyn/mission/constants.py,sha256=oSsl0XR1-fNzHASGNqs541YEO8qi64eewvbY9ICKaxE,435
|
|
5
|
-
bosdyn/mission/exceptions.py,sha256=UqGT0XK3zA6Bgwo_7KNC44yi_MvW9h3c8_pHKML8ELQ,3941
|
|
6
|
-
bosdyn/mission/remote_client.py,sha256=rWMgI-Il8cZ-gGjUu7vHnfhyiNHTEk39NlDDK_5t-eg,12196
|
|
7
|
-
bosdyn/mission/server_util.py,sha256=ytvamtXK_CzLmnAn-4ybJ7PNyGfpG-HGfJZFuARxHcs,1661
|
|
8
|
-
bosdyn/mission/util.py,sha256=dO8zMy-zgp_rt-q9dAQfvnr_1OnJ7mUfhHBo2skZJyA,13577
|
|
9
|
-
bosdyn_mission-3.3.2.dist-info/METADATA,sha256=4YmV_fDakosgaauANGxEozLC2P08YTD35ypD2O9SPRo,1782
|
|
10
|
-
bosdyn_mission-3.3.2.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
11
|
-
bosdyn_mission-3.3.2.dist-info/top_level.txt,sha256=an2OWgx1ej2jFjmBjPWNQ68ZglvUfKhmXWW-WhTtDmA,7
|
|
12
|
-
bosdyn_mission-3.3.2.dist-info/RECORD,,
|
|
File without changes
|