You walk into a cafe, looking for your friend. Seems like an easy task, until you see it’s so packed that you can’t see through the crowd at all, and everyone’s talking so loud that you can barely hear anything. The only things you know are your movements, and how far you are from your friend (through the special psychic bond you two share). How will you find each other?
I wanted to solve the exact same problem, but with devices instead of people (so no psychic connection for me), existing in a space of hundreds of other devices. Working the problem taught me a lot of really interesting science relating to robotics and state estimation, and I wrote this post so you can learn, too.
The Formal Problem: Range-Only Relative Localization
I have two microcontrollers (the large blue boards). Each has an inertial measurement unit (IMU, small board on top right), which gives me data including acceleration and compass heading. They also have an ultra-wideband unit (UWB, small board in slot on left), which gives the distance to the other unit in the pair.
The Beacons in question.
Each of these packages will be contained within a wearable device, and can therefore prompt its wearer to move around. This is an important freedom, because it means we can use the change in distance over time to determine location during the localization process, rather than purely statically.
Potential Solutions
To get us in the mindset of doing a technical implementation, let’s understand some options we have and see why they are or aren’t a good fit for what we’re trying to do.
Ultra-wideband localization, found in location-aware products including AirTags, uses a simple call-and-response system known as time of flight. The UWB measures the time it takes for a roundtrip exchange of information, which is then turned into a distance d = c ⋅ ( T l o o p − T r e p l y ) / 2 d = c \cdot (T_{loop} - T_{reply})/2 d=c⋅(Tloop−Treply)/2.
The initiator sends out a timestamped pulse to the responder, which then responds in T r e p l y T_{reply} Treply time (reported by the responder) with its own timestamp packet. The whole exchange takes T l o o p T_{loop} Tloop time, calculated at the initiator:
... continue reading