Why my ArUco pose estimates jittered (and how a 3-line filter fixed it)
Small markers seen almost face-on have an ambiguous pose: two solutions fit the four corners nearly equally well, and solvePnP happily flips between them from frame to frame.
Switching to SOLVEPNP_IPPE_SQUARE gives you both candidates. Keep the one closest to the previous frame:
ok, rvecs, tvecs, errs = cv2.solvePnPGeneric(obj, corners, K, D,
flags=cv2.SOLVEPNP_IPPE_SQUARE)
best = min(range(len(rvecs)), key=lambda i: np.linalg.norm(rvecs[i] - prev_rvec))
Add light exponential smoothing on the translation and the jitter is gone.