Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordc42 <dcrocker@eschertech.com>2021-10-08 12:59:47 +0300
committerGitHub <noreply@github.com>2021-10-08 12:59:47 +0300
commit5f90c9fd384b3d2dd24bb8c225942e561d98be53 (patch)
treed92ba1ce3d34ea50c913e7bfc7bf11f3976c37df /src/Movement
parentffd7aa7d821efdfc17004c41f2ad6fbf8a9713e6 (diff)
parent986fe2d410043261a899b3b385093fdb7f07f6a2 (diff)
Merge pull request #545 from tobbelobb/3.4-dev
Fixes for Hangprinter's forward kinematics
Diffstat (limited to 'src/Movement')
-rw-r--r--src/Movement/Kinematics/HangprinterKinematics.cpp431
-rw-r--r--src/Movement/Kinematics/HangprinterKinematics.h12
2 files changed, 62 insertions, 381 deletions
diff --git a/src/Movement/Kinematics/HangprinterKinematics.cpp b/src/Movement/Kinematics/HangprinterKinematics.cpp
index 9f8f405c..ae211220 100644
--- a/src/Movement/Kinematics/HangprinterKinematics.cpp
+++ b/src/Movement/Kinematics/HangprinterKinematics.cpp
@@ -94,7 +94,6 @@ void HangprinterKinematics::Init() noexcept
ARRAY_INIT(motorGearTeeth, DefaultMotorGearTeeth);
ARRAY_INIT(spoolGearTeeth, DefaultSpoolGearTeeth);
ARRAY_INIT(fullStepsPerMotorRev, DefaultFullStepsPerMotorRev);
- doneAutoCalibration = false;
Recalc();
}
@@ -102,36 +101,6 @@ void HangprinterKinematics::Init() noexcept
void HangprinterKinematics::Recalc() noexcept
{
printRadiusSquared = fsquare(printRadius);
- Da2 = fsquare(anchors[A_AXIS][0]) + fsquare(anchors[A_AXIS][1]) + fsquare(anchors[A_AXIS][2]);
- Db2 = fsquare(anchors[B_AXIS][0]) + fsquare(anchors[B_AXIS][1]) + fsquare(anchors[B_AXIS][2]);
- Dc2 = fsquare(anchors[C_AXIS][0]) + fsquare(anchors[C_AXIS][1]) + fsquare(anchors[C_AXIS][2]);
- Xab = anchors[A_AXIS][0] - anchors[B_AXIS][0]; // maybe zero
- Xbc = anchors[B_AXIS][0] - anchors[C_AXIS][0];
- Xca = anchors[C_AXIS][0] - anchors[A_AXIS][0];
- Yab = anchors[A_AXIS][1] - anchors[B_AXIS][1];
- Ybc = anchors[B_AXIS][1] - anchors[C_AXIS][1];
- Yca = anchors[C_AXIS][1] - anchors[A_AXIS][1];
- Zab = anchors[A_AXIS][2] - anchors[B_AXIS][2];
- Zbc = anchors[B_AXIS][2] - anchors[C_AXIS][2];
- Zca = anchors[C_AXIS][2] - anchors[A_AXIS][2];
- P = ( anchors[B_AXIS][0] * Yca
- - anchors[A_AXIS][0] * anchors[C_AXIS][1]
- + anchors[A_AXIS][1] * anchors[C_AXIS][0]
- - anchors[B_AXIS][1] * Xca
- ) * 2;
- P2 = fsquare(P);
- Q = ( anchors[B_AXIS][Y_AXIS] * Zca
- - anchors[A_AXIS][Y_AXIS] * anchors[C_AXIS][Z_AXIS]
- + anchors[A_AXIS][Z_AXIS] * anchors[C_AXIS][Y_AXIS]
- - anchors[B_AXIS][Z_AXIS] * Yca
- ) * 2;
- R = - ( anchors[B_AXIS][0] * Zca
- + anchors[A_AXIS][0] * anchors[C_AXIS][2]
- + anchors[A_AXIS][2] * anchors[C_AXIS][0]
- - anchors[B_AXIS][2] * Xca
- ) * 2;
- U = (anchors[A_AXIS][2] * P2) + (anchors[A_AXIS][0] * Q * P) + (anchors[A_AXIS][1] * R * P);
- A = (P2 + fsquare(Q) + fsquare(R)) * 2;
// This is the difference between a "line length" and a "line position"
// "line length" == ("line position" + "line length in origin")
@@ -164,8 +133,6 @@ void HangprinterKinematics::Recalc() noexcept
// Calculate the steps per unit that is correct at the origin
platform.SetDriveStepsPerUnit(i, stepsPerUnitTimesRTmp[i] / spoolRadii[i], 0);
}
-
- //debugPrintf("Recalced params\nDa2: %.2f, Db2: %.2f, Dc2: %.2f, Xab: %.2f, Xbc: %.2f, Xca: %.2f, Yab: %.2f, Ybc: %.2f, Yca: %.2f, Zab: %.2f, Zbc: %.2f, Zca: %.2f, P: %.2f, P2: %.2f, Q: %.2f, R: %.2f, U: %.2f, A: %.2f\n", (double)Da2, (double)Db2, (double)Dc2, (double)Xab, (double)Xbc, (double)Xca, (double)Yab, (double)Ybc, (double)Yca, (double)Zab, (double)Zbc, (double)Zca, (double)P, (double)P2, (double)Q, (double)R, (double)U, (double)A);
}
// Return the name of the current kinematics
@@ -332,17 +299,18 @@ inline float HangprinterKinematics::MotorPosToLinePos(const int32_t motorPos, si
return (fsquare(motorPos / k0[axis] + spoolRadii[axis]) - spoolRadiiSq[axis]) / k2[axis];
}
-// Convert motor coordinates to machine coordinates. Used after homing and after individual motor moves.
+// Convert motor coordinates to machine coordinates.
+// Assumes lines are tight and anchor location norms are followed
void HangprinterKinematics::MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const noexcept
{
- InverseTransform(
+ ForwardTransform(
MotorPosToLinePos(motorPos[A_AXIS], A_AXIS) + lineLengthsOrigin[A_AXIS],
MotorPosToLinePos(motorPos[B_AXIS], B_AXIS) + lineLengthsOrigin[B_AXIS],
MotorPosToLinePos(motorPos[C_AXIS], C_AXIS) + lineLengthsOrigin[C_AXIS],
+ MotorPosToLinePos(motorPos[D_AXIS], D_AXIS) + lineLengthsOrigin[D_AXIS],
machinePos);
}
-
static bool isSameSide(float const v0[3], float const v1[3], float const v2[3], float const v3[3], float const p[3]){
float const h0[3] = {v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]};
float const h1[3] = {v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]};
@@ -471,7 +439,7 @@ AxesBitmap HangprinterKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool di
#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE
-// Write the parameters that are set by auto calibration to a file, returning true if success
+// Write the parameters to a file, returning true if success
bool HangprinterKinematics::WriteCalibrationParameters(FileStore *f) const noexcept
{
bool ok = f->Write("; Hangprinter parameters\n");
@@ -514,343 +482,66 @@ bool HangprinterKinematics::WriteCalibrationParameters(FileStore *f) const noexc
// Write any calibration data that we need to resume a print after power fail, returning true if successful
bool HangprinterKinematics::WriteResumeSettings(FileStore *f) const noexcept
{
- return !doneAutoCalibration || WriteCalibrationParameters(f);
+ return WriteCalibrationParameters(f);
}
#endif
-// Calculate the Cartesian coordinates from the motor coordinates
-void HangprinterKinematics::InverseTransform(float La, float Lb, float Lc, float machinePos[3]) const noexcept
-{
- // Calculate PQRST such that x = (Qz + S)/P, y = (Rz + T)/P
- const float S = - Yab * (fsquare(Lc) - Dc2)
- - Yca * (fsquare(Lb) - Db2)
- - Ybc * (fsquare(La) - Da2);
- const float T = - Xab * (fsquare(Lc) - Dc2)
- + Xca * (fsquare(Lb) - Db2)
- + Xbc * (fsquare(La) - Da2);
-
- // Calculate quadratic equation coefficients
- const float halfB = (S * Q) - (R * T) - U;
- const float C = fsquare(S) + fsquare(T) + (anchors[A_AXIS][Y_AXIS] * T - anchors[A_AXIS][X_AXIS] * S) * P * 2 + (Da2 - fsquare(La)) * P2;
- //debugPrintf("S: %.2f, T: %.2f, halfB: %.2f, C: %.2f, P: %.2f, A: %.2f\n", (double)S, (double)T, (double)halfB, (double)C, (double)P, (double) A);
-
- // Solve the quadratic equation for z
- machinePos[2] = (- halfB - fastSqrtf(fabsf(fsquare(halfB) - A * C)))/A;
-
- // Substitute back for X and Y
- machinePos[0] = (Q * machinePos[2] + S)/P;
- machinePos[1] = (R * machinePos[2] + T)/P;
-
- //debugPrintf("Motor %.2f,%.2f,%.2f to Cartesian %.2f,%.2f,%.2f\n", (double)La, (double)Lb, (double)Lc, (double)machinePos[0], (double)machinePos[1], (double)machinePos[2]);
-}
-
-// Auto calibrate from a set of probe points returning true if it failed
-// We can't calibrate all the XY parameters because translations and rotations of the anchors don't alter the height. Therefore we calibrate the following:
-// 0, 1, 2 Spool zero length motor positions (this is like endstop calibration on a delta)
-// 3 Y coordinate of the B anchor
-// 4, 5 X and Y coordinates of the C anchor
-// 6, 7, 8 Heights of the A, B, C anchors
-// We don't touch the XY coordinates of the A anchor or the X coordinate of the B anchor.
-bool HangprinterKinematics::DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) noexcept
-{
- const size_t NumHangprinterFactors = 9; // maximum number of machine factors we can adjust
-
- if (numFactors != 3 && numFactors != 6 && numFactors != NumHangprinterFactors)
- {
- reply.printf("Hangprinter calibration with %d factors requested but only 3, 6, and 9 supported", numFactors);
- return true;
- }
-
- if (reprap.Debug(moduleMove))
- {
- String<StringLength256> scratchString;
- PrintParameters(scratchString.GetRef());
- //debugPrintf("%s\n", scratchString.c_str());
- }
-
- // The following is for printing out the calculation time, see later
- //uint32_t startTime = reprap.GetPlatform()->GetInterruptClocks();
-
- // Transform the probing points to motor endpoints and store them in a matrix, so that we can do multiple iterations using the same data
- FixedMatrix<floatc_t, MaxCalibrationPoints, 3> probeMotorPositions;
- floatc_t corrections[MaxCalibrationPoints];
- Deviation initialDeviation;
- const size_t numPoints = probePoints.NumberOfProbePoints();
-
- {
- floatc_t initialSum = 0.0, initialSumOfSquares = 0.0;
- for (size_t i = 0; i < numPoints; ++i)
- {
- corrections[i] = 0.0;
- float machinePos[3];
- const floatc_t zp = reprap.GetMove().GetProbeCoordinates(i, machinePos[X_AXIS], machinePos[Y_AXIS], probePoints.PointWasCorrected(i));
- machinePos[Z_AXIS] = 0.0;
-
- probeMotorPositions(i, A_AXIS) = fastSqrtf(LineLengthSquared(machinePos, anchors[A_AXIS]));
- probeMotorPositions(i, B_AXIS) = fastSqrtf(LineLengthSquared(machinePos, anchors[B_AXIS]));
- probeMotorPositions(i, C_AXIS) = fastSqrtf(LineLengthSquared(machinePos, anchors[C_AXIS]));
- initialSumOfSquares += fcsquare(zp);
- }
- initialDeviation.Set(initialSumOfSquares, initialSum, numPoints);
- }
-
- // Do 1 or more Newton-Raphson iterations
- Deviation finalDeviation;
- unsigned int iteration = 0;
- for (;;)
- {
- // Build a Nx9 matrix of derivatives with respect to xa, xb, yc, za, zb, zc, diagonal.
- FixedMatrix<floatc_t, MaxCalibrationPoints, NumHangprinterFactors> derivativeMatrix;
- for (size_t i = 0; i < numPoints; ++i)
- {
- for (size_t j = 0; j < numFactors; ++j)
- {
- const size_t adjustedJ = (numFactors == 8 && j >= 6) ? j + 1 : j; // skip diagonal rod length if doing 8-factor calibration
- derivativeMatrix(i, j) =
- ComputeDerivative(adjustedJ, probeMotorPositions(i, A_AXIS), probeMotorPositions(i, B_AXIS), probeMotorPositions(i, C_AXIS));
- }
- }
-
- if (reprap.Debug(moduleMove))
- {
- PrintMatrix("Derivative matrix", derivativeMatrix, numPoints, numFactors);
- }
-
- // Now build the normal equations for least squares fitting
- FixedMatrix<floatc_t, NumHangprinterFactors, NumHangprinterFactors + 1> normalMatrix;
- for (size_t i = 0; i < numFactors; ++i)
- {
- for (size_t j = 0; j < numFactors; ++j)
- {
- floatc_t temp = derivativeMatrix(0, i) * derivativeMatrix(0, j);
- for (size_t k = 1; k < numPoints; ++k)
- {
- temp += derivativeMatrix(k, i) * derivativeMatrix(k, j);
- }
- normalMatrix(i, j) = temp;
- }
- floatc_t temp = derivativeMatrix(0, i) * -((floatc_t)probePoints.GetZHeight(0) + corrections[0]);
- for (size_t k = 1; k < numPoints; ++k)
- {
- temp += derivativeMatrix(k, i) * -((floatc_t)probePoints.GetZHeight(k) + corrections[k]);
- }
- normalMatrix(i, numFactors) = temp;
- }
-
- if (reprap.Debug(moduleMove))
- {
- PrintMatrix("Normal matrix", normalMatrix, numFactors, numFactors + 1);
- }
-
- if (!normalMatrix.GaussJordan(numFactors, numFactors + 1))
- {
- reply.copy("Unable to calculate calibration parameters. Please choose different probe points.");
- return true;
- }
-
- floatc_t solution[NumHangprinterFactors];
- for (size_t i = 0; i < numFactors; ++i)
- {
- solution[i] = normalMatrix(i, numFactors);
- }
-
- if (reprap.Debug(moduleMove))
- {
- PrintMatrix("Solved matrix", normalMatrix, numFactors, numFactors + 1);
- PrintVector("Solution", solution, numFactors);
-
- // Calculate and display the residuals
- // Save a little stack by not allocating a residuals vector, because stack for it doesn't only get reserved when debug is enabled.
- //debugPrintf("Residuals:");
- for (size_t i = 0; i < numPoints; ++i)
- {
- floatc_t residual = probePoints.GetZHeight(i);
- for (size_t j = 0; j < numFactors; ++j)
- {
- residual += solution[j] * derivativeMatrix(i, j);
- }
- //debugPrintf(" %7.4f", (double)residual);
- }
-
- //debugPrintf("\n");
- }
-
- Adjust(numFactors, solution); // adjust the delta parameters
-
- float heightAdjust[3];
- for (size_t drive = 0; drive < 3; ++drive)
- {
- heightAdjust[drive] = (float)solution[drive]; // convert double to float
- }
- reprap.GetMove().AdjustMotorPositions(heightAdjust, 3); // adjust the motor positions
-
- // Calculate the expected probe heights using the new parameters
- {
- floatc_t expectedResiduals[MaxCalibrationPoints];
- floatc_t finalSum = 0.0, finalSumOfSquares = 0.0;
- for (size_t i = 0; i < numPoints; ++i)
- {
- for (size_t axis = 0; axis < 3; ++axis)
- {
- probeMotorPositions(i, axis) += solution[axis];
- }
- float newPosition[3];
- InverseTransform(probeMotorPositions(i, A_AXIS), probeMotorPositions(i, B_AXIS), probeMotorPositions(i, C_AXIS), newPosition);
- corrections[i] = newPosition[Z_AXIS];
- expectedResiduals[i] = probePoints.GetZHeight(i) + newPosition[Z_AXIS];
- finalSum += expectedResiduals[i];
- finalSumOfSquares += fcsquare(expectedResiduals[i]);
- }
-
- finalDeviation.Set(finalSumOfSquares, finalSum, numPoints);
-
- if (reprap.Debug(moduleMove))
- {
- PrintVector("Expected probe error", expectedResiduals, numPoints);
- }
- }
-
- // Decide whether to do another iteration. Two is slightly better than one, but three doesn't improve things.
- // Alternatively, we could stop when the expected RMS error is only slightly worse than the RMS of the residuals.
- ++iteration;
- if (iteration == 2)
- {
- break;
- }
- }
-
- if (reprap.Debug(moduleMove))
- {
- String<StringLength256> scratchString;
- PrintParameters(scratchString.GetRef());
- //debugPrintf("%s\n", scratchString.c_str());
- }
-
- reprap.GetMove().SetInitialCalibrationDeviation(initialDeviation);
- reprap.GetMove().SetLatestCalibrationDeviation(finalDeviation, numFactors);
-
- reply.printf("Calibrated %d factors using %d points, (mean, deviation) before (%.3f, %.3f) after (%.3f, %.3f)",
- numFactors, numPoints,
- (double)initialDeviation.GetMean(), (double)initialDeviation.GetDeviationFromMean(),
- (double)finalDeviation.GetMean(), (double)finalDeviation.GetDeviationFromMean());
-
- // We don't want to call MessageF(LogMessage, "%s\n", reply.c_str()) here because that will allocate a buffer within MessageF, which adds to our stack usage.
- // Better to allocate the buffer here so that it uses the same stack space as the arrays that we have finished with
- {
- String<StringLength256> scratchString;
- scratchString.printf("%s\n", reply.c_str());
- reprap.GetPlatform().Message(LogWarn, scratchString.c_str());
- }
-
- doneAutoCalibration = true;
- return false;
-}
-
-// Compute the derivative of height with respect to a parameter at the specified motor endpoints.
-// 'deriv' indicates the parameter as follows:
-// 0, 1, 2 = A, B, C line length adjustments
-// 3 = B anchor Y coordinate
-// 4, 5 = C anchor X and Y coordinates
-// 6, 7, 8 = A, B and C anchor Z coordinates
-floatc_t HangprinterKinematics::ComputeDerivative(unsigned int deriv, float La, float Lb, float Lc) const noexcept
-{
- const float perturb = 0.2; // perturbation amount in mm
- HangprinterKinematics hiParams(*this), loParams(*this);
- switch(deriv)
- {
- case 0:
- case 1:
- case 2:
- // Line length corrections
- break;
-
- case 3:
- hiParams.anchors[B_AXIS][Y_AXIS] += perturb;
- loParams.anchors[B_AXIS][Y_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
-
- case 4:
- hiParams.anchors[C_AXIS][X_AXIS] += perturb;
- loParams.anchors[C_AXIS][X_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
-
- case 5:
- hiParams.anchors[C_AXIS][Y_AXIS] += perturb;
- loParams.anchors[C_AXIS][Y_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
-
- case 6:
- hiParams.anchors[A_AXIS][Z_AXIS] += perturb;
- loParams.anchors[A_AXIS][Z_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
-
- case 7:
- hiParams.anchors[B_AXIS][Z_AXIS] += perturb;
- loParams.anchors[B_AXIS][Z_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
-
- case 8:
- hiParams.anchors[B_AXIS][Z_AXIS] += perturb;
- loParams.anchors[B_AXIS][Z_AXIS] -= perturb;
- hiParams.Recalc();
- loParams.Recalc();
- break;
- }
-
- float newPos[3];
- hiParams.InverseTransform((deriv == 0) ? La + perturb : La, (deriv == 1) ? Lb + perturb : Lb, (deriv == 2) ? Lc + perturb : Lc, newPos);
-
- const float zHi = newPos[Z_AXIS];
- loParams.InverseTransform((deriv == 0) ? La - perturb : La, (deriv == 1) ? Lb - perturb : Lb, (deriv == 2) ? Lc - perturb : Lc, newPos);
- const float zLo = newPos[Z_AXIS];
- return ((floatc_t)zHi - (floatc_t)zLo)/(floatc_t)(2 * perturb);
-}
-
-// Perform 3, 6 or 9-factor adjustment.
-// The input vector contains the following parameters in this order:
-// 0, 1, 2 = A, B, C line length adjustments
-// 3 = B anchor Y coordinate
-// 4, 5 = C anchor X and Y coordinates
-// 6, 7, 8 = A, B and C anchor Z coordinates
-void HangprinterKinematics::Adjust(size_t numFactors, const floatc_t v[]) noexcept
-{
- if (numFactors >= 4)
- {
- anchors[B_AXIS][Y_AXIS] += (float)v[3];
- }
- if (numFactors >= 5)
- {
- anchors[C_AXIS][X_AXIS] += (float)v[4];
- }
- if (numFactors >= 6)
- {
- anchors[C_AXIS][Y_AXIS] += (float)v[5];
- }
- if (numFactors >= 7)
- {
- anchors[A_AXIS][Z_AXIS] += (float)v[6];
- }
- if (numFactors >= 8)
- {
- anchors[B_AXIS][Z_AXIS] += (float)v[7];
- }
- if (numFactors >= 9)
- {
- anchors[C_AXIS][Z_AXIS] += (float)v[8];
- }
-
- Recalc();
+/**
+ * Hangprinter forward kinematics
+ * Basic idea is to subtract squared line lengths to get linear equations,
+ * and then to solve with variable substitution.
+ *
+ * If we assume anchor location norms are followed, then
+ * we get a fairly clean derivation by
+ * subtracting d*d from a*a, b*b, and c*c:
+ *
+ * a*a - d*d = k1 + k2*y + k3*z <---- a line (I)
+ * b*b - d*d = k4 + k5*x + k6*y + k7*z <---- a plane (II)
+ * c*c - d*d = k8 + k9*x + k10*y + k11*z <---- a plane (III)
+ *
+ * Use (I) to reduce (II) and (III) into lines. Eliminate y, keep z.
+ *
+ * (II): b*b - d*d = k12 + k13*x + k14*z
+ * <=> x = k0b + k1b*z, <---- a line (IV)
+ *
+ * (III): c*c - d*d = k15 + k16*x + k17*z
+ * <=> x = k0c + k1c*z, <---- a line (V)
+ *
+ * where k1, k2, ..., k17, k0b, k0c, k1b, and k1c are known constants.
+ *
+ * These two straight lines are not parallel, so they will cross in exactly one point.
+ * Find z by setting (IV) = (V)
+ * Find x by inserting z into (V)
+ * Find y by inserting z into (I)
+ *
+ * Warning: truncation errors will typically be in the order of a few tens of microns.
+ */
+void HangprinterKinematics::ForwardTransform(float const a, float const b, float const c, float const d, float machinePos[3]) const noexcept
+{
+ // Anchor location norms
+ if (fabsf(anchors[D_AXIS][X_AXIS]) > 0.1F ||
+ fabsf(anchors[D_AXIS][Y_AXIS]) > 0.1F ||
+ fabsf(anchors[A_AXIS][X_AXIS]) > 0.1F ||
+ fabsf(anchors[B_AXIS][X_AXIS]) < 0.1F ||
+ fabsf(anchors[C_AXIS][X_AXIS]) < 0.1F ||
+ fabsf(anchors[A_AXIS][Y_AXIS]) < 0.1F) {
+ return;
+ }
+ const float Asq = fsquare(lineLengthsOrigin[A_AXIS]);
+ const float Bsq = fsquare(lineLengthsOrigin[B_AXIS]);
+ const float Csq = fsquare(lineLengthsOrigin[C_AXIS]);
+ const float Dsq = fsquare(lineLengthsOrigin[D_AXIS]);
+ const float aa = fsquare(a);
+ const float dd = fsquare(d);
+ const float k0b = (-fsquare(b) + Bsq - Dsq + dd) / (2.0 * anchors[B_AXIS][X_AXIS]) + (anchors[B_AXIS][Y_AXIS] / (2.0 * anchors[A_AXIS][Y_AXIS] * anchors[B_AXIS][X_AXIS])) * (Dsq - Asq + aa - dd);
+ const float k0c = (-fsquare(c) + Csq - Dsq + dd) / (2.0 * anchors[C_AXIS][X_AXIS]) + (anchors[C_AXIS][Y_AXIS] / (2.0 * anchors[A_AXIS][Y_AXIS] * anchors[C_AXIS][X_AXIS])) * (Dsq - Asq + aa - dd);
+ const float k1b = (anchors[B_AXIS][Y_AXIS] * (anchors[A_AXIS][Z_AXIS] - anchors[D_AXIS][Z_AXIS])) / (anchors[A_AXIS][Y_AXIS] * anchors[B_AXIS][X_AXIS]) + (anchors[D_AXIS][Z_AXIS] - anchors[B_AXIS][Z_AXIS]) / anchors[B_AXIS][X_AXIS];
+ const float k1c = (anchors[C_AXIS][Y_AXIS] * (anchors[A_AXIS][Z_AXIS] - anchors[D_AXIS][Z_AXIS])) / (anchors[A_AXIS][Y_AXIS] * anchors[C_AXIS][X_AXIS]) + (anchors[D_AXIS][Z_AXIS] - anchors[C_AXIS][Z_AXIS]) / anchors[C_AXIS][X_AXIS];
+
+ machinePos[Z_AXIS] = (k0b - k0c) / (k1c - k1b);
+ machinePos[X_AXIS] = k0c + k1c * machinePos[Z_AXIS];
+ machinePos[Y_AXIS] = (Asq - Dsq - aa + dd) / (2.0 * anchors[A_AXIS][Y_AXIS]) + ((anchors[D_AXIS][Z_AXIS] - anchors[A_AXIS][Z_AXIS]) / anchors[A_AXIS][Y_AXIS]) * machinePos[Z_AXIS];
}
// Print all the parameters for debugging
diff --git a/src/Movement/Kinematics/HangprinterKinematics.h b/src/Movement/Kinematics/HangprinterKinematics.h
index aa1ffa16..1a9587a9 100644
--- a/src/Movement/Kinematics/HangprinterKinematics.h
+++ b/src/Movement/Kinematics/HangprinterKinematics.h
@@ -23,7 +23,6 @@ public:
void MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const noexcept override;
bool SupportsAutoCalibration() const noexcept override { return true; }
bool IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept override;
- bool DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) noexcept override;
void SetCalibrationDefaults() noexcept override { Init(); }
#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE
bool WriteCalibrationParameters(FileStore *f) const noexcept override;
@@ -62,11 +61,9 @@ private:
void Init() noexcept;
void Recalc() noexcept;
float LineLengthSquared(const float machinePos[3], const float anchor[3]) const noexcept; // Calculate the square of the line length from a spool from a Cartesian coordinate
- void InverseTransform(float La, float Lb, float Lc, float machinePos[3]) const noexcept;
+ void ForwardTransform(float a, float b, float c, float d, float machinePos[3]) const noexcept;
float MotorPosToLinePos(const int32_t motorPos, size_t axis) const noexcept;
- floatc_t ComputeDerivative(unsigned int deriv, float La, float Lb, float Lc) const noexcept; // Compute the derivative of height with respect to a parameter at a set of motor endpoints
- void Adjust(size_t numFactors, const floatc_t v[]) noexcept; // Perform 3-, 6- or 9-factor adjustment
void PrintParameters(const StringRef& reply) const noexcept; // Print all the parameters for debugging
float anchors[HANGPRINTER_AXES][3]; // XYZ coordinates of the anchors
@@ -80,13 +77,6 @@ private:
// Derived parameters
float k0[HANGPRINTER_AXES], spoolRadiiSq[HANGPRINTER_AXES], k2[HANGPRINTER_AXES], lineLengthsOrigin[HANGPRINTER_AXES];
float printRadiusSquared;
- float Da2, Db2, Dc2;
- float Xab, Xbc, Xca;
- float Yab, Ybc, Yca;
- float Zab, Zbc, Zca;
- float P, Q, R, P2, U, A;
-
- bool doneAutoCalibration; // True if we have done auto calibration
#if DUAL_CAN
// Some CAN helpers