motorRecord: key CDIR on the commanded stroke after a jog-stop backlash take-out - #254
Open
physwkim wants to merge 1 commit into
Open
motorRecord: key CDIR on the commanded stroke after a jog-stop backlash take-out#254physwkim wants to merge 1 commit into
physwkim wants to merge 1 commit into
Conversation
…sh take-out On the MIP_JOG_STOP path, postProcess() runs the drive-to-readback sync that forces pmr->diff = 0, so relpos = diff/mres is 0 when the shared `pmr->cdir = (relpos < 0.0) ? 0 : 1;` executes. That publishes CDIR = 1 (forward) unconditionally, even when the backlash take-out leg is commanded in reverse (BDST > 0, |BDST| >= |MRES|). The wrong CDIR makes ls_active misread the minus limit switch, so the record retries into a pressed reverse limit until RCNT > RTRY and latches MISS = 1. Set relpos = relbpos on the JOG_STOP branch after the take-out leg is dispatched. The commanded stroke sign equals sign(relbpos) in both the MOVE_REL (relbpos directly) and MOVE_ABS (bpos - drbv/mres = relbpos) cases, and relbpos is live on this path. This mirrors the sibling MIP_MOVE branch, which already reassigns relpos before the same cdir line. CDIR-only change: no WRITE_MSG on this branch uses relpos, so the take-out motion is unchanged.
Member
|
Was this PR created by an LLM? If so, which agent & model were used for it? |
Author
|
Yes — the agent was Claude Code, the model Claude Opus 4.8. It came out of a session auditing motorRecord.cc for a Rust port of the motor record; I reviewed the analysis and the patch before filing and take responsibility for both. Happy to rework anything that doesn't fit the project's conventions. |
Member
|
I don't think you need to rework anything. We don't have official guidelines yet, but I'm trying to label AI contributions so that people who feel strongly about it can make informed decisions. |
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.
motorRecord: key CDIR on the commanded stroke after a jog-stop backlash take-out
Summary
After a reverse jog is released,
postProcess()publishesCDIR = 1(forward) for the backlash take-out leg unconditionally, even when that
leg is actually commanded in the reverse direction. The commanded-direction
field
CDIRis derived fromrelpos, but on theMIP_JOG_STOPpathrelposhas just been forced to
0by the drive-to-readback sync at the top ofpostProcess(), so the sign test(relpos < 0.0)can never be true. Thispatch keys
CDIRon the stroke actually commanded (relbpos), which is liveon this path, without changing the take-out motion itself.
The defect
In
motorApp/MotorSrc/motorRecord.cc,postProcess():The "make drive values agree with readback" block runs for every
MIPexcept
{MIP_MOVE, MIP_MOVE_BL, MIP_JOG_BL1, MIP_JOG_BL2}— thepredicate does not exclude
MIP_JOG_STOP. Inside it,pmr->diff = 0.;.The
MIP_JOG_STOP || MIP_MOVEarm then computesrelpos = pmr->diff / pmr->mres;— which is0on the JOG_STOP pathbecause of step 1.
The JOG_STOP branch dispatches the take-out leg toward
dval - bdstviaWRITE_MSG(MOVE_REL, &relbpos)(encoder/readback in use) orWRITE_MSG(MOVE_ABS, &bpos).The shared assignment
pmr->cdir = (relpos < 0.0) ? 0 : 1;then runs withrelpos == 0, so(0 < 0.0)is false andcdir = 1regardless of thesign of the stroke actually commanded.
The sibling arms are self-consistent and are not touched:
MIP_MOVEcase is excluded from the sync in step 1, so itsrelposis live at the shared
cdirassignment (and is re-derived asrelpos * fracin its own branch).
MIP_JOG_BL1arm (MIP_JOG_BL1is likewise excluded from the sync)re-derives
relposbefore itscdirassignment.Only the JOG_STOP path zeroes the value it then keys
CDIRon.Reachability (why this is a real defect, not defensive noise)
Jog an axis in reverse, release it, with backlash enabled and non-trivial:
BDST > 0and|BDST| >= |MRES|(thefabs(pmr->bdst) >= fabs(pmr->mres)gate that enters the backlash block). The record commands the backlash
take-out in the negative direction but publishes
CDIR = 1(forward).Downstream damage from the wrong
CDIR:ls_active = (rhls && cdir) || (rlls && !cdir)fails to recognise theminus limit switch as active during the move.
retries into a pressed reverse limit until
RCNT > RTRY, and latchesMISS = 1.maybeRetry()derivesuser_cdirfromcdirand takes the wrong branch.The fix
On the JOG_STOP branch only, set
relpos = relbpos;immediately after thetake-out leg is dispatched, so the shared
pmr->cdir = (relpos < 0.0) ? 0 : 1;reflects the true commanded direction. This is valid because the commanded
stroke sign equals
sign(relbpos)in both modes:use_rel:MOVE_REL &relbposcommandsrelbpossteps directly.MOVE_ABS &bposmoves from the current raw position(
drbv / mres) tobpos = (dval - bdst) / mres; the raw stroke isbpos - drbv/mres = ((dval - bdst) - drbv) / mres = relbpos.relbposis computed live on this path and is unaffected by thediff = 0sync, so the sign is now correct. The reassignment mirrors the sibling
MIP_MOVEbranch, which already reassignsrelposbefore the same sharedcdirline. The change isCDIR-only: none of theWRITE_MSGdispatches onthe JOG_STOP branch use
relpos, so the take-out motion is unchanged.Scope / family check
Every
cdir =assignment inmotorRecord.ccwas audited:relpos, zeroed by the syncMIP_MOVEshared linerelpos, live (excluded from sync, re-derived)MIP_JOG_BL1armrelpos, live (excluded from sync, re-derived)MIP_HOMFflag +mressignjogfflag +mres/dirsignrdifTesting
Not compiled locally: this checkout has no EPICS support tree configured, so
makecannot build the module here. The change is a one-line addition of alocal-variable assignment plus a comment, in a branch that already reassigns
the same variable in its sibling; it relies on CI to compile. No behavioural
change to the commanded motion — only
CDIR(the published commandeddirection) is corrected on the reverse jog-stop backlash take-out.