Skip to content

docs: correct the section 5 claims hardware contradicted - #25

Merged
X-F-R merged 1 commit into
mainfrom
docs/correct-section-5-claims
Oct 11, 2026
Merged

X-F-R merged 1 commit into
mainfrom
docs/correct-section-5-claims

Conversation

@X-F-R

@X-F-R X-F-R commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Walked every entry point in DEVELOPER_GUIDE §5 — 15 subsections, about 60 entry points —
against a LiteArm 7-DOF running Litearm1.10.0-7J, calling only what the documents say.
186 of 190 checks held. Six claims did not. Two of those six would send a careful reader in the
wrong direction, so they are worth correcting rather than leaving as a footnote.

Independent of #24: both touch docs/DEVELOPER_GUIDE.md, but in different sections (there §5.1,
here §5.3 / §5.7 / §5.8 / §5.10), so they do not conflict.

1. set_joint_limits() does not reject widening

The doc says writing the current values back is judged a widening request and rejected
(ERR[23,2]), "so it is not idempotent". Measured on J1:

Request Result
write back the current values [-2.809546947, 2.809546947] accepted, no error, value unchanged
write a strictly wider range [-2.859547, 2.859547] accepted, no error, value unchanged

The firmware's own error text states the rule: "只许收窄, 照编译期默认值取交集" — intersect
with the compile-time default. Widening is therefore a silent no-op, not a rejection, and
writing the current values back is idempotent. The consequence the doc gets wrong is the
useful one: you cannot use this call to confirm that a limit write landed. ERR{0x23,0x02} is
for a NaN, an empty intersection or an out-of-range idx.

This is not the SDK swallowing the error: set_joint_limits goes through the same _cmd
ACK/ERR path as set_joint_param, which does surface ERR{0x22,0x02}.

Narrowing is also irreversible in RAM — the intersection only ever shrinks — which the doc
did not say. (It was not tested for that reason.)

2. CartPlan.settled — the commonest cause is missing

cart.py lists two causes for ok=True, settled=False: the trajectory was invalidated by
another motion, or get_tcp() could not be read. There is a third, and on this arm it dominates:
the arm settled but the TCP read back afterwards sits outside 6 mm / 0.03 rad.

Five consecutive move_l(wait=True) calls, 20 mm of travel, no other motion, get_tcp() healthy:

run settled settle_err_rad position error (limit 6 mm) orientation error (limit 0.03)
1 False 0.000383 7.92 mm 0.01017
2 False 0.000767 9.21 mm 0.01402
3 False 0.001150 9.08 mm 0.01481
4 False 0.000383 9.85 mm 0.01598
5 True 0.000381 2.70 mm 0.00508

This arm's TCP position repeatability measures 3–10 mm, i.e. right at the 6 mm tolerance, so
settled=False here is an ordinary outcome. Read from the doc alone it looks like "another
motion invalidated your trajectory", which is a different investigation entirely.

3–4. Two names that do not exist on the SDK side

  • The state frame renders ARM_MODE_MOVE_MIT_ALL as MIT_ALL (_protocol.MODE_NAMES), not
    MOVE_MIT_ALL. state.mode_name == "MOVE_MIT_ALL" is never true. The warning itself is right
    and now confirmed: send_mit_all reports MIT_ALL too, so the two really are
    indistinguishable from the state frame. (send_mit is a different mode, MOVE_MIT.)
  • LOG_MAX_SAMPLES and CTRL_HZ live in litearm.log and are not re-exported at package
    level, unlike LogSample / LogReader / parse_samples in the same subsection.

5–6. Two smaller ones from the same walk

  • move_c's start-mismatch check is local and raises InvalidCommandError; the
    CartesianPlanError in the same section covers the firmware's own err 1/2/3. The collinear
    check (err=2) also has a scale threshold — three collinear points 20 mm apart are accepted
    and planned (n_wp=7), 100 mm apart is rejected.
  • ERR{0x08,0x04} is unreachable from this SDK while hand-guiding: zero_g()'s guard rejects
    every other downstream command locally, before the frame is sent. It needs another host to
    have entered zero-g.

Changes

  • docs/DEVELOPER_GUIDE.md, docs/DEVELOPER_GUIDE.zh-CN.md — §5.3, §5.7, §5.8, §5.10 as above.
  • src/litearm/cart.py — the CartPlan docstring now lists three causes for
    ok=True, settled=False and says to rule out the TCP-tolerance one first.
  • src/litearm/params.py — set_joint_limits docstring records the intersection behaviour.

Documentation and two docstrings. No behaviour change.

Testing

$ LITEARM_LIVE=1 python3 -m pytest -q
659 passed, 2 skipped

The measurements above were taken on hardware. Everything reachable by document only was called
that way; the irreversible entry points listed in §7 (save_params, model.commit,
model.revert, params.reset_factory, model.set_jm, enter_dfu, activate) were not
executed, and neither was narrowing a joint limit.

Issues

None — found while doing a document-driven acceptance pass. No tracking issue.

Walked every entry point in DEVELOPER_GUIDE section 5 (15 subsections,
about 60 entry points) against a LiteArm 7-DOF running Litearm1.10.0-7J,
calling only what the documents say. 186 of 190 checks held. Six claims
did not.

set_joint_limits does not reject widening. The firmware intersects the
request with its compile-time default and answers ACK, so writing the
current values back is accepted with no error and no change -- the call
IS idempotent, and it cannot be used to confirm that a write landed. The
doc said the opposite, which sends anyone trying to verify a limit write
in the wrong direction. ERR{0x23,0x02} is for a NaN, an empty
intersection or an out-of-range idx. Narrowing is also irreversible in
RAM, which is worth saying out loud.

CartPlan.settled lists two causes for ok=True, settled=False; the
commonest one is missing. settled also requires the TCP read back after
arrival to sit inside 6 mm / 0.03 rad, and this arm's TCP repeatability
is 3-10 mm -- right at that edge. Measured on a 20 mm move_l: 4 of 5 runs
were settled=False purely from 7.9-9.9 mm of position error, with
settle_err_rad down at one quantisation step. Read from the doc alone,
that looks like "another motion invalidated your trajectory".

Two names do not exist on the SDK side: the state frame renders
ARM_MODE_MOVE_MIT_ALL as MIT_ALL, so mode_name == "MOVE_MIT_ALL" is never
true; and LOG_MAX_SAMPLES / CTRL_HZ live in litearm.log without being
re-exported at package level.

Two smaller ones in the same walk: move_c's start-mismatch check is local
and raises InvalidCommandError, not the CartesianPlanError used for the
firmware's own err 1/2/3; and its collinear check has a scale threshold
-- three collinear points 20 mm apart are accepted and planned, 100 mm
apart is rejected. ERR{0x08,0x04} is also unreachable from this SDK when
zero_g() belongs to this client, because the guard rejects locally before
the frame is sent.

Two docstrings (cart.py, params.py) plus both developer guides. No
behaviour change.
@X-F-R
X-F-R merged commit d0c283a into main Oct 11, 2026
2 checks passed
@X-F-R
X-F-R deleted the docs/correct-section-5-claims branch October 11, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants