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 seed, wszystkie 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.