scorecompute✳
← All engines

RUST ENGINE / triangulate_tracks

3D motion from multiple angular observers

Estimate a moving object’s position and velocity from timed azimuth/elevation measurements at different locations, with model-based uncertainties and explicit geometry limits.

Open the interactive demonstration ↗Try the live calculation ↗Connect an AI assistant →

How it works

Stationary observers provide original timed angle measurements and fixed clock corrections. A bounded weighted least-squares solver fits six position/velocity parameters in a spherical Earth-fixed frame, assuming one object at constant velocity. A common grid supports initialization and samples the displayed trajectory; interpolated points are not independent fit observations.

Inputs and units

Supply 2–4 observers, each with latitude between −89° and 89°, longitude ±180°, altitude −500 to 9000 m, declared angular standard deviations 0.01–10°, and 3–120 strictly time-ordered geometric angle samples. Azimuth is 0° to 360°, elevation −2° to 90°. Fixed clock offsets are supplied in seconds, not estimated. Corrected timestamps across all measurements span at most 3600 s, must overlap between observers, and each raw timestamp is bounded to ±10¹² s. Observer separation is at most 1000 km.

What the result contains

A status (estimated, inconsistent, degenerate or no_convergence), Earth-fixed state, component standard deviations, a 6×6 covariance matrix with its parameter units, geographic trajectory samples, per-observer residuals and solver diagnostics. The demonstration uses synthetic observations of a northbound object initially at 1000 m, moving at 200 km/h; it is not a real sighting.

Example MCP call

{
  "name": "triangulate_tracks",
  "arguments": {
    "observers": [
      {
        "lat": 48.85,
        "lon": 2.35,
        "elevation_m": 35,
        "clock_offset_s": 0,
        "sigma_az_deg": 0.2,
        "sigma_el_deg": 0.2,
        "samples": [
          {
            "t_s": 0,
            "azimuth_deg": 101.991260935,
            "elevation_deg": 14.447682585
          },
          {
            "t_s": 10,
            "azimuth_deg": 93.467590277,
            "elevation_deg": 14.732612639
          },
          {
            "t_s": 20,
            "azimuth_deg": 84.786897815,
            "elevation_deg": 14.70245413
          },
          {
            "t_s": 30,
            "azimuth_deg": 76.336410848,
            "elevation_deg": 14.362974947
          },
          {
            "t_s": 40,
            "azimuth_deg": 68.446289854,
            "elevation_deg": 13.773863939
          },
          {
            "t_s": 50,
            "azimuth_deg": 61.324990456,
            "elevation_deg": 13.022637731
          },
          {
            "t_s": 60,
            "azimuth_deg": 55.051414611,
            "elevation_deg": 12.194843666
          },
          {
            "t_s": 70,
            "azimuth_deg": 49.607028444,
            "elevation_deg": 11.356342386
          },
          {
            "t_s": 80,
            "azimuth_deg": 44.917906873,
            "elevation_deg": 10.549458666
          },
          {
            "t_s": 90,
            "azimuth_deg": 40.888140057,
            "elevation_deg": 9.79700007
          },
          {
            "t_s": 100,
            "azimuth_deg": 37.420214884,
            "elevation_deg": 9.108372913
          }
        ]
      },
      {
        "lat": 48.85,
        "lon": 2.45,
        "elevation_m": 35,
        "clock_offset_s": 0,
        "sigma_az_deg": 0.2,
        "sigma_el_deg": 0.2,
        "samples": [
          {
            "t_s": 0,
            "azimuth_deg": 258.008739065,
            "elevation_deg": 14.447682585
          },
          {
            "t_s": 10,
            "azimuth_deg": 266.532409723,
            "elevation_deg": 14.732612639
          },
          {
            "t_s": 20,
            "azimuth_deg": 275.213102185,
            "elevation_deg": 14.70245413
          },
          {
            "t_s": 30,
            "azimuth_deg": 283.663589152,
            "elevation_deg": 14.362974947
          },
          {
            "t_s": 40,
            "azimuth_deg": 291.553710146,
            "elevation_deg": 13.773863939
          },
          {
            "t_s": 50,
            "azimuth_deg": 298.675009544,
            "elevation_deg": 13.022637731
          },
          {
            "t_s": 60,
            "azimuth_deg": 304.948585389,
            "elevation_deg": 12.194843666
          },
          {
            "t_s": 70,
            "azimuth_deg": 310.392971556,
            "elevation_deg": 11.356342386
          },
          {
            "t_s": 80,
            "azimuth_deg": 315.082093127,
            "elevation_deg": 10.549458666
          },
          {
            "t_s": 90,
            "azimuth_deg": 319.111859943,
            "elevation_deg": 9.79700007
          },
          {
            "t_s": 100,
            "azimuth_deg": 322.579785116,
            "elevation_deg": 9.108372913
          }
        ]
      }
    ]
  }
}

Send this tool name and arguments through a connected MCP client. Discover the authoritative input schema with tools/list.

Execution and availability

ScoreCompute exposes this tool through MCP Streamable HTTP. Rust computation runs on a connected worker; the public website and MCP gateway run separately. Among these fourteen scientific tools, CUDA is implemented for simulate_pi; the other engines currently run on CPU. The separate contributor pilot has its own fixed integer Monte Carlo workload. Requests are bounded and concurrent work may be refused when capacity is occupied.

Record inputs, assumptions and returned provenance when sharing a result. The public observatory displays software client names and tool activity, without publishing calculation arguments or results.

Explore another engine →Agent-readable overview ↗