MultiAxis PT streaming motion

What is your ErrorLimitTriggerValueGet() on each axis?

I see that the 21 point move is supposed to end on positions 0, 0.
But the function seems to indicate that you are starting from position
0.0779877, -0.00151062.

You always want your first point passed to PT to be your current position. Otherwise you will be trying an instantaneous jump to that position. While I would be it is the ErrorLimit which triggering an error, it could also be safety features within a drive.

Got it.

Although, in this particular instance, going from 0.077987 to 0 for Axis X and from -0.00151062 to 0 should not trigger error limit with delta of 0.2 seconds. It should then also trigger the same when I am not sending data in chunks.

But nevertheless, Let me modify the code to accept current position as the first array item and see if it solves.

My ErrorLimitTriggerValue is 0.1 * User units or 0.1 * 65536

Here is the result with current position as the first 2 elements of the points array. No motiondonewait function is used.

There is a slight mismatch with user units data read before homing and what is being passed in the array. This is because brake is disengadged which shifts the values slightly.

This one is after modification where I am enabling the motors first and then taking the current position values and passing along the same. Eliminating the braking positional mismatch.

Hi @rdhillon,

I believe it is the empty count that you are setting. Since you are setting the empty count equal to the number of frames you are sending out, you are immediately triggering the Estop event to protect your system.

You want the empty count to be sufficient for EStopTime to complete within your profile, but not large enough that you should ever be in a situation where you’ve starved the buffer of loaded points to that point. It is your failsafe emergency buffer that you don’t want to get into.

Use the following as a seed function for the behavior you needed:

int DetermineEmptyCountFramesBasedOnTimes(const std::vector<double>& timeDelta, double requiredEStopTime) {
  double accumulatedTime = 0.0;
  int count = 0;

  for (double time : timeDelta) {
    accumulatedTime += time;
    ++count;

    if (accumulatedTime >= requiredEStopTime) {
      break;
    }
  }
  const int THERE_ARE_TWO_FRAMES_PER_POINT = 2;
  return count * THERE_ARE_TWO_FRAMES_PER_POINT;
}

Update your EMPTY_COUNT definition as follows:
const int EMPTY_COUNT = DetermineEmptyCountFramesBasedOnTimes(timeDelta, axis->EStopTimeGet());

Note, axis is the variable name of the MultiAxis parameter passed to the function example above.

Hi Jacob

Thanks, It makes sense. I tried that. I testedtwo scenarios.

1: No MotionDoneWait().
In this one I still got RSI State error.

  1. MotionDoneWait() function declared right after the PT motion command inside my iteration loop. This time the motion did execute for the first iteration but I got “State Error” for iteration 2.

First state error is slightly different than this time. In the first one its called RSIStataSTOPPING_ERROR while the second scenario says RSIStateERROR

But looks like in both situations its failing at 2nd iteration.

Hi @rdhillon,

Can you also include Axis::SourceGet() when you are in the error state? I believe we’ve been looking at Motion Out of Frames errors but I’d like to know for sure. Something is triggering the error and we need to find out what is causing it.

MotionDoneWait() shouldn’t be used with streaming motion until a final point has been sent. Otherwise you’ll always run Out of Frames. Case 2 is doomed.

Hi Jacob

Thanks for all the help so far. I have included the SourceGet function as well in the function. Is this the correct way of writing the function?

std::cout << "Source State Error: "<< axisX->SourceNameGet(axisX->SourceGet()) << std::endl;

These are the outputs recorded.

My UserLimitCount is set to 0 as per defaults.

The last line of Output “Axis State X: Motion: RSIStateSTOPPING_ERROR :: {motion.c, line 1398} (Error 3850) (Axis::ClearFaults) (Object 0) (File axis.cpp) (Line 5872) (Version 10.6.2.0)” is a weird one as it does not display the actual message I had put in the function call when it encounters this case but rather displays the message above !

You’re getting the error message for RSISourceUNKNOWN (which isn’t helpful in your case).

Also it seems like you may be calling ClearFaults() when you shouldn’t be clearing yet.

You’ll only want to print the source if/when the state is not MOVING or IDLE. Also, for the most information, you’ll want to check axisX, axisY and your MultiAxis (as each could have a different source)

Overall it seems like you’re not calling the final MovePT in time.

Hi Scott

Thanks for jumping in. I believe I am not clearing faults when trying to determine the cause of error.

This is the function I am using to determine the axis state.

std::string axisState(Axis *axis)
{
const int secondsToMilliseconds = 1000;

switch (axis->StateGet())
{

case RSIState::RSIStateMOVING:
  axis->Abort();
  axis->ClearFaults();
  //std::cout << "in RSI Moving state"<< std::endl;
  return "In Moving State";
  
//Wait standard stop time
case RSIState::RSIStateSTOPPING:
  //std::cout << "in RSI Stopping"<< std::endl;
  return "At Stopping State";

case RSIState::RSIStateSTOPPING_ERROR:
  std::cout << "in RSI Moving error state"<< std::endl;
  std::cout << "Source Stopping Error: "<< axis->SourceNameGet(axis->SourceGet()) << std::endl;
  //Assuming that Stop Time is greater than EStop Time.
  //std::this_thread::sleep_for((axis->StopTimeGet() * secondsToMilliseconds));
  std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(axis->StopTimeGet() * secondsToMilliseconds)));
  //You may still be stopping if you have bad settings.
  if (axis->StateGet() == RSIState::RSIStateSTOPPING || axis->StateGet() == RSIState::RSIStateSTOPPING_ERROR)
  {
    //Abort the axis.  You should stopped but likely have bad settling criteria.
    axis->Abort();
  }
  
  //axis->ClearFaults();
  return "Stopping Error State";
  break;
  
case RSIState::RSIStateERROR:
  std::cout << "Source State Error: "<< axis->SourceNameGet(axis->SourceGet()) << std::endl;
  return "State Error";

case RSIState::RSIStateSTOPPED:
  //axis->ClearFaults();
  return "Stopped State";
break;
case RSIState::RSIStateIDLE:
  //std::cout << "in Idle State"<< std::endl;
  return "IDLE State";
default:
  //std::cout << "in default state"<< std::endl;
  return "Default State";
break;

}
}

My clear faults line is commented in one of the cases.

In my main code, where I am calling a custom MovePT function I am just sending out commands to execute the motion without any declaration of clear faults. And I am printing these values on console before every iteration.

// Visualization: Print the position and time data
std::cout << "Iteration " << i / POINTS_PER_CALL + 1 << “\n”;
std::cout << "Raw Encoder X: " << axisX->EncoderPositionGet(RSIMotorFeedback::RSIMotorFeedbackPRIMARY) << “\n”;
std::cout << "Source State Error X: "<< axisX->SourceNameGet(axisX->SourceGet()) << std::endl;
std::cout << "Axis State X: " << axisState(axisX) << “\n\n”;
std::cout << "Raw Encoder Y: " << axisY->EncoderPositionGet(RSIMotorFeedback::RSIMotorFeedbackPRIMARY) << “\n”;
std::cout << "Source State Error Y: "<< axisY->SourceNameGet(axisY->SourceGet()) << std::endl;
std::cout << "Axis State Y: " << axisState(axisY) << “\n\n”;
std::cout << "Empty Count " << EMPTY_COUNT << “\n”;
std::cout << “Processing " << pointsThisIteration << " points\n”;
std::cout << "Positions: [ ";
for (double p : positions)
{
std::cout << p << " ";
}
std::cout << “]\n”
<< "Positions Array Size: " << positions.size() << “\n”;

std::cout << "Time: [ ";
for (int j = 0; j < pointsThisIteration; j++)
{
  std::cout << time[j] << " ";
}
std::cout << "]\n";

std::cout << "Final: " << std::boolalpha << final << "\n\n";

I will however, print out the multiaxis state as well to see if that helps to troubleshoot.

When I send data in batches, I get this error.

This is the line in my code which is supposed to call the axisState function and display the output from one of the cases.

But rather than displaying one of the return messages declared in axisState function, it just displays this error message.
Motion: RSIStateSTOPPING_ERROR :: {motion.c, line 1398} (Error 3850) (Axis::ClearFaults) (Object 0) (File axis.cpp) (Line 5872) (Version 10.6.2.0)

Maybe this error is one of the cases I have NOT setup in the axisState function?

This is an exception method coming from the Axis::ClearFaults() method and it’s trying to tell you that you can’t clear faults while the Axis is in the STOPPING_ERROR state.

Do you have some calls to ClearFaults() in your code? Maybe more context would help us troubleshoot.