Moduł 06 · analiza

Benchmark

Wspólny zbiór testowy — czas, błąd, success rate, stabilność dla każdego solvera.

Jak tu mierzymy?

Każdy solver otrzymuje ten sam zbiór testowy: NN losowych (ale deterministycznych — ziarno RNG jawne) konfiguracji qtrueq_\text{true} w ograniczeniach przegubowych, po czym FK generuje odpowiadające pozy TT^*. Jako seed dla solverów iteracyjnych podajemy qseed=qtrue+δq_\text{seed} = q_\text{true} + \boldsymbol{\delta} (drobny szum) — to realistyczna sytuacja w przemyśle: planer daje konfigurację w przybliżeniu, a solver dopina do celu.

Mierzone wartości:

  • Success rate — odsetek przypadków, dla których solver zbiega w tolerancji 1 mm / 0,57° (TOL_LIN = 10⁻³ m, TOL_ANG = 10⁻² rad).
  • Czas — średnia, mediana, 95. percentyl (wskazuje ogon powolnych przypadków).
  • Liczba iteracji (tylko dla iteracyjnych).
  • Residua końcowe — ‖Δp‖ i ΔR (median).

Wykres nie liczy iteracji na osi x, bo metody mają różne definicje iteracji (Nelder-Mead liczy ewaluacje simpleksa, DLS — kroki LM). Czas wallclock jest lepszym wspólnym mianownikiem.

Uruchom benchmark

Typowe wnioski

  • Solver analitycznywygrywa bezdyskusyjnie dla Pumy: 100% success, < 0,05 ms na przypadek, residuum na poziomie precyzji 101510^{-15}. To punkt odniesienia dla każdej innej metody — jeśli druga jest gorsza, ma być za to bardziej elastyczna (pracuje dla dowolnego robota).
  • DLS bije pseudoinwersję w stabilności, jest zaledwie o ~30% wolniejszy i ma znacznie lepszy tail (p95). To praktyczny standard.
  • Jacobian Transpose uwidacznia swoją słabą zbieżność — często osiąga limit 2000 iteracji bez wejścia w tolerancję. Pokazujemy go jako pedagogiczne minimum, nie jako zalecaną metodę.
  • Nelder-Mead jest odporny i dość szybki (kilka ms), ale jego mediana residuum jest zwykle o 1–2 rzędy wielkości gorsza niż DLS — kosztem elastyczności na niegładkie cele.
  • Gradient descent — najgorszy z iteracyjnych; bez drugiego rzędu (BFGS, L-BFGS) nie skaluje się dla IK. Pokazujemy jako edukacyjne zestawienie.

Na co uważać przy własnych benchmarkach

  • Obciążenie JIT — pierwsze uruchomienie w V8 kompiluje i optymalizuje hot paths; daj solverowi „warm-up".
  • Sprawiedliwy seedwszystkie solvery muszą startować z tego samego seeda. Inaczej porównanie nie ma sensu (analityczny nie używa seeda, reszta tak).
  • Cross-branch convergence — solver iteracyjny może zbiec do innej gałęzi niż qtrueq_\text{true}, osiągając tę samą pozę. W naszym teście sukcesem jest zgodność pozy, nie zgodność w przestrzeni konfiguracji.
  • Distribution shift — benchmark z losowych qq daje „łatwe" pozy (w środku zbioru osiągalnego). Aby znaleźć trudne przypadki, trzeba próbkować z okolic singularności lub granicy osiągalności; inaczej benchmark przeceni solvery.