Commit 2f20bf7
committed
Fix quaternion slerp when the endpoints are the same rotation
The slerp weights sin((1-s)t)/sin(t) and sin(s.t)/sin(t) are singular wherever
sin(t) vanishes, ie. at t=0 (coincident endpoints) and t=pi (antipodal endpoints,
which are the same rotation under the double cover). qslerp() guarded only t=0;
UnitQuaternion.interp() and .interp1() re-derived the weights inline and guarded
neither, so they raised on valid input:
q = UnitQuaternion.Rx(0.3)
q.interp(q, 0.5) # ZeroDivisionError
UnitQuaternion().interp1(0.5) # ZeroDivisionError
UnitQuaternion.Rx(pi).interp(UnitQuaternion.Rx(-pi), 0.5, shortest=True)
# ZeroDivisionError
UnitQuaternion.Rx(pi).interp(UnitQuaternion.Rx(-pi), 5)
# TypeError, non-unit result
qslerp() itself returned non-unit quaternions near t=pi: qslerp(q, -q, 0.5)
gave [0 0 0 0], and for endpoints 1e-9 from antipodal the norm reached 5.8e6.
Root of that: acos(dotprod) loses the small angle to rounding at both ends, so
sin(acos(dotprod)) is a bad denominator. Take sin(t) directly as the length of
the component of q1 orthogonal to q0, which keeps full relative precision, and
get t from atan2. The only remaining degenerate case is sin(t) == 0, where q0
and q1 are the same rotation and so is every interpolate.
Measured against a 50-digit q0*exp(s*log(q0^-1.q1)) reference over the whole
range of t and s, worst error for t within 1e-6 of pi drops from 4.4e-5 to
2.7e-10 rad, and the largest deviation from unit norm anywhere from 8.2e6 to
2.8e-4. Ordinary angles are unchanged to within 1 ulp, and the whole surface
still agrees with scipy's Slerp to 1.4e-15 rad over 10000 random pairs.
The two UnitQuaternion methods now call qslerp(), which their own :seealso:
already pointed at, so the formula lives in one place.1 parent 8b83c1f commit 2f20bf7
4 files changed
Lines changed: 80 additions & 57 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
789 | 789 | | |
790 | 790 | | |
791 | 791 | | |
792 | | - | |
| 792 | + | |
793 | 793 | | |
794 | 794 | | |
795 | 795 | | |
| |||
814 | 814 | | |
815 | 815 | | |
816 | 816 | | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
817 | 820 | | |
818 | 821 | | |
819 | 822 | | |
| |||
838 | 841 | | |
839 | 842 | | |
840 | 843 | | |
841 | | - | |
842 | | - | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
843 | 852 | | |
844 | 853 | | |
845 | | - | |
| 854 | + | |
846 | 855 | | |
847 | | - | |
| 856 | + | |
| 857 | + | |
848 | 858 | | |
849 | 859 | | |
850 | 860 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1946 | 1946 | | |
1947 | 1947 | | |
1948 | 1948 | | |
1949 | | - | |
1950 | | - | |
1951 | | - | |
1952 | 1949 | | |
1953 | | - | |
1954 | | - | |
1955 | | - | |
1956 | | - | |
1957 | | - | |
1958 | | - | |
1959 | | - | |
1960 | | - | |
1961 | | - | |
1962 | | - | |
1963 | | - | |
1964 | | - | |
1965 | | - | |
1966 | | - | |
1967 | | - | |
1968 | | - | |
1969 | | - | |
1970 | | - | |
1971 | | - | |
1972 | | - | |
1973 | | - | |
1974 | | - | |
1975 | | - | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
1976 | 1953 | | |
1977 | 1954 | | |
1978 | 1955 | | |
| |||
2019 | 1996 | | |
2020 | 1997 | | |
2021 | 1998 | | |
2022 | | - | |
2023 | | - | |
2024 | | - | |
2025 | | - | |
2026 | | - | |
2027 | | - | |
2028 | | - | |
2029 | | - | |
2030 | | - | |
2031 | | - | |
2032 | | - | |
2033 | | - | |
2034 | | - | |
2035 | | - | |
2036 | | - | |
2037 | | - | |
2038 | | - | |
2039 | | - | |
2040 | | - | |
2041 | | - | |
2042 | | - | |
2043 | | - | |
2044 | | - | |
2045 | | - | |
2046 | | - | |
2047 | | - | |
| 1999 | + | |
| 2000 | + | |
| 2001 | + | |
2048 | 2002 | | |
2049 | 2003 | | |
2050 | 2004 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
178 | 178 | | |
179 | 179 | | |
180 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
181 | 209 | | |
182 | 210 | | |
183 | 211 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
701 | 701 | | |
702 | 702 | | |
703 | 703 | | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
704 | 735 | | |
705 | 736 | | |
706 | 737 | | |
| |||
0 commit comments