3

I am trying to solve a system of trigonometric equations in Java, but I don't know where to start. I've used commons-math3 before to solve simple linear sets of equations, but this is above my head. Equations I am trying to solve:

  • a - e + bcosθ1 + csinθ1 + d*sin(θ21)= z

  • ( bsinθ1 + ccosθ1 + d*cos(θ21) * sinθ0 = x

  • ( bsinθ1 + ccosθ1 + d*cos(θ21) * sinθ0 = y

, where a,b,c,d and e are constants. In practical terms, given x, y, and z, I need to solve for θ0, θ1, θ2.

herrtim
  • 2,697
  • 1
  • 26
  • 36
  • 4
    Question appears to be primarily about mathematics rather than programming. – BambooleanLogic Feb 29 '16 at 13:50
  • Why the downvote?This is a valid programming question. – herrtim Feb 29 '16 at 13:52
  • 1
    @Smallhacker I disagree. I've already defined the math, now I need to solve it in Java. – herrtim Feb 29 '16 at 13:53
  • 1
    There are a question on quora that might be to some help: https://www.quora.com/Are-there-any-good-Java-libraries-for-performing-non-linear-least-square-fits – AnAmuser Feb 29 '16 at 14:16
  • Looks as this describes a set of 3D rotations. Can you describe the scenario? Maybe, there is a geometric solution. If not, I would try a numerical least squares solver. – Nico Schertler Feb 29 '16 at 16:04
  • 4
    @Smallhacker While this has a mathematical flavour, solving complicated systems of equations on a computer can involve numerical programming issues which go beyond pure math problems. I'd say it's applicable to SO. – eigenchris Feb 29 '16 at 17:02
  • Are you sure you did not miss some minus signs in terms involving θ_1? – Lutz Lehmann Feb 29 '16 at 18:55

2 Answers2

2

You need to use the root-finding algorithm.

It is usually studied in calculus as the Newton's method or Newton Raphson method.

You will have to use a multi-dimensional secant method or Muller's method. Numerical recipes has something on it.

Mochan
  • 84
  • 1
  • 5
1

You can use the least-squares-in-java project for this. Here’s the code that will solve your problem:

import org.junit.Assert;
import org.junit.Test;
import org.orangepalantir.leastsquares.Function;

public class NonLinearTrigonometricSolver {

  // Solves the following non-linear set of equations:

  //  a - e + bcosθ1 + csinθ1 +  d * sin(θ1 + θ2) ) = z

  //  ( bsinθ1 + ccosθ1 + d * cos(θ1 + θ2) ) * sinθ0 = x

  //  ( bsinθ1 + ccosθ1 + d * cos(θ1 + θ2) ) * cosθ0 = y

  // given x, y, z, solve for θ0, θ1, θ2

  static final double a = 125;
  static final double b = 143;
  static final double c = 50;
  static final double d = 142;
  static final double e = 96;

  static final double x = 0;
  static final double y = 192;
  static final double z = 172;

  @Test
  public void testNonLinearTrigonometricSolver() {

    double[][] xs = { { -1 }, { 0 }, { 1 } };

    double[] zs = { z, x, y };

    double r = Math.sqrt(x * x + y * y);
    final double sinTheta0 = x / r;
    final double cosTheta0 = y / r;

    Function f = new Function() {

      @Override
      public double evaluate(double[] values, double[] parameters) {

        double t1 = parameters[0];
        double t2 = parameters[1];
        if (values[0] == -1) {
          return a - e + b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1);

        } else if (values[0] == 0) {
          return (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1)) * sinTheta0;
        } else {
          return (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1)) * cosTheta0;
        }
      }

      @Override
      public int getNParameters() {

        return 2;
      }

      @Override
      public int getNInputs() {

        return 1;
      }
    };

    NonLinearSolver fit = new NonLinearSolver(f);
    fit.setData(xs, zs);
    double[] params = { 0, 0 };
    fit.setParameters(params);

    fit.fitData();
    // improving results.
    fit.setMinChange(1e-32);
    fit.setMinError(1e-32);
    fit.setStepSize(0.5);

    fit.fitData();

    double t1 = fit.getParameters()[0];
    double t2 = fit.getParameters()[1];
    double arg = y / (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1));
    // System.out.println(" " + arg);
    double theta0 = Math.acos(arg) * Math.signum(x);
    System.out.println(Math.toDegrees(theta0));
    System.out.println(Math.toDegrees(fit.getParameters()[0]));
    System.out.println(Math.toDegrees(fit.getParameters()[1]));

    Assert.assertEquals(0, Math.toDegrees(theta0), 1e-16);
    Assert.assertEquals(0, Math.toDegrees(fit.getParameters()[0]), 1e-16);
    Assert.assertEquals(0, Math.toDegrees(fit.getParameters()[1]), 1e-16);

  }
}
knowm
  • 36
  • 3