Hi all,
I am doing some motion tuning for a quite big and heavy machine. In general I noticed that having high values of jerk (about 500-600 mm/min) are good enough to travel circular paths smoothly (even tough it depends a lot on the mesh quality), but they are a bit high when printing corners, reducing a lot the effect of the input shaping and introducing lot of ringing.
Since I couldn't find a decent balance of jerks, acceleration and the Input Shaping L parameter, I modified a bit the function DDA::MatchSpeed and the command M566:
Basically my idea is to estimate the angle between two consecutive segments and if it is greater than a certain threshold I use a lower value of jerk.
I added to M566 a parameter J "junctionDeviation" which is the threshold below which an high value of jerk is used (the one set from M566 X-- Y--). For greater values, the minimum jerk multiplied by the parameter S is used.
I consider as threshold the difference between the X components of v1 and v2 in the reference frame of v1, and since v1 and v2 are unit vectors the threshold is equal to (1 - cos(alpha)).
void DDA::MatchSpeeds() noexcept
{
// v2 needs to be expressed in the reference frame of v1
// directionVector and next->directionVector are unit vectors
// The rotation matrix R(-alpha) can be expressed by using the directionVector[0] and directionVector[1] which are the X and Y components of v1 in the absolute reference frame (v1_0).
const float rotationMatrix[2][2] = {
{ directionVector[0], directionVector[1] },
{ -directionVector[1], directionVector[0] }
};
// Project v2 in the reference frame of v1 (v2_1)
const float nextVectorProjected[2] = {
rotationMatrix[0][0] * next->directionVector[0] + rotationMatrix[0][1] * next->directionVector[1],
rotationMatrix[1][0] * next->directionVector[0] + rotationMatrix[1][1] * next->directionVector[1]
};
// Difference of X and Y components in the reference frame of v1 (v1_1 - v2_1)
const float relativeFraction[2] = {
fabsf(1 - nextVectorProjected[0]),
fabsf(0 - nextVectorProjected[1])
};
for (size_t drive = 0; drive < MaxAxesPlusExtruders; ++drive)
{
if (directionVector[drive] != 0.0 || next->directionVector[drive] != 0.0)
{
const float totalFraction = fabsf(directionVector[drive] - next->directionVector[drive]);
const float jerk = totalFraction * beforePrepare.targetNextSpeed;
float allowedJerk = reprap.GetPlatform().GetInstantDv(drive);
// if dealing with X and Y axes reduce jerk if sharp edges
if (drive < 2 && relativeFraction[0] > reprap.GetPlatform().JunctionDeviation())
{
allowedJerk = ConvertSpeedFromMmPerSec(MinimumJerk * reprap.GetPlatform().MinimumJerkMultiplier());
}
if (jerk > allowedJerk)
{
beforePrepare.targetNextSpeed = allowedJerk/totalFraction;
}
}
}
}
Of course the code is not optimised, but it was just a first test to see if the idea could work.
I have done a couple of prints with a bit extreme setting (M566 X600 Y600 J0.01 S1) and I noticed a good improvement in print quality. Corners don't induce much ringing, so the input shaping can play a role there, and circular motions are done without too much scattering.
I'd like to have some feedback from this approach, especially if you see weird/dangerous edge cases that I didn't think about, in the code implementation and/or in the machine behaviour.
Thank you in advance to all of you!