Skip to content

Tape pick (#19): streamed straight-line descent, effort-checked grip, softer park - #20

Open
jss265 wants to merge 22 commits into
mainfrom
claude/issue-19-20261010-0111
Open

jss265 wants to merge 22 commits into
mainfrom
claude/issue-19-20261010-0111

Conversation

@jss265

@jss265 jss265 commented Oct 10, 2026

Copy link
Copy Markdown
Member

Adds scripts/piper_pick_tape.py, which plans and runs the tape pick in stages (read-only unless --go). The PiPER's MOVE J does not synchronize joints, which made the stepped descent jerky, so the descent, lift, put-back and return home are now streamed at 100 Hz along precomputed paths (a straight vertical fingertip line, and the joint-space line home), and the planner checks the move to the hover the way the arm really runs it. Stage 3 lifts only if the gripper's effort reading shows a firm grip, and puts the roll back if it slips. Parking sends the SDK's quick stop before the reset, to soften the drop. --trace logs joints and gripper at 100 Hz. Also includes the stage 1-2 videos and logs and the stage-2 video analysis under docs/issue-19, and Pi notes in CLAUDE.md. Stage 3 has not been run on the arm.

Refs #19

Generated with Claude Code

github-actions Bot and others added 5 commits October 10, 2026 00:02
scripts/piper_pick_tape.py locates the roll by calibrating the fixed Pi
camera against the arm's own forward kinematics, solves IK for a grasp
that closes on the roll's flat faces, and checks the path against the
table and the roll. It is read-only unless --go, and runs in stages
(pregrasp, descend, grasp) that each start and end at the rest pose.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…se (#19)

Adds --video to piper_pick_tape.py (MJPEG via rpicam-vid) and clamps the
home target into the joint limits, since the folded rest sits at J2 = -2 deg.
Commits the stage-1 clip, frame and log, and notes the recording recipe.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… log the bottom (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…park (#19)

The stage-2 descent was 15 chained MOVE J steps. The PiPER runs each
joint at the same speed and stops it on arrival (unsynchronized, seen in
the stage-2 video), so every 5 mm step stopped and restarted J2, J3 and
J5 and the gripper sprang back ~4 mm each time. The descent, lift,
put-back and return home are now streamed at 100 Hz along precomputed
paths (vertical fingertip line, 1 mm IK spacing; joint-space line home)
with a minimum-jerk profile. Only the move out to the hover stays one
MOVE J, and the planner now checks it as the arm really runs it.

Stage 3 lifts only if the fingers stop on the roll and the gripper's
reported effort reaches --min-grip-nm, and it puts the roll back if the
opening or effort changes while held. At home --park estop sends the
SDK's quick stop (documented as a slow descent) before the reset,
instead of a plain disable that drops the arm 2 deg in 50 ms. Adds a
100 Hz --trace, and the stage 1-2 logs that *.log had kept out of git.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… video analysis (#19)

If the fingers have closed on the roll and the run stops for any reason
(weak grip, slip, interruption), the cleanup now lowers it to the table
and opens before rising, instead of going home holding it. Dry-run
against a simulated arm: normal grasp, slip mid-lift, weak grip, and
both park modes.

docs/issue-19/stage3-prep: the gripper tracked through the stage-2
descent (springs back 3-5 mm at each 5 mm step; static scene patches
move < 0.3 px), the wrist drop at disable from the 100 Hz trace
(~10 mm in ~50 ms), and frames of the move to the hover showing the
forearm hold its angle until J3 arrives (MOVE J is unsynchronized).

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 10, 2026

Copy link
Copy Markdown
Member Author

I'm unplugging the robot and going home. When we get the E-Stop we can leave it plugged in over night.

For next time: re-run. Grippers probably needs to dip lower, and the grippers speed should be 1/4 what it is now.

@jss265

jss265 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

@claude:medium connect to the arm and resume the tape pick up test. Work area is clear.

@claude

claude Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 4m 43s —— View job


Tape pick: I couldn't resume because the arm isn't on the CAN bus

I connected to the Pi, but the arm sends no feedback, so I didn't move anything. While it's unreachable I did three things. I worked out why the 10-09 stage-3 run missed the roll (that run never reported back). I made the two changes you asked for, deeper dip and gripper at 1/4 speed. And I installed the updated script on the Pi.

  • Read the script, the logs and your notes (dip lower, gripper at 1/4 speed)
  • Connect to the Pi and check it read-only: no joint feedback (details below)
  • Recover and analyse the unreported 10-09 stage-3 run
  • Make the gripper ramp at 1/4 speed and dip 13 mm lower; check the plan in plan-only mode and the gripper ramp against a simulated gripper
  • Copy the script to the Pi (the old copy is kept as ~/piper_pick_tape.2026-10-09.py)
  • Run stage 3 again: blocked until the arm is powered

What I found on the Pi

  • can0 is up at 1 Mbit/s and the Pi has been up for 6 days. The bus has logged about 300 million error-passive events. The SDK gets 0 Hz joint feedback and every joint reports a communication fault. That looks like the arm's power (or its CAN cable) is still unplugged from 10-10.
  • The camera works. The arm is folded at rest and the roll is on the table (still).
  • The camera has moved since 10-09. The arm base and the roll both appear about 200 px further left, and the base looks bigger. So the pixel calibration that put the roll at r = 247 mm no longer applies. I can't tell from this one view whether the roll itself moved. Please check it's where it was on 10-09, or let me re-locate it once the arm is powered.

Why stage 3 missed on 10-09

That run (log, 100 Hz trace) did close on the roll, but couldn't keep it:

  • The gripper slammed shut. It went from 64 to 18 mm in about 80 ms, peaking near 500 mm/s. It stopped on the roll at about 17 mm and read about 5 N·m for 0.17 s, even though the script asked for 1.0 N·m.
  • Then the roll slipped out. The fingers closed to 1.3 mm, so the script said "closed on nothing", did not lift, and went home cleanly.
  • The fingertips were too high. In the video they sit at about the roll's top rim, not the planned 15 mm below the top of the roll. So the real fingertips are roughly 10–15 mm higher than the model puts them, and they pinched only the rim. This matches your "dip lower".

Video frames cropped to the gripper. The first row runs from the descent to the close; the roll is squeezed out around 12.5–12.6 s. Someone is in the uncropped video, so I haven't committed or uploaded it.

Changes in ba8903e (piper_pick_tape.py)

  • Gripper at 1/4 speed. The gripper takes only a target opening and an effort, with no speed setting. So the script now streams the target at 100 Hz at --grip-mm-s, default 60 mm/s. That is about 1/4 of the gripper's own ~250 mm/s average. It applies to opening, closing, releasing and the final close. Against a simulated gripper, closing onto a 17 mm roll took about 1 s instead of 0.1 s.
  • Dip lower. --overlap-mm goes from 15 to 28, so the planned fingertip height is 21 mm instead of 34. The plan stays inside the 20 mm table margin, with a straight descent (0.02 mm drift), 4.4 s down at 10 %. If the model is ~12 mm optimistic like last time, the real fingertips land about 16 mm into the roll.
  • Nothing else changed: the effort check, the slip check, the put-back and the park all work as before.

To resume

Power the arm (and check the roll hasn't moved), then post a new @claude comment that says the workspace is clear. That run will plan from the live joints and run --go --until grasp on video with the trace. I won't upload a clip with people in it to YouTube without their OK.
• claude/issue-19-20261010-0111

…ge-3 run (#19)

Stage 3 on 2026-10-09 closed on the roll at ~17 mm, held ~5 N*m for 0.17 s,
and the roll slipped out from fingertips that sat at its rim. The gripper
target now ramps at --grip-mm-s (60 mm/s) and --overlap-mm defaults to 28.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

@claude:medium I just power cycled. Attempt again

@claude

claude Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 3m 37s —— View job


Tape pick, stage 3 retry: the arm ran cleanly but the fingers closed beside the roll

After the power cycle the arm was back on the bus, so I ran stage 3 (--go --until grasp) on video with the trace. The motion was clean: the move to the hover, the 4.4 s straight descent to the deeper 21 mm fingertip height, the 1/4-speed close, and the return home. But the fingers closed on air. The roll isn't in the vertical plane the script aims at (J1 = 4.05°, where it was on 10-09). It looks to have moved toward the camera. The arm is parked and healthy, with no faults and the motors off.

  • Check the Pi: can0 error-active, feedback from all six joints, no fault flags
  • Plan from the live joints, aimed at the 10-09 plane (--plane-deg 4.05; the arm now rests at J1 = −1.3°)
  • Run --go --until grasp on video with the trace
  • Analyse it and commit the log, trace and frames (091bd81)
  • Grasp the roll: blocked until the roll is back in the arm's plane (see below)

What happened (log, 100 Hz trace)

  • The descent settled at a fingertip height of 22 mm (planned 21), about 27 mm below the top of the roll. If the roll had been between the fingers, they would have been well around it.
  • The gripper now closes at the slower speed. It went from 64 to 1.5 mm over about 1.3 s, compared with 80 ms on 10-09. It never stopped at the roll's ~17 mm, and the effort stayed under 0.3 N·m on the way through. Nothing was between the fingers, so the script didn't lift and went home.
  • In the video the roll sits lower in the frame than the fingertips and a little to their left (frames from the descent to the close):

The camera is low and side-on, so lower in the frame means closer to the camera. The roll is off the arm's plane on the camera side. Its reach along the arm still looks about right (≈247 mm, judged against the base and the folded gripper in the before still), but this camera can't measure depth, so I can't say how far off the plane it is. Retrying at guessed J1 angles would be guesswork, so I stopped after one run.

Also seen

During the first open, the gripper's reported opening stayed at 2.9 mm for about 2 s, then jumped to 64 mm once the arm started moving. The fingers were open for the descent, as the video shows, so the run wasn't affected. It may be the gripper being slow to enable after a power cycle. I'll keep an eye on it.

To resume, pick one

  1. Put the roll back in the arm's plane. Its centre should be about 247 mm out from the J1 axis, along the line the gripper pointed down on 10-09 (≈4° from the rest heading). A tape mark on the table would keep it there. Then comment @claude saying the workspace is clear.
  2. Or have the arm show you the spot. Ask me to run --until pregrasp and hold there, then slide the roll under the open fingers.

I didn't upload the video to YouTube. The descent frames show only the arm, but I didn't check the whole clip for people.
• claude/issue-19-20261010-0111

…roll (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

@claude:medium attempt again, the tape is in the correct place

@claude

claude Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 1m 25s —— View job


Tape pick, stage 3 retry: arm is ready, but I haven't moved it yet

The arm is healthy and the plan checks out. I stopped before any motion for two reasons. The repo's rule for the arm is that a run needs to say the workspace is clear, and your comment only said the tape is in place. Also, the camera shows the roll exactly where it sat before the last missed grasp.

  • Check the Pi read-only: can0 is error-active, all six joints report at 24 V and 23–30 °C with no faults, the arm status is NORMAL and the motors are off
  • Take a camera still and find the roll
  • Plan from the live joints with no motion (--plan-only --plane-deg 4.05): pregrasp fingertips at 109 mm, grasp at 21 mm, the descent drifts 0.02 mm off vertical, and the path to the hover clears the roll by 60 mm
  • Run --go --until grasp: waiting for you to confirm the workspace is clear

The roll looks like it hasn't moved

I found the green roll in today's still and in the still from just before the last run (camera_before.jpg). Its centre is at the same spot in both, as a fraction of the frame: (0.536, 0.811) now and (0.535, 0.810) then. That is within about 2 px. The camera is low and side-on, so a shift toward or away from it shows up mostly as a small vertical change, and I can't rule out a move along its line of sight. Still, it isn't the clear change I'd expect if the roll had been moved onto the arm's plane. Maybe it was already where you meant, and the miss came from my guessed plane angle (J1 = 4.05°, carried over from 10-09) instead of the roll.

Someone is also sitting at the right-hand end of the table in today's still. That's why I haven't committed the image.

To go ahead

Reply with one of these, and say the workspace is clear:

  1. @claude run the grasp, workspace clear: I'll run --go --until grasp on video with the trace, aimed at J1 = 4.05° as before.
  2. @claude go to pregrasp and hold, workspace clear (my recommendation): the arm moves to the hover 60 mm above the planned grasp point, takes a still and holds with the fingers open. You can check whether the roll sits under the fingers and nudge it there. Then the next run descends and grasps. This avoids another blind miss.
  3. If you placed the roll with the arm's rest heading in mind (the arm now rests at J1 ≈ −1.3°, not 4°), tell me and I'll aim at that plane.

No files changed this run, so there's nothing new on the branch.
• claude/issue-19-20261010-0111

@jss265

jss265 commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

@claude run the grasp, workspace clear

@claude

claude Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 18m 33s —— View job


Tape pick, stage 3: the arm picked the roll up

I ran --go --until grasp at J1 = 4.05° on video with the trace, and the whole pick worked. The fingers stopped on the roll at 27.4 mm, holding 1.04 N·m. The arm lifted it to the hover height, about 88 mm off the table, and held it for 1 s with no slip. It then set the roll back down, let go and went home. The arm is parked with the motors off, status NORMAL and can0 error-active.

The video suggests the roll was nudged at the hover, though, so a hands-off repeat is the real test (see below).

  • Check the Pi read-only: can0 up at 1 Mbit/s and error-active, arm status NORMAL, no other arm or camera process running, script on the Pi matches the branch
  • Re-plan from the live joints (--plane-deg 4.05): grasp at fingertip z = 21 mm, the descent drifts 0.01 mm off vertical, and the path to the hover clears the roll by 60 mm
  • Run --go --until grasp on video with the 100 Hz trace
  • Analyse this run and the earlier miss, and commit the log, trace, frames and plot (6de2568, 1f5768a)
  • Upload a cropped clip to YouTube: private video. It's cropped to the arm, and a grey box covers the corner where a hand comes into frame. @sgbaird can unlist or publish it.

The run (log, 100 Hz trace, plot script)

  • The gripper closed at about 57 mm/s. It met the roll at about 28 mm and the effort rose straight to the commanded 1.0 N·m, with no slam.
  • Through the lift and the hold, the opening stayed at 27.4 mm and the effort at 1.03–1.05 N·m, so the slip check never fired.
  • The roll was set down at a fingertip height of 22 mm. The fingers opened to 64 mm, and the quick stop and reset parked the arm as usual.

Why this run worked and the earlier one missed

  • Both runs put the arm in the same place. The pose at the bottom matched to within 0.05° per joint, and the stills before both runs show the roll in the same spot.
  • Earlier run: a finger pushed the roll away. Its video shows a fingertip coming down on the roll's curved top, at a modelled height of about 30 mm, and pushing it about 50 px toward the arm base. The fingers then closed on air. So the roll was near the arm's plane, but close enough to one finger's path that the finger landed on it instead of beside it.

  • This run: a hand nudged the roll at the hover. While the arm hovered (about 8.5–10.5 s into the video), a hand reached in from the right. The roll shifted slightly: its top rose about 4 px, meaning it moved a little away from the camera. It then stayed put, and the fingers came down on both sides of it. If you nudged it deliberately, that's what made the difference.
  • The roll should now be centred. The fingers centre the roll between them when they close, and the after-still shows it set down a little further from the camera than before. So it should now sit in the arm's plane, and a hands-off repeat would show whether the pick works without help.

A safety note: the hand was in the workspace while the motors were on and the arm was starting down. The fingertips were still about 90 mm up when it left. Until the E-stop arrives, please keep hands off the table while the arm is enabled. If placing the roll under the open fingers is useful, I can add a pause at the hover: the arm would hold still until told to continue, instead of carrying straight on.

Still not fixed: the first gripper open skips the slow ramp

While the arm was idle, the gripper ignored the 60 mm/s opening ramp. It then snapped open as soon as the arm started moving, going from 2.9 to 63.5 mm in 0.2 s, the same as in the last run. Closing and letting go did follow the ramp. The gripper probably only takes commands once the arm is in CAN control mode, so sending the mode command before the opening ramp should fix it. I didn't change the script this run.

Next, pick one

  1. @claude run the grasp again, hands off, workspace clear: repeat from where the arm set the roll down, to check the pick works without help.
  2. @claude fix the first gripper open, optionally with the pause at the hover. Each is a small script change, checked in plan-only mode and then on the arm.

The full, uncropped video is still in /tmp on the Pi. It shows a person, so I haven't committed or uploaded it.
• claude/issue-19-20261010-0111

@claude claude Bot mentioned this pull request Oct 15, 2026
github-actions Bot and others added 2 commits October 15, 2026 22:13
The 10-15 grasp run at J1 = 4.05 deg closed on the roll at 27.4 mm with
1.04 N*m, lifted it to the hover height, held it for 1 s with no slip,
set it down, let go and parked. Adds the log, the 100 Hz trace, a frame
strip of the pick (cropped, no people) and a plot of the fingertip
height, gripper opening and effort, with the script that draws it.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ide (#19)

Frames from that run's video: on the way down, at a modelled fingertip
height of about 30 mm, a finger came down on the roll's curved top and
pushed it about 50 px toward the arm base, so the fingers closed on air.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:medium Run it one more time. This time set the tape on the black shelf directly in front of the arm. THe workspace is clear. Record the motion. Keep all responses limited to 4 sentences.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 9m 55s —— View job


The arm picked up the roll and set it on the black shelf

The arm picked up the roll and set it on the shelf, about 370 mm out from the base (log, 100 Hz trace); piper_pick_tape.py has a new --place-r-mm option that carries it out and lets go 20 mm above the shelf, which I estimated from the camera at 60 mm high. The first two attempts didn't move the arm: the arm had been left in teaching mode, and then the joints didn't power on. The script now waits until all six joints are on, and the arm is parked with the motors off. Someone reached toward the roll while the arm was moving to it, so I didn't upload the video, which is still on the Pi; please keep hands off the table while the arm is on, and the grip slammed to 5.8 N·m again (asked for 1.0).


• claude/issue-19-20261010-0111

… line (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:medium You did great! Now pick up the tape and place it on the black shelf again. This time the black shelf is off of the plane at the zero position. The workspace is clear.

… for every joint to enable (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 10m 54s —— View job


Tape pick to the off-plane shelf: the roll is on the shelf, but it was dropped rather than placed

The arm picked the roll up and swung it toward the shelf, about 40° off the pick plane. Then, 19 s into the carry, the gripper overheated and let go. The roll fell about 5 cm and landed on the shelf, lying flat. The arm finished its return home and parked normally, but the gripper is still reporting motor overheating and a driver error.

  • Check the Pi and arm read-only: can0 error-active, status NORMAL, no faults
  • Locate the shelf from the camera: its centre is about 450 mm out, about 40° off the pick plane, on the far side from the camera. I scaled this from the shelf's 60 mm height and the arm's 285 mm upper arm.
  • Add --place-deg (carry along a straight horizontal line to a point off the pick plane) and --place-tilt-deg (tip the tool 20° there to keep J5 under 70°). Checked in plan-only mode: nothing comes closer than 71 mm above the shelf.
  • Run on video with the trace. The first try did nothing because the motors didn't enable, the same as on the last run; the second try ran.
  • Commit the log, trace and frames (72bffdf)
  • Set the roll down on the shelf: not done, the gripper let go early

Why it let go (log, trace)

The script asks the gripper for 1.0 N·m, but it squeezed at 7.2 N·m (5.8 N·m on the last run). After the close, the gripper's target position stays well inside the roll, so it keeps pushing. Its motor overheated and the driver turned the gripper off while the arm was at J1 ≈ 33°.

I've changed the script so that after closing, the target is only 3 mm inside the roll (--squeeze-mm). I haven't tested this on the arm.

Next

Let the gripper cool for a few minutes. Then stand the roll back up at the pick spot and post @claude saying the workspace is clear. That run will clear the gripper's error, check the new hold on the arm, and repeat the off-plane place.
• claude/issue-19-20261010-0111

…tilt-deg; hold just inside the roll (#19)

The gripper squeezed at 7.2 N*m instead of the 1.0 asked for, its motor overheated
19 s into the carry and it let go; the roll fell onto the shelf.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:medium You did great! I also liked that when returning home the arm was cloes enough to the J2 motor that the end effector didn't slam into the motor when the motors disengaged. Now pick up the tape and place it on the black shelf again. This time the black shelf is somewhere else on the table. Please carefully place the tape down this time so it doesn't fall over. Also note that the tape is perfectly in front of the arm at 0 deg. It is no longer off by 4deg. The workspace is clear. Keep your analysis limited to a paragram. Show a gif of the motion and a cool figure.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 8m 53s —— View job


The arm put the roll on the moved shelf, upright

The arm picked the roll at J1 = 0° and set it down standing upright on the shelf (still after release). From the camera I put the shelf behind the arm on the far side, about 360 mm out at J1 ≈ 130°. A straight carry there would have cut across the base, so the new --carry-arc option swings the roll round it instead. To keep it from tipping, I let go 5 mm above the shelf instead of 20 mm, and the lowering slows as it gets close. The new 3 mm squeeze held at about 1.7 N·m, down from last run's 7.2, and the gripper didn't overheat. The script now also clears the gripper's latched overheat error before enabling. Two hiccups on the Pi first: the first try didn't move (the same motors-enabled-but-idle glitch as last time), and its /tmp was full of old videos, which I moved to ~/pick_tape_videos without deleting anything. The arm is parked with the motors off and status NORMAL (log, trace, script).
• claude/issue-19-20261010-0111

@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:medium LOVELY! That worked perfect. Now pick it up, and bring it right back to the starting location of the tape. Format and limit the response just as before.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 6m 50s —— View job


Tape back to the start: planned and checked, waiting for "workspace clear" before moving

  • Check the Pi and arm read-only: can0 up, arm parked with motors off, no other arm or camera process running
  • Find the roll: last run released it at r = 360 mm, J1 = 130° on the 60 mm shelf. It's hidden behind the arm in today's still.
  • Add --pick-top-mm so the script knows the roll stands on the shelf (539d997, piper_pick_tape.py), copy it to the Pi and plan from the live joints without moving
  • Run on video with the trace: not done, waiting for you to confirm the workspace is clear

The plan is ready, but nothing has moved. The repo's rule is that a run needs the request to say the workspace is clear, and this comment didn't. Also, today's camera still shows someone standing right next to the table. I added --pick-top-mm, which counts the grasp and release heights from the shelf top. Without it, the script would have let go of the roll about 60 mm above the table. The plan: tool tipped 20° (the arm can't reach the hover at 10°), fingertips 28 mm into the roll at z = 81 mm, a 41 s carry back around the base on an arc at 159 mm, and a release with the roll 5 mm above the table at r = 247 mm, J1 = 0°. The closest the arm comes to the roll or shelf on the way in is 50 mm above the roll. The last run also turned out to have pushed its own GIF and figure (place_map.png, shelf_place_3x.gif), so I didn't add duplicates. Reply @claude run it, workspace clear and I'll run it straight away with video, then post the GIF and a figure.
• claude/issue-19-20261010-0111

github-actions Bot and others added 2 commits October 16, 2026 01:32
…a latched gripper fault before enabling (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The roll stands on the 60 mm shelf, so the grasp, the carry height and the
release height count from the shelf top, and the moves to and from the
pick stay the table margin above the shelf's height.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:xhigh the workspace is clear and nothing has moved at all. Also, wait for my signal (via comment in this PR without @ + claude) and try the experiment again (recording a second clip/gif). On this second attempt the tape will be in a new hidden location and you need to move the arm so that you can see the tape and only use the 100Hz visual feedback loop to locate the tape - and keep this smooth, like path correcting as it goes along smoot and slow - not waypoint to waypoint. I want this second test to be efficient.

Finally, once both experiements are complete, display the results of each test - being one gif of the motion, one technical and relevant figure, and a paragraph explaining the result. After both results, report how you complete this operation. Are you using a custom or open source inverse kinematic library? Are you using a neural network? or something else? How would we reproduce this operation without AI assistance? Limit this response to 2 paragraphs. And finally, finally, one sentence explaining if these videos are going to youtube or not. if so add the link.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Tape pick: test 1 worked; in test 2 the camera found the roll but the grasp missed

Warning

Don't run the arm until J1 is checked. In test 2, J1's reported angle drifted from the real one by about 8° per run, and the parked arm now sits about 20–25° from where it was this morning, though J1 still reads −3.9°. Before/after photo. Please power-cycle the arm. I can compare it with the camera read-only next time. The arm is parked with the motors off, status NORMAL, and the roll is still on the shelf where you hid it.

Test 1: shelf → start

The arm took the roll off the shelf (J1 = 130°, r = 360 mm) and carried it round the base on a 41 s arc at 159 mm. It stood the roll back up at the start (J1 = 0°, r = 247 mm, released 5 mm up), then parked. The fingers stopped on the roll at 15.2 mm, and the 3 mm squeeze held it at 1.56 N·m with no slip. The first try didn't move. I later found why: after the parking reset, the arm sits in STANDBY mode and ignores commands. This run's video also calibrated the camera. The arm carries the green roll along a path it knows exactly, so about 900 frames of "where the camera sees it" against "where the arm says it is" fix the camera's position, focal length and lens distortion to about 2 px (log, trace, fit).

Test 2: find the hidden roll with the camera

The arm unfolded out of the camera's way. The camera spotted the roll at the back of the shelf, behind where the folded arm had been, before the arm even finished rising. The 100 Hz loop then steered the fingertips there in one continuous arc at up to 50 mm/s, re-aiming on every camera frame instead of running through waypoints. It went straight down and closed, but on air: the fingers came down about 65 mm beside the roll. The cause is the arm, not the vision. To fix the idle first try, I switched the arm to CAN mode before enabling it. On every run done that way, J1's reading jumped +7.9° the moment the motors came on, without the arm moving. So the arm stopped 7.9° short, and the camera overlays agree. Parking at the old reading then turned the folded arm further each run, about 8° a time going by the readings. A check run (two poses, no roll) confirmed the drift, so I stopped. piper_seek_tape.py now refuses to move if any joint reading changes on enabling. One limit to fix too: the camera runs at 56 fps, not 100. Its 120 fps mode crops off the start spot, so the 100 Hz loop interpolates between frames (run log, trace, detections).

How it works, and doing it without AI

No neural network, and no outside IK library: it's classical geometry and control. piper_vision.py runs on the Pi. It thresholds green in each camera frame (OpenCV), takes the roll's lowest point, and projects it through the fitted camera model onto the table or shelf height. That gives the roll's x, y in the arm's frame, smoothed over frames and ignoring frames where the arm itself blocks the view. The inverse kinematics is our own damped-least-squares solver on the arm's DH parameters (the only thing taken from AgileX's open-source piper_sdk). It is precomputed into a table of joint angles for a gripper-down pose over reach and height (make_iktable.py), then interpolated every 10 ms. The motion is a speed-capped, critically damped chase of the latest target, in reach, angle and height so it swings round the base. It is streamed to the arm as joint targets at 100 Hz.

At run time nothing calls an AI. I wrote the scripts, chose the parameters and diagnosed the failures, and all of it is in the repo. To repeat it by hand, follow the exact commands in this README: run test 1 on video with piper_pick_tape.py. Fit the camera with fit_camera.py, build the table once with make_iktable.py, then run piper_seek_tape.py --go --video … --trace … on the Pi. That needs the camera not to move, J1's zero to be right, and the roll standing on its edge. One weakness stays even then. The camera is low and side-on, so at the shelf 1 px of image height is about 10 mm along its line of sight. A second camera or a wrist camera would remove that.

Both clips are on the BYU Vertical Cloud Lab channel as private videos, cropped to the arm with no one in frame: test 1 and test 2. @sgbaird can unlist or publish them.

Checklist and Pi changes
  • Test 1 on video with the 100 Hz trace (d95a53e)
  • Camera calibrated against the arm; vision and steering scripts built and tested on a simulated arm
  • Waited for your go-ahead (02:14), then ran test 2. Run 0: STANDBY, didn't move. Run 1: arm pointed at the camera, roll not locked. Run 2: the run above. Then a J1 check run (12bdf8b)
  • Test 2 grasp: blocked on J1
  • On the Pi: new ~/vision-venv (numpy, OpenCV), runs in ~/seek/, copies of the new scripts in ~. All of this is recorded in CLAUDE.md.

View job run • claude/issue-19-20261010-0111

@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

Great job with test 1. The workspace is clear, so try test two.

github-actions Bot and others added 3 commits October 16, 2026 02:34
…dden roll (#19)

Test 1: piper_pick_tape.py picked the roll off the shelf (J1 = 130 deg, r = 360 mm)
and stood it at the start (r = 247 mm, J1 = 0) along the --carry-arc path; the first try
did not move (motors enabled but idle) and the second ran cleanly.

piper_vision.py finds the green roll on every frame of the fixed camera (full field, 56 fps)
and back-projects it onto the table and shelf heights with a camera model fitted to the arm
(camera.json). piper_seek_tape.py steers the fingertips at 100 Hz toward the hover over the
latest estimate, re-aimed on every frame, then descends, grasps, carries the roll to the start
and parks. iktable.json is its tool-down joint table (make_iktable.py).

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the grasp missed (#19)

Test 2's 100 Hz loop locked onto the hidden roll on the shelf while the arm was still rising
and steered to it in one continuous move, but the fingers closed 66 mm beside it: J1's reading
jumped +7.9 deg on enabling, without the arm moving, on every run that switched to CAN mode
before enabling (the fix for the enabled-but-idle first tries). Parking at the old reading then
turned the folded arm a further 7.9 deg each run; it now sits about 20-25 deg from the morning
pose while J1 still reads -3.9. piper_seek_tape.py now refuses to move if a reading changes
on enabling. The vision now uses the roll's lowest point (camera.json refitted on it), ignores
frames where the arm is between the camera and the roll, and the IK table reaches 540 mm.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:medium J1 is now fixed, please pick up where you left off

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 2m 54s —— View job


Test 2: J1 checks out, and test 2 is ready to run. I need "workspace clear" before I move the arm

  • Check the Pi and arm read-only: can0 error-active, status NORMAL, all six joints at 23–24 V with no faults, motors off
  • Compare J1 with the camera: it's fixed. J1 now reads +23.45°; before the fix it read −3.9° with the arm in the same turned pose. I drew the modelled arm over a still at both readings. At +23.45° (red) it lies on the folded arm, and at −3.9° (blue) it's off by about 100 px at the elbow. So the reading matches the arm again, and the camera hasn't moved, which means the camera calibration still applies.
  • Update the Pi's copies of piper_seek_tape.py and piper_vision.py to the branch versions. The Pi still had the copies from before the J1 safety check (it refuses to move if a joint's reading changes when the motors switch on); I kept the old copies as *.2026-10-16.py.
  • Run the seek script in read-only mode. The camera works (56 fps) and doesn't see the roll yet. That's expected while it's hidden behind the folded arm: the run moves the arm out of the way first.
  • Run test 2 (piper_seek_tape.py --go on video with the trace): waiting for you to say the workspace is clear

I haven't moved the arm. The repo's rule is that a run needs the request itself to say the workspace is clear, and this one doesn't (the last "clear" was 1.5 hours ago). Reply @claude run test 2, workspace clear and I'll run it right away. That run gives the GIF, a figure, a short write-up and a private YouTube clip, like test 1. I recorded the J1 check in the branch's CLAUDE.md, and the overlay and its script are in f80e903.
• claude/issue-19-20261010-0111

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jss265

This comment was marked as duplicate.

@claude

This comment was marked as duplicate.

@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude:low the workspace is clear. Run immediately, ensure motors are disabled, then report.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 2m 48s —— View job


Test 2 ran, and the arm is parked with the motors off

The camera found the hidden roll and the arm picked it up. The arm then carried the roll back to the start spot (J1 = 0°, r = 247 mm) and let go. I checked the release only from the arm's own readings: I haven't looked at the video, so I can't yet say whether the roll is standing up.

  • Finding it: the camera saw the roll at the back of the shelf, at J1 ≈ 129° and r ≈ 478 mm, before the arm reached its viewing pose. The arm steered there in one continuous path and came down to a fingertip height of 83 mm (planned 81).
  • J1 is fixed: its reading moved only 0.11° when the motors switched on, compared with +7.9° last time.
  • Grip: the fingers stopped at 18.3 mm, which means they were on the roll. The first squeeze peaked at 5.88 N·m against the 1.0 N·m asked for, then eased to a 1.92 N·m hold, with no slip and no overheating.
  • End state: the arm is home, status NORMAL, and all six motors report disabled.

The log and the 100 Hz trace are in 75b7438 (run4.log, run4_trace.csv). I haven't checked the video for people yet, so it's still on the Pi in ~/seek/run4/ and isn't on YouTube. A follow-up run can make the GIF and figure, and upload the clip once it's cropped.
• claude/issue-19-20261010-0111

…it (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

This comment was marked as duplicate.

@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@claude I got tired of waiting, so I ran test 2 with a :low context ping. DO NOT enable or move the motors, just finish the report requested in #20 (comment)

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @jss265's task in 16m 46s —— View job


Tape pick: test 1 and test 2 results

I didn't enable or move the motors this run. I only copied run 4's video and logs off the Pi.

Test 1: shelf → start

The arm took the roll off the shelf (J1 = 130°, r = 360 mm), carried it round the base on a 41 s arc at 159 mm height, and stood it back up at the start (J1 = 0°, r = 247 mm), letting go 5 mm above the table. The fingers stopped on the roll at 15.2 mm, and the 3 mm squeeze held it at 1.56 N·m with no slip. The first try didn't move, because the arm was still in STANDBY mode from the last parking reset. The video also calibrated the camera. About 900 frames compare where the camera saw the roll in the gripper with where the joint readings put it, and they fix the camera's position, focal length and lens distortion to about 2 px (log, trace, fit).

Test 2: find the hidden roll with the camera (run 4)

The arm rose out of the camera's way, and 2 s into the rise the camera spotted the roll at the back of the shelf (J1 ≈ 129°, r ≈ 478 mm), where the folded arm had hidden it. From there the 100 Hz loop steered the fingertips to it in one continuous arc at up to 50 mm/s, re-aiming on each of the camera's 56 frames per second while its estimate settled by 23 mm. There were no waypoints and no stops. The arm went straight down to 83 mm, 26 mm below the roll's top. The fingers stopped on the roll at 18.3 mm and squeezed to a 5.9 N·m peak (1.0 was asked), so the close still overshoots. They then held at 1.9 N·m round the base with no slip. After the release, the camera puts the standing roll at r = 248 mm and 0.6°, against a target of 247 mm and 0°. The run took 88 s and ended with all six motors disabled. Run 2 had missed because J1's reading was 7.9° high. Run 3, from the 04:01 session that was cancelled, refused to move because J1's reading jumped when the motors came on (log, trace, camera log, figure script).

Warning

My 03:39 J1 check was wrong. The +23.45° reading was about 24° off. Run 3's enable changed it by −23.84° while the arm stayed still (the video shows no motion), and run 4 then held about 0° and reached the roll. The modelled arm drawn over the folded arm still matches +23.45° in run 4's last frame, where the reading is known to be right, so that overlay can't check J1 (frames). After a power cycle, trust J1 only once its reading holds through an enable. I've corrected the note in the branch's CLAUDE.md.

How it works, and doing it without AI

There's no neural network and no outside IK library. It is classical geometry and control, all in this repo. On the Pi, piper_vision.py thresholds green in every camera frame with OpenCV. It projects the roll's lowest point through the camera model fitted in test 1 onto the table or shelf height, which gives the roll's x, y in the arm's frame, filtered over frames. The inverse kinematics is our own damped-least-squares solver. It runs on the arm's DH parameters, which are the one thing taken from AgileX's open-source piper_sdk; the SDK also handles the CAN link. make_iktable.py precomputes the IK into a table of joint angles for a gripper-down pose over reach and height. piper_seek_tape.py interpolates that table every 10 ms and chases the latest camera target with a speed cap and critical damping. It works in reach, angle and height, so the path swings round the base, and it streams the joint targets to the arm at 100 Hz.

At run time nothing calls an AI. I wrote the scripts, chose the parameters and diagnosed the failures, and it's all in the repo. To repeat it by hand, follow the commands in this README. Run test 1 on video with piper_pick_tape.py, fit the camera to that video with fit_camera.py, and build the IK table once with make_iktable.py. After that, piper_seek_tape.py --go --video … --trace … on the Pi does test 2 by itself. This needs the camera to stay put, J1's reading to be right, and the roll standing on its edge. The weak spot is depth. The camera is low and side-on, so at the shelf 1 px of image height is about 10 mm along its line of sight. A second camera or a wrist camera would fix that.

The clips are on the BYU Vertical Cloud Lab channel as private videos, cropped to the arm so no one is in frame: test 1, test 2 run 2 (the miss) and test 2 run 4 (the pick); @sgbaird can unlist or publish them.

What this run did
  • Copied run 4's and run 3's videos and logs from the Pi over SSH, rate-capped. No CAN commands; the motors were not touched.
  • Checked every frame of run 4. The only person is at the right edge of the full frame (0–9 s), outside the crop.
  • Committed run 4's GIF, figure and camera log, plus run 3's log (e5fb1e0), the J1 correction in CLAUDE.md (b2b837e) and run 4's command in the README (e258e11).
  • Uploaded run 4's cropped real-time clip as a private video.
  • The raw videos are still on the Pi in ~/seek/run3/ and ~/seek/run4/.
• [`claude/issue-19-20261010-0111`](https://github.com/vertical-cloud-lab/robot-arms/tree/claude/issue-19-20261010-0111)

@jss265

jss265 commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

Putting this test to bed. Next time lets adjust the tape to a new location and twist it to see if the robot can adjust it's grip to match the orientation of the tape

github-actions Bot and others added 3 commits October 16, 2026 04:32
Run 4 (04:12 UTC) found the hidden roll on the shelf with the camera, picked it
and stood it back at the start: after the release the camera puts it at
r = 248 mm, 0.6 deg (target 247 mm, 0 deg). Run 3 (04:05 UTC, from the
cancelled 04:01 session) refused to move: J1's reading changed by -23.84 deg on
enabling, and its video shows the arm did not move.

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the wrong reading (#19)

Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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