An interactive guide to sensor fusion with quaternions

(quaternion.cafe)

75 points | by Bogdanp 23 hours ago

4 comments

  • mci 20 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 12 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 9 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 11 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 19 hours ago
      in other words, dilation + rotation
      • xelxebar 10 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 12 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.)
  • Unirely01 5 hours ago
    [dead]
  • oneshtein 20 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 19 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 19 hours ago
        Sorry, but x,y and z are not even being used in that function...
        • noodlejs 18 hours ago
          LOL ok yeah, that's a copy-paste issue. I'll fix it up here shortly.
          • xeonmc 18 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 18 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 9 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 9 hours ago
        Yes, and low effort backhanded comments about "AI slop" are also getting tiresome.
    • feoren 19 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 18 hours ago
        It cannot work, because x,y,z are not used at all.
        • margalabargala 17 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 10 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.

      • CamperBob2 18 hours ago
        Then again, that's just the AI would say...
    • dzidol 14 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 14 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).