[wpimath] Implement Rotation3d interpolation as slerp instead of lerp#8529
Conversation
22de6e4 to
b5a04f8
Compare
KangarooKoala
left a comment
There was a problem hiding this comment.
We'll see what the tests say, but I expect that a - b needs to be transformed into b.RelativeTo(a), not a.RelativeTo(b).
b5a04f8 to
df86aab
Compare
|
Why's that? |
|
My bad, I misspoke- The relative order of |
3a6ef75 to
298259a
Compare
| // We flip the argument order if the quaternion dot product is less than | ||
| // zero to ensure the shortest path is always taken. | ||
| if (m_q.Dot(endValue.m_q) >= 0.0) { | ||
| return Rotation3d{(endValue.m_q * m_q.Inverse()).Pow(t) * m_q}; | ||
| } else { | ||
| return Rotation3d{(m_q * endValue.m_q.Inverse()).Pow(t) * endValue.m_q}; | ||
| } |
There was a problem hiding this comment.
| // We flip the argument order if the quaternion dot product is less than | |
| // zero to ensure the shortest path is always taken. | |
| if (m_q.Dot(endValue.m_q) >= 0.0) { | |
| return Rotation3d{(endValue.m_q * m_q.Inverse()).Pow(t) * m_q}; | |
| } else { | |
| return Rotation3d{(m_q * endValue.m_q.Inverse()).Pow(t) * endValue.m_q}; | |
| } | |
| // We negate the delta if the delta's W is negative to ensure the shortest path is always taken. | |
| Quaternion delta = endValue.m_q * m_q.Inverse(); | |
| if (delta.W() < 0.0) { | |
| delta = Quaternion{0, 0, 0, 0} - delta; | |
| } | |
| return Rotation3d{delta.Pow(t) * m_q}; |
From https://en.wikipedia.org/wiki/Slerp#Quaternion_slerp:
However, because the covering is double (q and −q map to the same rotation), the rotation path may turn either the "short way" (less than 180°) or the "long way" (more than 180°). Long paths can be prevented by negating one end if the dot product, cos Ω, is negative, thus ensuring that −90° ≤ Ω ≤ 90°.
Flipping the argument order just changes the direction along the same arc. In order to change whether we travel the major arc or the minor arc, we need to negate the components of the quaternion. (For example, instead of -1/2 + √3/2 î (2 cos⁻¹(-1/2) = 240° rotation around the +X axis), use 1/2 - √3/2 î (2 cos⁻¹(1/2) = 120° rotation around the -X axis).)
There was a problem hiding this comment.
I wish these Wikipedia articles made their intent clearer. Ω wasn't explicitly defined to be q₁q₀⁻¹.
There was a problem hiding this comment.
I don't think using the delta quaternion there is correct either. They said to negate one end, not both. Again, this article is clear as mud.
There was a problem hiding this comment.
Hm... Negating endValue.m_q is equivalent to negating delta, though, right? (And negating m_q does the same exact with an extra negation on the top level, which doesn't affect the actual representing rotation.)
Agreed that my initial explanation wasn't quite right (and also that the article is not very clear), but I think the implementation is still okay (though we should probably update the comments).
53555a9 to
3f71674
Compare
Also replace arithmetic operators since they're not commutative, which is confusing for users.
3f71674 to
b61f7dd
Compare
Also replace arithmetic operators since they're not commutative, which is confusing for users.