motor-python 0.0.9__tar.gz → 0.0.10__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.
Files changed (22) hide show
  1. {motor_python-0.0.9 → motor_python-0.0.10}/PKG-INFO +1 -1
  2. {motor_python-0.0.9 → motor_python-0.0.10}/pyproject.toml +1 -1
  3. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/__init__.py +1 -1
  4. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/cube_mars_motor_can.py +37 -10
  5. {motor_python-0.0.9 → motor_python-0.0.10}/.gitignore +0 -0
  6. {motor_python-0.0.9 → motor_python-0.0.10}/LICENSE +0 -0
  7. {motor_python-0.0.9 → motor_python-0.0.10}/README.md +0 -0
  8. {motor_python-0.0.9 → motor_python-0.0.10}/scripts/README.md +0 -0
  9. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/__main__.py +0 -0
  10. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/base_motor.py +0 -0
  11. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/can_protocol.py +0 -0
  12. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/can_utils.py +0 -0
  13. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/cube_mars_motor.py +0 -0
  14. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/definitions.py +0 -0
  15. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/examples.py +0 -0
  16. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/examples_can.py +0 -0
  17. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/motor_control_using_pid.py +0 -0
  18. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/motor_manager.py +0 -0
  19. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/motor_status_parser.py +0 -0
  20. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/pid_controller.py +0 -0
  21. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/second_order_low_pass_filter.py +0 -0
  22. {motor_python-0.0.9 → motor_python-0.0.10}/src/motor_python/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: motor_python
3
- Version: 0.0.9
3
+ Version: 0.0.10
4
4
  Summary: CubeMars motor module for Aries exosuits.
5
5
  Project-URL: homepage, https://github.com/TUM-Aries-Lab/motor-module
6
6
  Author-email: Tsmorz <tony.smoragiewicz@tum.de>, Hannes Nguyen <hannes.nguyen@tum.de>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "motor_python"
3
- version = "0.0.9"
3
+ version = "0.0.10"
4
4
  description = "CubeMars motor module for Aries exosuits."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Tsmorz", email = "tony.smoragiewicz@tum.de"},{ name = "Hannes Nguyen", email = "hannes.nguyen@tum.de" }]
@@ -5,7 +5,7 @@ Legacy UART interface: CubeMarsAK606v3.
5
5
  Base class: BaseMotor (for shared interface & safety logic).
6
6
  """
7
7
 
8
- __version__ = "0.0.9"
8
+ __version__ = "0.0.10"
9
9
 
10
10
  from typing import Literal
11
11
 
@@ -1282,10 +1282,17 @@ class CubeMarsBaseCAN(BaseMotor):
1282
1282
  return None
1283
1283
 
1284
1284
  def send_neutral_command(self) -> None:
1285
- """Return latest parsed motor telemetry.
1285
+ """Send the enter-motor-mode frame.
1286
1286
 
1287
- Per CubeMars manual AK80-6 (Page 41): re-sending the enter MIT command
1288
- returns current state in a stateless manner.
1287
+ The name and the docstring this replaced were both wrong -- it was
1288
+ described as returning telemetry, copied from get_status(). What it
1289
+ sends is FF..FC, the MIT enter-motor-mode helper, which is why calling
1290
+ it was the difference between a motor that produced torque and one
1291
+ that accepted every command and produced none.
1292
+
1293
+ Nothing here is neutral. Prefer enable_mit_mode(), which sends the
1294
+ same frame and reports whether the motor answered; this remains for
1295
+ callers that want the frame alone.
1289
1296
  """
1290
1297
  if not self.connected:
1291
1298
  return
@@ -1412,13 +1419,13 @@ class CubeMarsBaseCAN(BaseMotor):
1412
1419
 
1413
1420
  self._mit_enabled = False
1414
1421
  neutral = self._mit_neutral_payload()
1415
- feedback_before = self._last_feedback_monotonic
1416
- sent = self._send_mit_payload(neutral, capture_response=True)
1417
- if sent and self._last_feedback_monotonic > feedback_before:
1418
- self._mit_enabled = True
1419
- logger.info("MIT mode ready via direct MIT command handshake")
1420
- return
1421
1422
 
1423
+ # The helper frame is what actually enters motor mode. It is sent
1424
+ # first, not as a fallback, because fresh feedback cannot tell an
1425
+ # enabled motor from a disabled one: the motor answers an MIT-format
1426
+ # frame either way. Concluding from that alone reported success
1427
+ # against a motor that then produced no torque -- commands accepted,
1428
+ # position and speed reported, torque frozen at one value.
1422
1429
  helper_frames: list[tuple[str, bytes]] = []
1423
1430
  if self._helper_policy in {"fcfd", "legacy"}:
1424
1431
  helper_frames.append(("FF..FC", self._CAN_HELPER_ENABLE))
@@ -1427,10 +1434,14 @@ class CubeMarsBaseCAN(BaseMotor):
1427
1434
 
1428
1435
  for label, frame in helper_frames:
1429
1436
  logger.debug(f"Attempting MIT handshake with helper frame {label}")
1437
+ # No response captured: the helper is a fire-and-forget command
1438
+ # and proves nothing by replying. The MIT payload below is what
1439
+ # the enable is verified against, so demanding a reply here would
1440
+ # only add a second thing to go wrong.
1430
1441
  helper_sent = self._send_raw(
1431
1442
  arbitration_id=self.motor_can_id,
1432
1443
  data=frame,
1433
- capture_response=True,
1444
+ capture_response=False,
1434
1445
  )
1435
1446
  if not helper_sent:
1436
1447
  continue
@@ -1442,6 +1453,22 @@ class CubeMarsBaseCAN(BaseMotor):
1442
1453
  logger.info(f"MIT mode ready after helper frame {label}")
1443
1454
  return
1444
1455
 
1456
+ # No helper frame is available under the strict policy, and under the
1457
+ # others none got through. Falling back to the direct handshake keeps
1458
+ # those callers working, but it proves only that the motor is
1459
+ # answering -- so say so rather than logging readiness.
1460
+ feedback_before = self._last_feedback_monotonic
1461
+ sent = self._send_mit_payload(neutral, capture_response=True)
1462
+ if sent and self._last_feedback_monotonic > feedback_before:
1463
+ self._mit_enabled = True
1464
+ logger.warning(
1465
+ "MIT mode assumed ready from a direct command handshake: the "
1466
+ "motor is answering, but nothing confirms it entered motor "
1467
+ "mode, and a disabled motor answers identically. Expect "
1468
+ "commands to be accepted and produce no torque if it did not."
1469
+ )
1470
+ return
1471
+
1445
1472
  can_state = self._read_can_state(force=True)
1446
1473
  raise RuntimeError(
1447
1474
  "Failed to enable MIT mode: no fresh feedback observed after MIT handshake "
File without changes
File without changes
File without changes