Trajectory Planner using Ruckig Lib

More
2 years 11 months ago - 2 years 11 months ago #285017 by Grotius
@Joco,

Now it can cut a circle... Hahaha.
Quite stupid mistake from my side. But ok, we can repair it.

The downsides of this in a nutshell.
If a circle has a centerpoint and the start & end point are the same, the circle is 2d defined, not 3d defined.
The scurve planner uses 3d defined arc's and 3d defined lines for future gcode generation.
So now using a 2d circle is kind of a gcode language paradox problemf for me. image missing /media/kunena/emoticons/silly.png

Circle test ok, did just one test and added a circle testfile :

Git is now updated. Will be back monday.

 
Last edit: 2 years 11 months ago by Grotius.
The following user(s) said Thank You: akb1212, tommylight, tivoi

Please Log in or Create an account to join the conversation.

More
2 years 11 months ago - 2 years 11 months ago #285075 by Joco
Hello.  Have been running some tests as was particulary interested in the "pause" behaviour being observed in certain situations.  I wanted to zero in on that while also doing proof runs.

The pauses seem to be on hard direction changes suach at the edge of a square with a hard 90 degree corner.  There are a few examples of this in the sample gcode file being used for testing.  Isolated down here is the oncentric "squares".
 

File Attachment:

File Name: sinlge_obj...lbem.ngc
File Size:1.1 KB


However when you look closely at this (loading in either lcnc or in an external gcoder viewer you can see the inner and outter sqaures have "fillets" blending the corners where as the middle square has hard 90 degree corners.  These cause the pauses.

@Grotius - I am guessing that the TP is not doing any kind of blending on these corners and using G64 to generate any intermediate points to soften the change in direction.  The ruckig lib does not seem to do that blending for us.  We ask for postion x,y,z and it gives us the jerk constrained set of points and accerl/vel to get there. If we want some smoothing to happen I presume the TP needs to do that before feeding target states to ruckig.  A bit of a laymans description but hopefully makes some sense.

For anyone interested here is there vido recording the test file being run on real h/w with the plot and halscope up together.  So you can see what is being processed and the halscope values for acceleration and velocoty from the TP. I would suggest sound off and you might end up skipping through bits.  The key is to see the motion/accleration/velocity behaviour on the different shapes.


This is the log file linked to this video run.  Currently I can not run the file more than once.  Tryimg again gets tinker error messages in Axis. I have to stop and restart Axis to get another run to work.
 

File Attachment:

File Name: axis-scurv...ov24.txt
File Size:1.55 MB


Cheers - J.
Last edit: 2 years 11 months ago by Joco.
The following user(s) said Thank You: Grotius

Please Log in or Create an account to join the conversation.

More
2 years 11 months ago #285080 by ihavenofish
My thought is for any transition blended with g64, jerk control can be disabled, and then reenabled for any move that does not blend. I assume there is some what to determine which transitions get blended and nix them from the function.

Jerk limited blending can come later, as I assume it is a MUCH harder thing to do. SOME jerk control is better than no jerk control, so don't get sucked into adding it for every feature. That is why I think a lot of past efforts failed.
The following user(s) said Thank You: Grotius

Please Log in or Create an account to join the conversation.

More
2 years 11 months ago #285247 by Grotius
@Grotius - I am guessing that the TP is not doing any kind of blending on these corners and using G64 to generate any intermediate points to soften the change in direction.  The ruckig lib does not seem to do that blending for us.  We ask for postion x,y,z and it gives us the jerk constrained set of points and accerl/vel to get there. If we want some smoothing to happen I presume the TP needs to do that before feeding target states to ruckig.  A bit of a laymans description but hopefully makes some sense.

No blending is done. Blending could be done later on. For plasma i never used blending, always followed the exact path.

Ruckig is given a target position. When it's running to the target position, the velocity max may be modified.
This is like moving the velocity slider in axis.

When segments are colineair within 10 degrees (this is a path rule), the target position
is the sum of the colineair segments. So you can change the pathrule's yourself in the source file at the moment.

When user request's a pause, ruckig is changed from position mode to velocity mode and will run to velocity=0.
I think the pause behaviour at sharp corners could be limited by using different jerk & acceleration values.
In theory the velocity end should be 0 at a 90 degrees corner. Using a velocity end can be done later on.

We don't ask for a xyz position. The planner is just one dof(1) for target position. The xyz is the outcome of 0-1% path progress.

Currently I can not run the file more than once.
When the program is finished in axis, you can run it again with pressing the "arrow-right" button (right side from start), then press "pause-resume."

I think the video is ok for now.
The following user(s) said Thank You: akb1212, tivoi

Please Log in or Create an account to join the conversation.

More
2 years 11 months ago #285290 by Joco

We don't ask for a xyz position. The planner is just one dof(1) for target position. The xyz is the outcome of 0-1% path progress

Think I need a little help with this line. I have been investing time looking at ruckig example code, the standard planner and the skynet scurve planner to get my head around the code base so I can try some things.

1. “We don’t ask for xyz powition” - which flows on to the dof comment.  Given we are working in 3d space how does that work? It looked like ruckig was sorting all that out based on an a 3d space target and on each time slice it returned a new progression in 3d to that target and a return status of Done or Working.

2. “… the outcome of 0-1% path  progress” - is this reflecting the time slice element? I can recall a constant of 0.001 being aet that was (i thought) something to do with that.

On the topic of the pauses - given the difference in morion behaviour between a “square” with a small chamfer or arc replacing the 90deg corner v’s a  pure square with true 90deg corner, there are some choices.
a. The user needs to design geometry to achieve desired behaviour from the planner.
b. The CAM path software drives paths that avoid hard corners. e.g loop or triangle over cutting  on external corners
c. Path following tolerance between geometry elements allows for some blending and thus on the fly addition of new target points within tolerances that soften harsh transitions which would otherwise introduce these pauses.

a and b are probably the more correct approach but c could be a nice back stop.   It would be interesting to know what the expectation is on commercial machines with these types of scurve planners already in place. 

Cheers - J
The following user(s) said Thank You: Grotius

Please Log in or Create an account to join the conversation.

More
2 years 11 months ago - 2 years 11 months ago #285299 by TheRoslyak
Hello everyone.
I decided to join the discussion. I'm currently trying to construct a trajectory with acceleration and deceleration, but I'm burnt out for today. Generally, I wanted to know what advantages this library offers. Let's say I'm trying to divide a segment into 7 parts. First, I divide it into 3 parts: acceleration, constant motion, and deceleration. Then I take the acceleration or deceleration segment and divide it into 3 parts: initial jerk, linear segment, and final jerk. Accordingly, with zero jerk, the time for this segment equals speed divided by acceleration. At 100% jerk, this time is twice as long, and consequently, I have no linear segment. With this logic, I'm trying to build the graphs. I will show part of the code for now. I can upload the entire project later. I have the following questions: How is the use of this library better than the approach I've described above? And the second point, what parameters can I set using this library, apart from speed, acceleration, and the magnitude of jerk? Is it possible to change the duration of the jerk? Can these values be set separately for the acceleration and deceleration phases?
Code:
MotionData SCurveTp::calculateMotion(double maxSpeed, double acceleration, double jerkTimePercentage) {     MotionData data;     double distance = 100.0; // Total driving distance     // Calculation of the total acceleration and deceleration time without taking into account jerk     double baseTimeAcceleration = maxSpeed / acceleration;     double jerkTime = baseTimeAcceleration * (jerkTimePercentage / 100.0);     // Total time for acceleration and deceleration phase including jerk     double totalTimeAcceleration = baseTimeAcceleration + 2 * jerkTime;     double totalTimeDeceleration = totalTimeAcceleration;     // Calculation of time and distance for the constant speed phase     double distanceAcceleration = 0.5 * acceleration * pow(totalTimeAcceleration - jerkTime, 2) + acceleration * jerkTime * (totalTimeAcceleration - 0.5 * jerkTime);     double distanceDeceleration = distanceAcceleration;     double distanceConstantSpeed = distance - (distanceAcceleration + distanceDeceleration);     double timeConstantSpeed = distanceConstantSpeed / maxSpeed;     // Total driving time     double totalTime = totalTimeAcceleration + timeConstantSpeed + totalTimeDeceleration;     double currentSpeed = 0.0, currentPosition = 0.0, currentAcceleration = 0.0, currentJerk = 0.0;     double timeStep = 0.01; // Time step     for (double t = 0; t <= totalTime; t += timeStep) {         // Determining the current phase of movement         if (t < jerkTime) {             currentJerk = acceleration / jerkTime;             currentAcceleration += currentJerk * timeStep;         } else if (t < totalTimeAcceleration - jerkTime) {             currentJerk = 0;             currentAcceleration = acceleration;         } else if (t < totalTimeAcceleration) {             currentJerk = -acceleration / jerkTime;             currentAcceleration += currentJerk * timeStep;         } else if (t < totalTimeAcceleration + timeConstantSpeed) {             currentJerk = 0;             currentAcceleration = 0;             currentSpeed = maxSpeed;         } else if (t < totalTime - totalTimeDeceleration + jerkTime) {             currentJerk = -acceleration / jerkTime;             currentAcceleration += currentJerk * timeStep;         } else if (t < totalTime - jerkTime) {             currentJerk = 0;             currentAcceleration = -acceleration;         } else {             currentJerk = acceleration / jerkTime;             currentAcceleration += currentJerk * timeStep;         }         // Calculate speed and position         currentSpeed += currentAcceleration * timeStep;         currentPosition += currentSpeed * timeStep;         // Speed ​​and Position Limit         if (currentSpeed > maxSpeed) currentSpeed = maxSpeed;         if (currentSpeed < 0) currentSpeed = 0;         if (currentPosition > distance) currentPosition = distance;         // Adding data to lists         data.trajectory.append(QPointF(t, currentPosition));         data.velocity.append(QPointF(t, currentSpeed));         data.acceleration.append(QPointF(t, currentAcceleration));         data.jerk.append(QPointF(t, currentJerk));     }     double t=totalTime;     // If the total time is less than the maximum time, fill in the remaining time     while (t < 100.0) {         currentSpeed = (t >= totalTime) ? 0.0 : currentSpeed; // Speed ​​0 after end of movement         currentAcceleration = (t >= totalTime) ? 0.0 : currentAcceleration; // Acceleration 0 after end of movement         currentJerk = (t >= totalTime) ? 0.0 : currentJerk; // Jerk 0 after movement ends         data.trajectory.append(QPointF(t, currentPosition));         data.velocity.append(QPointF(t, currentSpeed));         data.acceleration.append(QPointF(t, currentAcceleration));         data.jerk.append(QPointF(t, currentJerk));         t += timeStep;     }     return data; }
For now, I'll upload part of the code. I can upload the full project tomorrow. Maybe someone will be able to comment on it
Last edit: 2 years 11 months ago by TheRoslyak.
The following user(s) said Thank You: akb1212, Grotius

Please Log in or Create an account to join the conversation.

Time to create page: 0.602 seconds
Powered by Kunena Forum