moteus 0.3.91__tar.gz → 0.3.92__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.
- {moteus-0.3.91 → moteus-0.3.92}/PKG-INFO +1 -1
- {moteus-0.3.91 → moteus-0.3.92}/moteus/command.py +4 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/moteus.py +46 -1
- {moteus-0.3.91 → moteus-0.3.92}/moteus/transport.py +72 -10
- {moteus-0.3.91 → moteus-0.3.92}/moteus/version.py +1 -1
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/PKG-INFO +1 -1
- {moteus-0.3.91 → moteus-0.3.92}/setup.py +1 -1
- {moteus-0.3.91 → moteus-0.3.92}/README.md +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/__init__.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/aioserial.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/aiostream.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/calibrate_encoder.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/device_info.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/export.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/fdcanusb.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/fdcanusb_device.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/moteus_tool.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/multiplex.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/posix_aioserial.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/protocol.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/pythoncan.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/pythoncan_device.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/reader.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/regression.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/transport_device.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/transport_factory.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/transport_wrapper.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus/win32_aioserial.py +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/SOURCES.txt +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/dependency_links.txt +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/entry_points.txt +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/requires.txt +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/moteus.egg-info/top_level.txt +0 -0
- {moteus-0.3.91 → moteus-0.3.92}/setup.cfg +0 -0
@@ -24,6 +24,10 @@ class Command():
|
|
24
24
|
can_prefix = 0x0000 # a 13 bit CAN prefix
|
25
25
|
expected_reply_size = 0
|
26
26
|
|
27
|
+
# An optional function object which when passed a Frame returns
|
28
|
+
# True if the frame matches what is expected for this command.
|
29
|
+
reply_filter = None
|
30
|
+
|
27
31
|
# If True, then the following parameters are used directly instead
|
28
32
|
# of being calculated from destination and source (i.e. for
|
29
33
|
# non-moteus devices).
|
@@ -271,14 +271,27 @@ class Controller:
|
|
271
271
|
return buf.getvalue(), expected_reply_size
|
272
272
|
|
273
273
|
def _format_query(self, query, query_override, data_buf, result):
|
274
|
+
def expect_reply(frame):
|
275
|
+
# For a reply to these requests, the first byte should be
|
276
|
+
# one of the reply or error frames.
|
277
|
+
if len(frame.data) < 1:
|
278
|
+
return False
|
279
|
+
|
280
|
+
if frame.data[0] & 0xf0 == 0x20 or frame.data[0] == 0x31:
|
281
|
+
return True
|
282
|
+
|
283
|
+
return False
|
284
|
+
|
274
285
|
if query_override is not None:
|
275
286
|
query_data, expected_reply_size = \
|
276
287
|
self._make_query_data(query_override)
|
277
288
|
data_buf.write(query_data)
|
278
289
|
result.expected_reply_size = expected_reply_size
|
290
|
+
result.reply_filter = expect_reply
|
279
291
|
elif query:
|
280
292
|
data_buf.write(self._query_data)
|
281
293
|
result.expected_reply_size = self._default_query_reply_size
|
294
|
+
result.reply_filter = expect_reply
|
282
295
|
|
283
296
|
def _make_command(self, *, query, query_override=None):
|
284
297
|
result = cmd.Command()
|
@@ -311,7 +324,18 @@ class Controller:
|
|
311
324
|
else:
|
312
325
|
result.data = self._query_data
|
313
326
|
result.expected_reply_size = self._default_query_reply_size
|
314
|
-
|
327
|
+
|
328
|
+
def expect_reply(frame):
|
329
|
+
if len(frame.data) < 1:
|
330
|
+
return False
|
331
|
+
|
332
|
+
if frame.data[0] & 0xf0 == 0x20 or frame.data[0] == 0x31:
|
333
|
+
return True
|
334
|
+
|
335
|
+
return False
|
336
|
+
|
337
|
+
result.reply_filter = expect_reply
|
338
|
+
return result
|
315
339
|
|
316
340
|
async def query(self, **kwargs):
|
317
341
|
return await self.execute(self.make_query(**kwargs))
|
@@ -336,6 +360,17 @@ class Controller:
|
|
336
360
|
|
337
361
|
result.data = data_buf.getvalue()
|
338
362
|
result.expected_reply_size = c.reply_size
|
363
|
+
|
364
|
+
def expect_reply(frame):
|
365
|
+
if len(frame.data) < 1:
|
366
|
+
return False
|
367
|
+
|
368
|
+
if frame.data[0] & 0xf0 == 0x20 or frame.data[0] == 0x31:
|
369
|
+
return True
|
370
|
+
|
371
|
+
return False
|
372
|
+
|
373
|
+
result.reply_filter = expect_reply
|
339
374
|
return result
|
340
375
|
|
341
376
|
async def custom_query(self, *args, **kwargs):
|
@@ -906,6 +941,7 @@ class Controller:
|
|
906
941
|
data_buf.write(data)
|
907
942
|
|
908
943
|
result.data = data_buf.getvalue()
|
944
|
+
|
909
945
|
return result
|
910
946
|
|
911
947
|
async def send_diagnostic_write(self, *args, **kwargs):
|
@@ -923,6 +959,15 @@ class Controller:
|
|
923
959
|
|
924
960
|
result.data = data_buf.getvalue()
|
925
961
|
result.expected_reply_size = 3 + max_length
|
962
|
+
|
963
|
+
def expect_diagnostic_response(frame):
|
964
|
+
if len(frame.data) < 3:
|
965
|
+
return False
|
966
|
+
|
967
|
+
return frame.data[0] == 0x41
|
968
|
+
|
969
|
+
result.reply_filter = expect_diagnostic_response
|
970
|
+
|
926
971
|
return result
|
927
972
|
|
928
973
|
async def diagnostic_read(self, *args, **kwargs):
|
@@ -321,16 +321,36 @@ class Transport:
|
|
321
321
|
# responses.
|
322
322
|
return lambda f: True
|
323
323
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
324
|
+
dest_id = self._make_canid(command.destination)
|
325
|
+
source_id = command.source
|
326
|
+
reply_filter = getattr(command, 'reply_filter', None)
|
327
|
+
prefix = getattr(command, 'can_prefix', 0)
|
328
|
+
|
329
|
+
def predicate(f,
|
330
|
+
dest_id=dest_id,
|
331
|
+
source_id=source_id,
|
332
|
+
prefix=prefix):
|
333
|
+
if ((f.arbitration_id >> 16) & 0x1fff) != prefix:
|
334
|
+
return False
|
335
|
+
|
336
|
+
if ((f.arbitration_id >> 8) & 0x7f != dest_id and
|
337
|
+
dest_id != 0x7f):
|
338
|
+
return False
|
339
|
+
|
340
|
+
if f.arbitration_id & 0x7f != source_id:
|
341
|
+
return False
|
342
|
+
|
343
|
+
if reply_filter and not reply_filter(f):
|
344
|
+
return False
|
345
|
+
|
346
|
+
return True
|
347
|
+
|
348
|
+
return predicate
|
329
349
|
|
330
350
|
async def _cycle_batch(self, commands, request_attitude,
|
331
351
|
read_unsolicited, force_can_check):
|
332
352
|
# Group requests by device. This is a map from device to:
|
333
|
-
#
|
353
|
+
# [TransportDevice.Request, ...]
|
334
354
|
device_requests = collections.defaultdict(list)
|
335
355
|
|
336
356
|
for i, command in enumerate(commands):
|
@@ -396,10 +416,52 @@ class Transport:
|
|
396
416
|
tasks = []
|
397
417
|
device_list = []
|
398
418
|
for device, request_list in device_requests.items():
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
419
|
+
# We can send at most one broadcast frame that needs
|
420
|
+
# replies per transaction.
|
421
|
+
broadcast_with_reply = lambda request: (
|
422
|
+
(request.frame.arbitration_id & 0x7f) == 0x7f and
|
423
|
+
request.frame_filter is not None)
|
424
|
+
|
425
|
+
broadcast_requests = [x for x in request_list
|
426
|
+
if broadcast_with_reply(x)]
|
427
|
+
non_broadcast_requests = [x for x in request_list
|
428
|
+
if not broadcast_with_reply(x)]
|
429
|
+
|
430
|
+
async def run_in_sequence(d=device,
|
431
|
+
br=broadcast_requests,
|
432
|
+
nbr=non_broadcast_requests):
|
433
|
+
|
434
|
+
this_request_attitude = request_attitude
|
435
|
+
this_force_can_check = force_can_check
|
436
|
+
|
437
|
+
for b in br:
|
438
|
+
await d.transaction(
|
439
|
+
[b],
|
440
|
+
request_attitude=this_request_attitude,
|
441
|
+
force_can_check=this_force_can_check)
|
442
|
+
|
443
|
+
this_request_attitude = False
|
444
|
+
this_force_can_check = None
|
445
|
+
|
446
|
+
if nbr:
|
447
|
+
await d.transaction(
|
448
|
+
nbr,
|
449
|
+
request_attitude=this_request_attitude,
|
450
|
+
force_can_check=this_force_can_check)
|
451
|
+
|
452
|
+
if (len(broadcast_requests) + (1 if non_broadcast_requests else 0)) == 1:
|
453
|
+
# We can use a single transaction, either because we
|
454
|
+
# have a single broadcast request and no other
|
455
|
+
# requests, or no broadcast requests.
|
456
|
+
tasks.append(device.transaction(
|
457
|
+
request_list,
|
458
|
+
request_attitude=request_attitude,
|
459
|
+
force_can_check=force_can_check))
|
460
|
+
else:
|
461
|
+
# We have to do multiple transactions to complete
|
462
|
+
# this.
|
463
|
+
tasks.append(run_in_sequence())
|
464
|
+
|
403
465
|
device_list.append(device)
|
404
466
|
|
405
467
|
# Wait for all transports to complete.
|
@@ -25,7 +25,7 @@ long_description = (here / 'README.md').read_text(encoding='utf-8')
|
|
25
25
|
|
26
26
|
setuptools.setup(
|
27
27
|
name = 'moteus',
|
28
|
-
version = "0.3.
|
28
|
+
version = "0.3.92",
|
29
29
|
description = 'moteus brushless controller library and tools',
|
30
30
|
long_description = long_description,
|
31
31
|
long_description_content_type = 'text/markdown',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|