Repository navigation
docs: fix the onboarding gaps found by a new-user walkthrough - #18
Merged
Merged
Conversation
A walkthrough was run on real hardware, following only what this
repository documents. Several steps either fail outright or mislead;
this corrects the documentation without changing any code.
Quick start: the arm boots into the EMERGENCY latch, so enable() was
rejected with ERR{0x10,0x06} before a single motion. Add the reset()
that clears it, replace the fully extended joint pose -- a singular
pose no Cartesian motion can be planned out of -- with one whose
joints all stay clear of their limits, and drive the Cartesian moves
from the measured TCP instead of a hand-written pose with no IK
solution.
Also documents serial permissions, the save_params() and
clear_faults() preconditions, the state frame's mode and flags, the
ROS 2 pytest failure, and links the troubleshooting guide, which had
no entry point from the README.
X-F-R
pushed a commit
that referenced
this pull request
Oct 10, 2026
Follow-up to the onboarding walkthrough in #18, which covers the quick start, the install steps and the serial permissions. What is left here is the part that walkthrough did not reach. The blocking one is TROUBLESHOOTING.md:144, which says a cartesian move from the fully-extended home pose "always" fails with err=1. Measured on hardware: a 1-4 mm step is accepted and reconstructs the arm by 13-60 deg while the tool moves 1-3 mm. The gate catches large steps, not small ones, so "always" sends the reader the wrong way about the one pose that is actually dangerous. examples/03_move_p.py described its default as "a small step you can step back from". From the zero pose the same 1 cm target reconstructs the arm by 86.88 deg (J1 74 deg, J3 52 deg) and the script still prints move_p arrived. The mechanism is firmware-side: move_p reaches the bus through kin_runner_request_move_p, which has no adjacent-solution gate, while move_l/move_c/move_path go through cart_plan.c and reject a jump beyond CART_MAX_IK_STEP (0.35 rad). Both this example and examples/06_cartesian.py now leave the singularity before issuing a cartesian command. Three API claims corrected in docs/DEVELOPER_GUIDE.md and README.md: * wait=False skips only the wait for the arm to settle. Both values block for the plan reply, so poll_cart() never yields a result from one -- its real use is recovering a call whose ACK timed out. * enable() returns before the state stream reflects it: 2.0-2.7 ms to return against 7.0-7.8 ms for the flag to turn true, so reading enabled on the next line always shows False. Also recorded in the docstring. * the cartesian snippet used three absolute poses with rpy=(pi,0,0), an orientation that solves only about half the time; it now offsets the measured pose. Testing: LITEARM_LIVE=1 pytest -> 659 passed. Both examples and the revised snippet run against the arm: 03_move_p.py --go EXIT=0, 06_cartesian.py --go EXIT=0 (n_wp 5/7/9/6).
|
🎉 This PR is included in version 1.1.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
X-F-R
added a commit
that referenced
this pull request
Oct 10, 2026
…es (#23) * docs: fix the onboarding gaps found by a new-user walkthrough A walkthrough was run on real hardware, following only what this repository documents. Several steps either fail outright or mislead; this corrects the documentation without changing any code. Quick start: the arm boots into the EMERGENCY latch, so enable() was rejected with ERR{0x10,0x06} before a single motion. Add the reset() that clears it, replace the fully extended joint pose -- a singular pose no Cartesian motion can be planned out of -- with one whose joints all stay clear of their limits, and drive the Cartesian moves from the measured TCP instead of a hand-written pose with no IK solution. Also documents serial permissions, the save_params() and clear_faults() preconditions, the state frame's mode and flags, the ROS 2 pytest failure, and links the troubleshooting guide, which had no entry point from the README. * docs: correct the singular-pose claim, three API notes and two examples Follow-up to the onboarding walkthrough in #18, which covers the quick start, the install steps and the serial permissions. What is left here is the part that walkthrough did not reach. The blocking one is TROUBLESHOOTING.md:144, which says a cartesian move from the fully-extended home pose "always" fails with err=1. Measured on hardware: a 1-4 mm step is accepted and reconstructs the arm by 13-60 deg while the tool moves 1-3 mm. The gate catches large steps, not small ones, so "always" sends the reader the wrong way about the one pose that is actually dangerous. examples/03_move_p.py described its default as "a small step you can step back from". From the zero pose the same 1 cm target reconstructs the arm by 86.88 deg (J1 74 deg, J3 52 deg) and the script still prints move_p arrived. The mechanism is firmware-side: move_p reaches the bus through kin_runner_request_move_p, which has no adjacent-solution gate, while move_l/move_c/move_path go through cart_plan.c and reject a jump beyond CART_MAX_IK_STEP (0.35 rad). Both this example and examples/06_cartesian.py now leave the singularity before issuing a cartesian command. Three API claims corrected in docs/DEVELOPER_GUIDE.md and README.md: * wait=False skips only the wait for the arm to settle. Both values block for the plan reply, so poll_cart() never yields a result from one -- its real use is recovering a call whose ACK timed out. * enable() returns before the state stream reflects it: 2.0-2.7 ms to return against 7.0-7.8 ms for the flag to turn true, so reading enabled on the next line always shows False. Also recorded in the docstring. * the cartesian snippet used three absolute poses with rpy=(pi,0,0), an orientation that solves only about half the time; it now offsets the measured pose. Testing: LITEARM_LIVE=1 pytest -> 659 passed. Both examples and the revised snippet run against the arm: 03_move_p.py --go EXIT=0, 06_cartesian.py --go EXIT=0 (n_wp 5/7/9/6). --------- Co-authored-by: thetooler <wuruihao@nexform.tech> Co-authored-by: YOLO-DT <3199429837@qq.com>
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 new-user walkthrough was run on real hardware (Litearm 7-axis,
/dev/ttyACM0,firmware
Litearm1.10.0-7J), following only what this repository documents. Severalsteps a new user hits first either fail outright or mislead. This corrects the
documentation; no code or behaviour changes.
The blocking one: right after power-up the arm sits in the
EMERGENCYlatch, so thequick start's first
enable()throwsERR{0x10,0x06}before sending a single retry —and the quick start never mentions
reset(). The two Cartesian lines that follow failas well: the
movejbefore them leaves the arm fully extended (a singular pose), andboth the
move_ltarget and theik()target are unusable from there.Changes
README.zh-CN.mdandREADME.md:reset()that clears the power-on latch, and say why it isnot optional. Replace
movej([0.1, 0, 0, 0, 0, 0, 0])with a pose whose joints allkeep a healthy margin to their limits. Drive
move_l/ikfrom the measured TCPinstead of
(0.30, 0.0, 0.40, 3.1416, 0.0, 0.0), which has no IK solution.usermod -aG dialoutis not always required: checkls -l /dev/ttyACM0first. Document the udev rule that makes the nodecrw-rw-rw-,including that any local user on such a machine can drive the arm.
clear_faults()clears the singleFAULTbit;EMERGENCYandFB_STALEare latches onlyreset()clears.save_params()requires the arm to be disabled(
ERR{0x25,0x04}otherwise), and disabling drops it out of the position loop, so aside-mounted or loaded arm sags. Support it first.
mode/flags: the 8mode_namevalues, why
WD_TRIPPEDis normal rather than a fault, whyFB_STALEis a livecondition, and that
mode == ZERO_G(the arm) andzero_g_active(this session) candisagree. Also the exception to the "
hzandtimestampare both 0" rule: the firstframe a process reads reports
hz=0.0.pytestdie during collection(
ModuleNotFoundError: No module named 'lark'); give the two working invocations.either top-level README.
TROUBLESHOOTING.zh-CN.mdandTROUBLESHOOTING.md:ZERO_Gandzero_g_stop()does nothing. A newsession cannot send the exit frame, and the firmware rejects every motion command
until one arrives. Give the enter/exit pairing that recovers, and how to recognise
the state (
mode_name == "ZERO_G"whilezero_g_activereadsFalse).Testing
The firmware-sync tests skip unless a
litearm-stm32checkout is present; they accountfor 20 of the 22 skips above.
The replacement quick start was extracted from the edited README and run verbatim on the
arm, from power-up, with no exception handling around it:
reset()→enable()→movej→move_l→get_state→get_tcp→ik→home,every step returning a valid result.
Issues
None — no issue was filed for this; the findings come from the walkthrough. Happy to
file the code-side findings separately if you want them tracked.