moteus 0.3.86__py3-none-any.whl → 0.3.88__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/fdcanusb.py +30 -17
- moteus/moteus.py +19 -1
- moteus/moteus_tool.py +6 -4
- moteus/pythoncan.py +13 -8
- moteus/version.py +1 -1
- {moteus-0.3.86.dist-info → moteus-0.3.88.dist-info}/METADATA +1 -2
- {moteus-0.3.86.dist-info → moteus-0.3.88.dist-info}/RECORD +10 -10
- {moteus-0.3.86.dist-info → moteus-0.3.88.dist-info}/WHEEL +0 -0
- {moteus-0.3.86.dist-info → moteus-0.3.88.dist-info}/entry_points.txt +0 -0
- {moteus-0.3.86.dist-info → moteus-0.3.88.dist-info}/top_level.txt +0 -0
moteus/fdcanusb.py
CHANGED
@@ -136,17 +136,34 @@ class Fdcanusb:
|
|
136
136
|
# individually.
|
137
137
|
return [await self._do_command(x) for x in commands]
|
138
138
|
|
139
|
+
def _parse_message(self, line):
|
140
|
+
fields = line.split(b" ")
|
141
|
+
message = CanMessage()
|
142
|
+
message.data = _dehexify(fields[2])
|
143
|
+
message.arbitration_id = int(fields[1], 16)
|
144
|
+
|
145
|
+
flags = fields[3] if len(fields) > 3 else ''
|
146
|
+
if b'E' in flags:
|
147
|
+
message.is_extended_id = True
|
148
|
+
if b'B' in flags:
|
149
|
+
message.bitrate_switch = True
|
150
|
+
if b'F' in flags:
|
151
|
+
message.is_fd = True
|
152
|
+
|
153
|
+
return message
|
154
|
+
|
139
155
|
async def _do_command(self, command):
|
140
156
|
await self.write(command)
|
141
157
|
reply_required = command.reply_required
|
142
158
|
|
143
159
|
# Get the OK response.
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
160
|
+
while True:
|
161
|
+
ok_response = await self._readline(self._serial)
|
162
|
+
if ok_response.startswith(b"OK"):
|
163
|
+
break
|
164
|
+
# Ignore spurious responses until we get an OK.
|
148
165
|
|
149
|
-
|
166
|
+
while reply_required:
|
150
167
|
line = await self._readline(self._serial)
|
151
168
|
|
152
169
|
if not line.startswith(b"rcv"):
|
@@ -157,16 +174,15 @@ class Fdcanusb:
|
|
157
174
|
self._debug_log.write(f'{time.time()} < '.encode('latin1') +
|
158
175
|
line.rstrip() + b'\n')
|
159
176
|
|
160
|
-
|
161
|
-
|
162
|
-
message.
|
163
|
-
message.arbitration_id = int(fields[1], 16)
|
177
|
+
message = self._parse_message(line)
|
178
|
+
|
179
|
+
moteus_id = (message.arbitration_id >> 8) & 0x7f
|
164
180
|
|
165
|
-
|
166
|
-
|
167
|
-
# source/destination or CAN prefix.
|
181
|
+
if command.raw or moteus_id == command.destination:
|
182
|
+
return command.parse(message)
|
168
183
|
|
169
|
-
|
184
|
+
# We are not raw and the message wasn't from the device we
|
185
|
+
# were writing to, so just loop and try some more.
|
170
186
|
|
171
187
|
async def write(self, command):
|
172
188
|
# This merely sends a command and doesn't even wait for an OK
|
@@ -201,10 +217,7 @@ class Fdcanusb:
|
|
201
217
|
self._debug_log.write(f'{time.time()} < '.encode('latin1') +
|
202
218
|
line.rstrip() + b'\n')
|
203
219
|
|
204
|
-
|
205
|
-
message = CanMessage()
|
206
|
-
message.data = _dehexify(fields[2])
|
207
|
-
message.arbitration_id = int(fields[1], 16)
|
220
|
+
message = self._parse_message(line)
|
208
221
|
return message
|
209
222
|
|
210
223
|
def _round_up_dlc(self, size):
|
moteus/moteus.py
CHANGED
@@ -578,7 +578,7 @@ class Result:
|
|
578
578
|
def make_parser(id):
|
579
579
|
def parse(message):
|
580
580
|
result = Result()
|
581
|
-
result.id =
|
581
|
+
result.id = (message.arbitration_id >> 8) & 0x7f
|
582
582
|
result.values = parse_reply(message.data)
|
583
583
|
|
584
584
|
# We store these things just for reference, so that our
|
@@ -630,6 +630,11 @@ def make_diagnostic_parser(id, channel):
|
|
630
630
|
return parse
|
631
631
|
|
632
632
|
|
633
|
+
class FaultError(RuntimeError):
|
634
|
+
def __init__(self, mode, code):
|
635
|
+
super(FaultError, self).__init__(f"Fault mode={mode} code={code}")
|
636
|
+
|
637
|
+
|
633
638
|
class Controller:
|
634
639
|
"""Operates a single moteus controller across some communication
|
635
640
|
medium.
|
@@ -1019,6 +1024,9 @@ class Controller:
|
|
1019
1024
|
reports that the trajectory has been completed.
|
1020
1025
|
|
1021
1026
|
If the controller is unresponsive, this method will never return.
|
1027
|
+
|
1028
|
+
If the controller reports a fault or position mode timeout, a
|
1029
|
+
FaultError exception will be raised.
|
1022
1030
|
"""
|
1023
1031
|
|
1024
1032
|
if query_override is None:
|
@@ -1026,6 +1034,10 @@ class Controller:
|
|
1026
1034
|
else:
|
1027
1035
|
query_override = copy.deepcopy(query_override)
|
1028
1036
|
|
1037
|
+
if query_override.mode == mp.IGNORE:
|
1038
|
+
query_override.mode = mp.INT8
|
1039
|
+
if query_override.fault == mp.IGNORE:
|
1040
|
+
query_override.fault = mp.INT8
|
1029
1041
|
query_override.trajectory_complete = mp.INT8
|
1030
1042
|
|
1031
1043
|
count = 2
|
@@ -1041,6 +1053,12 @@ class Controller:
|
|
1041
1053
|
result.values[Register.TRAJECTORY_COMPLETE]):
|
1042
1054
|
return result
|
1043
1055
|
|
1056
|
+
current_mode = result.values.get(Register.MODE, Mode.STOPPED)
|
1057
|
+
fault_code = result.values.get(Register.FAULT, 0)
|
1058
|
+
|
1059
|
+
if current_mode == Mode.FAULT or current_mode == Mode.TIMEOUT:
|
1060
|
+
raise FaultError(current_mode, fault_code)
|
1061
|
+
|
1044
1062
|
await asyncio.sleep(period_s)
|
1045
1063
|
|
1046
1064
|
def make_vfoc(self,
|
moteus/moteus_tool.py
CHANGED
@@ -1273,7 +1273,7 @@ class Stream:
|
|
1273
1273
|
|
1274
1274
|
async def find_encoder_cal_voltage(self, input_V, winding_resistance):
|
1275
1275
|
if self.args.cal_ll_encoder_voltage:
|
1276
|
-
return self.args.cal_ll_encoder_voltage
|
1276
|
+
return self.args.cal_ll_encoder_voltage
|
1277
1277
|
|
1278
1278
|
# We're going to try and select a voltage to roughly achieve
|
1279
1279
|
# "--cal-motor-power".
|
@@ -1618,13 +1618,15 @@ class Stream:
|
|
1618
1618
|
# non-linear, corrupting the result.
|
1619
1619
|
|
1620
1620
|
# What we'll do is take the very last result, and the last
|
1621
|
-
# result that is less than
|
1621
|
+
# result that is less than X% of the current of the last
|
1622
1622
|
# result.
|
1623
1623
|
|
1624
1624
|
last_result = results[-1]
|
1625
1625
|
|
1626
|
-
|
1627
|
-
|
1626
|
+
less_than_X = [x for x in results if x[1] < 0.60 * last_result[1]]
|
1627
|
+
if len(less_than_X) == 0:
|
1628
|
+
raise RuntimeError(f"Could not detect resistance, is motor connected? Peak current only {last_result[1]:.3f}A w/ {last_result[0]:.3f}V applied.")
|
1629
|
+
less_than = less_than_X[-1]
|
1628
1630
|
|
1629
1631
|
resistance = ((last_result[0] - less_than[0]) /
|
1630
1632
|
(last_result[1] - less_than[1]))
|
moteus/pythoncan.py
CHANGED
@@ -95,16 +95,16 @@ class PythonCan:
|
|
95
95
|
async def _do_command(self, command):
|
96
96
|
await self.write(command)
|
97
97
|
|
98
|
-
|
99
|
-
|
98
|
+
while command.reply_required:
|
99
|
+
reply = await self.read()
|
100
100
|
|
101
|
-
|
101
|
+
moteus_id = (reply.arbitration_id >> 8) & 0x7f
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
# checking.
|
103
|
+
if command.raw or command.destination == moteus_id:
|
104
|
+
return command.parse(reply)
|
106
105
|
|
107
|
-
|
106
|
+
# We did not get a response from the device we were hoping
|
107
|
+
# for, so just keep waiting.
|
108
108
|
|
109
109
|
async def write(self, command):
|
110
110
|
reply_required = command.reply_required
|
@@ -125,7 +125,12 @@ class PythonCan:
|
|
125
125
|
|
126
126
|
async def read(self):
|
127
127
|
self._maybe_setup()
|
128
|
-
|
128
|
+
while True:
|
129
|
+
frame = await self._reader.get_message()
|
130
|
+
if not frame.is_error_frame:
|
131
|
+
return frame
|
132
|
+
# Just ignore error frames entirely and keep reading until
|
133
|
+
# we get a good one.
|
129
134
|
|
130
135
|
def _round_up_dlc(self, size):
|
131
136
|
if size <= 8:
|
moteus/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: moteus
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.88
|
4
4
|
Summary: moteus brushless controller library and tools
|
5
5
|
Home-page: https://github.com/mjbots/moteus
|
6
6
|
Author: mjbots Robotic Systems
|
@@ -13,7 +13,6 @@ Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Requires-Python: >=3.7, <4
|
14
14
|
Description-Content-Type: text/markdown
|
15
15
|
Requires-Dist: importlib-metadata >=3.6
|
16
|
-
Requires-Dist: numpy <2
|
17
16
|
Requires-Dist: pyelftools >=0.26
|
18
17
|
Requires-Dist: pyserial >=3.5
|
19
18
|
Requires-Dist: python-can >=3.3
|
@@ -4,20 +4,20 @@ moteus/aiostream.py,sha256=YAkVF6QWsA49vqO-GgXEohDghqm_-nnajJzhO_Q9qNQ,3696
|
|
4
4
|
moteus/calibrate_encoder.py,sha256=Ami5e-LFw4RLoLseKcZx9QfS1PjQZJUwygvNZfPqd04,15494
|
5
5
|
moteus/command.py,sha256=UkOsbtkso6Oyex8CfbpAKpBNriik519ymxL86EZGkRs,1169
|
6
6
|
moteus/export.py,sha256=XitBUuf4MDRIneXQSUptizIhZi2BdHyFO2Vo_2d2CFI,1742
|
7
|
-
moteus/fdcanusb.py,sha256=
|
8
|
-
moteus/moteus.py,sha256=
|
9
|
-
moteus/moteus_tool.py,sha256=
|
7
|
+
moteus/fdcanusb.py,sha256=SOAvUlleI6bKwQiApo7nYAaqBM4JoNPn4PHdPqsgsQQ,7707
|
8
|
+
moteus/moteus.py,sha256=QH1y5W-KQ0hKoGDPv7lLkWTIS7YBS5pNO3gbYKoF5vw,53241
|
9
|
+
moteus/moteus_tool.py,sha256=FmV-opl8PyhOHY9z_B86dyLuwbMwtkMRsH2CCNOf1Fo,98072
|
10
10
|
moteus/multiplex.py,sha256=2tdNX5JSh21TOjN6N9LKribLQtVYyyYbXjzwXB64sfA,12119
|
11
11
|
moteus/posix_aioserial.py,sha256=2oDrw8TBEwuEQjY41g9rHeuFeffcPHqMwNS3nf5NVq8,3137
|
12
|
-
moteus/pythoncan.py,sha256=
|
12
|
+
moteus/pythoncan.py,sha256=j7Gv9tugQqTZbanm1lQGIoTvfmeS2kAxigB0n1a50lo,5039
|
13
13
|
moteus/reader.py,sha256=9i1-h4aGd4syfqtWJcpg70Bl-bmunkGU4FmXmOLyRt8,12121
|
14
14
|
moteus/regression.py,sha256=M5gjDBYJQ64iBXIrvBhMkD8TYhtlnQ85x8U4py0niGA,1196
|
15
15
|
moteus/router.py,sha256=501W5GZ12rFoc1lmcH3S7IYsoc-Q_-FJ4B3i37RzE3Q,2061
|
16
16
|
moteus/transport.py,sha256=WhkW2G9i25lkOlO55eI5_oXmU0PhDmxTeJ75Sg_7nTI,1021
|
17
|
-
moteus/version.py,sha256=
|
17
|
+
moteus/version.py,sha256=bYmrQeWLHbeSIrqSgHNqnNU3m7WMEJx3w6Szx9slMuo,627
|
18
18
|
moteus/win32_aioserial.py,sha256=culdl-vYxBKD5n2s5LkIMGyUaHyCcEc8BL5-DWEaxX8,2025
|
19
|
-
moteus-0.3.
|
20
|
-
moteus-0.3.
|
21
|
-
moteus-0.3.
|
22
|
-
moteus-0.3.
|
23
|
-
moteus-0.3.
|
19
|
+
moteus-0.3.88.dist-info/METADATA,sha256=9dBQGXpZ4BTL8pA26Cvh2aD5WlHdgRj-3klygfDOvMA,3417
|
20
|
+
moteus-0.3.88.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
21
|
+
moteus-0.3.88.dist-info/entry_points.txt,sha256=accRcwir_K8wCf7i3qHb5R6CPh5SiSgd5a1A92ibb9E,56
|
22
|
+
moteus-0.3.88.dist-info/top_level.txt,sha256=aZzmI_yecTaDrdSp29pTJuowaSQ9dlIZheQpshGg4YQ,7
|
23
|
+
moteus-0.3.88.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|