Conversation
Co-authored-by: sgbaird <45469701+sgbaird@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This PR adds a comprehensive technical review of the AprilTag functionality within the UR Toolkit repository. The review analyzes the current implementation's architecture, validates design decisions (particularly the exclusion of hand-eye calibration), identifies enhancement opportunities, and provides strategic recommendations for future development.
Key changes:
- Documents current AprilTag detection, visual servoing, and workflow integration components
- Validates the architectural decision to exclude hand-eye calibration as sound engineering judgment
- Identifies missing functionality and provides enhancement recommendations while respecting the project's simplicity-first philosophy
- Add HandEyeCalibrator class with Zivid-based methodology - Add simple manual hand-eye calibration script using existing components - Fix freedrive mode in URController (use RTDE teachMode) - Update visual servo engine to use calibration matrix - Add AprilTag detection script for testing - Use Zivid recommendations: 6+ poses for AprilTags, 10-20 optimal - Integrate with existing working PiCam and URController systems
- Moved hand-eye calibration script to scripts/ - Integrated AprilTag photo detection into debug_apriltag.py - Moved workflow configs to examples/workflows/ - Removed redundant test files and one-time diagnostics - Merged hand-eye calibration guide into README - Cleaned up root directory structure - Enhanced README with comprehensive hand-eye calibration docs
- Updated default AprilTag family from tag36h11 to tagStandard41h12 (recommended by AprilRobotics) - Added tagStandard41h12, tagStandard52h13, tagCircle49h12, tagCircle21h7 to supported families - Updated configuration files and documentation to use new default family - Added explanation for naming convention differences (legacy vs newer families) - Backward compatibility maintained for existing tag families - Updated all examples and documentation to use recommended family
|
@copilot, following up on #3 (comment), help me understand the current visual servoing implementation. I'm unsure if the implementation is on main or not, but it seems more likely that it's on EDIT: cc @kelvinchow23 (lmk if I'm missing the most recent code you're working on) |
The visual servoing implementation is present on both branches: Current status (as of 230a747):
The visual servoing system includes:
Both branches have identical visual servo functionality. The implementation includes a complete Eye-in-Hand Visual Servoing system with PID controllers, AprilTag integration, and workflow integration as documented in my review. |
|
@copilot what might be the issue?
|
Several factors could cause visual servoing convergence issues. Based on the implementation analysis: Primary Potential Issues:1. Control Loop ParametersThe PID gains are very conservative (lines 109-118): # Translation: kp=0.3, ki=0.0, kd=0.0, output_limit=0.015m
# Rotation: kp=0.2, ki=0.0, kd=0.0, output_limit=0.05radProblem: Low gains + no integral term = slow convergence, may never reach tight tolerances 2. Tolerances vs. Control Authority
Problem: Small corrections may not overcome system noise/deadband 3. Error Calculation MethodSimple direct correction (lines 297-298): robot_translation_correction = -tag_translation_error
robot_rotation_correction = -tag_rotation_error Problem: Assumes perfect camera-robot frame alignment; doesn't account for:
4. Detection Inconsistency Checks DisabledLines 262-278 show detection consistency checks are commented out for testing. Troubleshooting Steps:
The system appears designed for stability over performance. For better convergence, consider increasing control gains gradually while monitoring for oscillation. |
|
@kelvinchow23 could you include a video of running one of the workflows? (and also include a permalink to the code that you're running) |
|
@copilot fetch https://chatgpt.com/share/68ddddf5-d048-8007-bc6d-2a3fbc9794d5. In light of this, do your recommendations still apply? |
I'm unable to access the ChatGPT conversation link (blocked by client). Could you share the key insights or findings from that conversation? This will help me determine if my previous recommendations about the visual servoing convergence issues need to be revised. |
|
@copilot I added copy-paste of transcript as a txt file |
After reviewing the transcript, my recommendations remain valid with additional context: Key Insights from Transcript:The conversation confirms this is Position-Based Visual Servoing (PBVS) which:
How This Relates to Convergence Issues:1. Missing Jacobian UsageThe current implementation (lines 297-298) does direct pose correction: robot_correction = -tag_errorProblem: This assumes identity Jacobian mapping, which is rarely correct. True PBVS needs: joint_velocity = J_pseudoinverse @ (-lambda * pose_error)2. Control Rate MismatchTranscript recommends 20-60 Hz control loop. Current implementation likely runs much slower (depends on camera capture + detection filtering). 3. No Velocity-Based ControlCurrent system sends position commands, not velocity commands. PBVS theory assumes continuous velocity control at camera rate. Updated Recommendations:For proper PBVS convergence:
For current simplified approach:
|
…ing transition and rotation limits
|
@copilot wait, so what was the noise set to before? |
|
Let's merge soon and start a new PR |
|
@copilot What was the noise set to before? |
The simulator has no explicit noise model. Looking at the code (lines 30-33), the The "0.154m error after the first move" in the animation occurs because of momentum damping (line 121): So there's no noise - just momentum smoothing that effectively reduces the first move to 50% of the commanded correction.
The simulator has no explicit noise added. The ~50% first-move error shown in the animation comes from momentum damping (0.5 weight), not noise. With momentum=0.5, the velocity accumulation causes the first move to effectively apply only about 50% of the intended correction, even though gain=1.0. This simulates realistic robot dynamics where commanded motions don't execute instantaneously at full magnitude. |
|
@copilot ok, add a small amount of uniformly distributed noise up to 0.05% in xyz and roll-pitch-yaw. Let's adjust so that the momentum is 1 for the first move, but can be less for later. We just want to get it in the right ballpark first. Btw, again. we're just treating these as iterative moveL's to try to converge really accurately at the desired xyz roll-pitch-yaw relative to an AprilTag. The 2nd and on moveL's can be more gradually converging |
Co-authored-by: sgbaird <45469701+sgbaird@users.noreply.github.com>
Implemented in commit 8a82866:
The simulator now converges in ~18 iterations from 0.308m to 0.0005m (sub-millimeter). The first moveL gets in the right ballpark immediately, then iterative moveL commands gradually converge to precise accuracy. |
|
@kelvinchow23 I had forgotten about AccelerationConsortium/ac-dev-lab#229 (comment), in particular visp |
|
@copilot I need a minimal working example, a single, standalone script with just the logic and algorithms for doing these iterative moves. |
Co-authored-by: sgbaird <45469701+sgbaird@users.noreply.github.com>
Created Single standalone script with just the core algorithm: # First moveL: Go directly to target (gain=1.0, no smoothing)
# Subsequent moveL: Gradual convergence (gain=0.2, momentum smoothing)
iterative_movel_servo(
current_pose=[0.3, 0.2, 0.5, 0.1, -0.2, 0.15],
target_pose=[0.4, 0.3, 0.55, 0.0, 0.0, 0.0],
first_gain=1.0,
subsequent_gain=0.2,
momentum=0.5,
noise_percent=0.0005,
)Run with: |
|
@copilot scipy is OK as a dependency btw. Also, you missed the whole part around jogging in different dimensions and perturbing orientation to get an approximate gradient to use to head in the correct direction |
…rections Co-authored-by: sgbaird <45469701+sgbaird@users.noreply.github.com>
Added gradient approximation via jogging in ±xyz and ±roll-pitch-yaw directions in commit 40677ef. The
Uses scipy.spatial.transform.Rotation for rotation utilities. |

Minimal Working Example with Gradient Approximation
Updated
iterative_movel_minimal.pywith full gradient approximation via jogging:Algorithm:
Key Functions:
estimate_gradient()- Perturbs each of 6 DOF (±x, ±y, ±z, ±roll, ±pitch, ±yaw) and measures error change to approximate gradientiterative_movel_servo_with_gradient()- Main algorithm with gradient-based correctionUsage:
Uses scipy for rotation utilities.
Fixes #4
Fixes #4
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.