- Posts: 459
- Thank you received: 158
LinuxCNC S-Curve Accelerations
- arvidb
- Offline
- Platinum Member
-
rmu wrote:
arvidb wrote: Another question: Why is cubic interpolation applied to TELEOP motion (axis jogs)?
what exactly are you referring to? IIRC, everything goes through cubic interpolation, I suppose to avoid discontinuities in the velocities.
Sorry, I should have elaborated much more.
When looking at the code and comments in emc/motion/control.c it looks like, sometime in the past, the trajectory planner was run at the "traj rate". (This might be the CYCLE_TIME set under TASK? - anyway, slower than the servo rate. See e.g. control.c:1578 or search the code for "traj rate".) And the cubic interpolator was used to smooth out the motion between the coarse positions returned from the trajectory planner at this slower rate.
Today, trajectory planning and kinematics are run at the servo rate (although there are several FIXME comments in the code saying these should be changed to run at the traj rate). I assumed cubic interpolation helped smooth out direction transitions which could still be useful for coordinated movement.
Joint jogs does not use the cubic interpolator, but axis jogs does, which seems strange to me since the axis jog planner (simple_tp) should produce smooth, acceleration-limited motion already. simple_tp also supplies (or could easily supply) acceleration and velocity setpoints so getting those are also no reasons for using the interpolator.
One thing I noted is that there are several places where teleop_tp->curr_vel is forcibly set to zero instead of letting the planner slow down with limited acceleration. I guess using the interpolator at least partly mitigates those bugs. (This is a perfect example of why data encapsulation is important: "outside" code should never have been allowed to modify simple_tp's curr_vel directly.)
The background to all this is of course that I'm trying to figure out how to fit my jerk-limited jog planner into the code, so I need to understand not only how things work but also the rationale behind it.
Please Log in or Create an account to join the conversation.
- rmu
- Offline
- Elite Member
-
- Posts: 279
- Thank you received: 101
arvidb wrote:
When looking at the code and comments in emc/motion/control.c it looks like, sometime in the past, the trajectory planner was run at the "traj rate". (This might be the CYCLE_TIME set under TASK? - anyway, slower than the servo rate. See e.g. control.c:1578 or search the code for "traj rate".) And the cubic interpolator was used to smooth out the motion between the coarse positions returned from the trajectory planner at this slower rate.
AFAIU, the trajectory planner could be run at an arbitrary rate, even in the non-realtime-domain, as long as it supplies segments fast enough. "Execution" of the segments happens in the servo thread. Segments are either lines or circular arcs. I'm not talking about the simple_tp, and spindle synced motion also is a somewhat separate story.
I agree that the code is bowl of spaghetti, pluck a noodle and everything moves. Cleaning that up would be a major undertaking and it is unlikely any major change could ever be merged.
Please Log in or Create an account to join the conversation.
- arvidb
- Offline
- Platinum Member
-
- Posts: 459
- Thank you received: 158
free_tp: joint jog planner, instance of simple_tp. Joint coordinate space.
teleop_tp: axis jog planner, instance of simple_tp. Cartesian space.
coord_tp: coordinated move planner, instance of TP_STRUCT. Cartesian space.
rmu wrote: AFAIU, the trajectory planner could be run at an arbitrary rate, even in the non-realtime-domain, as long as it supplies segments fast enough. "Execution" of the segments happens in the servo thread. Segments are either lines or circular arcs. I'm not talking about the simple_tp, and spindle synced motion also is a somewhat separate story.
We are at a lower level than line or arc segments here, in emc/motion/control.c. Look at the code starting at line 1309, case EMCMOT_MOTION_COORD. If the cubic interpolator needs a new point, tpRunCycle() and tpGetPos() are run on coord_tp to get a new cartesian position command (carte_pos_cmd). This is run through inverse kinematics. The results are assigned to the respective joint's coarse_pos member, and are also fed into the cubic interpolator.
Then as a final step the actual "fine" joint position (joint->pos_cmd) as well as velocity and acceleration commands are gotten from the cubic interpolator.
I haven't looked into the cubic interpolator, but maybe this significantly reduces the cpu load by running the inverse kinematics much more seldom than otherwise needed? It looks like it isn't run at the servo rate after all (unless the interpolator requests a new point every cycle).
After some more code reading: The "traj period" is a parameter to motmod.so. It is set to the servo period if not specified .
Ok, so this explains why the output from teleop_tp is run through the interpolator: it allows to run inverse kinematics at a lower rate than the servo thread, during axis jogs, by specifying traj_period_nsec to be larger than servo_period_nsec.
Then a new question arises: is this feature still meaningful today? The only reason to use it that I can see is if inverse kinematics is too slow to fit in a servo period, and then you'd get a realtime delay in the servo thread each time the traj period is reached anyway.
Edit: Why not move the cubic interpolation to the kinematics module instead? Then it could be completely skipped on trivial machines. Machines with difficult kinematics could apply it if necessary, internally computing fewer "true" waypoints than requested at the servo thread rate and interpolating the rest.
Please Log in or Create an account to join the conversation.
- andypugh
- Offline
- Moderator
-
- Posts: 19899
- Thank you received: 4655
arvidb wrote: Then a new question arises: is this feature still meaningful today?
I would guess not. But how would you know? We can change the code and see if anyone sues, I suppose.
[quote[ Why not move the cubic interpolation to the kinematics module instead? [/quote]I don't think that _in_ the kins is the way to go. But in that area makes sense.
This ties in to something that I keep meaning to try..
Kins is maths. If we calculate kins at "then" "now" and "next" then we know joint velocity and joint accel. Nearly as good is "then-1", "then", "no", ie a 2-deep buffer. In either case we can use kins as numerical differentiation to stay within Joint velocity and accel limits.
Please Log in or Create an account to join the conversation.
- Grotius
- Offline
- Platinum Member
-
- Posts: 2419
- Thank you received: 2349
I have done some coding in the past to integrate s-curve : github.com/grotius-cnc/S-curve-motion-planning
This code is working and tested on real hardware but not finished.
When you are at speed and do a second acceleration, that piece of code is not finished.
I could finish the code soon.
At the moment i have a stripped down lcnc version. archive-link
The purpose is to use the hal layer and to use components like linuxcnc-ethercat with qt c++.
The graphical environment is opencascade.
The motion planning is done in c++ and goes into the hal servo threat. A hal stepgen component is the back-end pid controller in rt.
Please Log in or Create an account to join the conversation.
- arvidb
- Offline
- Platinum Member
-
- Posts: 459
- Thank you received: 158
That would probably be the only way to find out, unless someone chimes in and says they're using that feature. But making interpolation the responsibility of kinematics and keeping the feature seems like a better idea!andypugh wrote: I would guess not. But how would you know? We can change the code and see if anyone sues, I suppose.
If interpolation is done by kinematics (no not "in" kinematics), that would mean kinematics delivers not only joint positions but also velocity and acceleration setpoints (since those come from the interpolator today). It'd be natural to feed the velocity and acceleration setpoints from the planners into kinematics as well, so that trivkins could just feed them through. More complicated kins could either use the interpolator or use some other algorithm, more suitable for the specific kinematics. Or differentiate, of course.andypugh wrote: I don't think that _in_ the kins is the way to go. But in that area makes sense.
This ties in to something that I keep meaning to try..
Kins is maths. If we calculate kins at "then" "now" and "next" then we know joint velocity and joint accel. Nearly as good is "then-1", "then", "no", ie a 2-deep buffer. In either case we can use kins as numerical differentiation to stay within Joint velocity and accel limits.
Not sure how you would use those values to keep within the joint limits though? Dynamically adjust net_feed_scale? That could be done today if someone writes the code - the datapoints already exist.
Please Log in or Create an account to join the conversation.