Angle Tolerance
For certain paths, such as those with many short linear interpolation segments, a small angle at the corner between two interpolations should not cause the axes to stop. The angleToleranceDegrees parameter can be used to not stop at corners with angles below a certain tolerance. This parameter requires the setAngleTolerance parameter to be set to TRUE.
The angle for this parameter is measured as the change in direction of advMotion at the corner. Two linear interpolations that move in the same direction will have a 0 degree angle, and two linear interpolations that move in opposite directions will have a 180 degree angle.
The accLimit parameter will not consider the change in acceleration caused by turning a corner below angleToleranceDegrees. This is because the change in acceleration when turning a corner is dependent on the cycle time, and the acceleration becomes infinity as the cycle time approaches 0. An axis may encounter acceleration above the accLimit if the angleToleranceDegrees is set sufficiently high.
The angle tolerance also affects interfaces between a linear interpolation and a circular interpolation, or two circular interpolations.
No Angle Tolerance Example
The following sample code executes a path interpolation that forms an imperfect circle with 36 linear interpolations.
//Create the path interpolation with look ahead buffer
wmxlib_AdvancedMotion->advMotion->CreatePathIntplLookaheadBuffer(0, 1000);
//Configure the path interpolation with look ahead channel
AdvMotion::PathIntplLookaheadConfiguration conf;
conf.axisCount = 2;
conf.axis[0] = 0;
conf.axis[1] = 1;
conf.compositeVel = 1000;
conf.compositeAcc = 4000;
conf.sampleDistance = 50;
wmxlib_AdvancedMotion->advMotion->SetPathIntplLookaheadConfiguration(0, &conf);
//Add the path interpolation with look ahead commands
AdvMotion::PathIntplLookaheadCommand path;
path.numPoints = 36;
double PI = 3.141592653589793238;
for (int i = 0; i < 36; i++) {
path.point[i].type = AdvMotion::PathIntplLookaheadSegmentType::Linear;
path.point[i].data.linear.axisCount = 2;
path.point[i].data.linear.axis[0] = 0;
path.point[i].data.linear.axis[1] = 1;
path.point[i].data.linear.target[0] = -1000+1000*cos((i+1)/36.0*(2*PI));
path.point[i].data.linear.target[1] = 0+1000*sin((i+1)/36.0*(2*PI));
}
wmxlib_AdvancedMotion->advMotion->AddPathIntplLookaheadCommand(0, &path);
//Execute path interpolation with look ahead
wmxlib_AdvancedMotion->advMotion->StartPathIntplLookahead(0);
//Wait for the path interpolation with look ahead to complete
AdvMotion::PathIntplLookaheadStatus pathStatus;
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.remainCommandCount > 0) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Move the axes to Idle state
wmxlib_AdvancedMotion->advMotion->StopPathIntplLookahead(0);
//Wait until the path interpolation with look ahead is in Stopped state
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.state != AdvMotion::PathIntplLookaheadState::Stopped) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Free the path interpolation with look ahead buffer (normally, the buffer should only be freed at the end of the application)
wmxlib_AdvancedMotion->advMotion->FreePathIntplLookaheadBuffer(0);
The following plots show the two-dimensional trajectory and the velocity and acceleration of each axis when the above sequence is executed from position (0, 0).

At the end of each linear interpolation segment, the axes must stop, causing the advMotion to execute slowly.
Angle Tolerance Example
The following sample code executes the same path interpolation as the previous example, but with the angle tolerance set to 11 degrees (above the 10 degrees between each linear interpolation).
//Create the path interpolation with look ahead buffer
wmxlib_AdvancedMotion->advMotion->CreatePathIntplLookaheadBuffer(0, 1000);
//Configure the path interpolation with look ahead channel
AdvMotion::PathIntplLookaheadConfiguration conf;
conf.axisCount = 2;
conf.axis[0] = 0;
conf.axis[1] = 1;
conf.compositeVel = 1000;
conf.compositeAcc = 4000;
conf.sampleDistance = 50;
conf.setAngleTolerance = true;
conf.angleToleranceDegrees = 11;
wmxlib_AdvancedMotion->advMotion->SetPathIntplLookaheadConfiguration(0, &conf);
//Add the path interpolation with look ahead commands
AdvMotion::PathIntplLookaheadCommand path;
path.numPoints = 36;
double PI = 3.141592653589793238;
for (int i = 0; i < 36; i++) {
path.point[i].type = AdvMotion::PathIntplLookaheadSegmentType::Linear;
path.point[i].data.linear.axisCount = 2;
path.point[i].data.linear.axis[0] = 0;
path.point[i].data.linear.axis[1] = 1;
path.point[i].data.linear.target[0] = -1000+1000*cos((i+1)/36.0*(2*PI));
path.point[i].data.linear.target[1] = 0+1000*sin((i+1)/36.0*(2*PI));
}
wmxlib_AdvancedMotion->advMotion->AddPathIntplLookaheadCommand(0, &path);
//Execute path interpolation with look ahead
wmxlib_AdvancedMotion->advMotion->StartPathIntplLookahead(0);
//Wait for the path interpolation with look ahead to complete
AdvMotion::PathIntplLookaheadStatus pathStatus;
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.remainCommandCount > 0) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Move the axes to Idle state
wmxlib_AdvancedMotion->advMotion->StopPathIntplLookahead(0);
//Wait until the path interpolation with look ahead is in Stopped state
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.state != AdvMotion::PathIntplLookaheadState::Stopped) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Free the path interpolation with look ahead buffer (normally, the buffer should only be freed at the end of the application)
wmxlib_AdvancedMotion->advMotion->FreePathIntplLookaheadBuffer(0);
The following plots show the two-dimensional trajectory and the velocity and acceleration of each axis when the above sequence is executed from position (0, 0).

The execution time is much faster, as the axes do not need to stop at the end of each linear interpolation. However, there is a large spike in the acceleration after each linear interpolation, meaning that the angle tolerance of 11 degrees is likely too high for this path and path parameters.
As discussed above, the accLimit parameter does not consider the acceleration caused by turning a corner below the angle tolerance. Setting this parameter will not reduce the acceleration spikes.
Using Smooth Radius Instead of Angle Tolerance
The normal method of turning corners without stopping and without encountering acceleration spikes is to set the smoothRadius.
The following sample code executes the same path interpolation, but adds a short smoothRadius to each linear interpolation.
//Create the path interpolation with look ahead buffer
wmxlib_AdvancedMotion->advMotion->CreatePathIntplLookaheadBuffer(0, 1000);
//Configure the path interpolation with look ahead channel
AdvMotion::PathIntplLookaheadConfiguration conf;
conf.axisCount = 2;
conf.axis[0] = 0;
conf.axis[1] = 1;
conf.compositeVel = 1000;
conf.compositeAcc = 4000;
conf.sampleDistance = 50;
wmxlib_AdvancedMotion->advMotion->SetPathIntplLookaheadConfiguration(0, &conf);
//Add the path interpolation with look ahead commands
AdvMotion::PathIntplLookaheadCommand path;
path.numPoints = 36;
double PI = 3.141592653589793238;
for (int i = 0; i < 36; i++) {
path.point[i].type = AdvMotion::PathIntplLookaheadSegmentType::Linear;
path.point[i].data.linear.axisCount = 2;
path.point[i].data.linear.axis[0] = 0;
path.point[i].data.linear.axis[1] = 1;
path.point[i].data.linear.target[0] = -1000+1000*cos((i+1)/36.0*(2*PI));
path.point[i].data.linear.target[1] = 0+1000*sin((i+1)/36.0*(2*PI));
path.point[i].data.linear.smoothRadius = 20;
}
wmxlib_AdvancedMotion->advMotion->AddPathIntplLookaheadCommand(0, &path);
//Execute path interpolation with look ahead
wmxlib_AdvancedMotion->advMotion->StartPathIntplLookahead(0);
//Wait for the path interpolation with look ahead to complete
AdvMotion::PathIntplLookaheadStatus pathStatus;
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.remainCommandCount > 0) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Move the axes to Idle state
wmxlib_AdvancedMotion->advMotion->StopPathIntplLookahead(0);
//Wait until the path interpolation with look ahead is in Stopped state
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
while(pathStatus.state != AdvMotion::PathIntplLookaheadState::Stopped) {
Sleep(10);
wmxlib_AdvancedMotion->advMotion->GetPathIntplLookaheadStatus(0, &pathStatus);
}
//Free the path interpolation with look ahead buffer (normally, the buffer should only be freed at the end of the application)
wmxlib_AdvancedMotion->advMotion->FreePathIntplLookaheadBuffer(0);
The following plots show the two-dimensional trajectory and the velocity and acceleration of each axis when the above sequence is executed from position (0, 0).
