Geared motion using actual positions

We use one geared motion in our system, with the ZL axis as the leader, and the Z,ZR and ZB as the followers. We specify actual position for gearing:
pZ->GearingEnable(pZL, RSIAxisMasterType::RSIAxisMasterTypeAXIS_ACTUAL_POSITION, 1, 1);
pZR->GearingEnable(pZL, RSIAxisMasterType::RSIAxisMasterTypeAXIS_ACTUAL_POSITION, 1, 1);
pZB->GearingEnable(pZL, RSIAxisMasterType::RSIAxisMasterTypeAXIS_ACTUAL_POSITION, 1, 1);
auto axisState = pZL->StateGet();
if (axisState == RSIState::RSIStateERROR || axisState == RSIState::RSIStateSTOPPING_ERROR)
…error handling stuff
pZL->MoveSCurve(cmd._posn, cmd._speed, cmd._accel, cmd._decel, cmd._jerk);
pZL->MotionDoneWait();
pZ->GearingDisable();
pZR->GearingDisable();
pZB->GearingDisable();

When we look at the actual positions we find that in most cases the followers are not at the same location, and are ~3-7um off, and curiously all follows are off by the same amount. How can this happen? I have attached an image with some of the position data we collected. Notice how layer 3 is almost exactly correct but the others show the difference.

Are you noticing differences in parts produced, or only in the position data recording?

The ZL columns appear to have less resolution than the other columns (always 0 in the thousandths). Is there a rounding error here?

Depending on the servo tuning of ZL, you might want to considering gearing off COMMAND_POSITION. When you gear of ACTUAL_POSITION, your following axes will get all of ZL’s tuning artifacts injected into their command trajectories.

One final consideration (unlikely a culprit) would be to look at the axis indexes. Ideally the master axis would be the lowest axis number. In the RMP firmware, the axes are processed by index, so if your master axis number is greater than a follower’s number, there will be a one sample lag in the follower’s command.

The ZL is the lead which and we set the position to a number that happens to have 0 in the thousands place. The resolution of the ZL, ZR and ZB are the same (Z is a little lower).
I will try switching to COMMAND_POSITION and running a test.

Are you using the Recorder (or MotionScope) to get your data?

No, we have our own logging functions (using the rapidcode functions)

Ok. If you determine that you need time-synchronized recording, you can use the Recorder, which can record up to 32 values every RMP cycle, for your software to read out as needed.

https://rapidcode.roboticsys.com/class_r_s_i_1_1_rapid_code_1_1_motion_controller.html#MotionController-Recorder