NHacker Next
login
▲An interactive guide to sensor fusion with quaternionsquaternion.cafe
70 points by Bogdanp 18 hours ago | 23 comments
Loading comments...
mci 15 hours ago [-]
> a quaternion is a 4D representation of a rotation in 3D space

A unit quaternion represents a rotation in R³.

A quaternion represents the quotient of two vectors in R³. That's what Hamilton had in mind.

nextaccountic 7 hours ago [-]
> quotient of two vectors

How does it make sense to divide a vector by another? Can we at least multiply two vectors as well? (So that if the quaternion q is the vector a divided by the vector b, then q times b is a)

xelxebar 4 hours ago [-]
In a particular sense, division and subtraction are more general than their supposedly more primitive inverse operations.

For example, we can take the "difference" of two points to get a vector, i.e. the grocery store is in that direction, while it doesn't make much sense to add two points---this location plus the grocery store? Similarly with temperature (of a given scale), today can be 5 degrees hotter than yesterday, but saying "the total temperature between yesterday and today is 57 degrees" doesn't have a clear meaning.

So, in that vein, what operation transforms one 3D vector into another?

Well a combination of rotation and scaling, of course! There is some freedom in how you want to represent this scaling+rotation operation; we could use 3x3 matrices, meaning that the quotient of 3D vectors is reasonably described by a matrix. However, 3x3 matrices have 9 degrees of freedom, which is way overkill, since we just need 4 numbers: an axis (2 params), an angle, and a scale factor. For this reason, quaternions are a particularly natural representation of 3D vector division.

The general concept of division that we're getting at here has the terrible name "g-torsor". If you're not familiar with abstract algebra, though, the definition is not very enlightening. However, John Baez has a really accessible article[0] that comes to the rescue!

Side note: notice that in general, the results of division are different objects than the things doing the division. As such, it's somewhat unfortunate that we use the same units for both in many cases, e.g. temperature and temperature differences are really different things. Talking about units quickly turns into type theory, though, so I'll stop there.

[0]:https://math.ucr.edu/home/baez/torsors.html

reikonomusha 6 hours ago [-]
It doesn't make sense in and of itself. We usually think of division as a closed operation: we divide two things (like real numbers) and we get the same kind of thing out (another real number).

In Hamilton's original view of quaternions, he defined a "geometric quotient" of two 3d directed lines (one kind of object) as being a quaternion (another kind of object), and gave all sorts of complicated geometric formulas for how to calculate it.

xeonmc 14 hours ago [-]
in other words, dilation + rotation
xelxebar 5 hours ago [-]
Also, "double" rotations, which have no analogue in 3D space. The extra degree of freedom in 4D lets you perform 2 orthogonal rotations. This means that you can rotate around in 4D space, leaving only the origin fixed. In 3D rotations always fix some axis.

Trying to think about this stuff can be mind-bending, since it's natural to try to visualize things. So to give a little intuition, consider the coordinates of a 4D vector (x,y,z,w) and notice that we can spin around in both the x-y and z-w planes at the same time without interfering with each other!

thekoma 7 hours ago [-]
That’s nice. I’m interested in why you went for a complementary filter specifically, if it was enough for your purpose or just the first one you tried out. (I see you reference the ahrs package where there are also implementations for other attitude estimators.)
RossBencina 4 hours ago [-]
Indeed there is a whole world of observers over Lie groups. Examples:

https://en.wikipedia.org/wiki/Invariant_extended_Kalman_filt...

https://trumpf.id.au/pubs/Hua_Zamani_Trumpf_Mahony_Hamel_CDC...

Unirely01 45 minutes ago [-]
[dead]
oneshtein 15 hours ago [-]

  /* Produce a quaternion from an axis-angle representation.*/
  function quat_from_axis(theta: number, x: number, y: number, z: number) {    
    const halfcos = Math.cos(theta * 0.5);    
    const halfsin = Math.sin(theta * 0.5);    

    return new Quaternion(
        halfcos,
        axis[0] * halfsin,
        axis[1] * halfsin,
        axis[2] * halfsin,
    );    
  }
Function is vibe coded.
noodlejs 15 hours ago [-]
Hi! Author here. I hand wrote this website and the source code of the examples mostly comes from my own debugging tools. That method in particular is just a very minimal implementation of section 8.5.2 of this textbook (but I tried to make it friendly for the blog post).

https://gamemath.com/book/orient.html#quaternion_geometry

polishdude20 14 hours ago [-]
Sorry, but x,y and z are not even being used in that function...
noodlejs 14 hours ago [-]
LOL ok yeah, that's a copy-paste issue. I'll fix it up here shortly.
xeonmc 14 hours ago [-]
imo it's better to express the conversion relation as exp-log pairs:

    fn exp(q: Quat) -> Quat {
        let ijk = sqrt(q.i*q.i + q.j*q.j + q.k*q.k);
        Quat {
            i: exp(q.l) * sin(ijk) * q.i / ijk,
            j: exp(q.l) * sin(ijk) * q.j / ijk,
            k: exp(q.l) * sin(ijk) * q.k / ijk,
            l: exp(q.l) * cos(ijk),
        }
    }

    fn log(q: Quat) -> Quat {
        let ijk = sqrt(q.i*q.i + q.j*q.j + q.k*q.k);
        Quat {
            i: atan2(ijk, q.l) * q.i / ijk,
            j: atan2(ijk, q.l) * q.j / ijk,
            k: atan2(ijk, q.l) * q.k / ijk,
            l: 0.5 * log(q.i*q.i + q.j*q.j + q.k*q.k + q.l*q.l),
        }
    }
ARob109 14 hours ago [-]
I've been seeing "that's vibe coded" comments a lot lately on posts. Comments that call out code that may or may not be vibe-coded. At what point should these types of posts start getting down-voted? It's not constructive, and IMO imparts a negative connotation.

HN: Show HN Awesome New LLM can Code!! Also HN: TFA is vibe coded angry pitchfork or ugh

bubblyworld 4 hours ago [-]
I agree, this is becoming HN's new favourite way to detail a conversation unproductively. It's up there with doxxing and ad hominems in my opinion - unverifiable and usually antagonistic.
RossBencina 5 hours ago [-]
Yes, and low effort backhanded comments about "AI slop" are also getting tiresome.
feoren 15 hours ago [-]
What makes you so confident that you can tell that a 3-line function is AI? Especially given that the author denies it, with evidence.
oneshtein 13 hours ago [-]
It cannot work, because x,y,z are not used at all.
margalabargala 13 hours ago [-]
This looks more like a copy paste error, where the function signature requests xyz, but the function itself uses an undefined array "axis" of which xyz correspond to indexes 0-2.

The code is correct aside from the obvious bug.

Bugs predate the existence of AI by decades. This particular bug doesn't look like one an AI would write.

throwaway290 6 hours ago [-]
unused variables is typical LLM.

Also it's a short function. It's impossible to miss unused parame if you read your own code at all. And if you somehow don't... then it's deserved anyway.

cindyllm 5 hours ago [-]
[dead]
CamperBob2 13 hours ago [-]
Then again, that's just the AI would say...
dzidol 9 hours ago [-]
I love vibe coding. Even the variables don't match (x, y, x vs axis[3]) and the coder is left with no knowledge what's they doing. You'll probably either prompt for fixing it or fix it yourself, but will still not get substantial amount of the domain knowledge -- and let's be honest, this is example just the simplest term there, that's why the code is so easy to correct even without thinking...
dzidol 9 hours ago [-]
I just figured out from subcomments it's an excerpt from article, so my comment just doesn't fit here (thought author of the comment I replied to just braged they can vibe code something ad hoc and don't need to read about domain). Apologies for the mistake (still keeping my opinion about vibe coding).