Skip to content

Offer the Franka arm's error recovery on a channel a console asks on - #744

Open
v-positronic wants to merge 1 commit into
mainfrom
wedge-p3-recovery-wire
Open

Offer the Franka arm's error recovery on a channel a console asks on#744
v-positronic wants to merge 1 commit into
mainfrom
wedge-p3-recovery-wire

Conversation

@v-positronic

Copy link
Copy Markdown
Collaborator

The gap

franka.Robot runs recover_from_errors() only inside its own run loop, on no channel, and that branch fires only while state().error != 0. A latched fault leaves the arm in libfranka mode Reflex with error reading 0, so the automatic path never runs and nothing outside the driver can reach it. On 2026-09-10 an arm latched this way rejected every jog and every home for a whole session (Positronic-Robotics/internal#1255).

What this ships

Two ports on franka.Robot:

  • recover — a receiver. The run loop reads it each tick; an ask runs recover_from_errors() regardless of state().error, so it reaches a latched Reflex the automatic branch never sees.
  • recovery_result — an emitter carrying whether the recovery cleared the fault.

This is the positronic half of internal#1255. The console half already exists (platform#479, merged): the panel draws a Clear robot fault control that emits on EvalUI.recover_arm and greys itself while the wire is bound to nothing. A later platform change binds console.recover_arm to recover and reads recovery_result, at which point the control goes live.

Scope

  • Cut from origin/main. P3 in the plan; independent of positronic#678 and P2, which touch nearby lines in run() and will need a rebase against whichever lands first.

Tests

Driver-level, no rig: a console ask runs the recovery and reports the result; a fault that does not clear reports False; an untouched arm reports no result. uv run --locked pytest positronic/drivers/roboarm/tests/test_franka.py is green (35 passed). pre-commit (ruff, ruff format, basedpyright) passed on commit.

The check-rules fan-out is skipped this pass to keep the shared box free while other agents work; the rules check is due before merge.

The arm ran recover_from_errors only inside the driver's own loop, on no
channel, and that loop fires only while state().error is set. A latched fault
leaves the arm in mode Reflex with error reading 0, so the automatic path never
runs and nothing outside the driver can reach it.

Add a recover receiver and a recovery_result emitter on franka.Robot. The run
loop reads the receiver each tick; an ask runs recover_from_errors and emits
whether it cleared. This is the positronic half of internal#1255; the console
binds console.recover_arm to recover and reports recovery_result.

Ticket: none — positronic half of internal#1255; PR body links it.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4aa0372d01

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +374 to +375
self.recover = pimm.ControlSystemReceiver[bool](self)
self.recovery_result = pimm.ControlSystemEmitter[bool](self)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Couple recovery requests to their replies

Rule hidden-dependency violated:
recover and recovery_result implement one request/reply operation as two independent signals, so a result cannot be correlated with its request and the default size-one signal queues can discard back-to-back requests or replies. Expose a single ControlSystemHandler[None, bool] and answer each incoming call instead.

AGENTS.md reference: AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

# in libfranka mode Reflex while ``state().error`` reads 0, so nothing else fires recovery. The
# emitter reports whether the recovery cleared it.
self.recover = pimm.ControlSystemReceiver[bool](self)
self.recovery_result = pimm.ControlSystemEmitter[bool](self)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Name the result for the boolean verdict

Rule misleading-name violated:
recovery_result exposes a bool under an activity/result name, leaving consumers to discover what True asserts. Name the signal for its verdict, such as fault_cleared, so boolean uses read as the claim being tested.

AGENTS.md reference: AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

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.

1 participant