moteus 0.3.92__tar.gz → 0.3.94__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.92 → moteus-0.3.94}/PKG-INFO +1 -1
- {moteus-0.3.92 → moteus-0.3.94}/moteus/moteus.py +27 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/moteus_tool.py +3 -17
- {moteus-0.3.92 → moteus-0.3.94}/moteus/transport.py +1 -1
- {moteus-0.3.92 → moteus-0.3.94}/moteus/transport_factory.py +25 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/version.py +1 -1
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/PKG-INFO +1 -1
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/requires.txt +1 -0
- {moteus-0.3.92 → moteus-0.3.94}/setup.py +2 -1
- {moteus-0.3.92 → moteus-0.3.94}/README.md +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/__init__.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/aioserial.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/aiostream.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/calibrate_encoder.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/command.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/device_info.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/export.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/fdcanusb.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/fdcanusb_device.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/multiplex.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/posix_aioserial.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/protocol.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/pythoncan.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/pythoncan_device.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/reader.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/regression.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/transport_device.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/transport_wrapper.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus/win32_aioserial.py +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/SOURCES.txt +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/dependency_links.txt +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/entry_points.txt +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/moteus.egg-info/top_level.txt +0 -0
- {moteus-0.3.92 → moteus-0.3.94}/setup.cfg +0 -0
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import asyncio
|
|
16
16
|
import argparse
|
|
17
|
+
import collections.abc
|
|
17
18
|
import copy
|
|
18
19
|
import enum
|
|
19
20
|
import io
|
|
@@ -30,6 +31,32 @@ from .transport_factory import TRANSPORT_FACTORIES, get_singleton_transport, mak
|
|
|
30
31
|
import moteus.reader
|
|
31
32
|
|
|
32
33
|
|
|
34
|
+
def namedtuple_to_dict(obj):
|
|
35
|
+
'''Convert a namedtuple recursively into a nested dictionary.
|
|
36
|
+
|
|
37
|
+
This function handles namedtuples, dictionaries, and sequences,
|
|
38
|
+
converting them to nested dictionaries and lists suitable for
|
|
39
|
+
JSON serialization.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
obj: The object to convert (typically a namedtuple)
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
dict, list, or primitive type representation of the input
|
|
46
|
+
'''
|
|
47
|
+
|
|
48
|
+
if isinstance(obj, tuple) and hasattr(obj, "_fields"):
|
|
49
|
+
return {field: namedtuple_to_dict(getattr(obj, field)) for field in obj._fields}
|
|
50
|
+
|
|
51
|
+
if isinstance(obj, collections.abc.Mapping):
|
|
52
|
+
return {k: namedtuple_to_dict(v) for k, v in obj.items()}
|
|
53
|
+
|
|
54
|
+
if isinstance(obj, collections.abc.Sequence) and not isinstance(obj, (str, bytes, bytearray)):
|
|
55
|
+
return [namedtuple_to_dict(x) for x in obj]
|
|
56
|
+
|
|
57
|
+
return obj
|
|
58
|
+
|
|
59
|
+
|
|
33
60
|
def _merge_resolutions(a, b):
|
|
34
61
|
if a == mp.IGNORE:
|
|
35
62
|
return b
|
|
@@ -37,6 +37,7 @@ from . import moteus
|
|
|
37
37
|
from . import aiostream
|
|
38
38
|
from . import regression
|
|
39
39
|
from . import calibrate_encoder as ce
|
|
40
|
+
from .moteus import namedtuple_to_dict
|
|
40
41
|
|
|
41
42
|
from .device_info import DeviceAddress
|
|
42
43
|
|
|
@@ -63,21 +64,6 @@ CURRENT_QUALITY_MIN = 20
|
|
|
63
64
|
VOLTAGE_MODE_QUALITY_MIN = 40
|
|
64
65
|
|
|
65
66
|
|
|
66
|
-
def _deep_asdict(obj):
|
|
67
|
-
'''Convert a namedtuple recursively into a nested dictionary'''
|
|
68
|
-
|
|
69
|
-
if isinstance(obj, tuple) and hasattr(obj, "_fields"):
|
|
70
|
-
return {field: _deep_asdict(getattr(obj, field)) for field in obj._fields}
|
|
71
|
-
|
|
72
|
-
if isinstance(obj, collections.abc.Mapping):
|
|
73
|
-
return {k: _deep_asdict(v) for k, v in obj.items()}
|
|
74
|
-
|
|
75
|
-
if isinstance(obj, collections.abc.Sequence) and not isinstance(obj, (str, bytes, bytearray)):
|
|
76
|
-
return [_deep_asdict(x) for x in obj]
|
|
77
|
-
|
|
78
|
-
return obj
|
|
79
|
-
|
|
80
|
-
|
|
81
67
|
def _wrap_neg_pi_to_pi(value):
|
|
82
68
|
while value > math.pi:
|
|
83
69
|
value -= 2.0 * math.pi
|
|
@@ -1014,7 +1000,7 @@ class Stream:
|
|
|
1014
1000
|
|
|
1015
1001
|
async def do_read(self, channel):
|
|
1016
1002
|
result = await self.read_data(channel)
|
|
1017
|
-
print(json.dumps(
|
|
1003
|
+
print(json.dumps(namedtuple_to_dict(result), indent=2))
|
|
1018
1004
|
|
|
1019
1005
|
async def do_flash(self, elffile):
|
|
1020
1006
|
elf = _read_elf(elffile, [".text", ".ARM.extab", ".ARM.exidx",
|
|
@@ -1177,7 +1163,7 @@ class Stream:
|
|
|
1177
1163
|
print()
|
|
1178
1164
|
print("*** FAILED: Gate driver fault (code=33) during calibration: ")
|
|
1179
1165
|
drv8323 = await self.read_data("drv8323")
|
|
1180
|
-
print(json.dumps(
|
|
1166
|
+
print(json.dumps(namedtuple_to_dict(drv8323), indent=2))
|
|
1181
1167
|
sys.exit(1)
|
|
1182
1168
|
else:
|
|
1183
1169
|
raise
|
|
@@ -419,7 +419,7 @@ class Transport:
|
|
|
419
419
|
# We can send at most one broadcast frame that needs
|
|
420
420
|
# replies per transaction.
|
|
421
421
|
broadcast_with_reply = lambda request: (
|
|
422
|
-
(request.frame.arbitration_id & 0x7f) == 0x7f and
|
|
422
|
+
(request.frame and ((request.frame.arbitration_id & 0x7f) == 0x7f)) and
|
|
423
423
|
request.frame_filter is not None)
|
|
424
424
|
|
|
425
425
|
broadcast_requests = [x for x in request_list
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import argparse
|
|
17
17
|
import importlib_metadata
|
|
18
18
|
import sys
|
|
19
|
+
import warnings
|
|
19
20
|
|
|
20
21
|
from . import fdcanusb_device
|
|
21
22
|
from . import pythoncan_device
|
|
@@ -141,12 +142,36 @@ def make_transport_args(parser):
|
|
|
141
142
|
help='Force the given transport type to be used exclusively')
|
|
142
143
|
|
|
143
144
|
|
|
145
|
+
def check_gui_compatibility():
|
|
146
|
+
try:
|
|
147
|
+
import moteus_gui
|
|
148
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
149
|
+
from packaging.version import parse as parse_version
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
gui_version = version('moteus-gui')
|
|
153
|
+
if parse_version(gui_version) < parse_version('0.3.93'):
|
|
154
|
+
warnings.warn(
|
|
155
|
+
"moteus-gui is outdated. Please upgrade: python -m pip install -U moteus-gui",
|
|
156
|
+
UserWarning
|
|
157
|
+
)
|
|
158
|
+
except PackageNotFoundError:
|
|
159
|
+
pass
|
|
160
|
+
except ImportError:
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
|
|
144
164
|
def get_singleton_transport(args=None):
|
|
145
165
|
global GLOBAL_TRANSPORT
|
|
146
166
|
|
|
147
167
|
if GLOBAL_TRANSPORT:
|
|
148
168
|
return GLOBAL_TRANSPORT
|
|
149
169
|
|
|
170
|
+
# We check this here because it will likely only be called once
|
|
171
|
+
# per application instance, and will nearly always be called by
|
|
172
|
+
# the GUI.
|
|
173
|
+
check_gui_compatibility()
|
|
174
|
+
|
|
150
175
|
if args and args.can_debug:
|
|
151
176
|
args.can_debug = open(args.can_debug, 'wb')
|
|
152
177
|
|
|
@@ -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.94",
|
|
29
29
|
description = 'moteus brushless controller library and tools',
|
|
30
30
|
long_description = long_description,
|
|
31
31
|
long_description_content_type = 'text/markdown',
|
|
@@ -53,5 +53,6 @@ setuptools.setup(
|
|
|
53
53
|
'scipy>=1.8.0',
|
|
54
54
|
'importlib_metadata>=3.6',
|
|
55
55
|
'pywin32;platform_system=="Windows"',
|
|
56
|
+
'packaging',
|
|
56
57
|
],
|
|
57
58
|
)
|
|
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
|