
Robots Play Catch — Throwing and Catching Between Two Arms
/play_catch
Two six-axis robot arms in a CoppeliaSim scene throw a ball back and forth. One arm throws, the other catches, and then they swap roles and keep going.
Cover: the F&P P-Arm 2R that both simulated arms are modeled on. Image from the F&P Robotics datasheet.
- Context
- Course project, Kinematics & Dynamics of Robots (EN.535.630), Johns Hopkins
- Timeline
- Spring 2026
- Team
- Norman Chen-Liaw, James Englander, Xiaolei Hu
- My part
- Simulation scene, catching, inverse kinematics, final integration
Tools & skills
- Simulation
- CoppeliaSim, Lua scene scripts, simIK plugin
- Kinematics
- Denavit–Hartenberg model, analytical IK with kinematic decoupling, damped least squares
- Software
- Python, ZeroMQ Remote API, Git
- Robots
- F&P P-Arm (6-DOF), Barrett Hand gripper
Demo
The final simulation: the arms trade throws, and the graph tracks the ball's x and z position.
Why catch is hard for robots
Playing catch looks easy because people do it without thinking. For a robot it means three hard things at once: release the ball at exactly the right speed and direction, predict where it will come down, and have the other hand there and closed at the right moment.
We set up two P-Arms facing each other in the same plane, with a ball between them. Mirroring the arms made the throw symmetric, so one solution works in both directions. The P-Arm has six revolute joints and no link offsets, which keeps the kinematics clean. It ships without a hand, so we fitted each arm with a Barrett Hand from CoppeliaSim's model library.

One state machine, two roles
Both arms run the same scripts. A shared state machine decides who is throwing and who is catching. The thrower moves to the start of its throwing path and follows it, letting go of the ball at the end. The catcher waits in position until the ball touches its palm, then closes its fingers. Then the roles flip.
The hand changes its grip with its role. The catching grip is wide, to give the ball a large area to land in. The throwing grip puts the fingers behind the ball so the push goes in the direction of the throw, and the thumb lets go to release it.




Throwing along an arc
A throw is set by where the ball leaves the hand, where it should land, and the launch angle. From those we worked out the speed and direction the ball needs at release.
Because the P-Arm only has rotating joints, the natural throwing motion is an arc that ends at the release point. We held the hand at a constant speed along the arc, equal to the launch speed, and tuned the arc's radius in simulation. Splitting the arc into points gives the positions the hand has to pass through. Inverse kinematics turns each point into joint angles.
Solving the arm
My part of the math was the inverse kinematics: given where the hand needs to be, find the six joint angles. I modeled the P-Arm with Denavit–Hartenberg parameters. Its first three joints work like an elbow, and its last three meet at a single point, a spherical wrist. That split the problem in two. First I found the wrist center by stepping back from the hand along its axis, and solved the first three joints from that point with plane geometry. Then the last three joints came from the rotation left between the forearm and the hand.
The solver gave correct angles on its own. But when we drove the scene from Python over CoppeliaSim's remote connection, the hand landed slightly off target. Small differences between my frames and the scene's frames added up, and the connection's lag made the time steps unreliable. Catching depends on exact timing, so that was not good enough.
We moved the control into Lua scripts that run inside the scene, used a finer simulation time step, and switched the arm motion to CoppeliaSim's built-in IK solver, which works directly on the simulated joints. My solver stayed as the reference for the arm's geometry; the built-in solver did the work during the run.

What I would do next
The catcher picks its catch point before the throw and never adjusts it. When a throw drifts, the ball misses. The next step is to track the ball in flight with the projectile equations and keep moving the catch point while the ball is in the air.