Moduł 03 · numeryczne

Metody Jakobianowe

Jacobian Transpose, pseudoinwersja, Damped Least Squares, SDLS.

Dlaczego nie zamkniętą formułą?

Metoda analityczna (moduły 1–2) daje dokładne rozwiązanie i jest właściwym wyborem, gdy znamy zamkniętą formę dla danej geometrii — np. Puma 560 (forma A Piepera) czy UR5 (forma B). Schody zaczynają się gdy: (a) manipulator ma 7+ DOF — wtedy IK ma nieskończenie wiele rozwiązań i potrzeba dodatkowych kryteriów (Franka Panda, KUKA LBR iiwa); (b) używamy nietypowej geometrii bez gotowego wyprowadzenia — roboty chirurgiczne, prototypy, custom mechanizmy; (c) uczenie się dynamicznie zmienia model (np. estymacja online długości ogniw przy soft-robotach).

Dla typowych przemysłowych 6-DOF rozwiązanie zamknięte zawsze istnieje (Raghavan–Roth dowodzą, że dowolny 6-DOF ma co najwyżej 16 rzeczywistych rozwiązań i wszystkie da się wyznaczyć analitycznie), ale w praktyce jego wyprowadzenie bywa pracochłonne. Solvery numeryczne dają rozwiązanie „od ręki" dla dowolnej geometrii podanej tabelą DH — bez ręcznej algebry, bez zgadywania struktury wzorów. To czyni je domyślną opcją w prototypowaniu.

Potrzebujemy więc solverów numerycznych — działających dla dowolnego manipulatora, nawet jeśli równania są nieliniowe w sposób, który uniemożliwia ich odwrócenie ręcznie. Wszystkie metody tego modułu oparte są na jednym pomyśle: linearyzacji przez Jakobian.

Intuicja: metoda Newtona w jednym wymiarze

Zanim przejdziemy do przestrzeni konfiguracji 6-DOF, popatrzmy na analogiczny problem w 1D. Chcemy rozwiązać równanie f(x)=0f(x) = 0 dla pewnej gładkiej, nieliniowej funkcji ff. Bez zamkniętej formuły — używamy metody Newtona–Raphsona:

  1. Zgadujemy startową wartość x0x_0.
  2. Liczymy styczną do wykresu w punkcie (x0,f(x0))(x_0, f(x_0)).
  3. Przedłużamy styczną do przecięcia z osią X — nowe przybliżenie x1=x0f(x0)/f(x0)x_1 = x_0 - f(x_0)/f'(x_0).
  4. Powtarzamy: x2x_2 ze stycznej w x1x_1, i tak dalej.

Każda kolejna styczna „lepiej się dopasowuje" do miejsca zerowego xx^*. Po kilku iteracjach osiągamy dowolną precyzję:

xf(x)-2-112f(x) = x³ − 4x − 1x0x1x2x3 ≈ x*Iteracja Newtona:xₖ₊₁ = xₖ − f(xₖ) / f′(xₖ)styczna → przecięcie z osią x

Kluczowe spostrzeżenie: w jednym kroku nie próbujemy od razu trafić w rozwiązanie. Zamiast tego zastępujemy trudną, nieliniową funkcję ff jej łatwą, liniową aproksymacją (styczną) i rozwiązujemy problem liniowy — który umiemy. Dopiero powtarzanie tego schematu doprowadza nas do celu.

Czym właściwie jest Jakobian?

W 1D rolę „wrażliwości" wyjścia na wejście pełni pochodna f(x)f'(x). Mówi ona: „jeżeli zmienię xx o jednostkę, to y=f(x)y = f(x) zmieni się w przybliżeniu o f(x)f'(x) jednostek". W robotyce mamy wejście q=(q1,,qn)q = (q_1, \dots, q_n) (kąty przegubów) i wyjście ξ=(vx,vy,vz,ωx,ωy,ωz)\xi = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z) (prędkość liniowa i kątowa końcówki) — sześć liczb wyjścia, n liczb wejścia. „Pochodna" takiego odwzorowania to macierz — właśnie Jakobian J(q)R6×nJ(q) \in \mathbb{R}^{6 \times n}:

J(q)  =  [vxq1vxqnωzq1ωzqn]J(q) \;=\; \begin{bmatrix} \dfrac{\partial v_x}{\partial q_1} & \cdots & \dfrac{\partial v_x}{\partial q_n} \\[2pt] \vdots & \ddots & \vdots \\[2pt] \dfrac{\partial \omega_z}{\partial q_1} & \cdots & \dfrac{\partial \omega_z}{\partial q_n} \end{bmatrix}

Wiersze macierzy odpowiadają sześciu składowym prędkości końcówki (3 translacyjne + 3 obrotowe). Kolumny macierzy odpowiadają poszczególnym przegubom — każda kolumna JiJ_i mówi, jak jednostkowa prędkość i-tego przegubu wpływa na końcówkę:

„Jeśli obrócę przegub qᵢ o maleńki kąt —w którą stronę pojedzie końcówka?"q₁q₂końcówka (TCP)J₁ · q̇₁J₂ · q̇₂strzałki = chwilowy kierunek ruchu końcówkiprzy obrocie TYLKO tego przegubuKażda kolumna jakobianu =wkład jednego przegubudo ruchu końcówki.Kolumna J₁:prędkość końcówki,gdy q̇₁ = 1, reszta = 0Kolumna J₂:prędkość końcówki,gdy q̇₂ = 1, reszta = 0Suma wkładów:ξ = J₁q̇₁ + J₂q̇₂ = J(q) · q̇

Innymi słowy: wyobraź sobie, że obracasz tylko jeden przegub, resztę trzymasz nieruchomo. Końcówka zakreśla łuk — lokalnie wektor jej prędkości to właśnie kolumna Jakobianu odpowiadająca temu przegubowi. Jeśli wszystkie przeguby obracają się jednocześnie, ich wkłady się dodają liniowo (bo różniczkowanie jest liniowe):

ξ  =  J1(q)q˙1+J2(q)q˙2++Jn(q)q˙n  =  J(q)q˙\xi \;=\; J_1(q)\,\dot q_1 + J_2(q)\,\dot q_2 + \cdots + J_n(q)\,\dot q_n \;=\; J(q)\,\dot q

Trzy kluczowe rzeczy do zapamiętania o Jakobianie:

  1. Jakobian zależy od qq. To nie jest „stała macierz robota" — to pochodna cząstkowa w konkretnym punkcie. Gdy zmieniasz konfigurację, Jakobian się zmienia. Stąd w pętli iteracyjnej musimy go przeliczać za każdym razem.
  2. Jakobian łączy prędkości, nie pozycje. Relacja ξ=Jq˙\xi = J\dot q jest między prędkością końcówki a prędkościami przegubów. Dla małych przyrostów (lokalnie) mamy ΔxJΔq\Delta x \approx J \, \Delta q — stąd iteracyjne rozwiązanie IK.
  3. Dla przegubów obrotowych istnieje jawny wzór. Nie trzeba różniczkować symbolicznie — kolumnę JiJ_i można zapisać geometrycznie (zobacz StepPanel 1 niżej): wkład do prędkości liniowej końcówki to z^i×(peepi)\hat{\mathbf{z}}_i \times (\mathbf{p}_\text{ee} - \mathbf{p}_i) (iloczyn wektorowy osi obrotu z wektorem „promień od osi do końcówki"); wkład do prędkości kątowej — to sama oś z^i\hat{\mathbf{z}}_i. Dla przegubu przesuwnego jest jeszcze prościej: tylko wkład liniowy z^i\hat{\mathbf{z}}_i, zero wkładu kątowego.

Newton w 6 wymiarach — powrót do IK

Teraz łączymy obie intuicje. W IK rozwiązujemy F(q)=0\mathbf{F}(q) = \mathbf{0}, gdzie F(q)=Tf(q)\mathbf{F}(q) = T^{*} \ominus f(q) jest wektorowym błędem pozy (6-wymiarowym — translacja + rotacja). W metodzie Newtona rolę „dzielenia przez pochodną" (z 1D) pełni pseudoinwersja Jakobianu JJ^\dagger:

xk+1=xkf(xk)f(xk)1D Newtonqk+1=qk+J(qk)e(qk)6D Newton dla IK\underbrace{x_{k+1} = x_k - \frac{f(x_k)}{f'(x_k)}}_{\text{1D Newton}} \quad\longrightarrow\quad \underbrace{q_{k+1} = q_k + J^{\dagger}(q_k)\,\mathbf{e}(q_k)}_{\text{6D Newton dla IK}}

(znak się odwraca, bo definiujemy błąd jako e=Tf(q)\mathbf{e} = T^* \ominus f(q), nie f(q)Tf(q) - T^*, ale struktura kroku jest identyczna). Resztę wariantów — Jacobian Transpose, DLS, Adaptive DLS — zobaczymy niżej jako modyfikacje tego samego kroku, różnie radzące sobie z trudnościami, gdy Jakobian jest źle uwarunkowany.

Anatomia pojedynczej iteracji

Pojedyncza iteracja solvera Jakobianowego to pięć etapów wykonywanych w stałej kolejności. Po piątym sprawdzamy warunek stopu i albo kończymy, albo wracamy do pierwszego z nową wartością qq:

1. FK aktualnej konfiguracjiTₖ = f(qₖ)2. Oblicz błąd pozy (twist)eₖ = log(T* · Tₖ⁻¹) ∈ ℝ⁶3. Oblicz jakobian J(qₖ)macierz 6×n, zależna od qₖ4. Wyznacz krok Δqₖ (zależnie od wariantu)α · Jᵀ · e — transposeJ† · e — pseudoinverseJᵀ(JJᵀ + λ²I)⁻¹ · e — DLS5. Aktualizuj konfiguracjęqₖ₊₁ = qₖ + Δqₖ‖eₖ‖ < ε?warunek stoputakq* = qₖk ← k+1startq₀ = seed

Zauważ: JJ liczymy od nowa w każdej iteracji — bo zależy od aktualnego qkq_k. To nie jest „statyczna macierz robota"; to pochodna cząstkowa wyliczana w bieżącym punkcie przestrzeni konfiguracji. Gdyby FK była liniowa, wystarczyłaby jedna iteracja (tak jak Newton na funkcji liniowej trafia w zero od razu). FK jest silnie nieliniowe — stąd konieczność pętli.

Pseudokod

q ← q_seed              // zgadnięta/znana konfiguracja startowa
for k = 0, 1, 2, … do
    T_k ← FK(q)                            // 1. FK
    e_k ← twist_error(T_k, T_target)       // 2. błąd w SE(3)
    if  ‖e_k‖  <  ε  then  return  q       //    warunek stopu
    J_k ← jacobian(q)                      // 3. jakobian w aktualnym punkcie
    Δq  ← solve_step(J_k, e_k, method)     // 4. krok (Transpose / Pinv / DLS / SDLS)
    q   ← q + α · Δq                       // 5. aktualizacja (α = step size)
end for
return  q  // osiągnięto limit iteracji bez zbieżności

Klucz do zrozumienia — dwa poziomy „nieliniowości"

  • Zewnętrzna pętla po iteracjach — to ta, która pozwala nam pokonać nieliniowość FK. Po każdym kroku linearyzujemy od nowa w nowym punkcie qkq_k.
  • Wewnętrzny krok liniowy — rozwiązujemy układ JΔq=eJ\,\Delta q = e. To jest łatwe (algebra liniowa), ale wrażliwe: przy złym uwarunkowaniu JJ krok staje się ogromny, a wtedy punkt qk+1q_{k+1} wylatuje poza obszar, w którym linearyzacja obowiązywała. Stąd modyfikacje — tłumienie, ograniczanie kroku — które poznamy dalej.

Co oznacza „zbieżność" i kiedy jej brak

Zbieżność to spadek normy błędu ek\|\mathbf{e}_k\| do zera. W dobrym przypadku spadek jest kwadratowy (przy pełnym Newtonie i pseudoinwersji w okolicy rozwiązania): błąd w iteracji k+1k+1 jest proporcjonalny do kwadratu błędu w iteracji kk. Oznacza to, że liczba cyfr dokładnych się podwaja z każdym krokiem.

Co może pójść nie tak:

  • Rozbieżność — gdy krok Δq\Delta q jest za duży (np. w pobliżu singularności JJ źle uwarunkowana), qk+1q_{k+1} skacze do obszaru, gdzie linearyzacja już nie ma sensu. Kolejne iteracje pogłębiają problem. Ratunek: tłumienie (DLS) albo line-search.
  • Oscylacje — solver oscyluje w okolicy rozwiązania zamiast w nie wchodzić. Typowe dla Jacobian Transpose ze zbyt dużym α\alpha albo dla metod bez adaptacyjnego kroku.
  • Stagnacja — krok staje się mikroskopijny (np. Je0J^\top \mathbf{e} \approx 0 gdy Transpose trafi w lokalny pseudominimalny punkt). Solver „utyka" bez osiągnięcia tolerancji.
  • Zbieg do innej gałęzi — dla Pumy mamy 8 rozwiązań; iteracyjny solver przyciąga się do tego, które jest najbliższe seedowi. Zmiana seeda może dać inną gałąź. To nie jest błąd — to cecha metody.

W panelu „Porównanie na żywo" niżej zobaczysz te zjawiska w praktyce: Transpose często stagnuje (potrzebuje tysięcy iteracji), Pseudoinwersja bywa niestabilna przy singularnościach, DLS jest niezawodny ale z residualnym błędem, Adaptive DLS łączy zalety obydwu.

Krok 1

Jakobian geometryczny — definicja

Niech f:QSE(3)f: Q \to SE(3) będzie FK. Różniczka Frécheta dfq:TqQTf(q)SE(3)se(3)=R6df_q: T_q Q \to T_{f(q)} SE(3) \cong \mathfrak{se}(3) = \mathbb{R}^6 zapisana w bazie standardowej daje macierz 6×n zwaną jakobianem geometrycznym:

J(q)  =  [J1(q)    J2(q)        Jn(q)]R6×nJ(q) \;=\; \bigl[\,J_1(q)\;|\;J_2(q)\;|\;\cdots\;|\;J_n(q)\,\bigr] \in \mathbb{R}^{6 \times n}

Dla przegubu obrotowego i kolumna ma postać:

Ji(q)  =  [z^i×(peepi)z^i]J_i(q) \;=\; \begin{bmatrix} \hat{z}_i \times (\mathbf{p}_{\text{ee}} - \mathbf{p}_i) \\ \hat{z}_i \end{bmatrix}

gdzie z^i\hat{z}_i jest jednostkowym wektorem osi obrotu przegubu i w ramce bazowej, a pi\mathbf{p}_i — dowolnym punktem na tej osi (w implementacji: początek układu współrzędnych i-tej). Dla przegubu przesuwnego:Ji=[z^i;  0]J_i = [\hat{z}_i;\; \mathbf{0}].

Sens fizyczny: JiJ_i to wkład jednostkowej prędkości q˙i\dot q_i do wektora prędkości przestrzennej efektora ξ=[v;ω]\xi = [\mathbf{v};\, \boldsymbol{\omega}]^\top, a całościowo:

ξ=J(q)q˙\xi = J(q)\,\dot q

Nieliniowy problem IK staje się lokalnie liniowy:

e(q)J(q)ΔqΔq=J(q)e(q)\mathbf{e}(q) \approx J(q)\,\Delta q \quad \Rightarrow \quad \Delta q = J^{\dagger}(q)\,\mathbf{e}(q)

gdzie e(q)\mathbf{e}(q) to twist error:

e(q)=[pp(q)log ⁣(RR(q))]\mathbf{e}(q) = \begin{bmatrix} \mathbf{p}^* - \mathbf{p}(q) \\ \log\!\bigl(R^*\,R(q)^\top\bigr) \end{bmatrix}

Część obrotowa to logarytm SO(3) — wektorω=θk^\boldsymbol{\omega} = \theta\,\hat{k} reprezentujący obrót, który trzeba wykonać, by przejść z aktualnej orientacji do zadanej. Dla małych obrotów pokrywa się to z różnicą kątów Eulera, ale w ogólnym przypadku wymaga świadomej ekstrakcji osi i kąta z RSO(3)R \in SO(3).

Krok 2

Metoda I — Jacobian Transpose

Najprostsza iteracja: zamiast odwracać JJ, użyj jego transpozycji jako przybliżenia pseudoinwersji (kierunek ten sam, skala nieodpowiednia):

Δq=αJe\Delta q = \alpha\,J^{\top}\,\mathbf{e}

Metoda jest w istocie gradientem zstępowania na 12e2\tfrac{1}{2}\|\mathbf{e}\|^2 — pochodna względem qq to Je-J^\top \mathbf{e}. Optymalny krok (wzdłuż Jᵀe minimalizujący błąd liniowy) znajduje się z:

α=e,  JJeJJe2\alpha^* = \frac{\langle \mathbf{e},\; J J^\top \mathbf{e}\rangle}{\|J J^\top \mathbf{e}\|^2}

Zalety: nie wymaga rozwiązywania układu liniowego (tylko macierz-wektor), jest odporny na singularności (Jᵀ nigdy nie "wybucha"). Wady: zbieżność liniowa — setki–tysiące iteracji dla średnich pozycji docelowych.

const JtE  = matvec(Jᵀ, e);
const JJtE = matvec(J, JtE);
const α    = (e·JJtE) / (JJtE·JJtE);
Δq = JtE.map(v => α * v);
Krok 3

Metoda II — Pseudoinwersja Moore–Penrose

Bezpośrednie odwrócenie liniowego modelu. Dla n6n \geq 6 (kwadratowego lub nadokreślonego) prawostronna inwersja minimalizująca Δq\|\Delta q\|:

J=J(JJ)1,Δq=JeJ^{\dagger} = J^{\top}\,(J\,J^{\top})^{-1}, \qquad \Delta q = J^{\dagger}\,\mathbf{e}

Implementacyjnie: rozwiązujemy JJy=eJ J^\top y = \mathbf{e} (układ 6×6), a potem Δq=Jy\Delta q = J^\top y.

Problem singularności: gdy det(JJ)0\det(J J^\top) \to 0 (np. q50q_5 \to 0 dla nadgarstka sferycznego), (JJ)1(J J^\top)^{-1} ma bardzo duże wartości własne. Krok Δq\Delta q staje się ogromny → linearyzacja jest nieważna → solver rozbiega się lub „skacze" przez singularność.

Dla 7-DOF i innych manipulatorów redundantnych (n>6n > 6) wariant right pseudoinverse pozostawia przestrzeń zerową jakobianu (ang. null-space) N(J)\mathcal{N}(J) nietrywialną — czyli istnieją niezerowe zmiany kątów przegubów, które nie zmieniają pozy efektora. Można je wykorzystać do spełnienia dodatkowych ograniczeń (kolizje, limity przegubowe). Temat rozwiniemy w module 7.

Krok 4

Metoda III — Damped Least Squares (Levenberg–Marquardt)

Kompromis między pseudoinwersją (szybka, niestabilna) a transpozycją (powolna, stabilna): dodaj tłumienie λ2I\lambda^2 I do macierzy, którą odwracasz:

Δq=J(JJ+λ2I)1e\Delta q = J^{\top}\,(J J^\top + \lambda^2 I)^{-1}\,\mathbf{e}

Równoważnie Δq\Delta q minimalizuje funkcjonał:

Δq=argminΔq  eJΔq2+λ2Δq2\Delta q = \arg\min_{\Delta q}\;\|\mathbf{e} - J\,\Delta q\|^2 + \lambda^2\,\|\Delta q\|^2

To klasyczne tłumienie Tichonowa: λ\lambda jest kosztem za każde jednostkowe przemieszczenie Δq\Delta q. Macierz JJ+λ2IJ J^\top + \lambda^2 I jest zawsze dodatnio określona (nawet przy pełnej singularności JJ), więc solver pozostaje stabilny. Kosztem jest błąd residualny λ\sim \lambda — idealnie zerowa zbieżność wymaga λ0\lambda \to 0, co przywraca problemy pseudoinwersji.

Levenberg i Marquardt zaproponowali tę formę w kontekście nieliniowego najmniejszych kwadratów; dla IK jest to de facto standard przemysłowy (używany m.in. w ROS MoveIt jakoKDL Inverse Kinematics).

Krok 5

Metoda IV — Adaptive DLS (tłumienie zależne od residuum)

Słabość stałego λ\lambda: za małe ⇒ problemy w singularności; za duże ⇒ wolna zbieżność daleko od celu. Praktyczna heurystyka (Levenberg-Marquardt-style):

λeff(e)=max ⁣(λ0,  ce)\lambda_{\text{eff}}(\mathbf{e}) = \max\!\bigl(\lambda_0,\; c\,\|\mathbf{e}\|\bigr)

Daleko od celu (e\|\mathbf{e}\| duże) — λeff\lambda_{\text{eff}} duże, krok ostrożny. Blisko celu —λeffλ0\lambda_{\text{eff}} \to \lambda_0, zbieżność tight. Wariant dodatkowy: kap wielkości kroku per-przegub (tu 0,3 rad), zapobiega „przeskokom" przy dużej linearyzacji.

Buss–Kim (2005) Selectively DLS: prawdziwy SDLS używa SVD J=UΣVJ = U\Sigma V^\top i tłumi każdy kierunek osobno zależnie od σi\sigma_i. Dla celów dydaktycznych pokazujemy powyższy uproszczony wariant, który ma ten sam efekt ilościowy bez kosztu SVD.

Porównanie na żywo

Cztery solvery startują z tego samego seeda (konfiguracja głównego kontrolera) i zmierzają do tej samej pozy docelowej TT^*. Zobaczysz to, co odróżnia dobry solver od „papierowego": liczbę iteracji, czas i — krytyczne — stabilność przy trudnych celach (spróbuj pozy bliskiej wyciągnięcia ramienia lub wyrównania osi nadgarstka).

Konfiguracja przegubów

θ₁2.8°
θ₂-77.7°
θ₃6.8°
θ₄8.5°
θ₅-19.3°
θ₆172.0°

Poza efektora (T₀⁶)

Pozycja [m]
x = 0.5000
y = 0.1500
z = 0.3000
Orientacja RPY [°]
R = 0.00
P = 90.00
Y = 0.00

Poza docelowa T*

Pozycja [m]
Orientacja RPY [°]

Parametry porównania

1e-81e-71e-61e-51e-41e-31e-21e-11e+0000111iteracje‖Δp‖ [m]
1e-81e-71e-61e-51e-41e-31e-21e-11e+0000111iteracjeΔR [rad]
metodaiteracje‖Δp‖ końcowe [m]ΔR końcowe [rad]czas [ms]status

Trajektorie końcówki w trakcie iteracji

Każdy z czterech solverów startuje z tego samego seeda (aktualna konfiguracja głównego kontrolera) i zmierza do tej samej pozy docelowej (czerwona kropka). Pełna linia pokazuje ścieżkę TCP po kolejnych iteracjach — widać wprost, jak szybko solver dochodzi do celu i jaką drogą (prosta, kręta, oscylująca).

Syntetyczne porównanie

AspektTransposePinvDLSAdapt. DLS
Koszt iteracjiO(n²)O(n³)O(n³)O(n³)
Liczba iteracji~10³~10~10²~10²
Singularnościodpornyrozbiega sięodporny (z błędem ~λ)odporny + precyzyjny
Implementacjatrywialnaprostaprostaz heurystyką
W praktyce używany?rzadkotak, z zabezpieczeniamitak — standardtak — RMS, MoveIt

Co dalej

W module 4 sformułujemy IK jako problem optymalizacji z ograniczeniami (ograniczenia przegubowe, unikanie kolizji, multi-cel) i zastosujemy solvery globalne (Nelder–Mead, SQP, ewolucyjne). W module 7 wrócimy do tematu manipulacyjności i pokażemy, jak analiza SVD Jakobianu daje operatywną miarę odległości od singularności — i jak można ją włączyć jako dodatkowy cel optymalizacyjny w przestrzeni zerowej jakobianu.

Powiązania z dynamiką: Jakobian w tym module mapuje q̇ → ẋ (pierwsza pochodna). Druga pochodna i siły potrzebne do wytworzenia ruchu to temat modułu 9 (Newton-Euler): ten sam łańcuch propagacji od bazy do efektora, ale z prędkościami, przyspieszeniami i siłami w każdym ogniwie.