ephys-link 2.0.0b5__py3-none-any.whl → 2.0.0b9__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.
- ephys_link/__about__.py +1 -1
- ephys_link/__main__.py +51 -43
- ephys_link/back_end/platform_handler.py +315 -305
- ephys_link/back_end/server.py +274 -202
- ephys_link/bindings/{fake_bindings.py → fake_binding.py} +84 -59
- ephys_link/bindings/{mpm_bindings.py → mpm_binding.py} +315 -278
- ephys_link/bindings/{ump_4_bindings.py → ump_4_binding.py} +157 -131
- ephys_link/front_end/cli.py +104 -98
- ephys_link/front_end/gui.py +204 -215
- ephys_link/{util/base_bindings.py → utils/base_binding.py} +176 -148
- ephys_link/{util → utils}/console.py +127 -130
- ephys_link/utils/constants.py +23 -0
- ephys_link/utils/converters.py +86 -0
- ephys_link/utils/startup.py +65 -0
- ephys_link-2.0.0b9.dist-info/METADATA +91 -0
- ephys_link-2.0.0b9.dist-info/RECORD +25 -0
- {ephys_link-2.0.0b5.dist-info → ephys_link-2.0.0b9.dist-info}/WHEEL +1 -1
- {ephys_link-2.0.0b5.dist-info → ephys_link-2.0.0b9.dist-info}/licenses/LICENSE +674 -674
- ephys_link/resources/CP210xManufacturing.dll +0 -0
- ephys_link/resources/NstMotorCtrl.dll +0 -0
- ephys_link/resources/SiUSBXp.dll +0 -0
- ephys_link/util/common.py +0 -120
- ephys_link-2.0.0b5.dist-info/METADATA +0 -166
- ephys_link-2.0.0b5.dist-info/RECORD +0 -26
- /ephys_link/{util → utils}/__init__.py +0 -0
- {ephys_link-2.0.0b5.dist-info → ephys_link-2.0.0b9.dist-info}/entry_points.txt +0 -0
|
@@ -1,305 +1,315 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
from ephys_link.bindings.
|
|
29
|
-
from ephys_link.
|
|
30
|
-
from ephys_link.
|
|
31
|
-
from ephys_link.
|
|
32
|
-
from ephys_link.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class PlatformHandler:
|
|
37
|
-
"""Handler for platform commands."""
|
|
38
|
-
|
|
39
|
-
def __init__(self, options: EphysLinkOptions, console: Console) -> None:
|
|
40
|
-
"""Initialize platform handler.
|
|
41
|
-
|
|
42
|
-
:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# Store the CLI options.
|
|
47
|
-
self._options = options
|
|
48
|
-
|
|
49
|
-
# Store the console.
|
|
50
|
-
self._console = console
|
|
51
|
-
|
|
52
|
-
# Define bindings based on platform type.
|
|
53
|
-
self._bindings = self.
|
|
54
|
-
|
|
55
|
-
# Record which IDs are inside the brain.
|
|
56
|
-
self._inside_brain: set[str] = set()
|
|
57
|
-
|
|
58
|
-
# Generate a Pinpoint ID for proxy usage.
|
|
59
|
-
self._pinpoint_id = str(uuid4())[:8]
|
|
60
|
-
|
|
61
|
-
def
|
|
62
|
-
"""Match the platform type to the appropriate bindings.
|
|
63
|
-
|
|
64
|
-
:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"""
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
self.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return GetManipulatorsResponse(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
:
|
|
154
|
-
|
|
155
|
-
"""
|
|
156
|
-
try:
|
|
157
|
-
angles = await self._bindings.get_angles(manipulator_id)
|
|
158
|
-
except Exception as e:
|
|
159
|
-
self._console.exception_error_print("Get Angles", e)
|
|
160
|
-
return AngularResponse(error=self._console.pretty_exception(e))
|
|
161
|
-
else:
|
|
162
|
-
return AngularResponse(angles=angles)
|
|
163
|
-
|
|
164
|
-
async def get_shank_count(self, manipulator_id: str) -> ShankCountResponse:
|
|
165
|
-
"""Get the number of shanks on a manipulator.
|
|
166
|
-
|
|
167
|
-
:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
f"
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return PositionalResponse(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
:
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
1
|
+
"""Manipulator platform handler.
|
|
2
|
+
|
|
3
|
+
Responsible for performing the various manipulator commands.
|
|
4
|
+
Instantiates the appropriate bindings based on the platform type and uses them to perform the commands.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
Instantiate PlatformHandler with the platform type and call the desired command.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import final
|
|
11
|
+
from uuid import uuid4
|
|
12
|
+
|
|
13
|
+
from vbl_aquarium.models.ephys_link import (
|
|
14
|
+
AngularResponse,
|
|
15
|
+
BooleanStateResponse,
|
|
16
|
+
EphysLinkOptions,
|
|
17
|
+
GetManipulatorsResponse,
|
|
18
|
+
PlatformInfo,
|
|
19
|
+
PositionalResponse,
|
|
20
|
+
SetDepthRequest,
|
|
21
|
+
SetDepthResponse,
|
|
22
|
+
SetInsideBrainRequest,
|
|
23
|
+
SetPositionRequest,
|
|
24
|
+
ShankCountResponse,
|
|
25
|
+
)
|
|
26
|
+
from vbl_aquarium.models.unity import Vector4
|
|
27
|
+
|
|
28
|
+
from ephys_link.bindings.mpm_binding import MPMBinding
|
|
29
|
+
from ephys_link.utils.base_binding import BaseBinding
|
|
30
|
+
from ephys_link.utils.console import Console
|
|
31
|
+
from ephys_link.utils.converters import vector4_to_array
|
|
32
|
+
from ephys_link.utils.startup import get_bindings
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@final
|
|
36
|
+
class PlatformHandler:
|
|
37
|
+
"""Handler for platform commands."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, options: EphysLinkOptions, console: Console) -> None:
|
|
40
|
+
"""Initialize platform handler.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
options: CLI options.
|
|
44
|
+
console: Console instance.
|
|
45
|
+
"""
|
|
46
|
+
# Store the CLI options.
|
|
47
|
+
self._options = options
|
|
48
|
+
|
|
49
|
+
# Store the console.
|
|
50
|
+
self._console = console
|
|
51
|
+
|
|
52
|
+
# Define bindings based on platform type.
|
|
53
|
+
self._bindings = self._get_binding_instance(options)
|
|
54
|
+
|
|
55
|
+
# Record which IDs are inside the brain.
|
|
56
|
+
self._inside_brain: set[str] = set()
|
|
57
|
+
|
|
58
|
+
# Generate a Pinpoint ID for proxy usage.
|
|
59
|
+
self._pinpoint_id = str(uuid4())[:8]
|
|
60
|
+
|
|
61
|
+
def _get_binding_instance(self, options: EphysLinkOptions) -> BaseBinding:
|
|
62
|
+
"""Match the platform type to the appropriate bindings.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
options: CLI options.
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
ValueError: If the platform type is not recognized.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Bindings for the specified platform type.
|
|
72
|
+
"""
|
|
73
|
+
for binding_type in get_bindings():
|
|
74
|
+
binding_cli_name = binding_type.get_cli_name()
|
|
75
|
+
|
|
76
|
+
if binding_cli_name == options.type:
|
|
77
|
+
# Pass in HTTP port for Pathfinder MPM.
|
|
78
|
+
if binding_cli_name == "pathfinder-mpm":
|
|
79
|
+
return MPMBinding(options.mpm_port)
|
|
80
|
+
|
|
81
|
+
# Otherwise just return the binding.
|
|
82
|
+
return binding_type()
|
|
83
|
+
|
|
84
|
+
# Raise an error if the platform type is not recognized.
|
|
85
|
+
error_message = f'Platform type "{options.type}" not recognized.'
|
|
86
|
+
self._console.critical_print(error_message)
|
|
87
|
+
raise ValueError(error_message)
|
|
88
|
+
|
|
89
|
+
# Platform metadata.
|
|
90
|
+
|
|
91
|
+
def get_display_name(self) -> str:
|
|
92
|
+
"""Get the display name for the platform.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Display name for the platform.
|
|
96
|
+
"""
|
|
97
|
+
return self._bindings.get_display_name()
|
|
98
|
+
|
|
99
|
+
async def get_platform_info(self) -> PlatformInfo:
|
|
100
|
+
"""Get the manipulator platform type connected to Ephys Link.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Platform type config identifier (see CLI options for examples).
|
|
104
|
+
"""
|
|
105
|
+
return PlatformInfo(
|
|
106
|
+
name=self._bindings.get_display_name(),
|
|
107
|
+
cli_name=self._bindings.get_cli_name(),
|
|
108
|
+
axes_count=await self._bindings.get_axes_count(),
|
|
109
|
+
dimensions=self._bindings.get_dimensions(),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Manipulator commands.
|
|
113
|
+
|
|
114
|
+
async def get_manipulators(self) -> GetManipulatorsResponse:
|
|
115
|
+
"""Get a list of available manipulators on the current handler.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
List of manipulator IDs or an error message if any.
|
|
119
|
+
"""
|
|
120
|
+
try:
|
|
121
|
+
manipulators = await self._bindings.get_manipulators()
|
|
122
|
+
except Exception as e: # noqa: BLE001
|
|
123
|
+
self._console.exception_error_print("Get Manipulators", e)
|
|
124
|
+
return GetManipulatorsResponse(error=self._console.pretty_exception(e))
|
|
125
|
+
else:
|
|
126
|
+
return GetManipulatorsResponse(manipulators=manipulators)
|
|
127
|
+
|
|
128
|
+
async def get_position(self, manipulator_id: str) -> PositionalResponse:
|
|
129
|
+
"""Get the current translation position of a manipulator in unified coordinates (mm).
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
manipulator_id: Manipulator ID.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Current position of the manipulator and an error message if any.
|
|
136
|
+
"""
|
|
137
|
+
try:
|
|
138
|
+
unified_position = self._bindings.platform_space_to_unified_space(
|
|
139
|
+
await self._bindings.get_position(manipulator_id)
|
|
140
|
+
)
|
|
141
|
+
except Exception as e: # noqa: BLE001
|
|
142
|
+
self._console.exception_error_print("Get Position", e)
|
|
143
|
+
return PositionalResponse(error=str(e))
|
|
144
|
+
else:
|
|
145
|
+
return PositionalResponse(position=unified_position)
|
|
146
|
+
|
|
147
|
+
async def get_angles(self, manipulator_id: str) -> AngularResponse:
|
|
148
|
+
"""Get the current rotation angles of a manipulator in Yaw, Pitch, Roll (degrees).
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
manipulator_id: Manipulator ID.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Current angles of the manipulator and an error message if any.
|
|
155
|
+
"""
|
|
156
|
+
try:
|
|
157
|
+
angles = await self._bindings.get_angles(manipulator_id)
|
|
158
|
+
except Exception as e: # noqa: BLE001
|
|
159
|
+
self._console.exception_error_print("Get Angles", e)
|
|
160
|
+
return AngularResponse(error=self._console.pretty_exception(e))
|
|
161
|
+
else:
|
|
162
|
+
return AngularResponse(angles=angles)
|
|
163
|
+
|
|
164
|
+
async def get_shank_count(self, manipulator_id: str) -> ShankCountResponse:
|
|
165
|
+
"""Get the number of shanks on a manipulator.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
manipulator_id: Manipulator ID.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Number of shanks on the manipulator and an error message if any.
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
shank_count = await self._bindings.get_shank_count(manipulator_id)
|
|
175
|
+
except Exception as e: # noqa: BLE001
|
|
176
|
+
self._console.exception_error_print("Get Shank Count", e)
|
|
177
|
+
return ShankCountResponse(error=self._console.pretty_exception(e))
|
|
178
|
+
else:
|
|
179
|
+
return ShankCountResponse(shank_count=shank_count)
|
|
180
|
+
|
|
181
|
+
async def set_position(self, request: SetPositionRequest) -> PositionalResponse:
|
|
182
|
+
"""Move a manipulator to a specified translation position in unified coordinates (mm).
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
request: Request to move a manipulator to a specified position.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Final position of the manipulator and an error message if any.
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
# Disallow setting manipulator position while inside the brain.
|
|
192
|
+
if request.manipulator_id in self._inside_brain:
|
|
193
|
+
error_message = 'Can not move manipulator while inside the brain. Set the depth ("set_depth") instead.'
|
|
194
|
+
self._console.error_print("Set Position", error_message)
|
|
195
|
+
return PositionalResponse(error=error_message)
|
|
196
|
+
|
|
197
|
+
# Move to the new position.
|
|
198
|
+
final_platform_position = await self._bindings.set_position(
|
|
199
|
+
manipulator_id=request.manipulator_id,
|
|
200
|
+
position=self._bindings.unified_space_to_platform_space(request.position),
|
|
201
|
+
speed=request.speed,
|
|
202
|
+
)
|
|
203
|
+
final_unified_position = self._bindings.platform_space_to_unified_space(final_platform_position)
|
|
204
|
+
|
|
205
|
+
# Return error if movement did not reach target within tolerance.
|
|
206
|
+
for index, axis in enumerate(vector4_to_array(final_unified_position - request.position)):
|
|
207
|
+
# End once index is the number of axes.
|
|
208
|
+
if index == await self._bindings.get_axes_count():
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
# Check if the axis is within the movement tolerance.
|
|
212
|
+
if abs(axis) > self._bindings.get_movement_tolerance():
|
|
213
|
+
error_message = (
|
|
214
|
+
f"Manipulator {request.manipulator_id} did not reach target"
|
|
215
|
+
f" position on axis {list(Vector4.model_fields.keys())[index]}."
|
|
216
|
+
f" Requested: {request.position}, got: {final_unified_position}."
|
|
217
|
+
)
|
|
218
|
+
self._console.error_print("Set Position", error_message)
|
|
219
|
+
return PositionalResponse(error=error_message)
|
|
220
|
+
except Exception as e: # noqa: BLE001
|
|
221
|
+
self._console.exception_error_print("Set Position", e)
|
|
222
|
+
return PositionalResponse(error=self._console.pretty_exception(e))
|
|
223
|
+
else:
|
|
224
|
+
return PositionalResponse(position=final_unified_position)
|
|
225
|
+
|
|
226
|
+
async def set_depth(self, request: SetDepthRequest) -> SetDepthResponse:
|
|
227
|
+
"""Move a manipulator's depth translation stage to a specific value (mm).
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
request: Request to move a manipulator to a specified depth.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Final depth of the manipulator and an error message if any.
|
|
234
|
+
"""
|
|
235
|
+
try:
|
|
236
|
+
# Move to the new depth.
|
|
237
|
+
final_platform_depth = await self._bindings.set_depth(
|
|
238
|
+
manipulator_id=request.manipulator_id,
|
|
239
|
+
depth=self._bindings.unified_space_to_platform_space(Vector4(w=request.depth)).w,
|
|
240
|
+
speed=request.speed,
|
|
241
|
+
)
|
|
242
|
+
final_unified_depth = self._bindings.platform_space_to_unified_space(Vector4(w=final_platform_depth)).w
|
|
243
|
+
|
|
244
|
+
# Return error if movement did not reach target within tolerance.
|
|
245
|
+
if abs(final_unified_depth - request.depth) > self._bindings.get_movement_tolerance():
|
|
246
|
+
error_message = (
|
|
247
|
+
f"Manipulator {request.manipulator_id} did not reach target depth."
|
|
248
|
+
f" Requested: {request.depth}, got: {final_unified_depth}."
|
|
249
|
+
)
|
|
250
|
+
self._console.error_print("Set Depth", error_message)
|
|
251
|
+
return SetDepthResponse(error=error_message)
|
|
252
|
+
except Exception as e: # noqa: BLE001
|
|
253
|
+
self._console.exception_error_print("Set Depth", e)
|
|
254
|
+
return SetDepthResponse(error=self._console.pretty_exception(e))
|
|
255
|
+
else:
|
|
256
|
+
return SetDepthResponse(depth=final_unified_depth)
|
|
257
|
+
|
|
258
|
+
async def set_inside_brain(self, request: SetInsideBrainRequest) -> BooleanStateResponse:
|
|
259
|
+
"""Mark a manipulator as inside the brain or not.
|
|
260
|
+
|
|
261
|
+
This should restrict the manipulator's movement to just the depth axis.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
request: Request to set
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Inside brain state of the manipulator and an error message if any.
|
|
268
|
+
"""
|
|
269
|
+
try:
|
|
270
|
+
if request.inside:
|
|
271
|
+
self._inside_brain.add(request.manipulator_id)
|
|
272
|
+
else:
|
|
273
|
+
self._inside_brain.discard(request.manipulator_id)
|
|
274
|
+
except Exception as e: # noqa: BLE001
|
|
275
|
+
self._console.exception_error_print("Set Inside Brain", e)
|
|
276
|
+
return BooleanStateResponse(error=self._console.pretty_exception(e))
|
|
277
|
+
else:
|
|
278
|
+
return BooleanStateResponse(state=request.inside)
|
|
279
|
+
|
|
280
|
+
async def stop(self, manipulator_id: str) -> str:
|
|
281
|
+
"""Stop a manipulator.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
manipulator_id: Manipulator ID.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Error message if any.
|
|
288
|
+
"""
|
|
289
|
+
try:
|
|
290
|
+
await self._bindings.stop(manipulator_id)
|
|
291
|
+
except Exception as e: # noqa: BLE001
|
|
292
|
+
self._console.exception_error_print("Stop", e)
|
|
293
|
+
return self._console.pretty_exception(e)
|
|
294
|
+
else:
|
|
295
|
+
return ""
|
|
296
|
+
|
|
297
|
+
async def stop_all(self) -> str:
|
|
298
|
+
"""Stop all manipulators.
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Error message if any.
|
|
302
|
+
"""
|
|
303
|
+
try:
|
|
304
|
+
for manipulator_id in await self._bindings.get_manipulators():
|
|
305
|
+
await self._bindings.stop(manipulator_id)
|
|
306
|
+
except Exception as e: # noqa: BLE001
|
|
307
|
+
self._console.exception_error_print("Stop", e)
|
|
308
|
+
return self._console.pretty_exception(e)
|
|
309
|
+
else:
|
|
310
|
+
return ""
|
|
311
|
+
|
|
312
|
+
async def emergency_stop(self) -> None:
|
|
313
|
+
"""Stops all manipulators with a message."""
|
|
314
|
+
self._console.critical_print("Emergency Stopping All Manipulators...")
|
|
315
|
+
_ = await self.stop_all()
|