Repository navigation
fix: report a failed send with its cause and its type - #67
Merged
Merged
Conversation
`GripperActions._emit()` folded every failed `send_mit_frame()` into
`CommandError("MIT 帧下发失败(未连接或未使能)")`. On the bench the CAN
interface went ENETDOWN mid-move, so that message named a cause nobody had
checked: `is_connected` and `is_enabled` were both True at the instant it was
raised, and the actual `OSError(100, 'Network is down')` existed only as a
`log.warning` attached to no exception. The error table in README.md files a
mid-session write failure under `CommError` and not connected / not enabled
under `NotInitializedError`; neither is a `CommandError`.
The reason now travels. `LiteGripCAN.control_mit()` and
`control_mit_stream()` keep it in `last_send_error`, cleared on success.
`LiteGrip.send_mit_frame()` passes it up and supplies its own
`NotInitializedError` naming the step that was skipped. `_emit()` raises the
type the table names, and when nothing recorded a reason — a coarse
`send_mit_frame` stub, say — it says "原因未记录" rather than guessing. The
trajectory replay abort and the teleop loop's first-failure warning name the
same reason; neither changes what it does about it.
Note for callers: catching `CommandError` around a motion call no longer
catches a failed send. A caller that must keep catching one should catch
`LiteGripError`, the base both types share.
Closes #65
|
🎉 This PR is included in version 1.0.3 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A failed MIT frame now reports the cause and the type it actually has, instead of one fixed message that guessed.
GripperActions._emit()is the chokepoint for every frame the engine sends, and it turned a failedsend_mit_frame()intoCommandError("MIT 帧下发失败(未连接或未使能)"). On the bench this shipped a lie: the CAN interface wentENETDOWNpart-way through a move,is_connectedandis_enabledwere bothTrueat the instant the exception was raised, and the real cause —OSError(100, 'Network is down')— existed only as alog.warningattached to no exception, so a caller with no log handler saw the false message and nothing else.README.md's error table already says what these are: a CAN write that fails mid-session isCommError, and not connected / not enabled is whatNotInitializedErrorexists for.CommandErroris for a rejected command. The code now matches the table.Note for callers: this breaks catching
CommandErroraround a motion call — such a caller now seesCommErrororNotInitializedErrorinstead. Both areLiteGripErrorsubclasses, so catching the base still works. Publishes as a patch under this policy.Changes
src/litegrip/protocols/can_bus.py—LiteGripCAN.control_mit()/control_mit_stream()keep the failure in a newlast_send_errorproperty (the exception itself, type included; cleared on success,NotInitializedErrorwhen nothing is registered). TheFalsereturn and the warning are unchanged.src/litegrip/gripper.py— newLiteGrip.last_send_error.send_mit_frame()passes the bus reason up, and supplies its ownNotInitializedErrorwhen_can is Noneor the gripper is not enabled; the two messages are now single-sourced with_check_connected()/_check_enabled().src/litegrip/actions.py—_emit()raisesNotInitializedErrorfor a missing connection or enable,CommErrorcarrying the reason for a transport failure, and says "原因未记录" when nothing recorded one. The original exception rides along as__cause__.src/litegrip/trajectory.py— the replay abort keeps itsTrajectoryErrortype but carries the send's own reason instead of "未连接或未使能?".src/litegrip/teleop.py— the slave loop's first-failure warning names the reason rather than listing both possibilities. The loop still just counts; a lost frame must not abort it.tests/fake_can.py—FakeLiteGripCANmirrors the new attribute and gains asend_errorknob, so a test can make a send fail with a reason.last_send_errorand the typed report.tests/test_send_failure_reports_its_cause.py(13 cases, all three layers) and one intests/test_teleop.py.Testing
From
/home/qaz/litegrip-python:Baseline on the same machine before this branch:
Ran 440 tests ... OK (skipped=12). The 14 added are the 13 in the new module and the 1 intest_teleop.py.Each new case was checked against the unmodified code — with
src/stashed, all 13 error out; with onlyteleop.pystashed, the teleop case fails with the old line (the motor is not enabled or the CAN write failed). Nothing is skipped or weakened.Markdown lint runs clean with the CI version:
Issues
Closes #65