LinuxCNC S-Curve Accelerations
14 Apr 2021 09:58 #205869
by rodw
Replied by rodw on topic LinuxCNC S-Curve Accelerations
I think they are assumed to be constant as the ini file is meant to describe your unchanging hardware. I nearly mentioned in my last post you could experiment changing it on the fly with sim_pin but its a user space component
linuxcnc.org/docs/devel/html/man/man1/sim_pin.1.html
Its actually very handy for tuning pid loops etc.
When I looked at my config, the ini accel values are sent to the mesa stepgens so I'm not sure how that maps to motion.
linuxcnc.org/docs/devel/html/man/man1/sim_pin.1.html
Its actually very handy for tuning pid loops etc.
When I looked at my config, the ini accel values are sent to the mesa stepgens so I'm not sure how that maps to motion.
Please Log in or Create an account to join the conversation.
14 Apr 2021 14:24 #205898
by arvidb
Replied by arvidb on topic LinuxCNC S-Curve Accelerations
The hostmot2 accel limit seems to be just another layer of "motion filtering"? The position (or velocity) values that come from LinuxCNC should be acceleration limited already, so you could probably disable the hm2 acc limit (set it to zero)?
I've been looking at the code some more and the EMCMOT_SET_JOINT_ACC_LIMIT command seems to be issued in only two places: inihal.cc and inijoint.cc. The latter reads out the settings from the INI file and the former creates hal pins: ini.N.max_acceleration. These pins are monitored for changes and on change the new value is propagated to joint->acc_limit (in emc/motion/command.c). So it seems it's actuallly possible to change the acceleration limits on the fly.
BTW, there's a bug in emc/motion/control.c where the code that's supposed to adjust the joint velocity limit to net_feed_scale is unreachable. The whole thing is in a switch (emcmotStatus->motion_state) statement under case EMCMOT_MOTION_FREE. Then at line 1199 the if statement checks for (emcmotStatus->motion_state != EMCMOT_MOTION_FREE) ...
Also there's a weird if statement just above it that lowers joint->acc_limit if it's over the limit set in emcmotStatus, i.e. the acceleration limit for Trajectory moves (set with emcTrajSetAcceleration()). This is probably a bug, too?
I've been looking at the code some more and the EMCMOT_SET_JOINT_ACC_LIMIT command seems to be issued in only two places: inihal.cc and inijoint.cc. The latter reads out the settings from the INI file and the former creates hal pins: ini.N.max_acceleration. These pins are monitored for changes and on change the new value is propagated to joint->acc_limit (in emc/motion/command.c). So it seems it's actuallly possible to change the acceleration limits on the fly.
BTW, there's a bug in emc/motion/control.c where the code that's supposed to adjust the joint velocity limit to net_feed_scale is unreachable. The whole thing is in a switch (emcmotStatus->motion_state) statement under case EMCMOT_MOTION_FREE. Then at line 1199 the if statement checks for (emcmotStatus->motion_state != EMCMOT_MOTION_FREE) ...
Also there's a weird if statement just above it that lowers joint->acc_limit if it's over the limit set in emcmotStatus, i.e. the acceleration limit for Trajectory moves (set with emcTrajSetAcceleration()). This is probably a bug, too?
Please Log in or Create an account to join the conversation.
14 Apr 2021 15:53 #205912
by arvidb
Replied by arvidb on topic LinuxCNC S-Curve Accelerations
Another question: Why is cubic interpolation applied to TELEOP motion (axis jogs)?
Please Log in or Create an account to join the conversation.
15 Apr 2021 10:01 #205989
by rmu
what exactly are you referring to? IIRC, everything goes through cubic interpolation, I suppose to avoid discontinuities in the velocities.
Replied by rmu on topic LinuxCNC S-Curve Accelerations
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.
Please Log in or Create an account to join the conversation.
15 Apr 2021 10:08 #205991
by rmu
look at git blame (e.g. github.com/LinuxCNC/linuxcnc/blame/maste...tion/control.c#L1196) for a hint.
Replied by rmu on topic LinuxCNC S-Curve Accelerations
Also there's a weird if statement just above it that lowers joint->acc_limit if it's over the limit set in emcmotStatus, i.e. the acceleration limit for Trajectory moves (set with emcTrajSetAcceleration()). This is probably a bug, too?
look at git blame (e.g. github.com/LinuxCNC/linuxcnc/blame/maste...tion/control.c#L1196) for a hint.
Please Log in or Create an account to join the conversation.
15 Apr 2021 12:48 #206001
by arvidb
Replied by arvidb on topic LinuxCNC S-Curve Accelerations
The comment for that commit says "honor [TRAJ] ACCELERATION settings in free mode planner" - but that's a bug, right? Why would one want that? As a user, if I set MAX_ACCELERATION under [JOINT_N], I expect that acceleration to be used for joint jogs. Not the DEFAULT_LINEAR_ACCELERATION set for cartesian motion under [TRAJ]?
The commit was made in 2008 while axis and joints were not differentiated. Maybe it just happened to be left behind in that split?
(Regardless, the code is still buggy since it modifies joint->acc_limit (e.g. even if DEFAULT_LINEAR_ACCELERATION is raised again the value is not restored). Something like local_acc_limit = fmin(joint->acc_limit, emcmotStatus->acc); would probably have been more suitable?)
The commit was made in 2008 while axis and joints were not differentiated. Maybe it just happened to be left behind in that split?
(Regardless, the code is still buggy since it modifies joint->acc_limit (e.g. even if DEFAULT_LINEAR_ACCELERATION is raised again the value is not restored). Something like local_acc_limit = fmin(joint->acc_limit, emcmotStatus->acc); would probably have been more suitable?)
Please Log in or Create an account to join the conversation.
15 Apr 2021 13:13 #206003
by arvidb
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.
Replied by arvidb on topic LinuxCNC S-Curve Accelerations
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.
15 Apr 2021 16:58 #206021
by rmu
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.
Replied by rmu on topic LinuxCNC S-Curve Accelerations
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.
16 Apr 2021 14:16 - 16 Apr 2021 14:29 #206107
by arvidb
Replied by arvidb on topic LinuxCNC S-Curve Accelerations
Let's use the terminology from the source to avoid confusion:
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.
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.
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.
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.
Last edit: 16 Apr 2021 14:29 by arvidb.
Please Log in or Create an account to join the conversation.
16 Apr 2021 23:06 #206143
by andypugh
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.
Replied by andypugh on topic LinuxCNC S-Curve Accelerations
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.
Time to create page: 0.180 seconds