
Productive Robotics
Industrial Gripper System
Built a complete industrial gripper subsystem from CAN bus driver through ROS service layer to tablet UI — supporting a 3-position PWM servo gripper with basket detection and a magnetic gripper with on/off actuation. The synchronous-over-asynchronous CAN pattern uses std::condition_variable to transform the inherently asynchronous CAN bus into blocking ROS service calls. Integrated into the executive interpreter as first-class program steps.
Implemented the CAN gripper driver with 3-position PWM servo control: Release (0x01 → CAN ID 0x121), spring-grab (0x02 → 0x122), and hard-grab (0x03 → 0x123). Commands route through the /odrive/command ROS service to ODriveManager's raw CAN socket. The service uses a PendingResponse struct containing std::condition_variable and std::mutex — constructs a CAN frame, registers the pending response, sends the frame on the raw socket, then blocks on the condition variable until the RX thread receives a matching response or timeout expires. This transforms the asynchronous CAN bus into synchronous request/response semantics. Servo commands 0x09–0x13 configure PWM ranges for grip force and travel calibration. Basket detection parses a single-byte CAN response (DLC=2: [command_echo, basket_status]).
Built a magnetic gripper driver with binary on/off electromagnet actuation over CAN, sharing the same ROS service interface as the PWM gripper for transparent substitution. The gripper registry (attached_grippers.py) maintains connected grippers and dispatches commands to the correct driver during executive interpreter execution. On the FryBot platform, integrated gripper open/close/basket-check commands with android.speak() audio feedback — critical in a kitchen environment where the operator may not be watching the screen. UI components include a full Gripper.vue settings page for PWM calibration and a GripperSettings.vue tile for inline controls. Math.max(gripperWidth - 10, 0) prevents negative width values from arithmetic underflow.