Repository navigation
Conversation
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>
|
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. |
|
@claude:medium connect to the arm and resume the tape pick up test. Work area is clear. |
|
Claude finished @jss265's task in 4m 43s —— View job Tape pick: I couldn't resume because the arm isn't on the CAN busI 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.
What I found on the Pi
Why stage 3 missed on 10-09That run (log, 100 Hz trace) did close on the roll, but couldn't keep it:
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
|
…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>
|
@claude:medium I just power cycled. Attempt again |
|
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 rollAfter the power cycle the arm was back on the bus, so I ran stage 3 (
What happened (log, 100 Hz trace)
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 seenDuring 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
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. |
…roll (#19) Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@claude:medium attempt again, the tape is in the correct place |
|
Claude finished @jss265's task in 1m 25s —— View job Tape pick, stage 3 retry: arm is ready, but I haven't moved it yetThe 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.
The roll looks like it hasn't movedI found the green roll in today's still and in the still from just before the last run ( 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 aheadReply with one of these, and say the workspace is clear:
No files changed this run, so there's nothing new on the branch. |
|
@claude run the grasp, workspace clear |
|
Claude finished @jss265's task in 18m 33s —— View job Tape pick, stage 3: the arm picked the roll upI ran The video suggests the roll was nudged at the hover, though, so a hands-off repeat is the real test (see below).
The run (log, 100 Hz trace, plot script)
Why this run worked and the earlier one missed
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 rampWhile 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
The full, uncropped video is still in |
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>
|
@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 finished @jss265's task in 9m 55s —— View job The arm picked up the roll and set it on the black shelfThe arm picked up the roll and set it on the shelf, about 370 mm out from the base (log, 100 Hz trace); |
… line (#19) Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@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 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 placedThe 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.
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 ( NextLet the gripper cool for a few minutes. Then stand the roll back up at the pick spot and post |
…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>
|
@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 finished @jss265's task in 8m 53s —— View job The arm put the roll on the moved shelf, uprightThe 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 |
|
@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 finished @jss265's task in 6m 50s —— View job Tape back to the start: planned and checked, waiting for "workspace clear" before moving
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 |
…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>
|
@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. |
Tape pick: test 1 worked; in test 2 the camera found the roll but the grasp missedWarning 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 → startThe 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 cameraThe 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. How it works, and doing it without AINo neural network, and no outside IK library: it's classical geometry and control. 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 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
|
|
Great job with test 1. The workspace is clear, so try test two. |
…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>
|
@claude:medium J1 is now fixed, please pick up where you left off |
|
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
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 |
Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
|
@claude:low the workspace is clear. Run immediately, ensure motors are disabled, then report. |
|
Claude finished @jss265's task in 2m 48s —— View job Test 2 ran, and the arm is parked with the motors offThe 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.
The log and the 100 Hz trace are in |
…it (#19) Co-authored-by: Joshua Spiesman <99856667+jss265@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment was marked as duplicate.
This comment was marked as duplicate.
|
@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 finished @jss265's task in 16m 46s —— View job Tape pick: test 1 and test 2 resultsI didn't enable or move the motors this run. I only copied run 4's video and logs off the Pi. Test 1: shelf → startThe 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 AIThere's no neural network and no outside IK library. It is classical geometry and control, all in this repo. On the Pi, 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 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
|
|
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 |
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>

















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