moteus 0.3.67__py3-none-any.whl → 0.3.69__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/moteus.py CHANGED
@@ -619,6 +619,12 @@ class Controller:
619
619
  self.transport = get_singleton_transport()
620
620
  return self.transport
621
621
 
622
+ async def flush_transport(self):
623
+ try:
624
+ await asyncio.wait_for(self.transport.read(), 0.02)
625
+ except asyncio.TimeoutError:
626
+ pass
627
+
622
628
  def _make_query_data(self, query_resolution=None):
623
629
  if query_resolution is None:
624
630
  query_resolution = self.query_resolution
@@ -761,7 +767,7 @@ class Controller:
761
767
  async def set_stop(self, *args, **kwargs):
762
768
  return await self.execute(self.make_stop(**kwargs))
763
769
 
764
- def make_set_output(self, *,
770
+ def make_set_output(self, *args,
765
771
  position=0.0,
766
772
  query=False,
767
773
  query_override=None,
@@ -770,6 +776,9 @@ class Controller:
770
776
  """Return a moteus.Command structure with data necessary to send a
771
777
  set output nearest command."""
772
778
 
779
+ if len(args):
780
+ raise ValueError(f'unexpected positional arguments: {args}')
781
+
773
782
  result = self._make_command(
774
783
  query=query, query_override=query_override)
775
784
 
@@ -784,39 +793,42 @@ class Controller:
784
793
  result.data = data_buf.getvalue()
785
794
  return result
786
795
 
787
- def make_set_output_nearest(self, *,
796
+ def make_set_output_nearest(self, *args,
788
797
  position=0.0,
789
798
  query=False,
790
799
  query_override=None):
791
800
  return self.make_set_output(
801
+ *args,
792
802
  position=position, query=query, query_override=query_override,
793
803
  cmd=Register.SET_OUTPUT_NEAREST)
794
804
 
795
- def make_set_output_exact(self, *,
805
+ def make_set_output_exact(self, *args,
796
806
  position=0.0,
797
807
  query=False,
798
808
  query_override=None):
799
809
  return self.make_set_output(
810
+ *args,
800
811
  position=position, query=query, query_override=query_override,
801
812
  cmd=Register.SET_OUTPUT_EXACT)
802
813
 
803
814
  async def set_output(self, *args, cmd=None, **kwargs):
804
- return await self.execute(self.make_set_output(**kwargs, cmd=cmd))
815
+ return await self.execute(self.make_set_output(*args, **kwargs, cmd=cmd))
805
816
 
806
817
  async def set_output_nearest(self, *args, **kwargs):
807
- return await self.set_output(cmd=Register.SET_OUTPUT_NEAREST, **kwargs)
818
+ return await self.set_output(*args, cmd=Register.SET_OUTPUT_NEAREST, **kwargs)
808
819
 
809
820
  async def set_output_exact(self, *args, **kwargs):
810
- return await self.set_output(cmd=Register.SET_OUTPUT_EXACT, **kwargs)
821
+ return await self.set_output(*args, cmd=Register.SET_OUTPUT_EXACT, **kwargs)
811
822
 
812
823
 
813
824
  # For backwards compatibility, "*_output_nearest" used to be named
814
825
  # "make/set_rezero".
815
- def make_rezero(self, *,
826
+ def make_rezero(self, *args,
816
827
  rezero=0.0,
817
828
  query=False,
818
829
  query_override=None):
819
830
  return self.make_set_output(
831
+ *args,
820
832
  position=rezero, query=query, query_override=query_override,
821
833
  cmd=Register.SET_OUTPUT_NEAREST)
822
834
 
@@ -1176,8 +1188,8 @@ class Controller:
1176
1188
 
1177
1189
  combiner = mp.WriteCombiner(
1178
1190
  writer, 0x00, int(Register.AUX1_GPIO_COMMAND), [
1179
- mp.INT8 if aux1 else mp.IGNORE,
1180
- mp.INT8 if aux2 else mp.IGNORE,
1191
+ mp.INT8 if aux1 is not None else mp.IGNORE,
1192
+ mp.INT8 if aux2 is not None else mp.IGNORE,
1181
1193
  ])
1182
1194
 
1183
1195
  if combiner.maybe_write():
@@ -1355,11 +1367,7 @@ class Stream:
1355
1367
  self._read_data = b''
1356
1368
 
1357
1369
  # Now flush anything from the underlying transport if applicable.
1358
- try:
1359
- await asyncio.wait_for(self.controller._get_transport().read(), 0.02)
1360
- except asyncio.TimeoutError:
1361
- # This is the expected path.
1362
- pass
1370
+ await self.controller.flush_transport()
1363
1371
 
1364
1372
  async def _read_maybe_empty_line(self):
1365
1373
  while b'\n' not in self._read_data and b'\r' not in self._read_data:
moteus/moteus_tool.py CHANGED
@@ -305,6 +305,10 @@ def _round_nearest_4v(input_V):
305
305
  return round(input_V / 4) * 4
306
306
 
307
307
 
308
+ def _average(x):
309
+ return sum(x) / len(x)
310
+
311
+
308
312
  def expand_targets(targets):
309
313
  result = set()
310
314
 
@@ -951,16 +955,12 @@ class Stream:
951
955
  if encoder_type == 4: # hall
952
956
  hall_configured = True
953
957
 
954
- if self.args.cal_hall:
958
+ if self.args.cal_hall or hall_configured:
955
959
  if not hall_configured:
956
960
  raise RuntimeError("--cal-hall specified, but hall sensors " +
957
961
  "not configured on device")
958
962
  return await self.calibrate_encoder_mapping_hall(encoder_cal_voltage)
959
963
  else:
960
- if hall_configured:
961
- raise RuntimeError(
962
- "Cannot perform encoder mapping with hall sensors, " +
963
- "use --cal-hall")
964
964
  try:
965
965
  return await self.calibrate_encoder_mapping_absolute(encoder_cal_voltage)
966
966
  except:
@@ -1243,6 +1243,16 @@ class Stream:
1243
1243
  desired_encoder_bw_hz = min(
1244
1244
  desired_encoder_bw_hz, 2e-2 / inductance)
1245
1245
 
1246
+ # Also, limit the bandwidth for halls based on the number
1247
+ # of poles and the estimated calibration speed.
1248
+ if hall_output:
1249
+ max_pole_bandwidth_hz = (
1250
+ 0.5 * self.args.cal_motor_poles *
1251
+ self.args.cal_motor_speed)
1252
+ desired_encoder_bw_hz = min(
1253
+ desired_encoder_bw_hz, max_pole_bandwidth_hz)
1254
+
1255
+
1246
1256
  # And our bandwidth with the filter can be no larger than
1247
1257
  # 1/30th the control rate.
1248
1258
  encoder_bw_hz = min(control_rate_hz / 30, desired_encoder_bw_hz)
@@ -1312,32 +1322,42 @@ class Stream:
1312
1322
 
1313
1323
  start_time = time.time()
1314
1324
 
1325
+ SAMPLE_PERIOD_S = 0.02
1326
+ AVERAGE_PERIOD_S = 0.10
1327
+
1328
+ AVERAGE_COUNT = int(AVERAGE_PERIOD_S / SAMPLE_PERIOD_S)
1329
+
1315
1330
  def sign(x):
1316
1331
  return 1 if x >= 0 else -1
1317
1332
 
1318
- old_change = None
1319
- old_vel = None
1333
+ velocity_samples = []
1334
+
1320
1335
  while True:
1321
1336
  data = await self.read_servo_stats()
1322
- velocity = data.velocity
1337
+ velocity_samples.append(data.velocity)
1338
+
1339
+ if len(velocity_samples) > (3 * AVERAGE_COUNT):
1340
+ del velocity_samples[0]
1341
+
1342
+ recent_average = _average(velocity_samples[-AVERAGE_COUNT:])
1323
1343
 
1324
- # As a fallback, timeout after 1s of waiting.
1344
+ # As a fallback, timeout after a fixed amount of waiting.
1325
1345
  if (time.time() - start_time) > 2.0:
1326
- return velocity
1346
+ return recent_average
1327
1347
 
1328
- if abs(velocity) < 0.2:
1329
- return velocity
1348
+ if (len(velocity_samples) >= AVERAGE_COUNT and
1349
+ abs(recent_average) < 0.2):
1350
+ return recent_average
1330
1351
 
1331
- if old_vel is not None:
1332
- change = velocity - old_vel
1333
- if old_change is not None:
1334
- if sign(old_change) != sign(change):
1335
- return velocity
1336
- old_change = change
1352
+ if len(velocity_samples) == 3 * AVERAGE_COUNT:
1353
+ average_1 = _average(velocity_samples[:AVERAGE_COUNT])
1354
+ average_2 = _average(velocity_samples[AVERAGE_COUNT:2*AVERAGE_COUNT])
1355
+ average_3 = recent_average
1337
1356
 
1338
- old_vel = velocity
1357
+ if sign(average_3 - average_2) != sign(average_2 - average_1):
1358
+ return recent_average
1339
1359
 
1340
- await asyncio.sleep(0.1)
1360
+ await asyncio.sleep(SAMPLE_PERIOD_S)
1341
1361
 
1342
1362
  return velocity
1343
1363
 
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.67"
15
+ VERSION="0.3.69"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: moteus
3
- Version: 0.3.67
3
+ Version: 0.3.69
4
4
  Summary: moteus brushless controller library and tools
5
5
  Home-page: https://github.com/mjbots/moteus
6
6
  Author: mjbots Robotic Systems
@@ -5,8 +5,8 @@ moteus/calibrate_encoder.py,sha256=R3pRgGqrDCcmKQqFE7Fr4p8TSie179iqNfBwEJS3pL0,1
5
5
  moteus/command.py,sha256=UkOsbtkso6Oyex8CfbpAKpBNriik519ymxL86EZGkRs,1169
6
6
  moteus/export.py,sha256=vRIfldaqz1eHtWo3993SvatATtu73TZbejL0hzQe8YE,1646
7
7
  moteus/fdcanusb.py,sha256=7PrQiCTROY96gdT2zSZYU1bOCriw-I7H6NspaZpiEx4,7431
8
- moteus/moteus.py,sha256=dSlcEErC2b9Z7Lz37hHbAZxTU0yhAYZNdolDNg3_n0U,47890
9
- moteus/moteus_tool.py,sha256=uYR7klPSXS16RwE23fZL4rJDF5exsPajiZMZiypBYtw,69373
8
+ moteus/moteus.py,sha256=2x5i-4BpTwS3Uo9FWyWesR--acIO8TJb0wCQHbuKuxQ,48131
9
+ moteus/moteus_tool.py,sha256=ccrvAVdxRZEnheALvAgbR7mDrlU90Ses3kj1kfEsVfI,70167
10
10
  moteus/multiplex.py,sha256=LF6MuelzYHqqsCJuCB9YeEyUA03eBaTYRwAVotX3qm8,10120
11
11
  moteus/posix_aioserial.py,sha256=2oDrw8TBEwuEQjY41g9rHeuFeffcPHqMwNS3nf5NVq8,3137
12
12
  moteus/pythoncan.py,sha256=ofotOrDuaFhTLvaokaO3EJK6quVc75Bq-ue70lDMtXI,4071
@@ -14,10 +14,10 @@ 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=q4LPxNY63TQcpoLc62l1hxxwO8yOooz5ORImA1Tw6io,627
17
+ moteus/version.py,sha256=FEYQhXwueAJ_XxxIiWQCnSdWVFCa2egsxksGzbElp7g,627
18
18
  moteus/win32_aioserial.py,sha256=culdl-vYxBKD5n2s5LkIMGyUaHyCcEc8BL5-DWEaxX8,2025
19
- moteus-0.3.67.dist-info/METADATA,sha256=BEV8aecrlyr4X8sNZ2XgjL33IXYk5nIdFPG2KyYuG0E,3372
20
- moteus-0.3.67.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
21
- moteus-0.3.67.dist-info/entry_points.txt,sha256=accRcwir_K8wCf7i3qHb5R6CPh5SiSgd5a1A92ibb9E,56
22
- moteus-0.3.67.dist-info/top_level.txt,sha256=aZzmI_yecTaDrdSp29pTJuowaSQ9dlIZheQpshGg4YQ,7
23
- moteus-0.3.67.dist-info/RECORD,,
19
+ moteus-0.3.69.dist-info/METADATA,sha256=TRwp5Wf0k3CPaiHBxmpm-URMuJ2lL5wlTWErGm6eXjg,3372
20
+ moteus-0.3.69.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
21
+ moteus-0.3.69.dist-info/entry_points.txt,sha256=accRcwir_K8wCf7i3qHb5R6CPh5SiSgd5a1A92ibb9E,56
22
+ moteus-0.3.69.dist-info/top_level.txt,sha256=aZzmI_yecTaDrdSp29pTJuowaSQ9dlIZheQpshGg4YQ,7
23
+ moteus-0.3.69.dist-info/RECORD,,