moteus 0.3.91__py3-none-any.whl → 0.3.92__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.
moteus/command.py CHANGED
@@ -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).
moteus/moteus.py CHANGED
@@ -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
- return result;
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):
moteus/transport.py CHANGED
@@ -321,16 +321,36 @@ class Transport:
321
321
  # responses.
322
322
  return lambda f: True
323
323
 
324
- # Filter by both the source and destination device IDs.
325
- return lambda f: (
326
- (((f.arbitration_id >> 8) & 0x7f) == self._make_canid(command.destination) or
327
- self._make_canid(command.destination) == 0x7f) and
328
- (f.arbitration_id & 0x7f) == command.source)
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
- # (TransportDevice.Request)
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
- tasks.append(device.transaction(
400
- request_list,
401
- request_attitude=request_attitude,
402
- force_can_check=force_can_check))
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.
moteus/version.py CHANGED
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- VERSION="0.3.91"
15
+ VERSION="0.3.92"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: moteus
3
- Version: 0.3.91
3
+ Version: 0.3.92
4
4
  Summary: moteus brushless controller library and tools
5
5
  Home-page: https://github.com/mjbots/moteus
6
6
  Author: mjbots Robotic Systems
@@ -2,12 +2,12 @@ moteus/__init__.py,sha256=DxasQre5HmK3BS3I35K8GEUvFZF3_OE_hjVzQy-seIE,739
2
2
  moteus/aioserial.py,sha256=GeWuvsZKCRrfBN33JZFjtBXPr-0sKpQv9shRn2ulcDA,1079
3
3
  moteus/aiostream.py,sha256=YAkVF6QWsA49vqO-GgXEohDghqm_-nnajJzhO_Q9qNQ,3696
4
4
  moteus/calibrate_encoder.py,sha256=Ami5e-LFw4RLoLseKcZx9QfS1PjQZJUwygvNZfPqd04,15494
5
- moteus/command.py,sha256=_WYnIwyh7OZwhmlLVy4TlAYOLV2uWd4om0BQG2-_XUM,1302
5
+ moteus/command.py,sha256=f4r2NeFFKZ9ypS47cMKf325sr_eqS4OHfAYM4YsaXvo,1462
6
6
  moteus/device_info.py,sha256=TBYQtfXDfIlyg17HXnUOKj13JZNc6iWvt0ZiZm0MlXA,2292
7
7
  moteus/export.py,sha256=9cR_Y3JypZ756JYNKeYRamOwwzNmt5Ign8yJ7BRoBuk,2124
8
8
  moteus/fdcanusb.py,sha256=96WQjwjTgHEPeIAV0A0AsW0_n3hbyUEOl2ZuWsaiOBE,1058
9
9
  moteus/fdcanusb_device.py,sha256=rYJdncT9C7ikavNqiFpjb_9n8fsLbsd5CGpbdm_fSyw,11456
10
- moteus/moteus.py,sha256=Wj1RwvDORIAxCEyBno7LoEEfmoIY89jKpkAb7RxPqwM,40813
10
+ moteus/moteus.py,sha256=ygdZZfABT7xgGHkSiNp5NEtOmLTcR60VBptkJodl68A,41999
11
11
  moteus/moteus_tool.py,sha256=qhISCcMAtlDMhkkqUKxsPIbeyfMjquPpLW8aBgTVHFw,99724
12
12
  moteus/multiplex.py,sha256=2tdNX5JSh21TOjN6N9LKribLQtVYyyYbXjzwXB64sfA,12119
13
13
  moteus/posix_aioserial.py,sha256=2oDrw8TBEwuEQjY41g9rHeuFeffcPHqMwNS3nf5NVq8,3137
@@ -16,14 +16,14 @@ moteus/pythoncan.py,sha256=7VMCPHvFasy9V507kKVV5jUyzZXFjvhsbqT5hMYI-jA,864
16
16
  moteus/pythoncan_device.py,sha256=e-NGnMX4-tFhQY8PShNJiA8GLwf_iKU_BiJsTekM6B8,7710
17
17
  moteus/reader.py,sha256=9i1-h4aGd4syfqtWJcpg70Bl-bmunkGU4FmXmOLyRt8,12121
18
18
  moteus/regression.py,sha256=M5gjDBYJQ64iBXIrvBhMkD8TYhtlnQ85x8U4py0niGA,1196
19
- moteus/transport.py,sha256=3q1BepCO-BwAc_VbSl3UhkZBZV3iQg8PYHpD2Ur8gxA,25830
19
+ moteus/transport.py,sha256=jVrT47O5nv_TpZeNr2GUZd7oOz397zIJJnBQvXT82gY,28125
20
20
  moteus/transport_device.py,sha256=QDSqFiGuLQVvMo26a6CmnMXMzrSovdji6yzHSr_cDGA,5820
21
21
  moteus/transport_factory.py,sha256=vuLUXWl62DcGrXfoQTRKQvx4EAegx22lU8A-18JgJqg,5889
22
22
  moteus/transport_wrapper.py,sha256=7oOBFSvD7Zk5BiWjX_YcGSTlMIZC4GmL88uzVYVQBbE,1733
23
- moteus/version.py,sha256=cTdVf166IUGf348GCy3clzyXTJBb2FAu75uFxq962BA,627
23
+ moteus/version.py,sha256=sOdde-nLJoRFk_gUsRMwgXRDFyYYvlb0QNBcBaaJF0w,627
24
24
  moteus/win32_aioserial.py,sha256=culdl-vYxBKD5n2s5LkIMGyUaHyCcEc8BL5-DWEaxX8,2025
25
- moteus-0.3.91.dist-info/METADATA,sha256=hR4s9e0T53X3VjzYwuANd6xotsBzsZCWcnPfBECKUBU,3417
26
- moteus-0.3.91.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
27
- moteus-0.3.91.dist-info/entry_points.txt,sha256=accRcwir_K8wCf7i3qHb5R6CPh5SiSgd5a1A92ibb9E,56
28
- moteus-0.3.91.dist-info/top_level.txt,sha256=aZzmI_yecTaDrdSp29pTJuowaSQ9dlIZheQpshGg4YQ,7
29
- moteus-0.3.91.dist-info/RECORD,,
25
+ moteus-0.3.92.dist-info/METADATA,sha256=sJ_yH10MGLdY6_kP16ifmCpHWGprlL7CvdBx1g-nf5c,3417
26
+ moteus-0.3.92.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
27
+ moteus-0.3.92.dist-info/entry_points.txt,sha256=accRcwir_K8wCf7i3qHb5R6CPh5SiSgd5a1A92ibb9E,56
28
+ moteus-0.3.92.dist-info/top_level.txt,sha256=aZzmI_yecTaDrdSp29pTJuowaSQ9dlIZheQpshGg4YQ,7
29
+ moteus-0.3.92.dist-info/RECORD,,